@@ -22,9 +22,12 @@ import (
22
22
"net"
23
23
24
24
"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"
25
27
"github.com/pkg/errors"
26
28
apierrors "k8s.io/apimachinery/pkg/api/errors"
27
29
"k8s.io/apimachinery/pkg/runtime"
30
+ "k8s.io/apimachinery/pkg/util/sets"
28
31
"k8s.io/apimachinery/pkg/util/validation/field"
29
32
"k8s.io/apimachinery/pkg/util/version"
30
33
"k8s.io/klog/v2"
@@ -52,6 +55,9 @@ const (
52
55
cidrSizeMin = 16
53
56
vpcCniAddon = "vpc-cni"
54
57
kubeProxyAddon = "kube-proxy"
58
+
59
+ autoModeComputeNodePoolSystem = "system"
60
+ autoModeComputeNodePoolGeneral = "general-purpose"
55
61
)
56
62
57
63
// SetupWebhookWithManager will setup the webhooks for the AWSManagedControlPlane.
@@ -102,6 +108,8 @@ func (*awsManagedControlPlaneWebhook) ValidateCreate(_ context.Context, obj runt
102
108
allErrs = append (allErrs , r .validateSecondaryCIDR ()... )
103
109
allErrs = append (allErrs , r .validateEKSAddons ()... )
104
110
allErrs = append (allErrs , r .validateDisableVPCCNI ()... )
111
+ allErrs = append (allErrs , r .validateAccessConfig (nil )... )
112
+ allErrs = append (allErrs , r .validateAutoMode (nil )... )
105
113
allErrs = append (allErrs , r .validateRestrictPrivateSubnets ()... )
106
114
allErrs = append (allErrs , r .validateKubeProxy ()... )
107
115
allErrs = append (allErrs , r .Spec .AdditionalTags .Validate ()... )
@@ -142,6 +150,8 @@ func (*awsManagedControlPlaneWebhook) ValidateUpdate(ctx context.Context, oldObj
142
150
allErrs = append (allErrs , r .Spec .Bastion .Validate ()... )
143
151
allErrs = append (allErrs , r .validateIAMAuthConfig ()... )
144
152
allErrs = append (allErrs , r .validateSecondaryCIDR ()... )
153
+ allErrs = append (allErrs , r .validateAccessConfig (oldAWSManagedControlplane )... )
154
+ allErrs = append (allErrs , r .validateAutoMode (oldAWSManagedControlplane )... )
145
155
allErrs = append (allErrs , r .validateEKSAddons ()... )
146
156
allErrs = append (allErrs , r .validateDisableVPCCNI ()... )
147
157
allErrs = append (allErrs , r .validateRestrictPrivateSubnets ()... )
@@ -423,6 +433,90 @@ func validateDisableVPCCNI(vpcCni VpcCni, addons *[]Addon, path *field.Path) fie
423
433
return allErrs
424
434
}
425
435
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 && ekstypes .AuthenticationMode (* accessConfig .AuthenticationMode ) == ekstypes .AuthenticationModeConfigMap {
467
+ authConfigField := path .Child ("bootstrapAdminPermissions" )
468
+ allErrs = append (allErrs , field .Invalid (authConfigField , * accessConfig .BootstrapAdminPermissions , "authenticationMode CONFIG_MAP has no effect with the bootstrapAdminPermissions parameter" ))
469
+ }
470
+
471
+ return allErrs
472
+ }
473
+
474
+ func (r * AWSManagedControlPlane ) validateAutoMode (old * AWSManagedControlPlane ) field.ErrorList {
475
+ return validateAutoMode (r .Spec , old , field .NewPath ("spec" ))
476
+ }
477
+
478
+ func validateAutoMode (spec AWSManagedControlPlaneSpec , old * AWSManagedControlPlane , path * field.Path ) field.ErrorList {
479
+ var allErrs field.ErrorList
480
+
481
+ if spec .AutoMode == nil {
482
+ return nil
483
+ }
484
+
485
+ if spec .AutoMode .Enabled {
486
+ // EKS Auto mode is not compatible with configmap AuthenticationMode.
487
+ if * spec .AccessConfig .AuthenticationMode == string (ekstypes .AuthenticationModeConfigMap ) {
488
+ authConfigField := path .Child ("accessConfig" , "authenticationMode" )
489
+ allErrs = append (allErrs , field .Invalid (authConfigField , spec .AccessConfig .AuthenticationMode , "authenticationMode CONFIG_MAP couldn't be used with autoMode" ))
490
+ }
491
+
492
+ if old != nil {
493
+ // nodeRoleArn cannot be changed after the compute capability of EKS Auto Mode is enabled.
494
+ if old .Spec .AutoMode .Compute .NodeRoleArn != spec .AutoMode .Compute .NodeRoleArn {
495
+ nodeRoleArnField := path .Child ("autoMode" , "compute" , "nodeRoleArn" )
496
+ allErrs = append (allErrs , field .Invalid (nodeRoleArnField , spec .AutoMode .Compute .NodeRoleArn , "nodeRoleArn could not be changed" ))
497
+ }
498
+ }
499
+
500
+ if len (spec .AutoMode .Compute .NodePools ) > 0 {
501
+ // nodeRoleArn should be always defined with node pools.
502
+ if spec .AutoMode .Compute .NodeRoleArn == nil {
503
+ nodeRoleArnField := path .Child ("autoMode" , "compute" , "nodeRoleArn" )
504
+ allErrs = append (allErrs , field .Invalid (nodeRoleArnField , spec .AutoMode .Compute .NodeRoleArn , "nodeRoleArn is required when nodePools specified" ))
505
+ }
506
+
507
+ allowedPoolNames := sets .New [string ](autoModeComputeNodePoolSystem , autoModeComputeNodePoolGeneral )
508
+ for _ , poolName := range spec .AutoMode .Compute .NodePools {
509
+ nodePoolsField := path .Child ("autoMode" , "compute" , "nodePools" )
510
+ if ! allowedPoolNames .Has (poolName ) {
511
+ allErrs = append (allErrs , field .Invalid (nodePoolsField , poolName , "nodePools contains an invalid pool" ))
512
+ }
513
+ }
514
+ }
515
+ }
516
+
517
+ return allErrs
518
+ }
519
+
426
520
func (r * AWSManagedControlPlane ) validateRestrictPrivateSubnets () field.ErrorList {
427
521
return validateRestrictPrivateSubnets (r .Spec .RestrictPrivateSubnets , r .Spec .NetworkSpec , r .Spec .EKSClusterName , field .NewPath ("spec" ))
428
522
}
@@ -568,10 +662,16 @@ func (*awsManagedControlPlaneWebhook) Default(_ context.Context, obj runtime.Obj
568
662
}
569
663
}
570
664
665
+ if r .Spec .BootstrapSelfManagedAddons == nil {
666
+ r .Spec .BootstrapSelfManagedAddons = aws .Bool (true )
667
+ }
668
+
669
+ if r .Spec .AccessConfig .AuthenticationMode == nil {
670
+ r .Spec .AccessConfig .AuthenticationMode = aws .String (string (ekstypes .AuthenticationModeConfigMap ))
671
+ }
672
+
571
673
infrav1 .SetDefaults_Bastion (& r .Spec .Bastion )
572
674
infrav1 .SetDefaults_NetworkSpec (& r .Spec .NetworkSpec )
573
675
574
- // Set default value for BootstrapSelfManagedAddons
575
- r .Spec .BootstrapSelfManagedAddons = true
576
676
return nil
577
677
}
0 commit comments