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(ec2): Volume construct #8219

Merged
merged 7 commits into from Jun 26, 2020
Merged

feat(ec2): Volume construct #8219

merged 7 commits into from Jun 26, 2020

Conversation

ddneilson
Copy link
Contributor

@ddneilson ddneilson commented May 27, 2020

This adds an L2 construct for AWS::EC2:Volume that supports encryption with a customer-owned KMS key, or service-owned key. It provides methods for importing an existing Volume to the stack, and for granting AttachVolume and DetachVolume to a role.


Resolves #8218

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

@ddneilson
Copy link
Contributor Author

Testing

Aside from a pile of unit tests, I also deployed the following and used the AWS CLI to attach/detach the volume. With the Volume attached, I also mounted it, formatted, and wrote/read data to/from it to ensure that the instance could write/read the Volume.

import * as cdk from '@aws-cdk/core';
import * as kms from '@aws-cdk/aws-kms';
import * as ec2 from '@aws-cdk/aws-ec2';
import { EbsDeviceVolumeType } from '@aws-cdk/aws-ec2';

const app = new cdk.App();

const env = {
    account: process.env.CDK_DEFAULT_ACCOUNT,
    region: process.env.CDK_DEFAULT_REGION
}

const network = new cdk.Stack(app, 'CDKTestNetwork', { env });
const vpc = new ec2.Vpc(network, 'Vpc');
const key = new kms.Key(network, 'Key', {
    removalPolicy: cdk.RemovalPolicy.DESTROY,
});

const testing = new cdk.Stack(app, 'CDKTestTest', { env });
const instance = new ec2.BastionHostLinux(testing, 'MountInstance', {
    vpc,
    instanceType: new ec2.InstanceType('t3.small'),
    subnetSelection: {
        subnetType: ec2.SubnetType.PRIVATE,
    },
});
const bastion = new ec2.BastionHostLinux(testing, 'Bastion', {
    vpc,
    instanceType: new ec2.InstanceType('t3.small'),
    subnetSelection: {
        subnetType: ec2.SubnetType.PRIVATE,
    },
});

const volume1 = new ec2.Volume(testing, 'Volume', {
    availabilityZone: `${env.region}a`,
    sizeGiB: 8,
    encrypted: true,
    encryptionKey: key,
    autoEnableIo: true,
    volumeType: EbsDeviceVolumeType.GENERAL_PURPOSE_SSD,
})
volume1.grantAttachVolume(bastion, instance);
volume1.grantDetachVolume(bastion, instance);

app.synth();

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: ba3f1d8
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: 5c26dd8
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@ddneilson
Copy link
Contributor Author

@rix0rrr This is ready & waiting for your feedback.

rix0rrr
rix0rrr previously requested changes Jun 5, 2020
packages/@aws-cdk/aws-ec2/lib/volume.ts Outdated Show resolved Hide resolved
public abstract readonly encryptionKey?: IKey;

public grantAttachVolume(grantee: IGrantable, instance?: IInstance): Grant {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is IGrantable here ever expected to be anything other than an instance role?

In fact, is this ever anything other than an instance you would want to grant this to?

Also, in what cases would you want to grant attach separately from detach?

Copy link
Contributor Author

@ddneilson ddneilson Jun 5, 2020

Choose a reason for hiding this comment

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

Lack of imagination on my part seems safer to assume that there may be use-cases outside of an instance wanting to do the attach/detach. For instance, maybe there's a reason to have a lambda that's driving some external logic around moving/sharing an EBS volume between instances.

edit: Along that line of thought... maybe the instance arg should be an array of instances...

Also, in what cases would you want to grant attach separately from detach?

Yeah, one of the uses that I have for this is exactly that case. It's an ASG instance that will re-attach an EBS volume if it's replaced by the ASG, but never needs to detach it. The detachment happens automatically when the instance is terminated.

packages/@aws-cdk/aws-ec2/README.md Outdated Show resolved Hide resolved
packages/@aws-cdk/aws-ec2/lib/volume.ts Outdated Show resolved Hide resolved
@mergify mergify bot dismissed rix0rrr’s stale review June 6, 2020 21:25

Pull request has been modified.

@ddneilson
Copy link
Contributor Author

@rix0rrr All set for another round of review.

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: fb2fd78
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@ddneilson
Copy link
Contributor Author

@rix0rrr This is now ready for, hopefully, final review. I've sorted out the IAM permissions for the KMS key used for encryption. Access to the EBS volume & the KMS key is now properly separated -- you cannot attach the volume without access to the KMS key.

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: f5b045c
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: f741667
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository


The following is a sample skeleton of a script that can be used to attach a Volume to the Linux instance that it is running on:

```bash
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you turn this example into an instance.userData.addCommand()-style example?

People would benefit from the automatic interpolation of EBS_VOL_ID, for example.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

packages/@aws-cdk/aws-ec2/README.md Outdated Show resolved Hide resolved
This changes the permissions appended to the KMS key policy such they
are as minimal as possible. Permissions are split between a grant when
creating the volume -- a grant that allows the Volume to be created --
and a grant when allowing attachment of the Volume.

This properly restricts use of the CMK-encrypted volume to only those
users that have access to both the EBS volume and, separately, the CMK
used for encryption.
@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: 7b7522d
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

* Defaults to a hash calculated from this volume.
*/
grantAttachVolumeToSelf(instance: Instance, tagKeySuffix?: string): Grant;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm thinking that I should change this, and similarly the corresponding grantDetachVolumeFromSelf(), to grantAttachVolumeByTag(grantee: IGrantable, constructs: Construct[], tagKeySuffix?: string): Grant

Reason being that there are other instance-sources that this will not cover as it's implemented -- ASGs, EC2-Fleets, and SpotFleetRequests to name a few.

Implementation would be, essentially, the same except that the tag value would be applied to all given constructs.

Comment on lines 508 to 509
Tag.add(instance, tagKey, tagValue);
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you explain in a comment why the tag needs to be applied on this? That one surpised me.

For the other, don't forget to set { appliesToLaunchedInstances: true } (or whatever the option is), otherwise this still won't work for ASGs.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can you explain in a comment why the tag needs to be applied on this? That one surpised me.

Sure. It's a resource tag. So, all resources involved in the call must have the tag.

For the other, don't forget to set { appliesToLaunchedInstances: true } (or whatever the option is), otherwise this still won't work for ASGs.

Fortunately, it's true by default: https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_core.TagProps.html#applytolaunchedinstances

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: 47412bb
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: 2da39bf
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@rix0rrr rix0rrr changed the title feat(ec2): Adds an L2 construct for AWS::EC2::Volume feat(ec2): Volume construct Jun 26, 2020
@mergify
Copy link
Contributor

mergify bot commented Jun 26, 2020

Thank you for contributing! Your pull request will be updated from master and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork).

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: 17128cf
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@mergify
Copy link
Contributor

mergify bot commented Jun 26, 2020

Thank you for contributing! Your pull request will be updated from master and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork).

@mergify mergify bot merged commit 7490dee into aws:master Jun 26, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add an L2 construct for AWS::EC2::Volume
3 participants