From 595d44647cafe7063a3e1fabe21a77d7c695d707 Mon Sep 17 00:00:00 2001 From: Marco Dinis Date: Mon, 4 Nov 2024 11:16:05 +0000 Subject: [PATCH] [v17] Discover EKS: handle 'CONFIG_MAP' authentication mode gracefully (#48293) * Discover EKS: handle 'CONFIG_MAP' authentication mode gracefully EKS Cluster Access Config's Authentication mode can be set to one of: - API - API_AND_CONFIG_MAP - CONFIG_MAP Teleport requires either API or API_AND_CONFIG_MAP to install the helm chart. This PR checks this value before trying to install the helm chart. This way the user is presented with a better error message. * use vars coming from ekstypes --- .../awsoidc/eks_enroll_clusters.go | 11 ++++++ .../awsoidc/eks_enroll_clusters_test.go | 35 +++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/lib/integrations/awsoidc/eks_enroll_clusters.go b/lib/integrations/awsoidc/eks_enroll_clusters.go index 000854d4d3f82..e3cc9e355ab73 100644 --- a/lib/integrations/awsoidc/eks_enroll_clusters.go +++ b/lib/integrations/awsoidc/eks_enroll_clusters.go @@ -24,6 +24,7 @@ import ( "fmt" "log/slog" "net/url" + "slices" "strings" "sync" "time" @@ -375,6 +376,16 @@ func enrollEKSCluster(ctx context.Context, log *slog.Logger, clock clockwork.Clo return "", trace.AccessDenied(`can't enroll %q because it is not accessible from Teleport Cloud, please enable endpoint public access in your EKS cluster and try again.`, clusterName) } + // When clusters are using CONFIG_MAP, API is not acessible and thus Teleport can't install the Teleport's Helm chart. + // You can read more about the Authentication Modes here: https://aws.amazon.com/blogs/containers/a-deep-dive-into-simplified-amazon-eks-access-management-controls/ + allowedAuthModes := []eksTypes.AuthenticationMode{ + eksTypes.AuthenticationModeApi, + eksTypes.AuthenticationModeApiAndConfigMap, + } + if !slices.Contains(allowedAuthModes, eksCluster.AccessConfig.AuthenticationMode) { + return "", trace.BadParameter("can't enroll %q because its access config's authentication mode is %q, only %v are supported", clusterName, eksCluster.AccessConfig.AuthenticationMode, allowedAuthModes) + } + principalArn, err := getAccessEntryPrincipalArn(ctx, clt.GetCallerIdentity) if err != nil { return "", trace.Wrap(err) diff --git a/lib/integrations/awsoidc/eks_enroll_clusters_test.go b/lib/integrations/awsoidc/eks_enroll_clusters_test.go index f946e5f1508c5..ab05516d4cbd0 100644 --- a/lib/integrations/awsoidc/eks_enroll_clusters_test.go +++ b/lib/integrations/awsoidc/eks_enroll_clusters_test.go @@ -98,6 +98,9 @@ func TestEnrollEKSClusters(t *testing.T) { Tags: map[string]string{"label1": "value1"}, CertificateAuthority: &eksTypes.Certificate{Data: aws.String(testCAData)}, Status: eksTypes.ClusterStatusActive, + AccessConfig: &eksTypes.AccessConfigResponse{ + AuthenticationMode: eksTypes.AuthenticationModeApiAndConfigMap, + }, }, { Name: aws.String("EKS2"), @@ -108,6 +111,9 @@ func TestEnrollEKSClusters(t *testing.T) { Tags: map[string]string{"label2": "value2"}, CertificateAuthority: &eksTypes.Certificate{Data: aws.String(testCAData)}, Status: eksTypes.ClusterStatusActive, + AccessConfig: &eksTypes.AccessConfigResponse{ + AuthenticationMode: eksTypes.AuthenticationModeApiAndConfigMap, + }, }, } @@ -237,6 +243,29 @@ func TestEnrollEKSClusters(t *testing.T) { `can't enroll EKS cluster "EKS1" - expected "ACTIVE" state, got "PENDING".`) }, }, + { + name: "cluster with CONFIG_MAP authentication mode is not enrolled", + enrollClient: baseClient, + eksClusters: []eksTypes.Cluster{ + { + Name: aws.String("EKS1"), + Arn: aws.String(clustersBaseArn + "1"), + Tags: map[string]string{"label1": "value1"}, + CertificateAuthority: &eksTypes.Certificate{Data: aws.String(testCAData)}, + Status: eksTypes.ClusterStatusActive, + AccessConfig: &eksTypes.AccessConfigResponse{ + AuthenticationMode: eksTypes.AuthenticationModeConfigMap, + }, + }, + }, + request: baseRequest, + requestClusterNames: []string{"EKS1"}, + responseCheck: func(t *testing.T, response *EnrollEKSClusterResponse) { + require.Len(t, response.Results, 1) + require.ErrorContains(t, response.Results[0].Error, + `can't enroll "EKS1" because its access config's authentication mode is "CONFIG_MAP", only [API API_AND_CONFIG_MAP] are supported`) + }, + }, { name: "private cluster in cloud is not enrolled", enrollClient: baseClient, @@ -250,6 +279,9 @@ func TestEnrollEKSClusters(t *testing.T) { Tags: map[string]string{"label3": "value3"}, CertificateAuthority: &eksTypes.Certificate{Data: aws.String(testCAData)}, Status: eksTypes.ClusterStatusActive, + AccessConfig: &eksTypes.AccessConfigResponse{ + AuthenticationMode: eksTypes.AuthenticationModeApiAndConfigMap, + }, }, }, request: EnrollEKSClustersRequest{ @@ -279,6 +311,9 @@ func TestEnrollEKSClusters(t *testing.T) { Tags: map[string]string{"label3": "value3"}, CertificateAuthority: &eksTypes.Certificate{Data: aws.String(testCAData)}, Status: eksTypes.ClusterStatusActive, + AccessConfig: &eksTypes.AccessConfigResponse{ + AuthenticationMode: eksTypes.AuthenticationModeApiAndConfigMap, + }, }, }, request: EnrollEKSClustersRequest{