Use the Conformity Knowledge Base AI to help improve your Cloud Posture

Enable Encryption at Rest with Amazon KMS Keys

Trend Cloud One™ – Conformity is a continuous assurance tool that provides peace of mind for your cloud infrastructure, delivering over 1000 automated best practice checks.

Risk Level: High (should be achieved)
Rule ID: DynamoDB-004

Ensure that user data stored within Amazon DynamoDB tables is encrypted at rest using Amazon Key Management Service (KMS). Encryption at rest integrates with Amazon KMS for managing the encryption keys that are used to encrypt your tables. To have a more granular control over your data encryption and decryption process, ensure that your tables are configured to use the AWS-managed KMS key (i.e. **aws/dynamodb**) or your own KMS Customer Managed Key (CMK). To comply with rigorous regulatory standards, the AWS-owned key (default key) should not be used for encryption at rest in Amazon DynamoDB.

This rule can help you with the following compliance standards:

  • GDPR
  • APRA
  • NIST4

For further details on compliance standards supported by Conformity, see here.

This rule can help you work with the AWS Well-Architected Framework.

This rule resolution is part of the Conformity Security & Compliance tool for AWS.

Security

Encryption at rest in DynamoDB enhances security by encrypting your data using keys stored and managed with Amazon Key Management Service (KMS). Organizational policies, industry or government regulations, and internal compliance requirements often require the use of Amazon KMS keys for encryption of data at rest. Encryption with Amazon KMS simplifies the task of safeguarding sensitive data, reducing operational burden and complexity. By implementing encryption at rest with Amazon KMS keys, you can develop applications with robust security measures that comply with strict encryption standards and regulatory requirements.


Audit

To determine the encryption type configured for your Amazon DynamoDB tables, perform the following actions:

Using AWS Console

01 Sign in to the AWS Management Console.

02 Navigate to Amazon DynamoDB console available at https://console.aws.amazon.com/dynamodbv2/.

03 In the main navigation panel, under Dashboard, choose Tables.

04 Click on the name (link) of the Amazon DynamoDB table that you want to examine.

05 Select the Additional settings tab to access the additional configuration settings available for the selected table.

06 In the Encryption section, check the Key management attribute value. If the Key management value is set to Managed by DynamoDB, the data on the selected Amazon DynamoDB table is encrypted at rest using the AWS-owned key. This key is owned by DynamoDB and is used by default when a KMS key is not specified.

07 Repeat steps no. 4 – 6 for each Amazon DynamoDB table provisioned within the current AWS region.

08 Change the AWS cloud region from the navigation bar and repeat the Audit process for other regions.

Using AWS CLI

01 Run list-tables command (OSX/Linux/UNIX) with custom query filters to list the name of each Amazon DynamoDB table created in the selected AWS cloud region:

aws dynamodb list-tables
  --region us-east-1
  --output table
  --query 'TableNames'

02 The command output should return a table with the requested table name(s):

--------------------------
|       ListTables       |
+------------------------+
|  cc-product-reviews    |
|  cc-product-inventory  |
+------------------------+

03 Run describe-table command (OSX/Linux/UNIX) using the name of the Amazon DynamoDB table that you want to examine as the identifier parameter and custom query filters to describe the encryption type configured for the selected table:

aws dynamodb describe-table 
  --region us-east-1 
  --table-name cc-product-reviews 
  --query 'Table.SSEDescription.SSEType'

04 The command output should return "KMS" when the encryption type is KMS-based and is using Amazon KMS keys or null when the encryption type is DynamoDB-based (default encryption type) and is using the AWS-owned key:

null

If the describe-table command output returns null, as shown in the output example above, the data on the selected Amazon DynamoDB table is encrypted at rest using the AWS-owned key (i.e. default encryption type).

05 Repeat steps no. 3 and 4 for each DynamoDB table available in the selected AWS region.

06 Change the AWS cloud region by updating the --region command parameter value and repeat the Audit process for other regions.

Remediation / Resolution

To ensure that user data stored in your Amazon DynamoDB tables is encrypted at rest using Amazon Key Management Service (KMS), perform the following actions:

Using AWS CloudFormation

