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): expose cluster security group and encryption configuration #8317

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
22cfab8
Merge pull request #196 from aws/master
eduardomourar May 27, 2020
a1e707d
expose eks cluster additional attributes
eduardomourar May 27, 2020
236cb71
deal with boolean properly in resource config
eduardomourar May 27, 2020
1f0ccfa
Merge branch 'master' into feature/expose-cluster-security-group
eduardomourar Jun 2, 2020
7dc6764
update automated testing for eks
eduardomourar Jun 2, 2020
178b6da
fix linting
eduardomourar Jun 2, 2020
cd7ef84
fix integration test difference
eduardomourar Jun 2, 2020
2f9213a
fix
eduardomourar Jun 2, 2020
b29c415
Merge branch 'master' into feature/expose-cluster-security-group
eduardomourar Jun 2, 2020
c62b088
update readme
eduardomourar Jun 2, 2020
1d9bca9
add comments in handler code
eduardomourar Jun 4, 2020
4e3a6c2
update unit tests
eduardomourar Jun 4, 2020
f2d1bcc
update for failing unit tests
eduardomourar Jun 4, 2020
17a7df1
update integration test expected file
eduardomourar Jun 5, 2020
810e258
Merge branch 'master' into feature/expose-cluster-security-group
eduardomourar Jun 5, 2020
6f5bf1d
Merge branch 'master' into feature/expose-cluster-security-group
Jun 9, 2020
1b9182e
avoid "vendor response doesn't contain key" issues
Jun 9, 2020
0e635f4
update readme with encryption config
eduardomourar Jun 9, 2020
b98c7d1
Merge branch 'master' into feature/expose-cluster-security-group
eduardomourar Jun 10, 2020
6978ec4
update tests
Jun 10, 2020
2e63152
Merge branch 'master' into feature/expose-cluster-security-group
Jun 10, 2020
e7ef1cf
get rid of `decodeBooleans`
Jun 10, 2020
66ece9a
update expectations
Jun 10, 2020
9163484
Merge branch 'master' into feature/expose-cluster-security-group
Jun 10, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions packages/@aws-cdk/aws-eks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,33 @@ A convenience method for mapping a role to the `system:masters` group is also av
cluster.awsAuth.addMastersRole(role)
```

### Cluster Security Group
eduardomourar marked this conversation as resolved.
Show resolved Hide resolved

When you create an Amazon EKS cluster, a
[cluster security group](https://docs.aws.amazon.com/eks/latest/userguide/sec-group-reqs.html)
is automatically created as well. This security group is designed to allow
all traffic from the control plane and managed node groups to flow freely
between each other.

The ID for that security group can be retrieved after creating the cluster.

```ts
const clusterSecurityGroupId = cluster.clusterSecurityGroupId;
```

### Cluster Encryption Configuration

When you create an Amazon EKS cluster, envelope encryption of
Kubernetes secrets using the AWS Key Management Service (AWS KMS) can be enabled. The documentation
on [creating a cluster](https://docs.aws.amazon.com/eks/latest/userguide/create-cluster.html)
can provide more details about the customer master key (CMK) that can be used for the encryption.

The Amazon Resource Name (ARN) for that CMK can be retrieved.

```ts
const clusterEncryptionConfigKeyArn = cluster.clusterEncryptionConfigKeyArn;
```

### Node ssh Access

If you want to be able to SSH into your worker nodes, you must already
Expand Down
33 changes: 27 additions & 6 deletions packages/@aws-cdk/aws-eks/lib/cluster-resource-handler/cluster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,21 @@ export class ClusterResourceHandler extends ResourceHandler {
}

if (updates.updateLogging || updates.updateAccess) {
const updateResponse = await this.eks.updateClusterConfig({
const config: aws.EKS.UpdateClusterConfigRequest = {
name: this.clusterName,
logging: this.newProps.logging,
resourcesVpcConfig: this.newProps.resourcesVpcConfig,
});
};
if (updates.updateAccess) {
// Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here:
// https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html)
// will fail, therefore we take only the access fields explicitly
config.resourcesVpcConfig = {
eduardomourar marked this conversation as resolved.
Show resolved Hide resolved
endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess,
endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess,
publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs,
};
}
const updateResponse = await this.eks.updateClusterConfig(config);

return { EksUpdateId: updateResponse.update?.id };
}
Expand Down Expand Up @@ -197,9 +207,20 @@ export class ClusterResourceHandler extends ResourceHandler {
Name: cluster.name,
Endpoint: cluster.endpoint,
Arn: cluster.arn,
CertificateAuthorityData: cluster.certificateAuthority?.data,
OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer,
OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8), // Strips off https:// from the issuer url

// IMPORTANT: CFN expects that attributes will *always* have values,
// so return an empty string in case the value is not defined.
// Otherwise, CFN will throw with `Vendor response doesn't contain
// XXXX key`.

