Skip to content

✨ feat: Support setting EKS authentication mode #5578

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2208,6 +2208,28 @@ spec:
description: AWSManagedControlPlaneSpec defines the desired state of an
Amazon EKS Cluster.
properties:
accessConfig:
description: AccessConfig specifies the access configuration information
for the cluster
properties:
authenticationMode:
default: CONFIG_MAP
description: |-
AuthenticationMode specifies the desired authentication mode for the cluster
Defaults to CONFIG_MAP
enum:
- CONFIG_MAP
- API
- API_AND_CONFIG_MAP
type: string
bootstrapClusterCreatorAdminPermissions:
default: true
description: |-
BootstrapClusterCreatorAdminPermissions grants cluster admin permissions
to the IAM identity creating the cluster. Only applied during creation,
ignored when updating existing clusters. Defaults to true.
type: boolean
type: object
additionalTags:
additionalProperties:
type: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,28 @@ spec:
description: AWSManagedControlPlaneSpec defines the desired state
of an Amazon EKS Cluster.
properties:
accessConfig:
description: AccessConfig specifies the access configuration
information for the cluster
properties:
authenticationMode:
default: CONFIG_MAP
description: |-
AuthenticationMode specifies the desired authentication mode for the cluster
Defaults to CONFIG_MAP
enum:
- CONFIG_MAP
- API
- API_AND_CONFIG_MAP
type: string
bootstrapClusterCreatorAdminPermissions:
default: true
description: |-
BootstrapClusterCreatorAdminPermissions grants cluster admin permissions
to the IAM identity creating the cluster. Only applied during creation,
ignored when updating existing clusters. Defaults to true.
type: boolean
type: object
additionalTags:
additionalProperties:
type: string
Expand Down
1 change: 1 addition & 0 deletions controlplane/eks/api/v1beta1/conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ func (r *AWSManagedControlPlane) ConvertTo(dstRaw conversion.Hub) error {

dst.Spec.Partition = restored.Spec.Partition
dst.Spec.RestrictPrivateSubnets = restored.Spec.RestrictPrivateSubnets
dst.Spec.AccessConfig = restored.Spec.AccessConfig
dst.Spec.RolePath = restored.Spec.RolePath
dst.Spec.RolePermissionsBoundary = restored.Spec.RolePermissionsBoundary
dst.Status.Version = restored.Status.Version
Expand Down
1 change: 1 addition & 0 deletions controlplane/eks/api/v1beta1/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions controlplane/eks/api/v1beta2/awsmanagedcontrolplane_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,10 @@ type AWSManagedControlPlaneSpec struct { //nolint: maligned
// +optional
OIDCIdentityProviderConfig *OIDCIdentityProviderConfig `json:"oidcIdentityProviderConfig,omitempty"`

// AccessConfig specifies the access configuration information for the cluster
// +optional
AccessConfig *AccessConfig `json:"accessConfig,omitempty"`

// VpcCni is used to set configuration options for the VPC CNI plugin
// +optional
VpcCni VpcCni `json:"vpcCni,omitempty"`
Expand Down Expand Up @@ -248,6 +252,21 @@ type EndpointAccess struct {
Private *bool `json:"private,omitempty"`
}

// AccessConfig represents the access configuration information for the cluster
type AccessConfig struct {
// AuthenticationMode specifies the desired authentication mode for the cluster
// Defaults to CONFIG_MAP
// +kubebuilder:default=CONFIG_MAP
// +kubebuilder:validation:Enum=CONFIG_MAP;API;API_AND_CONFIG_MAP
AuthenticationMode EKSAuthenticationMode `json:"authenticationMode,omitempty"`

// BootstrapClusterCreatorAdminPermissions grants cluster admin permissions
// to the IAM identity creating the cluster. Only applied during creation,
// ignored when updating existing clusters. Defaults to true.
// +kubebuilder:default=true
BootstrapClusterCreatorAdminPermissions *bool `json:"bootstrapClusterCreatorAdminPermissions,omitempty"`
}

// EncryptionConfig specifies the encryption configuration for the EKS clsuter.
type EncryptionConfig struct {
// Provider specifies the ARN or alias of the CMK (in AWS KMS)
Expand Down
30 changes: 30 additions & 0 deletions controlplane/eks/api/v1beta2/awsmanagedcontrolplane_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ func (*awsManagedControlPlaneWebhook) ValidateUpdate(ctx context.Context, oldObj
allErrs = append(allErrs, r.validateEKSClusterNameSame(oldAWSManagedControlplane)...)
allErrs = append(allErrs, r.validateEKSVersion(oldAWSManagedControlplane)...)
allErrs = append(allErrs, r.Spec.Bastion.Validate()...)
allErrs = append(allErrs, r.validateAccessConfig(oldAWSManagedControlplane)...)
allErrs = append(allErrs, r.validateIAMAuthConfig()...)
allErrs = append(allErrs, r.validateSecondaryCIDR()...)
allErrs = append(allErrs, r.validateEKSAddons()...)
Expand Down Expand Up @@ -318,6 +319,35 @@ func validateEKSAddons(eksVersion *string, networkSpec infrav1.NetworkSpec, addo
return allErrs
}

func (r *AWSManagedControlPlane) validateAccessConfig(old *AWSManagedControlPlane) field.ErrorList {
var allErrs field.ErrorList

// If accessConfig is already set, do not allow removal of it.
if old.Spec.AccessConfig != nil && r.Spec.AccessConfig == nil {
allErrs = append(allErrs,
field.Invalid(field.NewPath("spec", "accessConfig"), r.Spec.AccessConfig, "removing AccessConfig is not allowed after it has been enabled"),
)
}

// AuthenticationMode is ratcheting - do not allow downgrades
if old.Spec.AccessConfig != nil && r.Spec.AccessConfig != nil &&
old.Spec.AccessConfig.AuthenticationMode != r.Spec.AccessConfig.AuthenticationMode &&
((old.Spec.AccessConfig.AuthenticationMode == EKSAuthenticationModeAPIAndConfigMap && r.Spec.AccessConfig.AuthenticationMode == EKSAuthenticationModeConfigMap) ||
old.Spec.AccessConfig.AuthenticationMode == EKSAuthenticationModeAPI) {
allErrs = append(allErrs,
field.Invalid(field.NewPath("spec", "accessConfig", "authenticationMode"), r.Spec.AccessConfig.AuthenticationMode, "downgrading authentication mode is not allowed after it has been enabled"),
)
}

// BootstrapClusterCreatorAdminPermissions only applies on create, but changes should not invalidate updates
if old.Spec.AccessConfig != nil && r.Spec.AccessConfig != nil &&
old.Spec.AccessConfig.BootstrapClusterCreatorAdminPermissions != r.Spec.AccessConfig.BootstrapClusterCreatorAdminPermissions {
mcpLog.Info("Ignoring changes to BootstrapClusterCreatorAdminPermissions on cluster update", "old", old.Spec.AccessConfig.BootstrapClusterCreatorAdminPermissions, "new", r.Spec.AccessConfig.BootstrapClusterCreatorAdminPermissions)
}

return allErrs
}

func (r *AWSManagedControlPlane) validateIAMAuthConfig() field.ErrorList {
return validateIAMAuthConfig(r.Spec.IAMAuthenticatorConfig, field.NewPath("spec.iamAuthenticatorConfig"))
}
Expand Down
106 changes: 106 additions & 0 deletions controlplane/eks/api/v1beta2/awsmanagedcontrolplane_webhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,112 @@ func TestWebhookUpdate(t *testing.T) {
},
expectError: false,
},
{
name: "no change in access config",
oldClusterSpec: AWSManagedControlPlaneSpec{
EKSClusterName: "default_cluster1",
AccessConfig: &AccessConfig{
AuthenticationMode: EKSAuthenticationModeConfigMap,
},
},
newClusterSpec: AWSManagedControlPlaneSpec{
EKSClusterName: "default_cluster1",
AccessConfig: &AccessConfig{
AuthenticationMode: EKSAuthenticationModeConfigMap,
},
},
expectError: false,
},
{
name: "change in access config to nil",
oldClusterSpec: AWSManagedControlPlaneSpec{
EKSClusterName: "default_cluster1",
AccessConfig: &AccessConfig{
AuthenticationMode: EKSAuthenticationModeConfigMap,
},
},
newClusterSpec: AWSManagedControlPlaneSpec{
EKSClusterName: "default_cluster1",
},
expectError: true,
},
{
name: "change in access config from nil to valid",
oldClusterSpec: AWSManagedControlPlaneSpec{
EKSClusterName: "default_cluster1",
},
newClusterSpec: AWSManagedControlPlaneSpec{
EKSClusterName: "default_cluster1",
AccessConfig: &AccessConfig{
AuthenticationMode: EKSAuthenticationModeConfigMap,
},
},
expectError: false,
},
{
name: "change in access config auth mode from ApiAndConfigMap to API is allowed",
oldClusterSpec: AWSManagedControlPlaneSpec{
EKSClusterName: "default_cluster1",
AccessConfig: &AccessConfig{
AuthenticationMode: EKSAuthenticationModeAPIAndConfigMap,
},
},
newClusterSpec: AWSManagedControlPlaneSpec{
EKSClusterName: "default_cluster1",
AccessConfig: &AccessConfig{
AuthenticationMode: EKSAuthenticationModeAPI,
},
},
expectError: false,
},
{
name: "change in access config auth mode from API to Config Map is denied",
oldClusterSpec: AWSManagedControlPlaneSpec{
EKSClusterName: "default_cluster1",
AccessConfig: &AccessConfig{
AuthenticationMode: EKSAuthenticationModeAPI,
},
},
newClusterSpec: AWSManagedControlPlaneSpec{
EKSClusterName: "default_cluster1",
AccessConfig: &AccessConfig{
AuthenticationMode: EKSAuthenticationModeConfigMap,
},
},
expectError: true,
},
{
name: "change in access config auth mode from APIAndConfigMap to Config Map is denied",
oldClusterSpec: AWSManagedControlPlaneSpec{
EKSClusterName: "default_cluster1",
AccessConfig: &AccessConfig{
AuthenticationMode: EKSAuthenticationModeAPIAndConfigMap,
},
},
newClusterSpec: AWSManagedControlPlaneSpec{
EKSClusterName: "default_cluster1",
AccessConfig: &AccessConfig{
AuthenticationMode: EKSAuthenticationModeConfigMap,
},
},
expectError: true,
},
{
name: "change in access config bootstrap admin permissions is ignored",
oldClusterSpec: AWSManagedControlPlaneSpec{
EKSClusterName: "default_cluster1",
AccessConfig: &AccessConfig{
BootstrapClusterCreatorAdminPermissions: ptr.To(true),
},
},
newClusterSpec: AWSManagedControlPlaneSpec{
EKSClusterName: "default_cluster1",
AccessConfig: &AccessConfig{
BootstrapClusterCreatorAdminPermissions: ptr.To(false),
},
},
expectError: false,
},
{
name: "change in encryption config to nil",
oldClusterSpec: AWSManagedControlPlaneSpec{
Expand Down
15 changes: 15 additions & 0 deletions controlplane/eks/api/v1beta2/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,21 @@ var (
EKSTokenMethodAWSCli = EKSTokenMethod("aws-cli")
)

// EKSAuthenticationMode defines the authentication mode for the cluster
type EKSAuthenticationMode string

var (
// EKSAuthenticationModeConfigMap indicates that only `aws-auth` ConfigMap will be used for authentication
EKSAuthenticationModeConfigMap = EKSAuthenticationMode("CONFIG_MAP")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good if we used values like:

  • configmap
  • api
  • configmap_and_api

We generally try not to have direct copies of the values like this as all caps is a bit jarring in the manifests. It would mean we'd need to add a "conversion" function.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@joshfrench Would you get a chance to make this change so we can merge this PR?


// EKSAuthenticationModeAPI indicates that only AWS Access Entries will be used for authentication
EKSAuthenticationModeAPI = EKSAuthenticationMode("API")

// EKSAuthenticationModeAPIAndConfigMap indicates that both `aws-auth` ConfigMap and AWS Access Entries will
// be used for authentication
EKSAuthenticationModeAPIAndConfigMap = EKSAuthenticationMode("API_AND_CONFIG_MAP")
)

var (
// DefaultEKSControlPlaneRole is the name of the default IAM role to use for the EKS control plane
// if no other role is supplied in the spec and if iam role creation is not enabled. The default
Expand Down
25 changes: 25 additions & 0 deletions controlplane/eks/api/v1beta2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading