AWS KMS Keys

If you need to secure your AWS Cloud account for various data content then you must know everything about AWS KMS keys.

In this tutorial we will learn everything we should know about AWS KMS keys and how to call these AWS KMS keys in IAM Policies.

Table of Content

  1. AWS KMS (Key Management Service)
  2. Symmetric Encryption KMS Keys
  3. Asymmetric KMS keys
  4. Data keys
  5. Custom key stores
  6. Key material
  7. Key policies in AWS KMS
  8. Default Key Policy
  9. Allowing user to access KMS keys with Key Policy
  10. Allowing Users and Roles to access KMS keys with Key Policy
  11. Access KMS Key by User in different account
  12. Creating KMS Keys
  13. What is Multi-region KMS Keys?
  14. Key Store and Custom Key Store
  15. How to Encrypt your AWS RDS using AWS KMS keys
  16. Encrypt AWS DB instance using AWS KMS keys
  17. Encrypting the AWS S3 bucket using AWS KMS Keys
  18. Applying Server-side Encryption on AWS S3 bucket
  19. Configure AWS S3 bucket to use S3 Bucket Key with Server Side E-KMS for new objects
  20. Client Side Encryption on AWS S3 Bucket
  21. Conclusion

AWS KMS (Key Management Service)

KMS is a managed service that makes it easy to create and control cryptographic key that protect your data by encrypting and decrypting. KMS uses Hardware security modules to protect and validate your keys.

KMS Keys contains a reference to the key material that is used when you perform cryptographic operations with the KMS key. Also, you cannot delete this key material; you must delete the KMS key. A KMS key contains metadata, such as the key ID, key spec, key usage, creation date, description, and key state. Key identifiers act like names for your KMS keys.

keyID: It acts like a name for example 1234abcd-12ab-34cd-56ef-1234567890a

Note: A cryptographic key is a string of bits used by a cryptographic algorithm to transform plain text into cipher text or vice versa. This key remains private and ensures secure communication.

  • The KMS keys that are created by us are customer managed keys. You have control over KMS policies, enable and disable, rotating key material, adding tags , creating alias. When you create an AWS KMS key, by default, you get a KMS key for symmetric encryption.
    • Symmetric encryption keys are used in symmetric encryption, where the same key is used for encryption and decryption.
    • An asymmetric KMS key represents a mathematically related public key and private key pair.
  • The KMS keys that are created automatically by AWS are AWS Managed keys. The aliases are represented as aws/redshift etc. All AWS’ managed keys are now rotated every 3 year
  • AWS owned keys are a collection of KMS keys that an AWS service owns and manages for use in multiple AWS accounts. Although AWS owned keys are not in your AWS account, an AWS service can use an AWS owned key to protect the resources in your account.
  • Alias: A user friendly name given to KMS key is an alias. For example: alias/ExampleAlias
  • custom key store is an AWS KMS resource backed by a key manager outside of AWS KMS that you own and manage
  • cryptographic operations are API operations that use KMS keys to protect data.
  • Key material is the string of bits used in a cryptographic algorithm.
  • Key policy determines who can manage the KMS keys and who can use it. The key policy that is attached to the KMS key. The key policy is always defined in the AWS account and Region that owns the KMS key.
  • All IAM policies that are attached to the IAM user or role making the request. IAM policies that govern a principal’s use of a KMS key are always defined in the principal’s AWS account.

Symmetric Encryption KMS Keys

When you create an AWS KMS key, by default, you get a KMS key for symmetric encryption. Symmetric key material never leaves AWS KMS unencrypted. To use a symmetric encryption KMS key, you must call AWS KMS. Symmetric encryption keys are used in symmetric encryption, where the same key is used for encryption and decryption.

AWS services that are integrated with AWS KMS use only symmetric encryption KMS keys to encrypt your data. These services do not support encryption with asymmetric KMS keys. 

You can use a symmetric encryption KMS key in AWS KMS to encrypt, decrypt, and re-encrypt data, and generate data keys and data key pairs.

When you create a request or raise a request then it happens as follows:

Requested Syntax:

{
   "EncryptionAlgorithm": "string",
   "EncryptionContext": {
      "string" : "string"
   },

   "GrantTokens": [ "string" ],
   "KeyId": "string",
   "Plaintext": blob
}
Response Syntax

{
   "CiphertextBlob": blob,
   "EncryptionAlgorithm": "string",
   "KeyId": "string"
}

Asymmetric KMS keys

You can create asymmetric KMS keys in AWS KMS. An asymmetric KMS key represents a mathematically related public key and private key pair. The private key never leaves AWS KMS unencrypted.

Data keys

Data keys are symmetric keys you can use to encrypt data, including large amounts of data and other data encryption keys. Unlike symmetric KMS keys, which can’t be downloaded, data keys are returned to you for use outside of AWS KMS.

Custom key stores

custom key store is an AWS KMS resource backed by a key manager outside of AWS KMS that you own and manage. When you use a KMS key in a custom key store for a cryptographic operation

Key material

Key material is the string of bits used in a cryptographic algorithm. Secret key material must be kept secret to protect the cryptographic operations that use it. Public key material is designed to be shared. You can use key material that AWS KMS generates, key material that is generated in the AWS CloudHSM cluster of a custom key store, or import your own key material.

Key policies in AWS KMS

A key policy is a resource policy for an AWS KMS key. Key policies are the primary way to control access to KMS keys. Every KMS key must have exactly one key policy. The statements in the key policy determine who has permission to use the KMS key and how they can use it. You can also use IAM policies and grants to control access to the KMS key, but every KMS key must have a key policy.

Unless the key policy explicitly allows it, you cannot use IAM policies to allow access to a KMS key. Without permission from the key policy, IAM policies that allow permissions have no effect. Unlike IAM policies, which are global, key policies are Regional

Default Key Policy

As soon as you create the KMS keys, the default key policy is also created which gives the AWS account that owns the KMS key full access to the KMS key. It also allows the account to use IAM policies to allow access to the KMS key, in addition to the key policy.

{
  "Sid": "Enable IAM policies",
  "Effect": "Allow",
  "Principal": {
    "AWS": "arn:aws:iam::111122223333:root"
   },
  "Action": "kms:*",
  "Resource": "*"
}

Allowing user to access KMS keys with Key Policy

You can create and manage key policies in AWS KMS console, by using KMS API Operations. First you need to allow users, role or admins in Key policy to use KMS keys. As shown the below key policy allows Alice user in Account(111122223333) to use KMS key

Note: to access KMS you need to create separate IAM policies.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Describe the policy statement",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::111122223333:user/Alice"
      },
      "Action": "kms:DescribeKey",
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "kms:KeySpec": "SYMMETRIC_DEFAULT"
        }
      }
    }
  ]
}

Allowing Users and Roles to access KMS keys with Key Policy

First you need to allow users, role or admins in Key policy to use KMS keys. For users to access KMS you need to create separate IAM policies. For example in the below policy allows Account(111122223333) and myRole in Account(111122223333) to use KMS keys.

{
    "Id": "key-consolepolicy",
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Enable IAM User Permissions",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::111122223333:root"
            },
            "Action": "kms:*",
            "Resource": "*"
        },
        {
            "Sid": "Allow access for Key Administrators",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::111122223333:role/myRole"
            },
            "Action": [
                "kms:Create*",
                "kms:Describe*",
                "kms:Enable*",
                "kms:List*",
                "kms:Put*",
                "kms:Update*",
                "kms:Revoke*",
                "kms:Disable*",
                "kms:Get*",
                "kms:Delete*",
                "kms:TagResource",
                "kms:UntagResource",
                "kms:ScheduleKeyDeletion",
                "kms:CancelKeyDeletion"
            ],
            "Resource": "*"
        },
        {
            "Sid": "Allow use of the key",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::111122223333:role/myRole"
            },
            "Action": [
                "kms:Encrypt",
                "kms:Decrypt",
                "kms:ReEncrypt*",
                "kms:GenerateDataKey*",
                "kms:DescribeKey"
            ],
            "Resource": "*"
        },
        {
            "Sid": "Allow attachment of persistent resources",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::111122223333:role/myRole"
            },
            "Action": [
                "kms:CreateGrant",
                "kms:ListGrants",
                "kms:RevokeGrant"
            ],
            "Resource": "*",
            "Condition": {
                "Bool": {
                    "kms:GrantIsForAWSResource": "true"
                }
            }
        }
    ]
}

Access KMS Key by User in different account

