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

Enable Encryption at Rest for Environment Variables using Customer Master 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 (not acceptable risk)
Rule ID: Lambda-009

Ensure that your Amazon Lambda environment variables are using customer-managed Customer Master Keys (CMKs) instead of AWS managed-keys (i.e. default keys used when there are no customer keys defined) in order to benefit from a more granular control over the data encryption and decryption process. The environment variables defined for your Amazon Lambda functions are key-value pairs that are used to store configuration settings without the need to change function code. By default, all Lambda environment variables with the key (name) set to "pass", "password", "*token*" (i.e. any key that has "token" string in it), "api", "API", "Key", "KEY", "key" are encrypted. You can also set your own environment variables names within the rule settings on your Trend Cloud One™ – Conformity account console.

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

When you utilize your own customer-managed Customer Master Keys (CMKs) to protect the sensitive data that you pass to your Amazon Lambda functions, you achieve full control over who can use the CMKs and access the data encrypted within the environment variables. The Amazon KMS service allows you to create, rotate, disable, enable, and audit Customer Master Keys for Lambda environment variables.


Audit

To determine if customer-managed Customer Master Keys (CMKs) are used to encrypt your Lambda function environment variables at rest, perform the following actions:

Using AWS Console

01 Sign in to the AWS Management Console.

02 Navigate to Amazon Lambda console at https://console.aws.amazon.com/lambda/.

03 In the left navigation panel, under AWS Lambda, choose Functions.

04 Click on the name (link) of the function that you want to examine.

05 Select the Configuration tab and choose Environment variables from the left menu.

06 In the Environment variables section, choose Edit to access the configuration settings available for the function's environment variables.

07 On the Edit environment variables page, choose Encryption configuration, and check the AWS KMS key to encrypt at rest configuration setting to determine the type of KMS key configured for encryption at rest. If the AWS KMS key to encrypt at rest is set to (default) aws/lambda, the environment variables defined for the selected Amazon Lambda function are encrypted at rest using the default master key (AWS-managed key) instead of a customer-managed Customer Master Key (CMK).

08 Repeat steps no. 4 – 7 for each Lambda function available within the current AWS region.

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

Using AWS CLI

01 Run list-functions command (OSX/Linux/UNIX) to list the name of each Amazon Lambda function available in the selected AWS cloud region:

aws lambda list-functions
  --region us-east-1
  --output table
  --query 'Functions[*].FunctionName'

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

---------------------
|   ListFunctions   |
+-------------------+
|   cc-sqs-poller   |
|   cc-s3-logging   |
|   s3-get-object   |
+-------------------+

03 Run get-function command (OSX/Linux/UNIX) using the name of the Amazon Lambda function that you want to examine as the identifier parameter and custom query filters to describe the ARN of the KMS key used to encrypt the environment variables defined for the selected function:

aws lambda get-function
  --region us-east-1
  --function-name cc-sqs-poller
  --query 'Configuration.KMSKeyArn'

04 The command output should return the requested KMS key identifier (ARN):

null

If the get-function command output returns null, as shown in the example above, the environment variables defined for the selected Amazon Lambda function are encrypted at rest using the default master key (i.e. aws/lambda key) instead of a customer-managed Customer Master Key (CMK).

05 Repeat step no. 3 and 4 for each Lambda function available in the selected AWS region.

06 Change the AWS region by updating the --region command parameter value and repeat steps no. 1 – 5 to perform the Audit process for other regions.

Remediation / Resolution

To enable encryption at rest for environment variables defined for your Amazon Lambda functions using KMS Customer Master Keys (CMKs), perform the following actions:

Using AWS CloudFormation

01 CloudFormation template (JSON):

