Skip to content
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 @@ -2292,6 +2292,85 @@ spec:
ignored when updating existing clusters. Defaults to true.
type: boolean
type: object
accessEntries:
description: |-
AccessEntries specifies the access entries for the cluster
Access entries require AuthenticationMode to be either "api" or "api_and_config_map"
items:
description: AccessEntry represents an AWS EKS access entry for
IAM principals
properties:
accessPolicies:
description: |-
AccessPolicies specifies the policies to associate with this access entry
Cannot be specified if Type is "ec2_linux" or "ec2_windows"
items:
description: AccessPolicyReference represents a reference
to an AWS EKS access policy
properties:
accessScope:
description: AccessScope specifies the scope for the policy
properties:
namespaces:
description: |-
Namespaces are the namespaces for the access scope
Only valid when Type is namespace
items:
type: string
minItems: 1
type: array
type:
default: cluster
description: Type is the type of access scope. Defaults
to "cluster".
enum:
- cluster
- namespace
type: string
required:
- type
type: object
policyARN:
description: PolicyARN is the Amazon Resource Name (ARN)
of the access policy
type: string
required:
- accessScope
- policyARN
type: object
maxItems: 20
type: array
kubernetesGroups:
description: |-
KubernetesGroups represents the Kubernetes groups for the access entry
Cannot be specified if Type is "ec2_linux" or "ec2_windows"
items:
type: string
type: array
principalARN:
description: PrincipalARN is the Amazon Resource Name (ARN)
of the IAM principal
type: string
type:
default: standard
description: Type is the type of access entry. Defaults to standard
if not specified.
enum:
- standard
- ec2_linux
- ec2_windows
- fargate_linux
- ec2
- hybrid_linux
- hyperpod_linux
type: string
username:
description: Username is the username for the access entry
type: string
required:
- principalARN
type: object
type: array
additionalTags:
additionalProperties:
type: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,87 @@ spec:
ignored when updating existing clusters. Defaults to true.
type: boolean
type: object
accessEntries:
description: |-
AccessEntries specifies the access entries for the cluster
Access entries require AuthenticationMode to be either "api" or "api_and_config_map"
items:
description: AccessEntry represents an AWS EKS access entry
for IAM principals
properties:
accessPolicies:
description: |-
AccessPolicies specifies the policies to associate with this access entry
Cannot be specified if Type is "ec2_linux" or "ec2_windows"
items:
description: AccessPolicyReference represents a reference
to an AWS EKS access policy
properties:
accessScope:
description: AccessScope specifies the scope for
the policy
properties:
namespaces:
description: |-
Namespaces are the namespaces for the access scope
Only valid when Type is namespace
items:
type: string
minItems: 1
type: array
type:
default: cluster
description: Type is the type of access scope.
Defaults to "cluster".
enum:
- cluster
- namespace
type: string
required:
- type
type: object
policyARN:
description: PolicyARN is the Amazon Resource
Name (ARN) of the access policy
type: string
required:
- accessScope
- policyARN
type: object
maxItems: 20
type: array
kubernetesGroups:
description: |-
KubernetesGroups represents the Kubernetes groups for the access entry
Cannot be specified if Type is "ec2_linux" or "ec2_windows"
items:
type: string
type: array
principalARN:
description: PrincipalARN is the Amazon Resource Name
(ARN) of the IAM principal
type: string
type:
default: standard
description: Type is the type of access entry. Defaults
to standard if not specified.
enum:
- standard
- ec2_linux
- ec2_windows
- fargate_linux
- ec2
- hybrid_linux
- hyperpod_linux
type: string
username:
description: Username is the username for the access
entry
type: string
required:
- principalARN
type: object
type: array
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 @@ -118,6 +118,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.AccessEntries = restored.Spec.AccessEntries
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.