In this section we will go through an example where AWS KMS key is present in Account 2 and user from Account 1 named Bob needs to access it. [Access KMS Key in Account 2 by User bob in Account 1]

  • User bob needs to assume role (engineering) in Account 1.
{
    "Role": {
        "Arn": "arn:aws:iam::111122223333:role/Engineering",
        "CreateDate": "2019-05-16T00:09:25Z",
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": {
                "Principal": {
                    "AWS": "arn:aws:iam::111122223333:user/bob"
                },
                "Effect": "Allow",
                "Action": "sts:AssumeRole"
            }
        },
        "Path": "/",
        "RoleName": "Engineering",
        "RoleId": "AROA4KJY2TU23Y7NK62MV"
    }
}
  • Attach IAM Policy to IAM Role  (engineering) in Account 1. The Policy contains allows anyone to access KMS key in another account. 
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "kms:Encrypt",
                "kms:Decrypt",
                "kms:ReEncryptFrom",
                "kms:ReEncryptTo",
                "kms:GenerateDataKey",
                "kms:GenerateDataKeyWithoutPlaintext",
                "kms:DescribeKey"
            ],
            "Resource": [
                "arn:aws:kms:us-west-2:444455556666:key/1234abcd-12ab-34cd-56ef-1234567890ab"
            ]
        }
    ]
}
  • Now, In Account 2 create KMS key policy that allows everyone to access from Account 1
{
    "Id": "key-policy-acct-2",
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Permission to use IAM policies",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::444455556666:root"
            },
            "Action": "kms:*",
            "Resource": "*"
        },
        {
            "Sid": "Allow account 1 to use this KMS key",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::111122223333:root"
            },
            "Action": [
                "kms:Encrypt",
                "kms:Decrypt",
                "kms:ReEncryptFrom",
                "kms:ReEncryptTo",
                "kms:GenerateDataKey",
                "kms:GenerateDataKeyWithoutPlaintext",
                "kms:DescribeKey"
            ],
            "Resource": "*"
        }
    ]
}

Creating KMS Keys

You can create the KMS Keys either in single region or multi region. By default the AWS KMS creates the key material. You need below permissions to create the KMS keys.

kms:CreateKey
kms:CreateAlias
kms:TagResource
iam:CreateServiceLinkedRole 
  • Navigate to AWS KMS service in AWS Management console.
  • Add Alias to the key and Description of the AWS Key that you created.
  • Next, add the permissions to the key and review the Key before creation.

What is Multi-region KMS Keys?

AWS KMS supports multi-Region keys, which are AWS KMS keys in different AWS Regions that can be used interchangeably – as though you had the same key in multiple Regions. Each set of related multi-Region keys has the same key material and key ID, so you can encrypt data in one AWS Region and decrypt it in a different AWS Region without re-encrypting or making a cross-Region call to AWS KMS.

  • You begin by creating a symmetric or asymmetric multi-Region primary key in an AWS Region that AWS KMS supports, such as US East (N. Virginia)
  • You set a key policy for the multi-Region key, and you can create grants, and add aliases and tags for categorization and authorization.
  • When you do, AWS KMS creates a replica key in the specified Region with the same key ID and other shared properties as the primary key. Then it securely transports the key material across the Region boundary and associates it with the new KMS key in the destination Region, all within AWS KMS

Key Store and Custom Key Store

key store is a secure location for storing cryptographic keys.  The default key store in AWS KMS also supports methods for generating and managing the keys that its stores.

By default, the cryptographic key material for the AWS KMS keys that you create in AWS KMS is generated in and protected by hardware security modules (HSMs). However, if you require even more control of the HSMs, you can create a custom key store.

custom key store is a logical key store within AWS KMS that is backed by a key manager outside of AWS KMS that you own and manage.

AWS KMS – Keys – Default Key store (IN AWS KMS) – HSM

AWS KMS – Keys – Custom Key Store (OUTSIDE AWS KMS) – Key Manager Manages it

There are two Custom Key Stores:

  • An AWS CloudHSM key store is an AWS KMS custom key store backed by an AWS CloudHSM cluster. You create and manage your custom key stores in AWS KMS and create and manage your HSM clusters in AWS CloudHSM.
  • An external key store is an AWS KMS custom key store backed by an external key manager outside of AWS that you own and control

How to Encrypt your AWS RDS using AWS KMS keys

Amazon RDS supports only symmetric KMS keys. You cannot use an asymmetric KMS key to encrypt data in an Amazon RDS database.

When you use KMS in RDS EBS or DB instances the service specifies encryption context. The encryption context is additional authenticated data ( AAD) and same encryption context is used to decrypt the data. Encryption context is also written to your CloudTrail logs.

At minimum, Amazon RDS always uses the DB instance ID for the encryption context, as in the following JSON-formatted example:

{ "aws:rds:db-id": "db-CQYSMDPBRZ7BPMH7Y3RTDG5QY" }

Encrypt AWS DB instance using AWS KMS keys

  • To encrypt a new DB instance, choose Enable encryption on the Amazon RDS console.
  • When you create an encrypted DB instance, you can choose a customer managed key or the AWS managed key for Amazon RDS to encrypt your DB instance.
  • If you don’t specify the key identifier for a customer managed key, Amazon RDS uses the AWS managed key for your new DB instance

Amazon RDS builds on Amazon Elastic Block Store (Amazon EBS) encryption to provide full disk encryption for database volumes.

When you create an encrypted Amazon EBS volume, you specify an AWS KMS key. By default, Amazon EBS uses the AWS managed key for Amazon EBS in your account (aws/ebs). However, you can specify a customer managed key that you create and manage.

