Non-encrypted confidential information - DynamoDB
Need
Secure encryption of confidential information in DynamoDB
Context
- Usage of Terraform for Infrastructure as Code (IaC)
- Usage of aws-sdk for interacting with Amazon Web Services (AWS) services
Description
Non compliant code
resource "aws_dynamodb_table" "basic-dynamodb-table" {
name = "GameScores"
billing_mode = "PROVISIONED"
read_capacity = 20
write_capacity = 20
hash_key = "UserId"
range_key = "GameTitle"
attribute {
name = "UserId"
type = "N"
}
attribute {
name = "GameTitle"
type = "S"
}
}
The vulnerable code above demonstrates a DynamoDB table being created without any encryption specified. The aws_dynamodb_table
resource block does not include the server_side_encryption
argument which is used to enable server-side encryption using an AWS managed KMS key or a Customer managed KMS key (CMK).
Because encryption is not specified, the DynamoDB table will use the default AWS managed KMS key for server-side encryption. This default key does not provide the same level of control and security as a CMK.
For example, with a CMK, you can create, rotate, disable, and define access controls, and you can audit the encryption keys used to protect your data. Also, AWS does not have access to your CMKs, which means the data is securely protected.
Therefore, the code is vulnerable as it does not use a CMK for encryption, potentially leading to unauthorized access or data breaches.
Steps
- Create a Customer Managed Key (CMK) in AWS Key Management Service (KMS)
- Enable encryption for the DynamoDB table
- Specify the CMK to be used for encryption in the DynamoDB table configuration
Compliant code
resource "aws_kms_key" "dynamodb" {
description = "KMS key for DynamoDB"
policy = <<POLICY
{
"Version": "2012-10-17",
"Id": "key-consolepolicy-3",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {"AWS": "arn:aws:iam::${var.account_id}:root"},
"Action": "kms:*",
"Resource": "*"
}
]
}
resource "aws_dynamodb_table" "basic-dynamodb-table" {
name = "GameScores"
billing_mode = "PROVISIONED"
read_capacity = 20
write_capacity = 20
hash_key = "UserId"
range_key = "GameTitle"
kms_key_arn = aws_kms_key.dynamodb.arn
attribute {
name = "UserId"
type = "N"
}
attribute {
name = "GameTitle"
type = "S"
}
}
The above code first creates a Customer Managed Key (CMK) using the aws_kms_key
resource. This key is then used to encrypt the DynamoDB table by specifying the kms_key_arn
attribute in the aws_dynamodb_table
resource.
The aws_kms_key
resource creates a new KMS key with a policy that allows all KMS actions for the root user of the AWS account. The ARN of the created key is then used in the aws_dynamodb_table
resource to enable server-side encryption using the created CMK.
This ensures that all data stored in the DynamoDB table is encrypted using the specified CMK, thereby fixing the vulnerability of non-encrypted confidential information.