@@ -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,94 @@ 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+ if accessConfig .AuthenticationMode != nil {
449+ for _ , accessMode := range ekstypes .AuthenticationMode ("" ).Values () {
450+ if ekstypes .AuthenticationMode (* accessConfig .AuthenticationMode ) == accessMode {
451+ authModeOK = true
452+ }
453+ }
454+
455+ if ! authModeOK {
456+ allErrs = append (allErrs , field .Invalid (authConfigField , * accessConfig .AuthenticationMode , "unsupported authenticationMode provided" ))
457+ }
458+ }
459+
460+ if old != nil && old .Spec .AccessConfig .AuthenticationMode != nil {
461+ if * old .Spec .AccessConfig .AuthenticationMode != * accessConfig .AuthenticationMode {
462+ if ekstypes .AuthenticationMode (* accessConfig .AuthenticationMode ) == ekstypes .AuthenticationModeConfigMap {
463+ allErrs = append (allErrs , field .Invalid (authConfigField , * accessConfig .AuthenticationMode , "cannot switch authenticationMode to legacy CONFIG_MAP mode" ))
464+ }
465+ }
466+ }
467+
468+ if accessConfig .BootstrapAdminPermissions != nil && * accessConfig .BootstrapAdminPermissions {
469+ if ekstypes .AuthenticationMode (* accessConfig .AuthenticationMode ) == ekstypes .AuthenticationModeConfigMap {
470+ authConfigField := path .Child ("bootstrapAdminPermissions" )
471+ allErrs = append (allErrs , field .Invalid (authConfigField , * accessConfig .BootstrapAdminPermissions , "authenticationMode CONFIG_MAP has no effect with the bootstrapAdminPermissions parameter" ))
472+ }
473+ }
474+
475+ return allErrs
476+ }
477+
478+ func (r * AWSManagedControlPlane ) validateAutoMode (old * AWSManagedControlPlane ) field.ErrorList {
479+ return validateAutoMode (r .Spec , old , field .NewPath ("spec" ))
480+ }
481+
482+ func validateAutoMode (spec AWSManagedControlPlaneSpec , old * AWSManagedControlPlane , path * field.Path ) field.ErrorList {
483+ var allErrs field.ErrorList
484+
485+ if spec .AutoMode == nil {
486+ return nil
487+ }
488+
489+ if spec .AutoMode .Enabled {
490+ // EKS Auto mode is not compatible with configmap AuthenticationMode.
491+ if * spec .AccessConfig .AuthenticationMode == string (ekstypes .AuthenticationModeConfigMap ) {
492+ authConfigField := path .Child ("accessConfig" , "authenticationMode" )
493+ allErrs = append (allErrs , field .Invalid (authConfigField , spec .AccessConfig .AuthenticationMode , "authenticationMode CONFIG_MAP couldn't be used with autoMode" ))
494+ }
495+
496+ if old != nil {
497+ // nodeRoleArn cannot be changed after the compute capability of EKS Auto Mode is enabled.
498+ if old .Spec .AutoMode .Compute .NodeRoleArn != spec .AutoMode .Compute .NodeRoleArn {
499+ nodeRoleArnField := path .Child ("autoMode" , "compute" , "nodeRoleArn" )
500+ allErrs = append (allErrs , field .Invalid (nodeRoleArnField , spec .AutoMode .Compute .NodeRoleArn , "nodeRoleArn could not be changed" ))
501+ }
502+ }
503+
504+ if len (spec .AutoMode .Compute .NodePools ) > 0 {
505+ // nodeRoleArn should be always defined with node pools.
506+ if spec .AutoMode .Compute .NodeRoleArn == nil {
507+ nodeRoleArnField := path .Child ("autoMode" , "compute" , "nodeRoleArn" )
508+ allErrs = append (allErrs , field .Invalid (nodeRoleArnField , spec .AutoMode .Compute .NodeRoleArn , "nodeRoleArn is required when nodePools specified" ))
509+ }
510+
511+ allowedPoolNames := sets .New [string ](autoModeComputeNodePoolSystem , autoModeComputeNodePoolGeneral )
512+ for _ , poolName := range spec .AutoMode .Compute .NodePools {
513+ nodePoolsField := path .Child ("autoMode" , "compute" , "nodePools" )
514+ if ! allowedPoolNames .Has (poolName ) {
515+ allErrs = append (allErrs , field .Invalid (nodePoolsField , poolName , "nodePools contains an invalid pool" ))
516+ }
517+ }
518+ }
519+ }
520+
521+ return allErrs
522+ }
523+
426524func (r * AWSManagedControlPlane ) validateRestrictPrivateSubnets () field.ErrorList {
427525 return validateRestrictPrivateSubnets (r .Spec .RestrictPrivateSubnets , r .Spec .NetworkSpec , r .Spec .EKSClusterName , field .NewPath ("spec" ))
428526}
@@ -568,10 +666,16 @@ func (*awsManagedControlPlaneWebhook) Default(_ context.Context, obj runtime.Obj
568666 }
569667 }
570668
669+ if r .Spec .BootstrapSelfManagedAddons == nil {
670+ r .Spec .BootstrapSelfManagedAddons = aws .Bool (true )
671+ }
672+
673+ if r .Spec .AccessConfig .AuthenticationMode == nil {
674+ r .Spec .AccessConfig .AuthenticationMode = aws .String (string (ekstypes .AuthenticationModeConfigMap ))
675+ }
676+
571677 infrav1 .SetDefaults_Bastion (& r .Spec .Bastion )
572678 infrav1 .SetDefaults_NetworkSpec (& r .Spec .NetworkSpec )
573679
574- // Set default value for BootstrapSelfManagedAddons
575- r .Spec .BootstrapSelfManagedAddons = true
576680 return nil
577681}
0 commit comments