From 8842151ae64cadc88c8106994979bf4bc03d063d Mon Sep 17 00:00:00 2001 From: Claudio Gisch Date: Mon, 2 May 2022 11:59:43 -0300 Subject: [PATCH] feat: support Auth provider to directly connect to GCP --- internal/config/config.go | 4 ++ internal/web/target/multi-cluster.go | 59 ++++++++++++++++------- internal/web/target/multi-cluster_test.go | 35 ++++---------- 3 files changed, 56 insertions(+), 42 deletions(-) diff --git a/internal/config/config.go b/internal/config/config.go index c617b9b12..b2d9cb165 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -20,6 +20,7 @@ import ( "github.com/spf13/pflag" "github.com/spf13/viper" corev1 "k8s.io/api/core/v1" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" ) const ( @@ -59,6 +60,9 @@ type ClusterConfig struct { Address string `json:"address"` Token string `json:"token"` TokenFile string `json:"tokenFile"` + CA string `json:"ca"` + + AuthProvider *clientcmdapi.AuthProviderConfig `json:"authProvider"` } var rpaasConfig struct { diff --git a/internal/web/target/multi-cluster.go b/internal/web/target/multi-cluster.go index b17f34246..c70a7ee6f 100644 --- a/internal/web/target/multi-cluster.go +++ b/internal/web/target/multi-cluster.go @@ -2,6 +2,8 @@ package target import ( "context" + "encoding/base64" + "errors" "io/ioutil" "net/http" "sync" @@ -11,6 +13,7 @@ import ( "github.com/tsuru/rpaas-operator/internal/pkg/rpaas" "github.com/tsuru/rpaas-operator/pkg/observability" extensionsruntime "github.com/tsuru/rpaas-operator/pkg/runtime" + _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" "k8s.io/client-go/rest" sigsk8sclient "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -83,15 +86,10 @@ func (m *multiClusterFactory) Manager(ctx context.Context, headers http.Header) span.SetTag("pool.name", poolName) } - bearerToken, err := m.getToken(clusterName) + kubernetesRestConfig, err := m.getKubeConfig(clusterName, address) if err != nil { return nil, err } - kubernetesRestConfig := &rest.Config{ - Host: address, - BearerToken: bearerToken, - WrapTransport: observability.OpentracingTransport, - } k8sClient, err := sigsk8sclient.New(kubernetesRestConfig, sigsk8sclient.Options{Scheme: extensionsruntime.NewScheme()}) if err != nil { return nil, err @@ -109,28 +107,55 @@ func (m *multiClusterFactory) Manager(ctx context.Context, headers http.Header) return manager, nil } -func (m *multiClusterFactory) getToken(clusterName string) (string, error) { - var defaultCluster *config.ClusterConfig = nil +func (m *multiClusterFactory) getKubeConfig(name, address string) (*rest.Config, error) { + selectedCluster := config.ClusterConfig{} + for _, cluster := range m.clusters { - if cluster.Default || cluster.Name == clusterName { - defaultCluster = &cluster + if cluster.Default { + selectedCluster = cluster + } + if cluster.Name == name { + selectedCluster = cluster break } } - if defaultCluster == nil { - return "", nil + if selectedCluster.Name == "" { + return nil, errors.New("cluster not found") + } + + if selectedCluster.Address != "" { + address = selectedCluster.Address + } + + restConfig := &rest.Config{ + Host: address, + BearerToken: selectedCluster.Token, + WrapTransport: observability.OpentracingTransport, + } + + if selectedCluster.AuthProvider != nil { + restConfig.AuthProvider = selectedCluster.AuthProvider } - if defaultCluster.Token != "" { - return defaultCluster.Token, nil + if selectedCluster.CA != "" { + caData, err := base64.StdEncoding.DecodeString(selectedCluster.CA) + if err != nil { + return nil, err + } + restConfig.TLSClientConfig.CAData = caData } - if defaultCluster.TokenFile != "" { - return m.readTokenFile(defaultCluster.TokenFile) + if selectedCluster.TokenFile != "" { + var err error + restConfig.BearerToken, err = m.readTokenFile(selectedCluster.TokenFile) + if err != nil { + return nil, err + } } - return "", nil + return restConfig, nil + } func (m *multiClusterFactory) readTokenFile(tokenFile string) (string, error) { diff --git a/internal/web/target/multi-cluster_test.go b/internal/web/target/multi-cluster_test.go index 1589b7d50..1fe6f48ca 100644 --- a/internal/web/target/multi-cluster_test.go +++ b/internal/web/target/multi-cluster_test.go @@ -14,21 +14,6 @@ import ( var ctx = context.Background() -func TestMultiClusterToken(t *testing.T) { - target := NewMultiClustersFactory([]config.ClusterConfig{ - { - Name: "my-cluster", - Token: "my-token", - }, - }) - - multiClusterTarget := target.(*multiClusterFactory) - token, err := multiClusterTarget.getToken("my-cluster") - - assert.NoError(t, err) - assert.Equal(t, token, "my-token") -} - func TestMultiClusterTokenFile(t *testing.T) { tmpfile, err := ioutil.TempFile("", "example") require.NoError(t, err) @@ -45,16 +30,16 @@ func TestMultiClusterTokenFile(t *testing.T) { defer os.Remove(tmpfile.Name()) multiClusterTarget := target.(*multiClusterFactory) - token, err := multiClusterTarget.getToken("my-cluster") + restConfig, err := multiClusterTarget.getKubeConfig("my-cluster", "") assert.NoError(t, err) - assert.Equal(t, token, "token-from-file") + assert.Equal(t, "token-from-file", restConfig.BearerToken) os.Remove(tmpfile.Name()) - token, err = multiClusterTarget.getToken("my-cluster") + restConfig, err = multiClusterTarget.getKubeConfig("my-cluster", "") assert.NoError(t, err) - assert.Equal(t, token, "token-from-file") + assert.Equal(t, "token-from-file", restConfig.BearerToken) } func TestMultiClusterNoToken(t *testing.T) { @@ -73,10 +58,10 @@ func TestMultiClusterNoToken(t *testing.T) { defer os.Remove(tmpfile.Name()) multiClusterTarget := target.(*multiClusterFactory) - token, err := multiClusterTarget.getToken("my-wrong-cluster") + _, err = multiClusterTarget.getKubeConfig("my-wrong-cluster", "") - assert.NoError(t, err) - assert.Equal(t, token, "") + require.Error(t, err) + assert.Equal(t, "cluster not found", err.Error()) } func TestMultiClusterDefaultToken(t *testing.T) { @@ -90,10 +75,10 @@ func TestMultiClusterDefaultToken(t *testing.T) { }) multiClusterTarget := target.(*multiClusterFactory) - token, err := multiClusterTarget.getToken("my-other-cluster") + restConfig, err := multiClusterTarget.getKubeConfig("my-other-cluster", "") assert.NoError(t, err) - assert.Equal(t, token, "my-token") + assert.Equal(t, "my-token", restConfig.BearerToken) } func TestMultiClusterNoHeaders(t *testing.T) { @@ -108,5 +93,5 @@ func TestMultiClusterNoHeaders(t *testing.T) { rpaasManager, err := target.Manager(ctx, http.Header{}) assert.Nil(t, rpaasManager) - assert.Equal(t, err, ErrNoClusterProvided) + assert.Equal(t, ErrNoClusterProvided, err) }