{
  "AWSTemplateFormatVersion":"2010-09-09",
  "Description": "Enable Encryption for Environment Variables",
  "Resources":{
    "FunctionExecutionRole": {
        "Type": "AWS::IAM::Role",
        "Properties": {
          "RoleName": "LambdaExecutionRole",
          "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [{
              "Effect": "Allow",
              "Principal": {
                "Service": [ "lambda.amazonaws.com" ]
              },
              "Action": [ "sts:AssumeRole" ]
            }]
          },
          "Path": "/",
          "Policies": [{
            "PolicyName": "AWSLambdaBasicExecutionRole",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [{
                "Effect": "Allow",
                "Action": [
                  "logs:CreateLogGroup",
                  "logs:CreateLogStream",
                  "logs:PutLogEvents"
                ],
                "Resource": "*"
              }]
            }
          }]
       }
    },
    "ConsumerFunction": {
        "Type": "AWS::Lambda::Function",
        "Properties": {
            "FunctionName": "cc-sqs-poller",
            "Handler": "lambda_function.lambda_handler",
            "Role": {
                "Fn::GetAtt": [
                    "FunctionExecutionRole",
                    "Arn"
                ]
            },
            "Code": {
                "S3Bucket": "cc-lambda-functions",
                "S3Key": "poller.zip"
            },
            "Runtime": "python3.9",
            "MemorySize" : 1024,
            "Timeout": 45,
            "Environment": {
              "Variables": {"key": "KSBh56s01TXsSO15A"}
            },
            "KmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/abcdabcd-1234-abcd-1234-abcd1234abcd"
        }
     }
  }
}

02 CloudFormation template (YAML):

AWSTemplateFormatVersion: '2010-09-09'
Description: Enable Encryption for Environment Variables
Resources:
  FunctionExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: LambdaExecutionRole
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: /
      Policies:
        - PolicyName: AWSLambdaBasicExecutionRole
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Resource: '*'
  ConsumerFunction:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: cc-sqs-poller
      Handler: lambda_function.lambda_handler
      Role: !GetAtt 'FunctionExecutionRole.Arn'
      Code:
        S3Bucket: cc-lambda-functions
        S3Key: poller.zip
      Runtime: python3.9
      MemorySize: 1024
      Timeout: 45
      Environment:
        Variables:
          key: KSBh56s01TXsSO15A
      KmsKeyArn: arn:aws:kms:us-east-1:123456789012:key/abcdabcd-1234-abcd-1234-abcd1234abcd

Using Terraform (AWS Provider)

01 Terraform configuration file (.tf):

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

  required_version = ">= 0.14.9"
}

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

resource "aws_iam_role" "function-execution-role" {
  name = "LambdaExecutionRole"
  path = "/"
  managed_policy_arns = [ "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" ]

  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Effect": "Allow"
    }
  ]
}
EOF
}

resource "aws_lambda_function" "lambda-function" {
  function_name    = "cc-sqs-poller"
  s3_bucket        = "cc-lambda-functions"
  s3_key           = "sqs-consumer.zip"
  role             = aws_iam_role.function-execution-role.arn
  handler          = "lambda_function.lambda_handler"
  runtime          = "python3.9"
  memory_size      = 1024
  timeout          = 45

  environment {
    variables = {
      key = "KSBh56s01TXsSO15A"
    }
  }

  # Enable Encryption for Environment Variables
  kms_key_arn = "arn:aws:kms:us-east-1:123456789012:key/1234abcd-1234-abcd-1234-abcd1234abcd"

}

Using AWS Console

01 Sign in to the AWS Management Console.

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

03 In the 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 CMK setup process.

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

  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. Under Advanced options, for Key material origin, select KMS as the source of the key material within the CMK.
  3. Under Advanced options, for Regionality, select whether to allow the new key to be replicated into other AWS regions.
  4. Choose Next to continue.

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 – optional box. (Optional) Use the Add tag button to create tags in order to categorize and identify your CMK. Choose Next to continue the setup process.

07 For Step 3 Define key administrative permissions, choose which IAM users and/or roles can administer your new 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 Next to continue.

