Skip to content

Commit 6348491

Browse files
joshfrenchadammw
andcommitted
Add Access Entry support
Co-authored-by: Adam Malcontenti-Wilson <[email protected]>
1 parent 42b4f94 commit 6348491

17 files changed

+2053
-0
lines changed

config/crd/bases/controlplane.cluster.x-k8s.io_awsmanagedcontrolplanes.yaml

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2303,6 +2303,85 @@ spec:
23032303
ignored when updating existing clusters. Defaults to true.
23042304
type: boolean
23052305
type: object
2306+
accessEntries:
2307+
description: |-
2308+
AccessEntries specifies the access entries for the cluster
2309+
Access entries require AuthenticationMode to be either "api" or "api_and_config_map"
2310+
items:
2311+
description: AccessEntry represents an AWS EKS access entry for
2312+
IAM principals
2313+
properties:
2314+
accessPolicies:
2315+
description: |-
2316+
AccessPolicies specifies the policies to associate with this access entry
2317+
Cannot be specified if Type is "ec2_linux" or "ec2_windows"
2318+
items:
2319+
description: AccessPolicyReference represents a reference
2320+
to an AWS EKS access policy
2321+
properties:
2322+
accessScope:
2323+
description: AccessScope specifies the scope for the policy
2324+
properties:
2325+
namespaces:
2326+
description: |-
2327+
Namespaces are the namespaces for the access scope
2328+
Only valid when Type is namespace
2329+
items:
2330+
type: string
2331+
minItems: 1
2332+
type: array
2333+
type:
2334+
default: cluster
2335+
description: Type is the type of access scope. Defaults
2336+
to "cluster".
2337+
enum:
2338+
- cluster
2339+
- namespace
2340+
type: string
2341+
required:
2342+
- type
2343+
type: object
2344+
policyARN:
2345+
description: PolicyARN is the Amazon Resource Name (ARN)
2346+
of the access policy
2347+
type: string
2348+
required:
2349+
- accessScope
2350+
- policyARN
2351+
type: object
2352+
maxItems: 20
2353+
type: array
2354+
kubernetesGroups:
2355+
description: |-
2356+
KubernetesGroups represents the Kubernetes groups for the access entry
2357+
Cannot be specified if Type is "ec2_linux" or "ec2_windows"
2358+
items:
2359+
type: string
2360+
type: array
2361+
principalARN:
2362+
description: PrincipalARN is the Amazon Resource Name (ARN)
2363+
of the IAM principal
2364+
type: string
2365+
type:
2366+
default: standard
2367+
description: Type is the type of access entry. Defaults to standard
2368+
if not specified.
2369+
enum:
2370+
- standard
2371+
- ec2_linux
2372+
- ec2_windows
2373+
- fargate_linux
2374+
- ec2
2375+
- hybrid_linux
2376+
- hyperpod_linux
2377+
type: string
2378+
username:
2379+
description: Username is the username for the access entry
2380+
type: string
2381+
required:
2382+
- principalARN
2383+
type: object
2384+
type: array
23062385
additionalTags:
23072386
additionalProperties:
23082387
type: string

config/crd/bases/controlplane.cluster.x-k8s.io_awsmanagedcontrolplanetemplates.yaml

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,87 @@ spec:
7575
ignored when updating existing clusters. Defaults to true.
7676
type: boolean
7777
type: object
78+
accessEntries:
79+
description: |-
80+
AccessEntries specifies the access entries for the cluster
81+
Access entries require AuthenticationMode to be either "api" or "api_and_config_map"
82+
items:
83+
description: AccessEntry represents an AWS EKS access entry
84+
for IAM principals
85+
properties:
86+
accessPolicies:
87+
description: |-
88+
AccessPolicies specifies the policies to associate with this access entry
89+
Cannot be specified if Type is "ec2_linux" or "ec2_windows"
90+
items:
91+
description: AccessPolicyReference represents a reference
92+
to an AWS EKS access policy
93+
properties:
94+
accessScope:
95+
description: AccessScope specifies the scope for
96+
the policy
97+
properties:
98+
namespaces:
99+
description: |-
100+
Namespaces are the namespaces for the access scope
101+
Only valid when Type is namespace
102+
items:
103+
type: string
104+
minItems: 1
105+
type: array
106+
type:
107+
default: cluster
108+
description: Type is the type of access scope.
109+
Defaults to "cluster".
110+
enum:
111+
- cluster
112+
- namespace
113+
type: string
114+
required:
115+
- type
116+
type: object
117+
policyARN:
118+
description: PolicyARN is the Amazon Resource
119+
Name (ARN) of the access policy
120+
type: string
121+
required:
122+
- accessScope
123+
- policyARN
124+
type: object
125+
maxItems: 20
126+
type: array
127+
kubernetesGroups:
128+
description: |-
129+
KubernetesGroups represents the Kubernetes groups for the access entry
130+
Cannot be specified if Type is "ec2_linux" or "ec2_windows"
131+
items:
132+
type: string
133+
type: array
134+
principalARN:
135+
description: PrincipalARN is the Amazon Resource Name
136+
(ARN) of the IAM principal
137+
type: string
138+
type:
139+
default: standard
140+
description: Type is the type of access entry. Defaults
141+
to standard if not specified.
142+
enum:
143+
- standard
144+
- ec2_linux
145+
- ec2_windows
146+
- fargate_linux
147+
- ec2
148+
- hybrid_linux
149+
- hyperpod_linux
150+
type: string
151+
username:
152+
description: Username is the username for the access
153+
entry
154+
type: string
155+
required:
156+
- principalARN
157+
type: object
158+
type: array
78159
additionalTags:
79160
additionalProperties:
80161
type: string