01 CloudFormation template (JSON):

{
	"AWSTemplateFormatVersion": "2010-09-09",
	"Description": "Enable Encryption at Rest using Amazon KMS Keys",
	"Resources": {
		"AWSDynamoDBTable" : {
			"Type" : "AWS::DynamoDB::Table",
			"Properties" : {
			"TableName" : "cc-game-scores",
			"BillingMode" : "PROVISIONED",
			"SSESpecification" : {
				"SSEEnabled" : true,
				"SSEType" : "KMS",
				"KMSMasterKeyId" : "arn:aws:kms:us-east-1:123456789012:key/abcd1234-abcd-1234-abcd-1234abcd1234"
			},
			"AttributeDefinitions" : [
				{
					"AttributeName" : "UserId",
					"AttributeType" : "S"   
				},
				{
					"AttributeName" : "GameTitle",
					"AttributeType" : "S"
				},
				{
					"AttributeName" : "TopScore",
					"AttributeType" : "N"
				}
			],
			"KeySchema" : [
				{
					"AttributeName" : "UserId",
					"KeyType" : "HASH"
				},
				{
					"AttributeName" : "GameTitle",
					"KeyType" : "RANGE"
				}
			],
			"ProvisionedThroughput" : {
				"ReadCapacityUnits" : "5",
				"WriteCapacityUnits" : "5"
			},
			"GlobalSecondaryIndexes" : [{
				"IndexName" : "GameTitleIndex",
				"KeySchema" : [
					{
						"AttributeName" : "GameTitle",
						"KeyType" : "HASH"
					},
					{
						"AttributeName" : "TopScore",
						"KeyType" : "RANGE"
					}
				],
				"Projection" : {
					"NonKeyAttributes" : ["Album","UserId"],
					"ProjectionType" : "INCLUDE"
				},
				"ProvisionedThroughput" : {
					"ReadCapacityUnits" : "5",
					"WriteCapacityUnits" : "5"
				}
			}]
			}
		}
	}
}

02 CloudFormation template (YAML):

AWSTemplateFormatVersion: '2010-09-09'
	Description: Enable Encryption at Rest using Amazon KMS Keys
	Resources:
		AWSDynamoDBTable:
		Type: AWS::DynamoDB::Table
		Properties:
			TableName: cc-game-scores
			BillingMode: PROVISIONED
			SSESpecification:
			SSEEnabled: true
			SSEType: KMS
			KMSMasterKeyId: arn:aws:kms:us-east-1:123456789012:key/abcd1234-abcd-1234-abcd-1234abcd1234
			AttributeDefinitions:
			- AttributeName: UserId
				AttributeType: S
			- AttributeName: GameTitle
				AttributeType: S
			- AttributeName: TopScore
				AttributeType: N
			KeySchema:
			- AttributeName: UserId
				KeyType: HASH
			- AttributeName: GameTitle
				KeyType: RANGE
			ProvisionedThroughput:
			ReadCapacityUnits: '5'
			WriteCapacityUnits: '5'
			GlobalSecondaryIndexes:
			- IndexName: GameTitleIndex
				KeySchema:
				- AttributeName: GameTitle
					KeyType: HASH
				- AttributeName: TopScore
					KeyType: RANGE
				Projection:
				NonKeyAttributes:
					- Album
					- UserId
				ProjectionType: INCLUDE
				ProvisionedThroughput:
				ReadCapacityUnits: '5'
				WriteCapacityUnits: '5'

Using Terraform (AWS Provider)

01 Terraform configuration file (.tf):

terraform {
	required_providers {
		aws = {
			source  = "hashicorp/aws"
			version = "~> 4.0"
		}
	}

	required_version = ">= 0.14.9"
}

provider "aws" {
	region  = "us-east-1"
}

