aws / aws/aws-cdk

(aws-eks): ServiceAccountIdentity Construct (alternative to ServiceAccount)

Open
#21,356 1 comment 0 reactions 0 assignees View on GitHub
@aws-cdk/aws-eks @aws-cdk/aws-eks-v2-alpha effort/large feature-request p2
Dominant language
TypeScript
Stars
12.9k
Forks
4.6k
Avg merge
2d 3h
Merged PRs (30d)
83

Description

### Describe the feature

AWS CDK provides the `ServiceAccount` construct for users that want to conveniently create a k8s ServiceAccount with an IAM role for EKS.

In some use-case users might want to conveniently create an IAM role for a multitude of (possibly pre-existing) ServiceAccounts. For these use-cases there should be an `ServiceAccountIdentity` construct.

### Use Case

You want to create an EKS IAM role for one or multiple (possible pre-existing) k8s ServiceAccount(s) and you maybe even want that role to have wildcards in its assume role conditions.

Concrete use-case: a piece of software has a multi-tenancy approach and deploys one ServiceAccount into each k8s namespace and each of the ServiceAccount needs exactly the same IAM role, hence you don't want to have specific roles for each namespace/service account. The service accounts are created via Helm or CDK8s chart and you simply want to pass the IAM role's ARN through the Chart's values.

### Proposed Solution

Something along those lines:

```typescript
import {OpenIdConnectPrincipal, Role} from "aws-cdk-lib/aws-iam";
import {Construct} from "constructs";
import {ICluster} from "aws-cdk-lib/aws-eks";
import {CfnJson} from "aws-cdk-lib";

export class ServiceAccountIdentity extends Construct {

role: Role;

constructor(parent: Construct,
private readonly id: string,
private readonly cluster: ICluster,
private readonly namespace: string,
private readonly serviceAccountName: string) {
super(parent, id);

this.role = new Role(this, 'Role', {
assumedBy: new OpenIdConnectPrincipal(this.cluster.openIdConnectProvider).withConditions(this.conditions),
roleName: this.roleName
});
}

private get audCondition(): any {
return {
[`${this.cluster.openIdConnectProvider.openIdConnectProviderIssuer}:aud`]: 'sts.amazonaws.com'
};
}

private get subCondition(): any {
return {
[`${this.cluster.openIdConnectProvider.openIdConnectProviderIssuer}:sub`]: `system:serviceaccount:${this.namespace}:${this.serviceAccountName}`
};
}

private cfnJson(value: any, idSuffix = ''): CfnJson {
return new CfnJson(this, `Condition${idSuffix}`, { value });
}

private get conditions(): any {
if (this.namespace === '*' || this.serviceAccountName === '*') {
return {
StringEquals: this.cfnJson(this.audCondition, 'Aud'),
StringLike: this.cfnJson(this.subCondition, 'Sub')
};
}

return {
StringEquals: this.cfnJson({...this.audCondition, ...this.subCondition})
};
}

private get roleName(): string | undefined {
// Use generated name if someone wants the full wildcard experience.
if (this.namespace === '*' && this.serviceAccountName === '*') return undefined;
if (this.namespace === '*') return `${this.cluster.clusterName}-${this.serviceAccountName}`;
if (this.serviceAccountName === '*') return `${this.cluster.clusterName}-${this.namespace}`;
return `${this.cluster.clusterName}-${this.namespace}-${this.serviceAccountName}`;
}
}
```

Topics up for discussion:
* One could if even allow to pass multiple namespace/serviceAccount and use a `ForAnyValue` condition so that multiple explicit service account references can be specified.
* More advanced role name handling
* Implement `addServiceAccountIdentity` method for `ICluster` (corresponding to the `addServiceAccount` method)

### Other Information

_No response_

### Acknowledgements

- [X] I may be able to implement this feature request
- [ ] This feature might incur a breaking change

### CDK version used

any

### Environment details (OS name and version, etc.)

any

Contributor guide

Open the contributing guide

Research direction

Start by comparing the existing ServiceAccount construct and ICluster.addServiceAccount entry point with the proposed ServiceAccountIdentity API. Resolve the open questions around multiple identities, wildcard conditions, role naming, and an ICluster.addServiceAccountIdentity method; done means the construct supports the stated pre-existing and wildcard ServiceAccount use cases.

Written by the indexing model from the issue text.

Assessment

Tech stack
aws, kubernetes, typescript
Domain
cloud, devops, infrastructure
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.