Skip to content

Lambda functions should have encryption in transit enabled for environment variables

Lambda environment variables frequently hold database credentials, API keys, and service tokens. AWS encrypts these at rest by default using an AWS-managed key, but specifying a customer-managed key via kms_key_arn gives you control over rotation schedules, key access policies, and a dedicated CloudTrail audit trail for every decrypt operation.

Skip this and you lose the ability to revoke decryption access independently of the Lambda service role's IAM policies. You also can't enforce separation of duties between the team deploying functions and the team that manages secrets.

Retrofit consideration

Existing Lambda functions need kms_key_arn added and their execution roles updated with kms:Decrypt on the new key. Terraform applies the change as a function update, re-encrypting all environment variables in place. Invocations running at that moment may see a brief disruption. Test in non-production before rolling this out to functions handling live traffic.

Implementation

Choose the approach that matches how you manage Terraform.

If you use terraform-aws-modules/lambda/aws, set the right module inputs for this control. You can later migrate to the compliance.tf module with minimal changes because it is compatible by design.

module "lambda" {
  source  = "terraform-aws-modules/lambda/aws"
  version = ">=8.0.0"

  create_package         = false
  function_name          = "abc123"
  handler                = "index.lambda_handler"
  local_existing_package = "lambda_function.zip"
  runtime                = "python3.12"

  kms_key_arn = "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012"
}

Use AWS provider resources directly. See docs for the resources involved: aws_lambda_function.

resource "aws_lambda_function" "this" {
  filename                       = "lambda_function.zip"
  function_name                  = "pofix-abc123"
  handler                        = "index.handler"
  reserved_concurrent_executions = 100
  role                           = "arn:aws:iam::123456789012:role/example-role"
  runtime                        = "python3.12"
  source_code_hash               = "base64encodedhashabcdef1234567890=="

  kms_key_arn = "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012"
}

What this control checks

The aws_lambda_function resource passes when kms_key_arn is set to a non-empty string pointing to a customer-managed KMS key. The referenced key policy and IAM permissions must allow Lambda to call kms:Decrypt at runtime.

It fails when kms_key_arn is omitted or set to an empty string. Some implementations of this control also flag functions with no environment block, requiring the argument even when no environment variables are configured.

Common pitfalls

  • Missing kms:Decrypt on execution role

    Invocation fails immediately if the execution role lacks kms:Decrypt on the key, even with kms_key_arn correctly set. Lambda can't decrypt environment variables at startup. Add a kms:Decrypt statement in either the aws_iam_role_policy attached to the execution role or directly in the aws_kms_key_policy.

  • Functions without environment variables still flagged

    Some control implementations flag every aws_lambda_function missing kms_key_arn, regardless of whether an environment block exists. Either add the argument uniformly across all functions or request a suppression for functions that genuinely hold no secrets. Consistency across the codebase is usually the easier path.

  • KMS key deletion orphans function config

    A disabled or pending-deletion KMS key breaks function invocations. Lambda can't decrypt environment variables and returns AccessDeniedException at runtime, with no warning before it hits production. Set up EventBridge rules on CloudTrail management events for DisableKey and ScheduleKeyDeletion to catch this before it affects live traffic.

  • Cross-region KMS keys are not supported

    Lambda only accepts a KMS key from the same region as the function. A cross-region key ARN causes CreateFunction or UpdateFunctionConfiguration to return an error immediately. For multi-region deployments, use aws_kms_replica_key or provision region-local keys for each deployment target.

Audit evidence

Config rule lambda-function-settings-check, configured with the kmsKeyArns parameter, should show all functions compliant. The Lambda function's Configuration tab should display a customer-managed key ARN under environment variable encryption settings. CloudTrail UpdateFunctionConfiguration and CreateFunction events should show KMSKeyArn populated in the request parameters. Supporting artifacts include the KMS key policy granting kms:Decrypt to the function's execution role, and a Security Hub or CSPM export confirming no functions rely solely on the AWS-managed default.

Tool mappings

Use these identifiers to cross-reference this control across tools, reports, and evidence.

  • Compliance.tf Control: lambda_function_encryption_enabled

  • Checkov Check: CKV_AWS_173

  • Powerpipe Control: aws_compliance.control.lambda_function_encryption_enabled

Last reviewed: 2026-03-09