Skip to content

Commit 7ad87d7

Browse files
stefanmcshanek0da
authored andcommitted
Add eks pod identities
Signed-off-by: Danil Grigorev <[email protected]>
1 parent 3e450d7 commit 7ad87d7

20 files changed

+788
-1
lines changed

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

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3116,6 +3116,36 @@ spec:
31163116
description: Partition is the AWS security partition being used. Defaults
31173117
to "aws"
31183118
type: string
3119+
podIdentityAssociations:
3120+
description: |-
3121+
PodIdentityAssociations represent Kubernetes Service Accounts mapping to AWS IAM Roles without IRSA, using EKS Pod Identity.
3122+
This requires using the AWS EKS Addon for Pod Identity.
3123+
items:
3124+
description: PodIdentityAssociation represents an association between
3125+
a Kubernetes Service Account in a namespace, and an AWS IAM role
3126+
which allows the service principal `pods.eks.amazonaws.com` in
3127+
its trust policy.
3128+
properties:
3129+
roleARN:
3130+
description: RoleARN is the ARN of an IAM role which the Service
3131+
Account can assume.
3132+
type: string
3133+
serviceAccountName:
3134+
description: ServiceAccountName is the name of the kubernetes
3135+
Service Account within the namespace
3136+
type: string
3137+
serviceAccountNamespace:
3138+
default: default
3139+
description: ServiceAccountNamespace is the kubernetes namespace,
3140+
which the kubernetes Service Account resides in. Defaults
3141+
to "default" namespace.
3142+
type: string
3143+
required:
3144+
- roleARN
3145+
- serviceAccountName
3146+
- serviceAccountNamespace
3147+
type: object
3148+
type: array
31193149
region:
31203150
description: The AWS Region the cluster lives in.
31213151
type: string

