Skip to content

Conversation

@pahud
Copy link
Contributor

@pahud pahud commented Nov 5, 2025

Issue # (if applicable)

Closes #35892.

Reason for this change

AWS accounts have a default limit of 1,000 IAM roles. When deploying many EKS ServiceAccounts, users can hit this limit because the ServiceAccount construct always creates an IAM role, even when the workload doesn't need AWS permissions. This forces users to request quota increases or implement workarounds.

Additionally, creating IAM roles for ServiceAccounts that only need Kubernetes-level permissions violates the principle of least privilege and creates unnecessary security surface area.

Description of changes

This PR adds IdentityType.NONE as a new member of the IdentityType enum, allowing users to create ServiceAccounts without IAM roles when AWS permissions are not needed.

Key changes:

  • Extended IdentityType enum with NONE member
  • Modified ServiceAccount constructor to conditionally create IAM resources based on identityType
  • When identityType is NONE:
    • No IAM Role is created
    • No OpenIdConnectProvider is created
    • No CfnPodIdentityAssociation is created
    • ServiceAccount Kubernetes manifest is created WITHOUT eks.amazonaws.com/role-arn annotation
    • role property is undefined
    • addToPrincipalPolicy() returns { statementAdded: false }

Breaking change: The role property on ServiceAccount is now optional (role?: IRole instead of role: IRole). This is necessary because when identityType is NONE, no IAM role is created.

Migration path for existing code:

// Before (will now fail TypeScript compilation):
serviceAccount.role.addToPrincipalPolicy(statement);

// After - Option 1 (recommended): Use the safe method
serviceAccount.addToPrincipalPolicy(statement);

// After - Option 2: Check for undefined
if (serviceAccount.role) {
  serviceAccount.role.addToPrincipalPolicy(statement);
}

// After - Option 3: Use optional chaining
serviceAccount.role?.addToPrincipalPolicy(statement);

Note: Existing code that doesn't specify identityType will continue to work without modification (defaults to IdentityType.IRSA). Only code that directly accesses the role property needs to be updated to handle the optional type.

Migration considerations when changing existing ServiceAccounts to IdentityType.NONE:

  1. IAM role removal: The IAM role will be deleted from CloudFormation. Any resources that reference this role (e.g., trust policies, resource-based policies) will be impacted and may need updates.

  2. Kubernetes ServiceAccount update behavior: The ServiceAccount itself will NOT be deleted and re-created. Behind the scenes, kubectl apply will update the Kubernetes manifest:

    • New pods will be created without the eks.amazonaws.com/role-arn annotation and will not have AWS credentials
    • Existing running pods will retain the annotation until they are restarted
    • To fully apply the change, restart your pods after the CDK deployment completes
  3. Testing recommendation: For large-scale ServiceAccount migrations, we strongly recommend testing in a non-production environment first to validate that your workloads function correctly without AWS IAM permissions.

Usage example:

import * as eks from 'aws-cdk-lib/aws-eks';

// ServiceAccount without AWS permissions
const sa = cluster.addServiceAccount('my-service-account', {
  identityType: eks.IdentityType.NONE,  // No IAM role created
});

// This will return { statementAdded: false }
sa.addToPrincipalPolicy(new iam.PolicyStatement({
  actions: ['s3:GetObject'],
  resources: ['*'],
}));

Describe any new or updated permissions being added

N/A - This change does not add any new IAM permissions. In fact, it provides a way to avoid creating IAM roles when they are not needed.

Description of how you validated changes

  • Unit tests: Added 4 comprehensive tests for IdentityType.NONE:

    1. Verifies no IAM resources are created (Role, OpenIdConnectProvider, PodIdentityAssociation)
    2. Tests addToPrincipalPolicy() returns { statementAdded: false } gracefully
    3. Validates custom annotations and labels work correctly
    4. Confirms Fargate cluster compatibility
  • Regression testing:

    • All existing EKS module tests pass
    • Verified that default behavior (IRSA) remains unchanged
    • Confirmed POD_IDENTITY identity type continues to work correctly
  • CloudFormation validation: Verified that when using IdentityType.NONE:

    • No AWS::IAM::Role resources are created for the ServiceAccount
    • No AWS::EKS::PodIdentityAssociation resources are created
    • Kubernetes ServiceAccount manifest is created without AWS annotations
    • Existing IRSA and POD_IDENTITY behaviors remain unchanged

Checklist


By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license

- Add new `NONE` identity type to `IdentityType` enum
- Update `ServiceAccount` to handle `NONE` identity type
- Make `role` property optional when `identityType` is `NONE`
- Remove duplicate `ServiceAccountOptions` interface definition
- Improve documentation for new `NONE` identity type
- Enhance flexibility for creating Kubernetes service accounts without AWS permissions
Rationale: Provides more granular control over service account creation, allowing users to create service accounts without automatically generating an IAM role, which can help reduce unnecessary IAM resources and follow least-privilege principles.
@aws-cdk-automation aws-cdk-automation requested a review from a team November 5, 2025 20:26
@github-actions github-actions bot added feature-request A feature should be added or improved. p2 labels Nov 5, 2025
@mergify mergify bot added the contribution/core This is a PR that came from AWS. label Nov 5, 2025
Copy link
Collaborator

@aws-cdk-automation aws-cdk-automation left a comment

Choose a reason for hiding this comment

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

The pull request linter fails with the following errors:

❌ Features must contain a change to a README file.
❌ Features must contain a change to an integration test file and the resulting snapshot.

If you believe this pull request should receive an exemption, please comment and provide a justification. A comment requesting an exemption should contain the text Exemption Request. Additionally, if clarification is needed, add Clarification Request to a comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contribution/core This is a PR that came from AWS. feature-request A feature should be added or improved. p2

Projects

None yet

Development

Successfully merging this pull request may close these issues.

eks: make IAM role creation optional in ServiceAccount construct

2 participants