resource "aws_dynamodb_table" "aws-dynamodb-table" {

	name           = "cc-game-scores"
	billing_mode   = "PROVISIONED"
	read_capacity  = 5
	write_capacity = 5
	hash_key       = "UserId"
	range_key      = "GameTitle"

	attribute {
		name = "UserId"
		type = "S"
	}

	attribute {
		name = "GameTitle"
		type = "S"
	}

	attribute {
		name = "TopScore"
		type = "N"
	}

	global_secondary_index {
		name               = "GameTitleIndex"
		hash_key           = "GameTitle"
		range_key          = "TopScore"
		write_capacity     = 5
		read_capacity      = 5
		projection_type    = "INCLUDE"
		non_key_attributes = ["UserId"]
	}

	# Enable Encryption at Rest using Amazon KMS Keys
	server_side_encryption {
		enabled     = true
		kms_key_arn = "arn:aws:kms:us-east-1:123456789012:key/abcd1234-abcd-1234-abcd-1234abcd1234"
	}

}

Using AWS Console

01 Sign in to the AWS Management Console.

02 Navigate to Amazon KMS console available at https://console.aws.amazon.com/kms/.

03 In the main navigation panel, under Key Management Service (KMS), select Customer managed keys.

04 Choose the Create Key button from the console top menu to initiate the key setup process.

05 For Step 1 Configure key, perform the following operations:

  1. Choose Symmetric from the Key type section. A symmetric key is a single encryption key that can be used for both encrypt and decrypt operations.
  2. Choose Encrypt and decrypt from the Key usage section. You can use this key only to encrypt and decrypt data.
  3. Under Advanced options, for Key material origin, select KMS - recommended as the source of the key material within the key.
  4. Under Advanced options, for Regionality, select whether to allow the new key to be replicated into other AWS regions.
  5. Choose Next to continue the setup process.

06 For Step 2 Add labels, type a unique name (alias) for your new master key in the Alias box and provide a short description for the key in Description – optionalbox. (Optional) Use the Add tag button to create tags in order to categorize and identify your new key. Choose Next to continue.

07 For Step 3 Define key administrative permissions, choose which IAM users and/or roles can administer your new Customer Managed Key (CMK) from the Key administrators section. You may need to add additional permissions for the users or roles to administer the key from the AWS console. For Key deletion, select Allow key administrators to delete this key. Choose Nextto continue.

08 For Step 4 Define key usage permissions, in the Key users section, select which IAM users and/or roles can use the new CMK for cryptographic operations. (Optional) In the Other AWS accounts section, choose Add another AWS account and enter an external AWS account ID in order to specify the external AWS account that can use the new key to encrypt and decrypt your DynamoDB data. The owners of the external AWS accounts must also provide access to this CMK by creating appropriate policies for their IAM users. Choose Next to continue.

09 For Step 5 Review, review the policy available in the Key policy section, then choose Finish to create your new Amazon KMS Customer Managed Key (CMK). Once the key is successfully created, the Amazon KMS console will display the following confirmation message: Success. Your AWS KMS key was created with alias [key-alias] and key ID [key-id]..

10 Navigate to Amazon DynamoDB console available at https://console.aws.amazon.com/dynamodbv2/.

11 In the main navigation panel, under Dashboard, choose Tables.

12 Click on the name (link) of the Amazon DynamoDB table that you want to configure.

13 Select the Additional settings tab to access the additional configuration settings available for the selected table.

14 In the Encryption section, choose Manage encryption to change the configuration settings available for encryption at rest.

15 Choose one of the following options from the Encryption at rest section:

  1. Select AWS managed key to use the AWS-managed KMS key (i.e. aws/dynamodb). This key is stored within your AWS account and is managed by Amazon KMS. Choose Save changes to apply the changes.
  2. Select Stored in your account, and owned and managed by you, and choose the Customer Managed Key (CMK) created earlier in the Remediation process from the selection box. This key is stored in your AWS account and is owned and managed by you. Choose Save changes to apply the changes.

16 Repeat steps no. 12 – 15 to enable encryption at rest using Amazon KMS for each DynamoDB table provisioned within the current AWS region.

17 Change the AWS cloud region from the navigation bar and repeat the Remediation process for other AWS regions.

Using AWS CLI

01 Define the policy that enables the selected IAM users and/or roles to manage your new Customer Managed Key (CMK), and to encrypt/decrypt your DynamoDB table data using the KMS API. Create a new policy document (JSON format), name the file dynamodb-kms-key-policy.json, and paste the following content (replace the highlighted details, i.e. the ARNs for the IAM users and/or roles, with your own details):