CertificateAuthorityData: cluster.certificateAuthority?.data ?? '',
ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '',
OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '',
OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', // Strips off https:// from the issuer url

// We can safely return the first item from encryption configuration array, because it has a limit of 1 item
// https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig
EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '',
},
};
}
Expand Down
11 changes: 11 additions & 0 deletions packages/@aws-cdk/aws-eks/lib/cluster-resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ export class ClusterResource extends Construct {
public readonly attrEndpoint: string;
public readonly attrArn: string;
public readonly attrCertificateAuthorityData: string;
public readonly attrClusterSecurityGroupId: string;
public readonly attrEncryptionConfigKeyArn: string;
public readonly attrOpenIdConnectIssuerUrl: string;
public readonly attrOpenIdConnectIssuer: string;
public readonly ref: string;
Expand Down Expand Up @@ -117,6 +119,13 @@ export class ClusterResource extends Construct {
properties: {
Config: props,
AssumeRoleArn: this.creationRole.roleArn,

// IMPORTANT: increment this number when you add new attributes to the
// resource. Otherwise, CloudFormation will error with "Vendor response
// doesn't contain XXX key in object" (see #8276) by incrementing this
// number, you will effectively cause a "no-op update" to the cluster
// which will return the new set of attribute.
AttributesRevision: 2,
},
});

Expand All @@ -126,6 +135,8 @@ export class ClusterResource extends Construct {
this.attrEndpoint = Token.asString(resource.getAtt('Endpoint'));
this.attrArn = Token.asString(resource.getAtt('Arn'));
this.attrCertificateAuthorityData = Token.asString(resource.getAtt('CertificateAuthorityData'));
this.attrClusterSecurityGroupId = Token.asString(resource.getAtt('ClusterSecurityGroupId'));
this.attrEncryptionConfigKeyArn = Token.asString(resource.getAtt('EncryptionConfigKeyArn'));
this.attrOpenIdConnectIssuerUrl = Token.asString(resource.getAtt('OpenIdConnectIssuerUrl'));
this.attrOpenIdConnectIssuer = Token.asString(resource.getAtt('OpenIdConnectIssuer'));
}
Expand Down
38 changes: 38 additions & 0 deletions packages/@aws-cdk/aws-eks/lib/cluster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,18 @@ export interface ICluster extends IResource, ec2.IConnectable {
* @attribute
*/
readonly clusterCertificateAuthorityData: string;

/**
* The cluster security group that was created by Amazon EKS for the cluster.
* @attribute
*/
readonly clusterSecurityGroupId: string;

/**
* Amazon Resource Name (ARN) or alias of the customer master key (CMK).
* @attribute
*/
readonly clusterEncryptionConfigKeyArn: string;
}

/**
Expand Down Expand Up @@ -84,6 +96,16 @@ export interface ClusterAttributes {
*/
readonly clusterCertificateAuthorityData: string;

/**
* The cluster security group that was created by Amazon EKS for the cluster.
*/
readonly clusterSecurityGroupId: string;

/**
* Amazon Resource Name (ARN) or alias of the customer master key (CMK).
*/
readonly clusterEncryptionConfigKeyArn: string;

