Skip to content

Commit f3c2166

Browse files
joshfrenchadammwdamdo
authored
✨ feat: Support setting EKS authentication mode (#5578)
* feat: support setting EKS AuthenticationMode * feat: support setting EKS AuthenticationMode * Update controlplane/eks/api/v1beta2/awsmanagedcontrolplane_webhook_test.go Co-authored-by: Damiano Donati <[email protected]> * add EOF to new files --------- Co-authored-by: Adam Malcontenti-Wilson <[email protected]> Co-authored-by: Damiano Donati <[email protected]>
1 parent 0050098 commit f3c2166

16 files changed

+841
-0
lines changed

config/crd/bases/controlplane.cluster.x-k8s.io_awsmanagedcontrolplanes.yaml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2270,6 +2270,28 @@ spec:
22702270
description: AWSManagedControlPlaneSpec defines the desired state of an
22712271
Amazon EKS Cluster.
22722272
properties:
2273+
accessConfig:
2274+
description: AccessConfig specifies the access configuration information
2275+
for the cluster
2276+
properties:
2277+
authenticationMode:
2278+
default: config_map
2279+
description: |-
2280+
AuthenticationMode specifies the desired authentication mode for the cluster
2281+
Defaults to config_map
2282+
enum:
2283+
- config_map
2284+
- api
2285+
- api_and_config_map
2286+
type: string
2287+
bootstrapClusterCreatorAdminPermissions:
2288+
default: true
2289+
description: |-
2290+
BootstrapClusterCreatorAdminPermissions grants cluster admin permissions
2291+
to the IAM identity creating the cluster. Only applied during creation,
2292+
ignored when updating existing clusters. Defaults to true.
2293+
type: boolean
2294+
type: object
22732295
additionalTags:
22742296
additionalProperties:
22752297
type: string

config/crd/bases/controlplane.cluster.x-k8s.io_awsmanagedcontrolplanetemplates.yaml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,28 @@ spec:
5353
description: AWSManagedControlPlaneSpec defines the desired state
5454
of an Amazon EKS Cluster.
5555
properties:
56+
accessConfig:
57+
description: AccessConfig specifies the access configuration
58+
information for the cluster
59+
properties:
60+
authenticationMode:
61+
default: config_map
62+
description: |-
63+
AuthenticationMode specifies the desired authentication mode for the cluster
64+
Defaults to config_map
65+
enum:
66+
- config_map
67+
- api
68+
- api_and_config_map
69+
type: string
70+
bootstrapClusterCreatorAdminPermissions:
71+
default: true
72+
description: |-
73+
BootstrapClusterCreatorAdminPermissions grants cluster admin permissions
74+
to the IAM identity creating the cluster. Only applied during creation,
75+
ignored when updating existing clusters. Defaults to true.
76+
type: boolean
77+
type: object
5678
additionalTags:
5779
additionalProperties:
5880
type: string

controlplane/eks/api/v1beta1/conversion.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ func (r *AWSManagedControlPlane) ConvertTo(dstRaw conversion.Hub) error {
117117

118118
dst.Spec.Partition = restored.Spec.Partition
119119
dst.Spec.RestrictPrivateSubnets = restored.Spec.RestrictPrivateSubnets
120+
dst.Spec.AccessConfig = restored.Spec.AccessConfig
120121
dst.Spec.RolePath = restored.Spec.RolePath
121122
dst.Spec.RolePermissionsBoundary = restored.Spec.RolePermissionsBoundary
122123
dst.Status.Version = restored.Status.Version

controlplane/eks/api/v1beta1/zz_generated.conversion.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

controlplane/eks/api/v1beta2/awsmanagedcontrolplane_types.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,10 @@ type AWSManagedControlPlaneSpec struct { //nolint: maligned
192192
// +optional
193193
OIDCIdentityProviderConfig *OIDCIdentityProviderConfig `json:"oidcIdentityProviderConfig,omitempty"`
194194

195+
// AccessConfig specifies the access configuration information for the cluster
196+
// +optional
197+
AccessConfig *AccessConfig `json:"accessConfig,omitempty"`
198+
195199
// VpcCni is used to set configuration options for the VPC CNI plugin
196200
// +optional
197201
VpcCni VpcCni `json:"vpcCni,omitempty"`
@@ -248,6 +252,21 @@ type EndpointAccess struct {
248252
Private *bool `json:"private,omitempty"`
249253
}
250254

255+
// AccessConfig represents the access configuration information for the cluster
256+
type AccessConfig struct {
257+
// AuthenticationMode specifies the desired authentication mode for the cluster
258+
// Defaults to config_map
259+
// +kubebuilder:default=config_map
260+
// +kubebuilder:validation:Enum=config_map;api;api_and_config_map
261+
AuthenticationMode EKSAuthenticationMode `json:"authenticationMode,omitempty"`
262+
263+
// BootstrapClusterCreatorAdminPermissions grants cluster admin permissions
264+
// to the IAM identity creating the cluster. Only applied during creation,
265+
// ignored when updating existing clusters. Defaults to true.
266+
// +kubebuilder:default=true
267+
BootstrapClusterCreatorAdminPermissions *bool `json:"bootstrapClusterCreatorAdminPermissions,omitempty"`
268+
}
269+
251270
// EncryptionConfig specifies the encryption configuration for the EKS clsuter.
252271
type EncryptionConfig struct {
253272
// Provider specifies the ARN or alias of the CMK (in AWS KMS)

controlplane/eks/api/v1beta2/awsmanagedcontrolplane_webhook.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ func (*awsManagedControlPlaneWebhook) ValidateCreate(_ context.Context, obj runt
107107
allErrs = append(allErrs, r.Spec.AdditionalTags.Validate()...)
108108
allErrs = append(allErrs, r.validateNetwork()...)
109109
allErrs = append(allErrs, r.validatePrivateDNSHostnameTypeOnLaunch()...)
110+
allErrs = append(allErrs, r.validateAccessConfigCreate()...)
110111

111112
if len(allErrs) == 0 {
112113
return nil, nil
@@ -140,6 +141,7 @@ func (*awsManagedControlPlaneWebhook) ValidateUpdate(ctx context.Context, oldObj
140141
allErrs = append(allErrs, r.validateEKSClusterNameSame(oldAWSManagedControlplane)...)
141142
allErrs = append(allErrs, r.validateEKSVersion(oldAWSManagedControlplane)...)
142143
allErrs = append(allErrs, r.Spec.Bastion.Validate()...)
144+
allErrs = append(allErrs, r.validateAccessConfigUpdate(oldAWSManagedControlplane)...)
143145
allErrs = append(allErrs, r.validateIAMAuthConfig()...)
144146
allErrs = append(allErrs, r.validateSecondaryCIDR()...)
145147
allErrs = append(allErrs, r.validateEKSAddons()...)
@@ -318,6 +320,53 @@ func validateEKSAddons(eksVersion *string, networkSpec infrav1.NetworkSpec, addo
318320
return allErrs
319321
}
320322

323+
func (r *AWSManagedControlPlane) validateAccessConfigUpdate(old *AWSManagedControlPlane) field.ErrorList {
324+
var allErrs field.ErrorList
325+
326+
// If accessConfig is already set, do not allow removal of it.
327+
if old.Spec.AccessConfig != nil && r.Spec.AccessConfig == nil {
328+
allErrs = append(allErrs,
329+
field.Invalid(field.NewPath("spec", "accessConfig"), r.Spec.AccessConfig, "removing AccessConfig is not allowed after it has been enabled"),
330+
)
331+
}
332+
333+
// AuthenticationMode is ratcheting - do not allow downgrades
334+
if old.Spec.AccessConfig != nil && r.Spec.AccessConfig != nil &&
335+
old.Spec.AccessConfig.AuthenticationMode != r.Spec.AccessConfig.AuthenticationMode &&
336+
((old.Spec.AccessConfig.AuthenticationMode == EKSAuthenticationModeAPIAndConfigMap && r.Spec.AccessConfig.AuthenticationMode == EKSAuthenticationModeConfigMap) ||
337+
old.Spec.AccessConfig.AuthenticationMode == EKSAuthenticationModeAPI) {
338+
allErrs = append(allErrs,
339+
field.Invalid(field.NewPath("spec", "accessConfig", "authenticationMode"), r.Spec.AccessConfig.AuthenticationMode, "downgrading authentication mode is not allowed after it has been enabled"),
340+
)
341+
}
342+
343+
// BootstrapClusterCreatorAdminPermissions only applies on create, but changes should not invalidate updates
344+
if old.Spec.AccessConfig != nil && r.Spec.AccessConfig != nil &&
345+
old.Spec.AccessConfig.BootstrapClusterCreatorAdminPermissions != r.Spec.AccessConfig.BootstrapClusterCreatorAdminPermissions {
346+
mcpLog.Info("Ignoring changes to BootstrapClusterCreatorAdminPermissions on cluster update", "old", old.Spec.AccessConfig.BootstrapClusterCreatorAdminPermissions, "new", r.Spec.AccessConfig.BootstrapClusterCreatorAdminPermissions)
347+
}
348+
349+
return allErrs
350+
}
351+
352+
func (r *AWSManagedControlPlane) validateAccessConfigCreate() field.ErrorList {
353+
var allErrs field.ErrorList
354+
355+
if r.Spec.AccessConfig != nil {
356+
if r.Spec.AccessConfig.AuthenticationMode == EKSAuthenticationModeConfigMap &&
357+
r.Spec.AccessConfig.BootstrapClusterCreatorAdminPermissions != nil &&
358+
!*r.Spec.AccessConfig.BootstrapClusterCreatorAdminPermissions {
359+
allErrs = append(allErrs,
360+
field.Invalid(field.NewPath("spec", "accessConfig", "bootstrapClusterCreatorAdminPermissions"),
361+
*r.Spec.AccessConfig.BootstrapClusterCreatorAdminPermissions,
362+
"bootstrapClusterCreatorAdminPermissions must be true if cluster authentication mode is set to config_map"),
363+
)
364+
}
365+
}
366+
367+
return allErrs
368+
}
369+
321370
func (r *AWSManagedControlPlane) validateIAMAuthConfig() field.ErrorList {
322371
return validateIAMAuthConfig(r.Spec.IAMAuthenticatorConfig, field.NewPath("spec.iamAuthenticatorConfig"))
323372
}

controlplane/eks/api/v1beta2/awsmanagedcontrolplane_webhook_test.go

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ func TestWebhookCreate(t *testing.T) {
179179
secondaryCidr *string
180180
secondaryCidrBlocks []infrav1.VpcCidrBlock
181181
kubeProxy KubeProxy
182+
accessConfig *AccessConfig
182183
}{
183184
{
184185
name: "ekscluster specified",
@@ -322,6 +323,47 @@ func TestWebhookCreate(t *testing.T) {
322323
Disable: true,
323324
},
324325
},
326+
{
327+
name: "BootstrapClusterCreatorAdminPermissions true with EKSAuthenticationModeConfigMap",
328+
eksClusterName: "default_cluster1",
329+
eksVersion: "v1.19",
330+
expectError: false,
331+
accessConfig: &AccessConfig{
332+
AuthenticationMode: EKSAuthenticationModeConfigMap,
333+
BootstrapClusterCreatorAdminPermissions: ptr.To(true),
334+
},
335+
},
336+
{
337+
name: "BootstrapClusterCreatorAdminPermissions false with EKSAuthenticationModeConfigMap",
338+
eksClusterName: "default_cluster1",
339+
eksVersion: "v1.19",
340+
expectError: true,
341+
expectErrorToContain: "bootstrapClusterCreatorAdminPermissions must be true if cluster authentication mode is set to config_map",
342+
accessConfig: &AccessConfig{
343+
AuthenticationMode: EKSAuthenticationModeConfigMap,
344+
BootstrapClusterCreatorAdminPermissions: ptr.To(false),
345+
},
346+
},
347+
{
348+
name: "BootstrapClusterCreatorAdminPermissions false with EKSAuthenticationModeAPIAndConfigMap",
349+
eksClusterName: "default_cluster1",
350+
eksVersion: "v1.19",
351+
expectError: false,
352+
accessConfig: &AccessConfig{
353+
AuthenticationMode: EKSAuthenticationModeAPIAndConfigMap,
354+
BootstrapClusterCreatorAdminPermissions: ptr.To(false),
355+
},
356+
},
357+
{
358+
name: "BootstrapClusterCreatorAdminPermissions false with EKSAuthenticationModeAPI",
359+
eksClusterName: "default_cluster1",
360+
eksVersion: "v1.19",
361+
expectError: false,
362+
accessConfig: &AccessConfig{
363+
AuthenticationMode: EKSAuthenticationModeAPI,
364+
BootstrapClusterCreatorAdminPermissions: ptr.To(false),
365+
},
366+
},
325367
}
326368

327369
for _, tc := range tests {
@@ -365,6 +407,9 @@ func TestWebhookCreate(t *testing.T) {
365407
if tc.secondaryCidr != nil {
366408
mcp.Spec.SecondaryCidrBlock = tc.secondaryCidr
367409
}
410+
if tc.accessConfig != nil {
411+
mcp.Spec.AccessConfig = tc.accessConfig
412+
}
368413

369414
err := testEnv.Create(ctx, mcp)
370415

@@ -603,6 +648,112 @@ func TestWebhookUpdate(t *testing.T) {
603648
},
604649
expectError: false,
605650
},
651+
{
652+
name: "no change in access config",
653+
oldClusterSpec: AWSManagedControlPlaneSpec{
654+
EKSClusterName: "default_cluster1",
655+
AccessConfig: &AccessConfig{
656+
AuthenticationMode: EKSAuthenticationModeConfigMap,
657+
},
658+
},
659+
newClusterSpec: AWSManagedControlPlaneSpec{
660+
EKSClusterName: "default_cluster1",
661+
AccessConfig: &AccessConfig{
662+
AuthenticationMode: EKSAuthenticationModeConfigMap,
663+
},
664+
},
665+
expectError: false,
666+
},
667+
{
668+
name: "change in access config to nil",
669+
oldClusterSpec: AWSManagedControlPlaneSpec{
670+
EKSClusterName: "default_cluster1",
671+
AccessConfig: &AccessConfig{
672+
AuthenticationMode: EKSAuthenticationModeConfigMap,
673+
},
674+
},
675+
newClusterSpec: AWSManagedControlPlaneSpec{
676+
EKSClusterName: "default_cluster1",
677+
},
678+
expectError: true,
679+
},
680+
{
681+
name: "change in access config from nil to valid",
682+
oldClusterSpec: AWSManagedControlPlaneSpec{
683+
EKSClusterName: "default_cluster1",
684+
},
685+
newClusterSpec: AWSManagedControlPlaneSpec{
686+
EKSClusterName: "default_cluster1",
687+
AccessConfig: &AccessConfig{
688+
AuthenticationMode: EKSAuthenticationModeConfigMap,
689+
},
690+
},
691+
expectError: false,
692+
},
693+
{
694+
name: "change in access config auth mode from ApiAndConfigMap to API is allowed",
695+
oldClusterSpec: AWSManagedControlPlaneSpec{
696+
EKSClusterName: "default_cluster1",
697+
AccessConfig: &AccessConfig{
698+
AuthenticationMode: EKSAuthenticationModeAPIAndConfigMap,
699+
},
700+
},
701+
newClusterSpec: AWSManagedControlPlaneSpec{
702+
EKSClusterName: "default_cluster1",
703+
AccessConfig: &AccessConfig{
704+
AuthenticationMode: EKSAuthenticationModeAPI,
705+
},
706+
},
707+
expectError: false,
708+
},
709+
{
710+
name: "change in access config auth mode from API to Config Map is denied",
711+
oldClusterSpec: AWSManagedControlPlaneSpec{
712+
EKSClusterName: "default_cluster1",
713+
AccessConfig: &AccessConfig{
714+
AuthenticationMode: EKSAuthenticationModeAPI,
715+
},
716+
},
717+
newClusterSpec: AWSManagedControlPlaneSpec{
718+
EKSClusterName: "default_cluster1",
719+
AccessConfig: &AccessConfig{
720+
AuthenticationMode: EKSAuthenticationModeConfigMap,
721+
},
722+
},
723+
expectError: true,
724+
},
725+
{
726+
name: "change in access config auth mode from APIAndConfigMap to Config Map is denied",
727+
oldClusterSpec: AWSManagedControlPlaneSpec{
728+
EKSClusterName: "default_cluster1",
729+
AccessConfig: &AccessConfig{
730+
AuthenticationMode: EKSAuthenticationModeAPIAndConfigMap,
731+
},
732+
},
733+
newClusterSpec: AWSManagedControlPlaneSpec{
734+
EKSClusterName: "default_cluster1",
735+
AccessConfig: &AccessConfig{
736+
AuthenticationMode: EKSAuthenticationModeConfigMap,
737+
},
738+
},
739+
expectError: true,
740+
},
741+
{
742+
name: "change in access config bootstrap admin permissions is ignored",
743+
oldClusterSpec: AWSManagedControlPlaneSpec{
744+
EKSClusterName: "default_cluster1",
745+
AccessConfig: &AccessConfig{
746+
BootstrapClusterCreatorAdminPermissions: ptr.To(true),
747+
},
748+
},
749+
newClusterSpec: AWSManagedControlPlaneSpec{
750+
EKSClusterName: "default_cluster1",
751+
AccessConfig: &AccessConfig{
752+
BootstrapClusterCreatorAdminPermissions: ptr.To(false),
753+
},
754+
},
755+
expectError: false,
756+
},
606757
{
607758
name: "change in encryption config to nil",
608759
oldClusterSpec: AWSManagedControlPlaneSpec{

controlplane/eks/api/v1beta2/types.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package v1beta2
1818

1919
import (
2020
"fmt"
21+
"strings"
2122

2223
ekstypes "github.com/aws/aws-sdk-go-v2/service/eks/types"
2324
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -79,6 +80,26 @@ var (
7980
EKSTokenMethodAWSCli = EKSTokenMethod("aws-cli")
8081
)
8182

83+
// EKSAuthenticationMode defines the authentication mode for the cluster
84+
type EKSAuthenticationMode string
85+
86+
// APIValue returns the corresponding EKS API value for the authentication mode
87+
func (e EKSAuthenticationMode) APIValue() ekstypes.AuthenticationMode {
88+
return ekstypes.AuthenticationMode(strings.ToUpper(string(e)))
89+
}
90+
91+
var (
92+
// EKSAuthenticationModeConfigMap indicates that only `aws-auth` ConfigMap will be used for authentication
93+
EKSAuthenticationModeConfigMap = EKSAuthenticationMode("config_map")
94+
95+
// EKSAuthenticationModeAPI indicates that only AWS Access Entries will be used for authentication
96+
EKSAuthenticationModeAPI = EKSAuthenticationMode("api")
97+
98+
// EKSAuthenticationModeAPIAndConfigMap indicates that both `aws-auth` ConfigMap and AWS Access Entries will
99+
// be used for authentication
100+
EKSAuthenticationModeAPIAndConfigMap = EKSAuthenticationMode("api_and_config_map")
101+
)
102+
82103
var (
83104
// DefaultEKSControlPlaneRole is the name of the default IAM role to use for the EKS control plane
84105
// if no other role is supplied in the spec and if iam role creation is not enabled. The default

0 commit comments

Comments
 (0)