(aws-eks): ServiceAccountIdentity Construct (alternative to ServiceAccount)
- 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
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