Cloud VendorsAmazon Web ServicesServicesKey Management Services

Key Management Services

Summary

KMS is a free managed service that allows you to created, administer, and use encryption keys. In the AWS console KMS is found under IAM. However, on the aws-cli it is in fact its own service accessible at aws kms. It is important that you understand that KMS and IAM are very closely related and are found in many of AWS services.

KMS keys are one of those services that have their own resource based permissions. That means that in addition to having the access on the user level, the resource must also allow the user access. This is a bit tough to grasp as first but is essential that you do. Here is an article that describes this in more depth.

EBS Volumes

I’m going to start with a very simple example that is very important to clearly grasp. AWS EC2 has a notion of a Volume. When creating a volume you may choose to have AWS encrypt the volume for you.

kms encryption keys

As seen in the image above is a list of several KMS encryption keys. All but one are created and managed by AWS as defaults. Let’s look and the key with the alias aws/ebs. This key is created for the purpose of encrypting EBS volumes for EC2.

I want you to understand just how KMS, and IAM works especially sensible defaults. I already knew the key-id from the AWS console. A key may have multiple policy names. I need to find this key’s policy name to further investigate it.

aws kms list-key-policies --key-id xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx

The response will look something similar to this:

{
    "PolicyNames": [
        "default"
    ]
}

Now I can invoke the following command to view the key policy that the aws/ebs key has:

aws kms get-key-policy --key-id xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx --policy-name default

The output of this may look a little funky since it is returning the key policy as a string. Here is a JSON formatted version of the policy:

{
  "Version": "2012-10-17",
  "Id": "auto-ebs-2",
  "Statement": [
    {
      "Sid": "Allow access through EBS for all principals in the account that are authorized to use EBS",
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": [
        "kms:Encrypt",
        "kms:Decrypt",
        "kms:ReEncrypt*",
        "kms:GenerateDataKey*",
        "kms:CreateGrant",
        "kms:DescribeKey"
      ],
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "kms:ViaService": "ec2.us-east-1.amazonaws.com",
          "kms:CallerAccount": "xxxxxxxxxxxx"
        }
      }
    },
    {
      "Sid": "Allow direct access to key metadata to the account",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::xxxxxxxxxxxx:root"
      },
      "Action": [
        "kms:Describe*",
        "kms:Get*",
        "kms:List*",
        "kms:RevokeGrant"
      ],
      "Resource": "*"
    }
  ]
}

What you should see from this is that the AWS service ec2 in the us-east-1 region for my account is granted access to the listed 6 actions.

We also see that the root user on my account may only perform low level actions like viewing the key and describing it. In this case the root user does not have access to administer this key, or even encrypt or decrypt data on its behalf.

The only entity that can actually utilize the key is the EC2 service for this account and no others. This is the basis to how EC2 handles whole disk encryption. When the volume is attached to an instance EC2 will see that it is encrypted and requires access to the key that encrypted the volume. With EC2 the default key used for volume encryption is the aws/ebs key. This is created by default with your account.

Now let’s say I want to create an encryption key for production. I want to make sure if I create snapshots, or images with this data it is encrypted and the access is limited.

volume encryption

In the example depicted above I had already created a KMS key.

kms key summary I create my new KMS encryption key. When I create that key I am given the choice to decide who can administer the key. This means I can decide who or what may have administrator access to this key.

kms key administrators

Then you may decide who or what may actually use the key. You may also grant external accounts access.

kms key users

You may add tags and enforce key rotation as well.

kms key rotation

Now I want to show that even if you have a role that has admin rights it can still be prevented from accessing the production encrypted data. There is one small adjustment that needs to be made. If you read this article and compare the first and second policy. You will see that in the first policy the principal is the root user. In the second policy, the policy’s principal may be a user or a role.

The default (first policy) essentially disables the resource-based permissions for the key. Therefore as long as the user in question has permission to access the key they do not need to be listed explicitly. This is really quite fine and probably a reasonable default. In our case we want to limit access even to those administrators. To do that we modify our policy and change the principal to a specific role. Now when we try to create an EC2 instance that attempts to utilize the KMS key in question there will be an error. This applies to volumes, and snapshots.

It’s all about trust

This should illustrate just how IAM/KMS works and why trust matters. There are companies that do not trust KMS and choose to mount EBS volumes and handle the encryption and decryption themselves. Once you do this you might as well not trust any form of IAM at all. People get very scared about data encryption, but there is absolutely no difference here. If you trust IAM for starting and stopping servers, you should trust it for managing your keys. I assure you, its probably more reliable than whatever system you come up with.

With that being said if you want to use AWS’s new secrets manager is still based on KMS. Storing encryption keys in any AWS service will at some point in time rely on IAM roles. So unless you are going to require manual intervention or host the private keys on an on-site server you are going to be in a very difficult situation.

Encryption As A Service