Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(eks): Allow passing of custom IAM role to Kube Ctl Lambda #17196

Merged
merged 9 commits into from
Nov 11, 2021
44 changes: 44 additions & 0 deletions packages/@aws-cdk/aws-eks/lib/cluster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,15 @@ export interface ICluster extends IResource, ec2.IConnectable {
*/
readonly kubectlPrivateSubnets?: ec2.ISubnet[];

/**
* An IAM role that can perform kubectl operations against this cluster.
*
* The role should be mapped to the `system:masters` Kubernetes RBAC role.
*
* This role is directly passed to the lambda handler that sends Kube Ctl commands to the cluster.
*/
readonly kubectlLambdaRole?: iam.IRole;

/**
* An AWS Lambda layer that includes `kubectl`, `helm` and the `aws` CLI.
*
Expand Down Expand Up @@ -260,6 +269,18 @@ export interface ClusterAttributes {
*/
readonly kubectlRoleArn?: string;

/**
* An IAM role that can perform kubectl operations against this cluster.
*
* The role should be mapped to the `system:masters` Kubernetes RBAC role.
*
* This role is directly passed to the lambda handler that sends Kube Ctl commands
* to the cluster.
* @default - if not specified, the default role created by a lambda function will
* be used.
*/
readonly kubectlLambdaRole?: iam.IRole;

/**
* Environment variables to use when running `kubectl` against this cluster.
* @default - no additional variables
Expand Down Expand Up @@ -676,6 +697,14 @@ export interface ClusterProps extends ClusterOptions {
* @default NODEGROUP
*/
readonly defaultCapacityType?: DefaultCapacityType;


/**
* The IAM role to pass to the Kubectl Lambda Handler.
*
* @default - Default Lambda IAM Execution Role
*/
readonly kubectlLambdaRole?: iam.IRole;
}

/**
Expand Down Expand Up @@ -745,6 +774,7 @@ abstract class ClusterBase extends Resource implements ICluster {
public abstract readonly clusterSecurityGroup: ec2.ISecurityGroup;
public abstract readonly clusterEncryptionConfigKeyArn: string;
public abstract readonly kubectlRole?: iam.IRole;
public abstract readonly kubectlLambdaRole?: iam.IRole;
public abstract readonly kubectlEnvironment?: { [key: string]: string };
public abstract readonly kubectlSecurityGroup?: ec2.ISecurityGroup;
public abstract readonly kubectlPrivateSubnets?: ec2.ISubnet[];
Expand Down Expand Up @@ -1050,6 +1080,18 @@ export class Cluster extends ClusterBase {
*/
public readonly kubectlRole?: iam.IRole;

/**
* An IAM role that can perform kubectl operations against this cluster.
*
* The role should be mapped to the `system:masters` Kubernetes RBAC role.
*
* This role is directly passed to the lambda handler that sends Kube Ctl commands to the cluster.
* @default - if not specified, the default role created by a lambda function will
* be used.
*/

public readonly kubectlLambdaRole?: iam.IRole;

/**
* Custom environment variables when running `kubectl` against this cluster.
*/
Expand Down Expand Up @@ -1158,6 +1200,7 @@ export class Cluster extends ClusterBase {
this.prune = props.prune ?? true;
this.vpc = props.vpc || new ec2.Vpc(this, 'DefaultVpc');
this.version = props.version;
this.kubectlLambdaRole = props.kubectlLambdaRole ? props.kubectlLambdaRole : undefined;

this.tagSubnets();

Expand Down Expand Up @@ -1823,6 +1866,7 @@ class ImportedCluster extends ClusterBase {
public readonly clusterArn: string;
public readonly connections = new ec2.Connections();
public readonly kubectlRole?: iam.IRole;
public readonly kubectlLambdaRole?: iam.IRole;
public readonly kubectlEnvironment?: { [key: string]: string; } | undefined;
public readonly kubectlSecurityGroup?: ec2.ISecurityGroup | undefined;
public readonly kubectlPrivateSubnets?: ec2.ISubnet[] | undefined;
Expand Down
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-eks/lib/kubectl-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ export class KubectlProvider extends NestedStack {
description: 'onEvent handler for EKS kubectl resource provider',
memorySize,
environment: cluster.kubectlEnvironment,
role: cluster.kubectlLambdaRole ? cluster.kubectlLambdaRole : undefined,

// defined only when using private access
vpc: cluster.kubectlPrivateSubnets ? cluster.vpc : undefined,
Expand Down
36 changes: 36 additions & 0 deletions packages/@aws-cdk/aws-eks/test/cluster.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2168,6 +2168,42 @@ describe('cluster', () => {
},
});

});

test('kubectl provider passes iam role environment to kube ctl lambda', () => {

const { stack } = testFixture();

const kubectlRole = new iam.Role(stack, 'KubectlIamRole', {
assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
});

// using _ syntax to silence warning about _cluster not being used, when it is
const cluster = new eks.Cluster(stack, 'Cluster1', {
version: CLUSTER_VERSION,
prune: false,
endpointAccess: eks.EndpointAccess.PRIVATE,
kubectlLambdaRole: kubectlRole,
});

cluster.addManifest('resource', {
kind: 'ConfigMap',
apiVersion: 'v1',
data: {
hello: 'world',
},
metadata: {
name: 'config-map',
},
});

// the kubectl provider is inside a nested stack.
const nested = stack.node.tryFindChild('@aws-cdk/aws-eks.KubectlProvider') as cdk.NestedStack;
expect(nested).toHaveResourceLike('AWS::Lambda::Function', {
Role: {
Ref: 'referencetoStackKubectlIamRole02F8947EArn',
},
});

});

Expand Down