For each volume, Amazon EBS asks AWS KMS to generate a unique data key encrypted under the KMS key that you specify. Amazon EBS stores the encrypted data key with the volume.

Similar to DB instances Amazon EBS uses an encryption context with a name-value pair that identifies the volume or snapshot in the request. 

Encrypting the AWS S3 bucket using AWS KMS Keys

Amazon S3 integrates with AWS Key Management Service (AWS KMS) to provide server-side encryption of Amazon S3 objects. Amazon S3 now applies server-side encryption with Amazon S3 managed keys (SSE-S3) as the base level of encryption for every bucket in Amazon S3.

Amazon S3 uses server-side encryption with AWS KMS (SSE-KMS) to encrypt your S3 object data.

When you configure your bucket to use an S3 Bucket Key for SSE-KMS, AWS generates a short-lived bucket-level key from AWS KMS then temporarily keeps it in S3

Applying Server-side Encryption on AWS S3 bucket

To apply server side encryption on AWS S3 bucket you need to create a AWS S3 policy and then apply bucket policy as shown below.

{
   "Version":"2012-10-17",
   "Id":"PutObjectPolicy",
   "Statement":[{
         "Sid":"DenyUnEncryptedObjectUploads",
         "Effect":"Deny",
         "Principal":"*",
         "Action":"s3:PutObject",
         "Resource":"arn:aws:s3:::DOC-EXAMPLE-BUCKET1/*",
         "Condition":{
            "StringNotEquals":{
               "s3:x-amz-server-side-encryption":"aws:kms"
            }
         }
      }
   ]
}

Configure AWS S3 bucket to use S3 Bucket Key with Server Side E-KMS for new objects

To enable an S3 Bucket Key when you create a new bucket follow the below steps.

  1. Sign in to the AWS Management Console and open the Amazon S3 console at https://console.aws.amazon.com/s3/.
  2. Choose Create bucket.
  3. Enter your bucket name, and choose your AWS Region.
  4. Under Default encryption, choose Enable.
  5. Under Encryption type, choose AWS Key Management Service key (SSE-KMS).
  6. Choose an AWS KMS key:
    1. Choose AWS managed key (aws/s3).
    1. Choose Customer managed key, and choose a symmetric encryption customer managed key in the same Region as your bucket.
  7. Under Bucket Key, choose Enable.
  8. Choose Create bucket.

Amazon S3 creates your bucket with an S3 Bucket Key enabled. New objects that you upload to the bucket will use an S3 Bucket Key. To disable an S3 Bucket Key, follow the previous steps, and choose disable.

Client Side Encryption on AWS S3 Bucket

Client-side encryption is the act of encrypting your data locally to ensure its security as it passes to the Amazon S3 service. The Amazon S3 service receives your encrypted data; it does not play a role in encrypting or decrypting it. For example, if you need to use KMS keys in Java application then use the below code.

AWSKMS kmsClient = AWSKMSClientBuilder.standard()
                .withRegion(Regions.DEFAULT_REGION)
                .build();

        // create KMS key for for testing this example
        CreateKeyRequest createKeyRequest = new CreateKeyRequest();
        CreateKeyResult createKeyResult = kmsClient.createKey(createKeyRequest);

// --
        // specify an AWS KMS key ID
        String keyId = createKeyResult.getKeyMetadata().getKeyId();

        String s3ObjectKey = "EncryptedContent1.txt";
        String s3ObjectContent = "This is the 1st content to encrypt";
// --

        AmazonS3EncryptionV2 s3Encryption = AmazonS3EncryptionClientV2Builder.standard()
                .withRegion(Regions.US_WEST_2)
                .withCryptoConfiguration(new CryptoConfigurationV2().withCryptoMode(CryptoMode.StrictAuthenticatedEncryption))
                .withEncryptionMaterialsProvider(new KMSEncryptionMaterialsProvider(keyId))
                .build();

        s3Encryption.putObject(bucket_name, s3ObjectKey, s3ObjectContent);
        System.out.println(s3Encryption.getObjectAsString(bucket_name, s3ObjectKey));

        // schedule deletion of KMS key generated for testing
        ScheduleKeyDeletionRequest scheduleKeyDeletionRequest =
                new ScheduleKeyDeletionRequest().withKeyId(keyId).withPendingWindowInDays(7);
        kmsClient.scheduleKeyDeletion(scheduleKeyDeletionRequest);

        s3Encryption.shutdown();
        kmsClient.shutdown();

Conclusion

In this article we learnt what is AWS KMS (Key Management Service) , key policy and IAM policies to access the KMS keys by users or roles in AWS cloud.

Advertisement