58 changes: 58 additions & 0 deletions controlplane/eks/api/v1beta2/awsmanagedcontrolplane_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,11 @@ type AWSManagedControlPlaneSpec struct { //nolint: maligned
// +optional
AccessConfig *AccessConfig `json:"accessConfig,omitempty"`

// AccessEntries specifies the access entries for the cluster
// Access entries require AuthenticationMode to be either "api" or "api_and_config_map"
// +optional
AccessEntries []AccessEntry `json:"accessEntries,omitempty"`

// VpcCni is used to set configuration options for the VPC CNI plugin
// +optional
VpcCni VpcCni `json:"vpcCni,omitempty"`
Expand Down Expand Up @@ -267,6 +272,59 @@ type AccessConfig struct {
BootstrapClusterCreatorAdminPermissions *bool `json:"bootstrapClusterCreatorAdminPermissions,omitempty"`
}

// AccessEntry represents an AWS EKS access entry for IAM principals
type AccessEntry struct {
// PrincipalARN is the Amazon Resource Name (ARN) of the IAM principal
// +kubebuilder:validation:Required
PrincipalARN string `json:"principalARN"`

// Type is the type of access entry. Defaults to standard if not specified.
// +kubebuilder:default=standard
// +kubebuilder:validation:Enum=standard;ec2_linux;ec2_windows;fargate_linux;ec2;hybrid_linux;hyperpod_linux
// +optional
Type AccessEntryType `json:"type,omitempty"`

// KubernetesGroups represents the Kubernetes groups for the access entry
// Cannot be specified if Type is "ec2_linux" or "ec2_windows"
// +optional
KubernetesGroups []string `json:"kubernetesGroups,omitempty"`

// Username is the username for the access entry
// +optional
Username string `json:"username,omitempty"`

// AccessPolicies specifies the policies to associate with this access entry
// Cannot be specified if Type is "ec2_linux" or "ec2_windows"
// +optional
// +kubebuilder:validation:MaxItems=20
AccessPolicies []AccessPolicyReference `json:"accessPolicies,omitempty"`
}

// AccessPolicyReference represents a reference to an AWS EKS access policy
type AccessPolicyReference struct {
// PolicyARN is the Amazon Resource Name (ARN) of the access policy
// +kubebuilder:validation:Required
PolicyARN string `json:"policyARN"`

// AccessScope specifies the scope for the policy
// +kubebuilder:validation:Required
AccessScope AccessScope `json:"accessScope"`
}

// AccessScope represents the scope for an access policy
type AccessScope struct {
// Type is the type of access scope. Defaults to "cluster".
// +kubebuilder:validation:Enum=cluster;namespace
// +kubebuilder:default=cluster
Type AccessScopeType `json:"type"`

// Namespaces are the namespaces for the access scope
// Only valid when Type is namespace
// +optional
// +kubebuilder:validation:MinItems=1
Namespaces []string `json:"namespaces,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
57 changes: 57 additions & 0 deletions controlplane/eks/api/v1beta2/awsmanagedcontrolplane_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ func (*awsManagedControlPlaneWebhook) ValidateCreate(_ context.Context, obj runt
allErrs = append(allErrs, r.validateNetwork()...)
allErrs = append(allErrs, r.validatePrivateDNSHostnameTypeOnLaunch()...)
allErrs = append(allErrs, r.validateAccessConfigCreate()...)
allErrs = append(allErrs, r.validateAccessEntries()...)

if len(allErrs) == 0 {
return nil, nil
Expand Down Expand Up @@ -150,6 +151,7 @@ func (*awsManagedControlPlaneWebhook) ValidateUpdate(ctx context.Context, oldObj
allErrs = append(allErrs, r.validateKubeProxy()...)
allErrs = append(allErrs, r.Spec.AdditionalTags.Validate()...)
allErrs = append(allErrs, r.validatePrivateDNSHostnameTypeOnLaunch()...)
allErrs = append(allErrs, r.validateAccessEntries()...)

if r.Spec.Region != oldAWSManagedControlplane.Spec.Region {
allErrs = append(allErrs,
Expand Down Expand Up @@ -367,6 +369,61 @@ func (r *AWSManagedControlPlane) validateAccessConfigCreate() field.ErrorList {
return allErrs
}

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

if len(r.Spec.AccessEntries) > 0 {
// AccessEntries require AuthenticationMode to be api or api_and_config_map
if r.Spec.AccessConfig == nil ||
(r.Spec.AccessConfig.AuthenticationMode != EKSAuthenticationModeAPI &&
r.Spec.AccessConfig.AuthenticationMode != EKSAuthenticationModeAPIAndConfigMap) {
allErrs = append(allErrs,
field.Invalid(field.NewPath("spec", "accessEntries"),
r.Spec.AccessEntries,
"accessEntries can only be used when authenticationMode is set to api or api_and_config_map",
),
)
}

for i, entry := range r.Spec.AccessEntries {
// Validate that EC2 types don't have kubernetes groups or access policies
if entry.Type == AccessEntryTypeEC2Linux || entry.Type == AccessEntryTypeEC2Windows {
if len(entry.KubernetesGroups) > 0 {
allErrs = append(allErrs,
field.Invalid(field.NewPath("spec", "accessEntries").Index(i).Child("kubernetesGroups"),
entry.KubernetesGroups,
"kubernetesGroups cannot be specified when type is ec2_linux or ec2_windows",
),
)
}

if len(entry.AccessPolicies) > 0 {
allErrs = append(allErrs,
field.Invalid(field.NewPath("spec", "accessEntries").Index(i).Child("accessPolicies"),
entry.AccessPolicies,
"accessPolicies cannot be specified when type is ec2_linux or ec2_windows",
),
)
}
}

// Validate namespace scopes
for j, policy := range entry.AccessPolicies {
if policy.AccessScope.Type == AccessScopeTypeNamespace && len(policy.AccessScope.Namespaces) == 0 {
allErrs = append(allErrs,
field.Invalid(field.NewPath("spec", "accessEntries").Index(i).Child("accessPolicies").Index(j).Child("accessScope", "namespaces"),
policy.AccessScope.Namespaces,
"at least one value must be provided when accessScope type is namespace",
),
)
}
}
}
}

return allErrs
}

func (r *AWSManagedControlPlane) validateIAMAuthConfig() field.ErrorList {
return validateIAMAuthConfig(r.Spec.IAMAuthenticatorConfig, field.NewPath("spec.iamAuthenticatorConfig"))
}
Expand Down
Loading