sydraz
sydraz

Reputation: 653

AWS Java SDK: Specifying KMS Key Id For EBS

In the AWS Java SDK 1.10.69, I can launch an instance and specify EBS volume mappings for the instance:

    RunInstancesRequest runInstancesRequest = new RunInstancesRequest();

    String userDataString = Base64.encodeBase64String(userData.toString().getBytes());

    runInstancesRequest
            .withImageId(machineImageId)
            .withInstanceType(instanceType.toString())
            .withMinCount(minCount)
            .withMaxCount(maxCount)
            .withKeyName(sshKeyName)
            .withSecurityGroupIds(securityGroupIds)
            .withSubnetId(subnetId)
            .withUserData(userDataString)
            .setEbsOptimized(true);


    final EbsBlockDevice ebsBlockDevice = new EbsBlockDevice();
    ebsBlockDevice.setDeleteOnTermination(true);
    ebsBlockDevice.setVolumeType(VolumeType.Gp2);
    ebsBlockDevice.setVolumeSize(256);
    ebsBlockDevice.setEncrypted(true);

    final BlockDeviceMapping mapping = new BlockDeviceMapping();
    mapping.setDeviceName("/dev/sdb");
    mapping.setEbs(ebsBlockDevice);

It seems that currently I can only enable / disable encryption on the volume, and not specify which KMS Customer Master Key to use for the volume.

Is there a way around this?

Upvotes: 3

Views: 613

Answers (2)

Dan Walker
Dan Walker

Reputation: 21

Edit: See my other answer below (https://stackoverflow.com/a/47602790/7692970) for the much easier solution now available

To specify a Customer Master Key (CMK) for an EBS volume for an instance, you have to combine the RunInstancesRequest with a CreateVolumeRequest and an AttachVolumeRequest. Otherwise, if you just specify true for encryption on the EbsBlockDevice it will use the default CMK.

First create the instance(s), without specifying the EBS volumes in the block device mapping of the RunInstancesRequest, then separately create the volumes, then attach them.

CreateVolumeRequest has withKmsKeyId()/setKmsKeyId() options.

For example, updating your code might look like:

RunInstancesRequest runInstancesRequest = new RunInstancesRequest();

String userDataString = Base64.encodeBase64String(userData.toString().getBytes());

runInstancesRequest
        .withImageId(machineImageId)
        .withInstanceType(instanceType.toString())
        .withMinCount(minCount)
        .withMaxCount(maxCount)
        .withKeyName(sshKeyName)
        .withSecurityGroupIds(securityGroupIds)
        .withSubnetId(subnetId)
        .withUserData(userDataString)
        .setEbsOptimized(true);
RunInstancesResult runInstancesResult = ec2Client.runInstances(runInstancesRequest);

for (Instance instance : runInstancesResult.getReservation()) {
    CreateVolumeRequest volumeRequest = new CreateVolumeRequest()
            .withAvailabilityZone(instance.getPlacement().getAvailabilityZone())
            .withKmsKeyId(/* CMK id or alias/yourkeyaliashere */)
            .withEncrypted(true)
            .withSize(256)
            .withVolumeType(VolumeType.Gp2);
    CreateVolumeResult volumeResult = ec2Client.createVolume(volumeRequest);
    AttachVolumeRequest attachRequest = new AttachVolumeRequest()
            .withDevice("/dev/sdb")
            .withInstanceId(instance.getInstanceId())
            .withVolumeId(volumeResult.getVolume().getVolumeId());
    ec2Client.attachVolume(attachRequest);
}

Note: If you make use of the block device mapping in instance metadata, it does not get updated when you attach a volume to a running instance. To bring it up to date, you can stop/start the instance.

Upvotes: 2

Dan Walker
Dan Walker

Reputation: 21

Good news! AWS has just added the ability to specify CMK key ids in the block device mapping when launching instances.

https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/ec2/model/EbsBlockDevice.html#setKmsKeyId-java.lang.String-

This was added to the AWS Java SDK in version 1.11.237.

Therefore in your original code you now just add

ebsBlockDevice.setKmsKeyId(keyId);

where keyId can be a CMK alias (in the form alias/<alias name>), key id (looks like 1234abcd-12ab-34cd-56ef-1234567890ab) or full CMK ARN (arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab).

Upvotes: 0

Related Questions