{
	"Id": "protected-kms-policy",
	"Version": "2012-10-17",
	"Statement": [
		{
			"Sid": "Enable IAM User Permissions",
			"Effect": "Allow",
			"Principal": {
				"AWS": "arn:aws:iam::<aws-account-id>:root"
			},
			"Action": "kms:*",
			"Resource": "*"
		},
		{
			"Sid": "Allow access for Key Administrators",
			"Effect": "Allow",
			"Principal": {
				"AWS": "arn:aws:iam::<aws-account-id>:role/<role-name>"
			},
			"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::<aws-account-id>:role/<role-name>"
			},
			"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::<aws-account-id>:role/<role-name>"
			},
			"Action": [
				"kms:CreateGrant",
				"kms:ListGrants",
				"kms:RevokeGrant"
			],
			"Resource": "*",
			"Condition": {
				"Bool": {
					"kms:GrantIsForAWSResource": "true"
				}
			}
		}
	]
}

02 Run create-key command (OSX/Linux/UNIX) using the policy document created at the previous step (i.e. dynamodb-kms-key-policy.json) as value for the --policy parameter, to create your new Amazon KMS Customer Managed Key (CMK):

aws kms create-key
  --region us-east-1
  --description 'Customer Managed Key for DynamoDB Data Encryption'
  --policy file://dynamodb-kms-key-policy.json
  --query 'KeyMetadata.Arn'

03 The command output should return the ARN of the new Customer Managed Key:

"arn:aws:kms:us-east-1:123456789012:key/abcd1234-abcd-1234-abcd-1234abcd1234"

04 Run create-alias command (OSX/Linux/UNIX) using the key ARN returned at the previous step to attach an alias to the new CMK. The alias must start with the prefix "alias/" (the command should not produce an output):

aws kms create-alias
  --region us-east-1
  --alias-name alias/DynamoDBDataCMK
  --target-key-id arn:aws:kms:us-east-1:123456789012:key/abcd1234-abcd-1234-abcd-1234abcd1234

05 Run update-table command (OSX/Linux/UNIX) using the name of the Amazon DynamoDB table that you want to configure as the identifier parameter, to update the encryption configuration available for the selected DynamoDB table in order to use to use a KMS key for encryption at rest. You can use the AWS-managed KMS key (i.e. aws/dynamodb) or your own Customer Managed Key (CMK). Replace the KMSMasterKeyId parameter value with "alias/aws/dynamodb" or the Amazon Resource Name (ARN) of the CMK returned at step no. 3:

aws dynamodb update-table
  --region us-east-1
  --table-name cc-product-reviews
  --sse-specification Enabled=true,SSEType="KMS",KMSMasterKeyId="arn:aws:kms:us-east-1:123456789012:key/abcd1234-abcd-1234-abcd-1234abcd1234"

06 The command output should return the configuration information available for the configured table:

{
	"TableDescription": {
		"TableArn": "arn:aws:dynamodb:us-east-1:123456789012:table/cc-product-reviews",
		"AttributeDefinitions": [
			{
				"AttributeName": "RuleName",
				"AttributeType": "S"
			},
			{
				"AttributeName": "RuleType",
				"AttributeType": "S"
			}
		],
		"ProvisionedThroughput": {
			"NumberOfDecreasesToday": 2,
			"WriteCapacityUnits": 5,
			"ReadCapacityUnits": 5
		},
		"TableName": "cc-product-reviews",
		"BillingModeSummary": {
			"BillingMode": "PAY_PER_REQUEST",
			"LastUpdateToPayPerRequestDateTime": "2023-12-12T12:12:40.660000+00:00"
		},
		"SSEDescription": {
			"Status": "UPDATING"
		},
		"TableClassSummary": {
			"TableClass": "STANDARD"
		}
	}
}

07 Repeat steps no. 5 and 6 to enable encryption at rest using Amazon KMS for each DynamoDB table available in the selected AWS region.

08 Change the AWS cloud region by updating the --region command parameter value and repeat the Remediation process for other AWS regions.

References