@@ -22,9 +22,12 @@ import (
2222 "net"
2323
2424 "github.com/apparentlymart/go-cidr/cidr"
25+ "github.com/aws/aws-sdk-go-v2/aws"
26+ ekstypes "github.com/aws/aws-sdk-go-v2/service/eks/types"
2527 "github.com/pkg/errors"
2628 apierrors "k8s.io/apimachinery/pkg/api/errors"
2729 "k8s.io/apimachinery/pkg/runtime"
30+ "k8s.io/apimachinery/pkg/util/sets"
2831 "k8s.io/apimachinery/pkg/util/validation/field"
2932 "k8s.io/apimachinery/pkg/util/version"
3033 "k8s.io/klog/v2"
@@ -52,6 +55,9 @@ const (
5255 cidrSizeMin = 16
5356 vpcCniAddon = "vpc-cni"
5457 kubeProxyAddon = "kube-proxy"
58+
59+ autoModeComputeNodePoolSystem = "system"
60+ autoModeComputeNodePoolGeneral = "general-purpose"
5561)
5662
5763// SetupWebhookWithManager will setup the webhooks for the AWSManagedControlPlane.
@@ -102,6 +108,8 @@ func (*awsManagedControlPlaneWebhook) ValidateCreate(_ context.Context, obj runt
102108 allErrs = append (allErrs , r .validateSecondaryCIDR ()... )
103109 allErrs = append (allErrs , r .validateEKSAddons ()... )
104110 allErrs = append (allErrs , r .validateDisableVPCCNI ()... )
111+ allErrs = append (allErrs , r .validateAccessConfig (nil )... )
112+ allErrs = append (allErrs , r .validateAutoMode (nil )... )
105113 allErrs = append (allErrs , r .validateRestrictPrivateSubnets ()... )
106114 allErrs = append (allErrs , r .validateKubeProxy ()... )
107115 allErrs = append (allErrs , r .Spec .AdditionalTags .Validate ()... )
@@ -142,6 +150,8 @@ func (*awsManagedControlPlaneWebhook) ValidateUpdate(ctx context.Context, oldObj
142150 allErrs = append (allErrs , r .Spec .Bastion .Validate ()... )
143151 allErrs = append (allErrs , r .validateIAMAuthConfig ()... )
144152 allErrs = append (allErrs , r .validateSecondaryCIDR ()... )
153+ allErrs = append (allErrs , r .validateAccessConfig (oldAWSManagedControlplane )... )
154+ allErrs = append (allErrs , r .validateAutoMode (oldAWSManagedControlplane )... )
145155 allErrs = append (allErrs , r .validateEKSAddons ()... )
146156 allErrs = append (allErrs , r .validateDisableVPCCNI ()... )
147157 allErrs = append (allErrs , r .validateRestrictPrivateSubnets ()... )
@@ -423,6 +433,92 @@ func validateDisableVPCCNI(vpcCni VpcCni, addons *[]Addon, path *field.Path) fie
423433 return allErrs
424434}
425435
436+ func (r * AWSManagedControlPlane ) validateAccessConfig (old * AWSManagedControlPlane ) field.ErrorList {
437+ return validateAccessConfig (r .Spec .AccessConfig , old , field .NewPath ("spec" , "accessConfig" ))
438+ }
439+
440+ func validateAccessConfig (accessConfig AccessConfig , old * AWSManagedControlPlane , path * field.Path ) field.ErrorList {
441+ var (
442+ allErrs field.ErrorList
443+ authModeOK bool
444+ )
445+
446+ authConfigField := path .Child ("authenticationMode" )
447+
448+ for _ , accessMode := range ekstypes .AuthenticationMode ("" ).Values () {
449+ if ekstypes .AuthenticationMode (* accessConfig .AuthenticationMode ) == accessMode {
450+ authModeOK = true
451+ }
452+ }
453+
454+ if ! authModeOK {
455+ allErrs = append (allErrs , field .Invalid (authConfigField , * accessConfig .AuthenticationMode , "unsupported authenticationMode provided" ))
456+ }
457+
458+ if old != nil {
459+ if * old .Spec .AccessConfig .AuthenticationMode != * accessConfig .AuthenticationMode {
460+ if ekstypes .AuthenticationMode (* accessConfig .AuthenticationMode ) == ekstypes .AuthenticationModeConfigMap {
461+ allErrs = append (allErrs , field .Invalid (authConfigField , * accessConfig .AuthenticationMode , "cannot switch authenticationMode to legacy CONFIG_MAP mode" ))
462+ }
463+ }
464+ }
465+
466+ if accessConfig .BootstrapAdminPermissions != nil && * accessConfig .BootstrapAdminPermissions {
467+ if ekstypes .AuthenticationMode (* accessConfig .AuthenticationMode ) == ekstypes .AuthenticationModeConfigMap {
468+ authConfigField := path .Child ("bootstrapAdminPermissions" )
469+ allErrs = append (allErrs , field .Invalid (authConfigField , * accessConfig .BootstrapAdminPermissions , "authenticationMode CONFIG_MAP has no effect with the bootstrapAdminPermissions parameter" ))
470+ }
471+ }
472+
473+ return allErrs
474+ }
475+
476+ func (r * AWSManagedControlPlane ) validateAutoMode (old * AWSManagedControlPlane ) field.ErrorList {
477+ return validateAutoMode (r .Spec , old , field .NewPath ("spec" ))
478+ }
479+
480+ func validateAutoMode (spec AWSManagedControlPlaneSpec , old * AWSManagedControlPlane , path * field.Path ) field.ErrorList {
481+ var allErrs field.ErrorList
482+
483+ if spec .AutoMode == nil {
484+ return nil
485+ }
486+
487+ if spec .AutoMode .Enabled {
488+ // EKS Auto mode is not compatible with configmap AuthenticationMode.
489+ if * spec .AccessConfig .AuthenticationMode == string (ekstypes .AuthenticationModeConfigMap ) {
490+ authConfigField := path .Child ("accessConfig" , "authenticationMode" )
491+ allErrs = append (allErrs , field .Invalid (authConfigField , spec .AccessConfig .AuthenticationMode , "authenticationMode CONFIG_MAP couldn't be used with autoMode" ))
492+ }
493+
494+ if old != nil {
495+ // nodeRoleArn cannot be changed after the compute capability of EKS Auto Mode is enabled.
496+ if old .Spec .AutoMode .Compute .NodeRoleArn != spec .AutoMode .Compute .NodeRoleArn {
497+ nodeRoleArnField := path .Child ("autoMode" , "compute" , "nodeRoleArn" )
498+ allErrs = append (allErrs , field .Invalid (nodeRoleArnField , spec .AutoMode .Compute .NodeRoleArn , "nodeRoleArn could not be changed" ))
499+ }
500+ }
501+
502+ if len (spec .AutoMode .Compute .NodePools ) > 0 {
503+ // nodeRoleArn should be always defined with node pools.
504+ if spec .AutoMode .Compute .NodeRoleArn == nil {
505+ nodeRoleArnField := path .Child ("autoMode" , "compute" , "nodeRoleArn" )
506+ allErrs = append (allErrs , field .Invalid (nodeRoleArnField , spec .AutoMode .Compute .NodeRoleArn , "nodeRoleArn is required when nodePools specified" ))
507+ }
508+
509+ allowedPoolNames := sets .New [string ](autoModeComputeNodePoolSystem , autoModeComputeNodePoolGeneral )
510+ for _ , poolName := range spec .AutoMode .Compute .NodePools {
511+ nodePoolsField := path .Child ("autoMode" , "compute" , "nodePools" )
512+ if ! allowedPoolNames .Has (poolName ) {
513+ allErrs = append (allErrs , field .Invalid (nodePoolsField , poolName , "nodePools contains an invalid pool" ))
514+ }
515+ }
516+ }
517+ }
518+
519+ return allErrs
520+ }
521+
426522func (r * AWSManagedControlPlane ) validateRestrictPrivateSubnets () field.ErrorList {
427523 return validateRestrictPrivateSubnets (r .Spec .RestrictPrivateSubnets , r .Spec .NetworkSpec , r .Spec .EKSClusterName , field .NewPath ("spec" ))
428524}
@@ -568,10 +664,16 @@ func (*awsManagedControlPlaneWebhook) Default(_ context.Context, obj runtime.Obj
568664 }
569665 }
570666
667+ if r .Spec .BootstrapSelfManagedAddons == nil {
668+ r .Spec .BootstrapSelfManagedAddons = aws .Bool (true )
669+ }
670+
671+ if r .Spec .AccessConfig .AuthenticationMode == nil {
672+ r .Spec .AccessConfig .AuthenticationMode = aws .String (string (ekstypes .AuthenticationModeConfigMap ))
673+ }
674+
571675 infrav1 .SetDefaults_Bastion (& r .Spec .Bastion )
572676 infrav1 .SetDefaults_NetworkSpec (& r .Spec .NetworkSpec )
573677
574- // Set default value for BootstrapSelfManagedAddons
575- r .Spec .BootstrapSelfManagedAddons = true
576678 return nil
577679}
0 commit comments