/**
* The security groups associated with this cluster.
*/
Expand Down Expand Up @@ -299,6 +321,16 @@ export class Cluster extends Resource implements ICluster {
*/
public readonly clusterCertificateAuthorityData: string;

/**
* The cluster security group that was created by Amazon EKS for the cluster.
*/
public readonly clusterSecurityGroupId: string;

/**
* Amazon Resource Name (ARN) or alias of the customer master key (CMK).
*/
public readonly clusterEncryptionConfigKeyArn: string;

/**
* Manages connection rules (Security Group Rules) for the cluster
*
Expand Down Expand Up @@ -420,6 +452,8 @@ export class Cluster extends Resource implements ICluster {

this.clusterEndpoint = resource.attrEndpoint;
this.clusterCertificateAuthorityData = resource.attrCertificateAuthorityData;
this.clusterSecurityGroupId = resource.attrClusterSecurityGroupId;
this.clusterEncryptionConfigKeyArn = resource.attrEncryptionConfigKeyArn;

const updateConfigCommandPrefix = `aws eks update-kubeconfig --name ${this.clusterName}`;
const getTokenCommandPrefix = `aws eks get-token --cluster-name ${this.clusterName}`;
Expand Down Expand Up @@ -1008,6 +1042,8 @@ export interface AutoScalingGroupOptions {
class ImportedCluster extends Resource implements ICluster {
public readonly vpc: ec2.IVpc;
public readonly clusterCertificateAuthorityData: string;
public readonly clusterSecurityGroupId: string;
public readonly clusterEncryptionConfigKeyArn: string;
public readonly clusterName: string;
public readonly clusterArn: string;
public readonly clusterEndpoint: string;
Expand All @@ -1021,6 +1057,8 @@ class ImportedCluster extends Resource implements ICluster {
this.clusterEndpoint = props.clusterEndpoint;
this.clusterArn = props.clusterArn;
this.clusterCertificateAuthorityData = props.clusterCertificateAuthorityData;
this.clusterSecurityGroupId = props.clusterSecurityGroupId;
this.clusterEncryptionConfigKeyArn = props.clusterEncryptionConfigKeyArn;

let i = 1;
for (const sgProps of props.securityGroups) {
Expand Down
8 changes: 1 addition & 7 deletions packages/@aws-cdk/aws-eks/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,7 @@
},
"awslint": {
"exclude": [
"resource-attribute:@aws-cdk/aws-eks.FargateCluster.clusterSecurityGroupId",
"resource-attribute:@aws-cdk/aws-eks.FargateCluster.clusterEncryptionConfigKeyArn",
"resource-attribute:@aws-cdk/aws-eks.Cluster.clusterSecurityGroupId",
"resource-attribute:@aws-cdk/aws-eks.Cluster.clusterEncryptionConfigKeyArn",
"props-no-arn-refs:@aws-cdk/aws-eks.ClusterProps.outputMastersRoleArn",
"resource-attribute:@aws-cdk/aws-eks.Cluster.clusterSecurityGroupId",
"resource-attribute:@aws-cdk/aws-eks.Cluster.clusterSecurityGroupId"
"props-no-arn-refs:@aws-cdk/aws-eks.ClusterProps.outputMastersRoleArn"
]
},
"stability": "experimental",
Expand Down
57 changes: 37 additions & 20 deletions packages/@aws-cdk/aws-eks/test/integ.eks-cluster.expected.json
Original file line number Diff line number Diff line change
Expand Up @@ -888,7 +888,8 @@
"ClusterCreationRole360249B6",
"Arn"
]
}
},
"AttributesRevision": 2
},
"DependsOn": [
"ClusterCreationRoleDefaultPolicyE8BDFC7B",
Expand Down Expand Up @@ -2355,7 +2356,7 @@
},
"/",
{
"Ref": "AssetParameters7c148fb102ee8790aaf67d5e2a2dce8f5d9b87285c8b7e91f984216ee66f1be6S3BucketB18DC500"
"Ref": "AssetParameters18f930a3a3efac8df646c455c3afda1a743c13805600915d02fd4f4be87443f5S3Bucket7B48152A"
},
"/",
{
Expand All @@ -2365,7 +2366,7 @@
"Fn::Split": [
"||",
{
"Ref": "AssetParameters7c148fb102ee8790aaf67d5e2a2dce8f5d9b87285c8b7e91f984216ee66f1be6S3VersionKeyBE7DFF7A"
"Ref": "AssetParameters18f930a3a3efac8df646c455c3afda1a743c13805600915d02fd4f4be87443f5S3VersionKey75927692"
}
]
}
Expand All @@ -2378,7 +2379,7 @@
"Fn::Split": [
"||",
{
"Ref": "AssetParameters7c148fb102ee8790aaf67d5e2a2dce8f5d9b87285c8b7e91f984216ee66f1be6S3VersionKeyBE7DFF7A"
"Ref": "AssetParameters18f930a3a3efac8df646c455c3afda1a743c13805600915d02fd4f4be87443f5S3VersionKey75927692"
}
]
}
Expand All @@ -2388,11 +2389,11 @@
]
},
"Parameters": {
"referencetoawscdkeksclustertestAssetParameters01ec3fa8451b6541733a25ec9c0c13a2b7dcee848ddad2edf6cb9c1f40cbc896S3Bucket35BE45A3Ref": {
"Ref": "AssetParameters01ec3fa8451b6541733a25ec9c0c13a2b7dcee848ddad2edf6cb9c1f40cbc896S3Bucket221B7FEE"
"referencetoawscdkeksclustertestAssetParameters95d3377fefffa0934741552d39e46eef13de3a2094050df1057480e0344b402cS3Bucket60058D6ARef": {
"Ref": "AssetParameters95d3377fefffa0934741552d39e46eef13de3a2094050df1057480e0344b402cS3Bucket7F8D74FE"
},
"referencetoawscdkeksclustertestAssetParameters01ec3fa8451b6541733a25ec9c0c13a2b7dcee848ddad2edf6cb9c1f40cbc896S3VersionKey60905A80Ref": {
"Ref": "AssetParameters01ec3fa8451b6541733a25ec9c0c13a2b7dcee848ddad2edf6cb9c1f40cbc896S3VersionKeyA8C9A018"
"referencetoawscdkeksclustertestAssetParameters95d3377fefffa0934741552d39e46eef13de3a2094050df1057480e0344b402cS3VersionKey42E00C5ARef": {
"Ref": "AssetParameters95d3377fefffa0934741552d39e46eef13de3a2094050df1057480e0344b402cS3VersionKey1DF2734D"
},
"referencetoawscdkeksclustertestAssetParameters5e49cf64d8027f48872790f80cdb76c5b836ecf9a70b71be1eb937a5c25a47c1S3BucketC7CBF350Ref": {
"Ref": "AssetParameters5e49cf64d8027f48872790f80cdb76c5b836ecf9a70b71be1eb937a5c25a47c1S3Bucket663A709C"
Expand Down Expand Up @@ -2707,24 +2708,40 @@
]
}
},
"ClusterSecurityGroupId": {
"Value": {
"Fn::GetAtt": [
"Cluster9EE0221C",
"ClusterSecurityGroupId"
]
}
},
"ClusterEncryptionConfigKeyArn": {
"Value": {
"Fn::GetAtt": [
"Cluster9EE0221C",
"EncryptionConfigKeyArn"
]
}
},
"ClusterName": {
"Value": {
"Ref": "Cluster9EE0221C"
}
}
},
"Parameters": {
"AssetParameters01ec3fa8451b6541733a25ec9c0c13a2b7dcee848ddad2edf6cb9c1f40cbc896S3Bucket221B7FEE": {
"AssetParameters95d3377fefffa0934741552d39e46eef13de3a2094050df1057480e0344b402cS3Bucket7F8D74FE": {
"Type": "String",
"Description": "S3 bucket for asset \"01ec3fa8451b6541733a25ec9c0c13a2b7dcee848ddad2edf6cb9c1f40cbc896\""
"Description": "S3 bucket for asset \"95d3377fefffa0934741552d39e46eef13de3a2094050df1057480e0344b402c\""
},
"AssetParameters01ec3fa8451b6541733a25ec9c0c13a2b7dcee848ddad2edf6cb9c1f40cbc896S3VersionKeyA8C9A018": {
"AssetParameters95d3377fefffa0934741552d39e46eef13de3a2094050df1057480e0344b402cS3VersionKey1DF2734D": {
"Type": "String",
"Description": "S3 key for asset version \"01ec3fa8451b6541733a25ec9c0c13a2b7dcee848ddad2edf6cb9c1f40cbc896\""
"Description": "S3 key for asset version \"95d3377fefffa0934741552d39e46eef13de3a2094050df1057480e0344b402c\""
},
"AssetParameters01ec3fa8451b6541733a25ec9c0c13a2b7dcee848ddad2edf6cb9c1f40cbc896ArtifactHashED8C0EF9": {
"AssetParameters95d3377fefffa0934741552d39e46eef13de3a2094050df1057480e0344b402cArtifactHash38FFB16E": {
"Type": "String",
"Description": "Artifact hash for asset \"01ec3fa8451b6541733a25ec9c0c13a2b7dcee848ddad2edf6cb9c1f40cbc896\""
"Description": "Artifact hash for asset \"95d3377fefffa0934741552d39e46eef13de3a2094050df1057480e0344b402c\""
},
"AssetParameters5e49cf64d8027f48872790f80cdb76c5b836ecf9a70b71be1eb937a5c25a47c1S3Bucket663A709C": {
"Type": "String",
Expand Down Expand Up @@ -2774,17 +2791,17 @@
"Type": "String",
"Description": "Artifact hash for asset \"4c04b604b3ea48cf40394c3b4b898525a99ce5f981bc13ad94bf126997416319\""
},
"AssetParameters7c148fb102ee8790aaf67d5e2a2dce8f5d9b87285c8b7e91f984216ee66f1be6S3BucketB18DC500": {
"AssetParameters18f930a3a3efac8df646c455c3afda1a743c13805600915d02fd4f4be87443f5S3Bucket7B48152A": {
"Type": "String",
"Description": "S3 bucket for asset \"7c148fb102ee8790aaf67d5e2a2dce8f5d9b87285c8b7e91f984216ee66f1be6\""
"Description": "S3 bucket for asset \"18f930a3a3efac8df646c455c3afda1a743c13805600915d02fd4f4be87443f5\""
},
"AssetParameters7c148fb102ee8790aaf67d5e2a2dce8f5d9b87285c8b7e91f984216ee66f1be6S3VersionKeyBE7DFF7A": {
"AssetParameters18f930a3a3efac8df646c455c3afda1a743c13805600915d02fd4f4be87443f5S3VersionKey75927692": {
"Type": "String",
"Description": "S3 key for asset version \"7c148fb102ee8790aaf67d5e2a2dce8f5d9b87285c8b7e91f984216ee66f1be6\""
"Description": "S3 key for asset version \"18f930a3a3efac8df646c455c3afda1a743c13805600915d02fd4f4be87443f5\""
},
"AssetParameters7c148fb102ee8790aaf67d5e2a2dce8f5d9b87285c8b7e91f984216ee66f1be6ArtifactHash5F906FBC": {
"AssetParameters18f930a3a3efac8df646c455c3afda1a743c13805600915d02fd4f4be87443f5ArtifactHash3F4FE787": {
"Type": "String",
"Description": "Artifact hash for asset \"7c148fb102ee8790aaf67d5e2a2dce8f5d9b87285c8b7e91f984216ee66f1be6\""
"Description": "Artifact hash for asset \"18f930a3a3efac8df646c455c3afda1a743c13805600915d02fd4f4be87443f5\""
},
"AssetParameters36525a61abfaf5764fad460fd03c24215fd00da60805807d6138c51be4d03dbcS3Bucket2D824DEF": {
"Type": "String",
Expand Down
2 changes: 2 additions & 0 deletions packages/@aws-cdk/aws-eks/test/integ.eks-cluster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ class EksClusterStack extends TestStack {
new CfnOutput(this, 'ClusterEndpoint', { value: cluster.clusterEndpoint });
new CfnOutput(this, 'ClusterArn', { value: cluster.clusterArn });
new CfnOutput(this, 'ClusterCertificateAuthorityData', { value: cluster.clusterCertificateAuthorityData });
new CfnOutput(this, 'ClusterSecurityGroupId', { value: cluster.clusterSecurityGroupId });
new CfnOutput(this, 'ClusterEncryptionConfigKeyArn', { value: cluster.clusterEncryptionConfigKeyArn });
new CfnOutput(this, 'ClusterName', { value: cluster.clusterName });
}
}
Expand Down
Loading