controlplane/eks/api/v1beta1/conversion.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,9 @@ func (r *AWSManagedControlPlane) ConvertTo(dstRaw conversion.Hub) error {
121121
dst.Spec.RolePermissionsBoundary = restored.Spec.RolePermissionsBoundary
122122
dst.Status.Version = restored.Status.Version
123123
dst.Spec.BootstrapSelfManagedAddons = restored.Spec.BootstrapSelfManagedAddons
124+
dst.Spec.UpgradePolicy = restored.Spec.UpgradePolicy
125+
dst.Spec.PodIdentityAssociations = restored.Spec.PodIdentityAssociations
126+
124127
return nil
125128
}
126129

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: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,11 @@ type AWSManagedControlPlaneSpec struct { //nolint: maligned
187187
// +optional
188188
Addons *[]Addon `json:"addons,omitempty"`
189189

190+
// PodIdentityAssociations represent Kubernetes Service Accounts mapping to AWS IAM Roles without IRSA, using EKS Pod Identity.
191+
// This requires using the AWS EKS Addon for Pod Identity.
192+
// +optional
193+
PodIdentityAssociations []PodIdentityAssociation `json:"podIdentityAssociations,omitempty"`
194+
190195
// IdentityProviderconfig is used to specify the oidc provider config
191196
// to be attached with this eks cluster
192197
// +optional

controlplane/eks/api/v1beta2/awsmanagedcontrolplane_webhook.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"github.com/pkg/errors"
2626
apierrors "k8s.io/apimachinery/pkg/api/errors"
2727
"k8s.io/apimachinery/pkg/runtime"
28+
"k8s.io/apimachinery/pkg/util/validation"
2829
"k8s.io/apimachinery/pkg/util/validation/field"
2930
"k8s.io/apimachinery/pkg/util/version"
3031
"k8s.io/klog/v2"
@@ -107,6 +108,8 @@ func (*awsManagedControlPlaneWebhook) ValidateCreate(_ context.Context, obj runt
107108
allErrs = append(allErrs, r.Spec.AdditionalTags.Validate()...)
108109
allErrs = append(allErrs, r.validateNetwork()...)
109110
allErrs = append(allErrs, r.validatePrivateDNSHostnameTypeOnLaunch()...)
111+
allErrs = append(allErrs, r.validateAccessConfigCreate()...)
112+
allErrs = append(allErrs, r.validServiceAccountName()...)
110113

111114
if len(allErrs) == 0 {
112115
return nil, nil
@@ -148,6 +151,7 @@ func (*awsManagedControlPlaneWebhook) ValidateUpdate(ctx context.Context, oldObj
148151
allErrs = append(allErrs, r.validateKubeProxy()...)
149152
allErrs = append(allErrs, r.Spec.AdditionalTags.Validate()...)
150153
allErrs = append(allErrs, r.validatePrivateDNSHostnameTypeOnLaunch()...)
154+
allErrs = append(allErrs, r.validServiceAccountName()...)
151155

152156
if r.Spec.Region != oldAWSManagedControlplane.Spec.Region {
153157
allErrs = append(allErrs,
@@ -458,6 +462,28 @@ func validatePrivateDNSHostnameTypeOnLaunch(networkSpec infrav1.NetworkSpec, pat
458462
return allErrs
459463
}
460464

465+
func (r *AWSManagedControlPlane) validServiceAccountName() field.ErrorList {
466+
var allErrs field.ErrorList
467+
468+
if r.Spec.PodIdentityAssociations != nil {
469+
for i, association := range r.Spec.PodIdentityAssociations {
470+
associationPath := field.NewPath("spec", "podIdentityAssociations").Index(i)
471+
if association.ServiceAccountName == "" {
472+
allErrs = append(allErrs, field.Required(associationPath.Child("serviceAccountName"), "serviceAccountName is required"))
473+
}
474+
475+
// kubernetes uses ValidateServiceAccountName internally, which maps to IsDNS1123Subdomain
476+
// https://github.com/kubernetes/apimachinery/blob/d794766488ac2892197a7cc8d0b4b46b0edbda80/pkg/api/validation/generic.go#L68
477+
478+
if validationErrs := validation.IsDNS1123Subdomain(association.ServiceAccountName); len(validationErrs) > 0 {
479+
allErrs = append(allErrs, field.Invalid(associationPath.Child("serviceAccountName"), association.ServiceAccountName, fmt.Sprintf("serviceAccountName is invalid: %v", validationErrs)))
480+
}
481+
}
482+
}
483+
484+
return allErrs
485+
}
486+
461487
func (r *AWSManagedControlPlane) validateNetwork() field.ErrorList {
462488
return validateNetwork("AWSManagedControlPlane", r.Spec.NetworkSpec, r.Spec.SecondaryCidrBlock, field.NewPath("spec"))
463489
}

controlplane/eks/api/v1beta2/conditions_consts.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@ const (
5252
EKSAddonsConfiguredFailedReason = "EKSAddonsConfiguredFailed"
5353
)
5454

55+
const (
56+
// EKSPodIdentityAssociationConfiguredCondition condition reports on the successful reconciliation of EKS pod identity associations.
57+
EKSPodIdentityAssociationConfiguredCondition clusterv1.ConditionType = "EKSPodIdentityAssociationConfigured"
58+
// EKSPodIdentityAssociationFailedReason is used to report failures while reconciling the EKS pod identity associations.
59+
EKSPodIdentityAssociationFailedReason = "EKSPodIdentityAssociationConfigurationFailed"
60+
)
61+
5562
const (
5663
// EKSIdentityProviderConfiguredCondition condition reports on the successful association of identity provider config.
5764
EKSIdentityProviderConfiguredCondition clusterv1.ConditionType = "EKSIdentityProviderConfigured"

controlplane/eks/api/v1beta2/types.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,3 +283,17 @@ type OIDCIdentityProviderConfig struct {
283283
// +optional
284284
Tags infrav1.Tags `json:"tags,omitempty"`
285285
}
286+
287+
// PodIdentityAssociation represents an association between a Kubernetes Service Account in a namespace, and an AWS IAM role which allows the service principal `pods.eks.amazonaws.com` in its trust policy.
288+
type PodIdentityAssociation struct {
289+
// ServiceAccountName is the name of the kubernetes Service Account within the namespace
290+
// +kubebuilder:validation:Required
291+
ServiceAccountName string `json:"serviceAccountName"`
292+
// ServiceAccountNamespace is the kubernetes namespace, which the kubernetes Service Account resides in. Defaults to "default" namespace.
293+
// +kubebuilder:validation:Required
294+
// +kubebuilder:default=default
295+
ServiceAccountNamespace string `json:"serviceAccountNamespace"`
296+
// RoleARN is the ARN of an IAM role which the Service Account can assume.
297+
// +kubebuilder:validation:Required
298+
RoleARN string `json:"roleARN,omitempty"`
299+
}

controlplane/eks/api/v1beta2/zz_generated.deepcopy.go

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

controlplane/eks/controllers/awsmanagedcontrolplane_controller_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -970,6 +970,11 @@ func mockedEKSCluster(ctx context.Context, g *WithT, eksRec *mock_eksiface.MockE
970970
}).Return(&eks.ListAddonsOutput{}, nil)
971971

972972
eksRec.UpdateClusterConfig(ctx, gomock.AssignableToTypeOf(&eks.UpdateClusterConfigInput{})).After(waitUntilClusterActiveCall).Return(&eks.UpdateClusterConfigOutput{}, nil)
973+
eksRec.ListPodIdentityAssociations(context.TODO(), gomock.Eq(&eks.ListPodIdentityAssociationsInput{
974+
ClusterName: aws.String("test-cluster"),
975+
})).Return(&eks.ListPodIdentityAssociationsOutput{
976+
Associations: []ekstypes.PodIdentityAssociationSummary{},
977+
}, nil)
973978

974979
awsNodeRec.ReconcileCNI(gomock.Any()).Return(nil)
975980
kubeProxyRec.ReconcileKubeProxy(gomock.Any()).Return(nil)

docs/book/src/SUMMARY_PREFIX.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
- [Creating a cluster](./topics/eks/creating-a-cluster.md)
2121
- [Using EKS Console](./topics/eks/eks-console.md)
2222
- [Using EKS Addons](./topics/eks/addons.md)
23+
- [Using EKS Pod Identity Associations](./topics/eks/pod-identity-associations.md)
2324
- [Enabling Encryption](./topics/eks/encryption.md)
2425
- [Cluster Upgrades](./topics/eks/cluster-upgrades.md)
2526
- [ROSA Support](./topics/rosa/index.md)

0 commit comments

Comments
 (0)