08 For Step 4 Define key usage permissions, within This account section, select which IAM users and/or roles can use the new Customer Master Key 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 environment variables. 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 Customer Master Key (CMK). Once the key is successfully created, the Amazon KMS console will display the following confirmation message: "Success. Your customer master key was created with alias <key-alias> and key ID <key-id>".

10 Navigate to Amazon Lambda console at https://console.aws.amazon.com/lambda/.

11 In the left navigation panel, under AWS Lambda, choose Functions.

12 Click on the name of the function that you want to reconfigure.

13 Select the Configuration tab and choose Environment variables from the left menu.

14 In the Environment variables section, choose Edit to access the configuration settings available for the function's environment variables.

15 On the Edit environment variables page, perform the following operations:

  1. Choose Encryption configuration to open the panel with the encryption configuration settings.
  2. Select Use a customer master key under AWS KMS key to encrypt at rest.
  3. Click inside the Customer master key box and choose the name of the KMS Customer Master Key (CMK) created at the previous steps.
  4. Choose Save to apply the changes.

16 Repeat steps no. 12 – 15 to enable encryption at rest for each Amazon Lambda function with environment variables, available within the current AWS region.

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

Using AWS CLI

01 Define the policy that enables the selected IAM users and/or roles to manage the new Customer Master Key (CMK), and to encrypt/decrypt your Lambda function environment variables using the KMS API. Create a new policy document (JSON format), name the file lambda-encryption-cmk-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": "ebs-default-encryption-key-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. lambda-encryption-cmk-policy.json) as value for the --policy parameter, to create your new customer-managed Customer Master Key (CMK):

aws kms create-key
  --region us-east-1
  --description 'Amazon KMS CMK for encrypting Lambda environment variables'
  --policy file://lambda-encryption-cmk-policy.json
  --query 'KeyMetadata.Arn'

03 The command output should return the ARN of the new Customer Master Key (CMK):

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

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/LambdaEncryptionCMK
  --target-key-id arn:aws:kms:us-east-1:123456789012:key/abcdabcd-1234-abcd-1234-abcd1234abcd

05 Run update-function-configuration command (OSX/Linux/UNIX) using the name of the Amazon Lambda function that you want to reconfigure as the identifier parameter, to enable encryption at rest for the environment variables defined for the selected function:

aws lambda update-function-configuration
  --region us-east-1
  --function-name cc-sqs-poller
  --kms-key-arn arn:aws:kms:us-east-1:123456789012:key/abcdabcd-1234-abcd-1234-abcd1234abcd

06 The command output should return the metadata available for the reconfigured function:

{
    "LastUpdateStatus": "Successful",
    "FunctionName": "cc-sqs-poller",
    "LastModified": "2021-08-30T09:00:00.000+0000",
    "RevisionId": "abcdabcd-1234-abcd-1234-abcd1234abcd",
    "MemorySize": 128,
    "State": "Active",
    "Version": "$LATEST",
    "Role": "arn:aws:iam::123456789012:role/cc-app-function-role",
    "Timeout": 45,
    "Runtime": "python3.9",
    "TracingConfig": {
        "Mode": "PassThrough"
    },
    "CodeSha256": "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcd",
    "Description": "",
    "CodeSize": 403,
    "FunctionArn": "arn:aws:lambda:us-east-1:123456789012:function:cc-sqs-poller",
    "KMSKeyArn": "arn:aws:kms:us-east-1:123456789012:key/abcdabcd-1234-abcd-1234-abcd1234abcd",
    "Handler": "lambda_function.lambda_handler"
}

07 Repeat steps no. 5 and 6 to enable encryption at rest for each Amazon Lambda function with environment variables, available in the selected AWS region.

08 Change the AWS cloud region by updating the --region command parameter value and repeat steps no. 1 – 7 to perform the Remediation process for other regions.

References

Publication date Dec 14, 2020