controlplane/eks/api/v1beta1/conversion.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ func (r *AWSManagedControlPlane) ConvertTo(dstRaw conversion.Hub) error {
116116
dst.Spec.Partition = restored.Spec.Partition
117117
dst.Spec.RestrictPrivateSubnets = restored.Spec.RestrictPrivateSubnets
118118
dst.Spec.AccessConfig = restored.Spec.AccessConfig
119+
dst.Spec.AccessEntries = restored.Spec.AccessEntries
119120
dst.Spec.RolePath = restored.Spec.RolePath
120121
dst.Spec.RolePermissionsBoundary = restored.Spec.RolePermissionsBoundary
121122
dst.Status.Version = restored.Status.Version

controlplane/eks/api/v1beta1/zz_generated.conversion.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

controlplane/eks/api/v1beta2/awsmanagedcontrolplane_types.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,11 @@ type AWSManagedControlPlaneSpec struct { //nolint: maligned
196196
// +optional
197197
AccessConfig *AccessConfig `json:"accessConfig,omitempty"`
198198

199+
// AccessEntries specifies the access entries for the cluster
200+
// Access entries require AuthenticationMode to be either "api" or "api_and_config_map"
201+
// +optional
202+
AccessEntries []AccessEntry `json:"accessEntries,omitempty"`
203+
199204
// VpcCni is used to set configuration options for the VPC CNI plugin
200205
// +optional
201206
VpcCni VpcCni `json:"vpcCni,omitempty"`
@@ -276,6 +281,59 @@ type AccessConfig struct {
276281
BootstrapClusterCreatorAdminPermissions *bool `json:"bootstrapClusterCreatorAdminPermissions,omitempty"`
277282
}
278283

284+
// AccessEntry represents an AWS EKS access entry for IAM principals
285+
type AccessEntry struct {
286+
// PrincipalARN is the Amazon Resource Name (ARN) of the IAM principal
287+
// +kubebuilder:validation:Required
288+
PrincipalARN string `json:"principalARN"`
289+
290+
// Type is the type of access entry. Defaults to standard if not specified.
291+
// +kubebuilder:default=standard
292+
// +kubebuilder:validation:Enum=standard;ec2_linux;ec2_windows;fargate_linux;ec2;hybrid_linux;hyperpod_linux
293+
// +optional
294+
Type AccessEntryType `json:"type,omitempty"`
295+
296+
// KubernetesGroups represents the Kubernetes groups for the access entry
297+
// Cannot be specified if Type is "ec2_linux" or "ec2_windows"
298+
// +optional
299+
KubernetesGroups []string `json:"kubernetesGroups,omitempty"`
300+
301+
// Username is the username for the access entry
302+
// +optional
303+
Username string `json:"username,omitempty"`
304+
305+
// AccessPolicies specifies the policies to associate with this access entry
306+
// Cannot be specified if Type is "ec2_linux" or "ec2_windows"
307+
// +optional
308+
// +kubebuilder:validation:MaxItems=20
309+
AccessPolicies []AccessPolicyReference `json:"accessPolicies,omitempty"`
310+
}
311+
312+
// AccessPolicyReference represents a reference to an AWS EKS access policy
313+
type AccessPolicyReference struct {
314+
// PolicyARN is the Amazon Resource Name (ARN) of the access policy
315+
// +kubebuilder:validation:Required
316+
PolicyARN string `json:"policyARN"`
317+
318+
// AccessScope specifies the scope for the policy
319+
// +kubebuilder:validation:Required
320+
AccessScope AccessScope `json:"accessScope"`
321+
}
322+
323+
// AccessScope represents the scope for an access policy
324+
type AccessScope struct {
325+
// Type is the type of access scope. Defaults to "cluster".
326+
// +kubebuilder:validation:Enum=cluster;namespace
327+
// +kubebuilder:default=cluster
328+
Type AccessScopeType `json:"type"`
329+
330+
// Namespaces are the namespaces for the access scope
331+
// Only valid when Type is namespace
332+
// +optional
333+
// +kubebuilder:validation:MinItems=1
334+
Namespaces []string `json:"namespaces,omitempty"`
335+
}
336+
279337
// EncryptionConfig specifies the encryption configuration for the EKS clsuter.
280338
type EncryptionConfig struct {
281339
// Provider specifies the ARN or alias of the CMK (in AWS KMS)

controlplane/eks/api/v1beta2/awsmanagedcontrolplane_webhook.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ func (*awsManagedControlPlaneWebhook) ValidateCreate(_ context.Context, obj runt
108108
allErrs = append(allErrs, r.validateNetwork()...)
109109
allErrs = append(allErrs, r.validatePrivateDNSHostnameTypeOnLaunch()...)
110110
allErrs = append(allErrs, r.validateAccessConfigCreate()...)
111+
allErrs = append(allErrs, r.validateAccessEntries()...)
111112

112113
if len(allErrs) == 0 {
113114
return nil, nil
@@ -150,6 +151,7 @@ func (*awsManagedControlPlaneWebhook) ValidateUpdate(ctx context.Context, oldObj
150151
allErrs = append(allErrs, r.validateKubeProxy()...)
151152
allErrs = append(allErrs, r.Spec.AdditionalTags.Validate()...)
152153
allErrs = append(allErrs, r.validatePrivateDNSHostnameTypeOnLaunch()...)
154+
allErrs = append(allErrs, r.validateAccessEntries()...)
153155

154156
if r.Spec.Region != oldAWSManagedControlplane.Spec.Region {
155157
allErrs = append(allErrs,
@@ -367,6 +369,61 @@ func (r *AWSManagedControlPlane) validateAccessConfigCreate() field.ErrorList {
367369
return allErrs
368370
}
369371

372+
func (r *AWSManagedControlPlane) validateAccessEntries() field.ErrorList {
373+
var allErrs field.ErrorList
374+
375+
if len(r.Spec.AccessEntries) > 0 {
376+
// AccessEntries require AuthenticationMode to be api or api_and_config_map
377+
if r.Spec.AccessConfig == nil ||
378+
(r.Spec.AccessConfig.AuthenticationMode != EKSAuthenticationModeAPI &&
379+
r.Spec.AccessConfig.AuthenticationMode != EKSAuthenticationModeAPIAndConfigMap) {
380+
allErrs = append(allErrs,
381+
field.Invalid(field.NewPath("spec", "accessEntries"),
382+
r.Spec.AccessEntries,
383+
"accessEntries can only be used when authenticationMode is set to api or api_and_config_map",
384+
),
385+
)
386+
}
387+
388+
for i, entry := range r.Spec.AccessEntries {
389+
// Validate that EC2 types don't have kubernetes groups or access policies
390+
if entry.Type == AccessEntryTypeEC2Linux || entry.Type == AccessEntryTypeEC2Windows {
391+
if len(entry.KubernetesGroups) > 0 {
392+
allErrs = append(allErrs,
393+
field.Invalid(field.NewPath("spec", "accessEntries").Index(i).Child("kubernetesGroups"),
394+
entry.KubernetesGroups,
395+
"kubernetesGroups cannot be specified when type is ec2_linux or ec2_windows",
396+
),
397+
)
398+
}
399+
400+
if len(entry.AccessPolicies) > 0 {
401+
allErrs = append(allErrs,
402+
field.Invalid(field.NewPath("spec", "accessEntries").Index(i).Child("accessPolicies"),
403+
entry.AccessPolicies,
404+
"accessPolicies cannot be specified when type is ec2_linux or ec2_windows",
405+
),
406+
)
407+
}
408+
}
409+
410+
// Validate namespace scopes
411+
for j, policy := range entry.AccessPolicies {
412+
if policy.AccessScope.Type == AccessScopeTypeNamespace && len(policy.AccessScope.Namespaces) == 0 {
413+
allErrs = append(allErrs,
414+
field.Invalid(field.NewPath("spec", "accessEntries").Index(i).Child("accessPolicies").Index(j).Child("accessScope", "namespaces"),
415+
policy.AccessScope.Namespaces,
416+
"at least one value must be provided when accessScope type is namespace",
417+
),
418+
)
419+
}
420+
}
421+
}
422+
}
423+
424+
return allErrs
425+
}
426+
370427
func (r *AWSManagedControlPlane) validateIAMAuthConfig() field.ErrorList {
371428
return validateIAMAuthConfig(r.Spec.IAMAuthenticatorConfig, field.NewPath("spec.iamAuthenticatorConfig"))
372429
}

0 commit comments

Comments
 (0)