Protect AWS Lambda Environment Variables from Prying Eyes by Encrypting Them in Transit

Lambda environment variables are encrypted at rest by default but anyone with access to the Lambda console of your AWS account can see the values of your environment variables. This is fine for variables like database endpoints but not good for variables that store some kind of secret, like a database password for example.

Values of variables can be obfuscated on the Lambda console (& when function metadata is fetched by AWS CLI or SDK) by encrypting them in transit using a KMS key of your choosing. Let’s see how this can be done. Say you have a Lambda function with an unencrypted environment variable. Start by opening the function in the AWS console. Scroll down to the environment variables section & click Edit:

Expand the Encryption configuration section at the bottom & select Enable helpers for encryption in transit:

Click the Encrypt button that appears next to the variable you want to protect:

In the popup that appears, select the KMS key (CMK) which will be used to encrypt the value of the variable & click Encrypt:

Save the environment variables & your variables will now be obfuscated on the console:

Use the following Node.js code to decrypt the value of this variable in your Lambda code:

const AWS = require('aws-sdk');
const functionName = process.env.AWS_LAMBDA_FUNCTION_NAME;
const encrypted = process.env['my_secret_env_var'];

// Decrypt code should run once and variables stored outside of the
// function handler so that these are decrypted once per container
const kms = new AWS.KMS();
const req = {
    CiphertextBlob: Buffer.from(encrypted, 'base64'),
    EncryptionContext: { LambdaFunctionName: functionName },
};
const data = await kms.decrypt(req).promise();
decrypted = data.Plaintext.toString('ascii');

Since the above code uses the KMS key to decrypt the secret, the Lambda function’s execution role must have access to the key. For that, add this policy to it:

{
  "Version": "2012-10-17",
  "Statement": {
    "Effect": "Allow",
    "Action": "kms:Decrypt",
    "Resource": "arn:aws:kms:ap-south-1:123456789012:key/b71362bd-92d9-4207-8247-0c8507f8dc74",
    "Condition": {
      "StringEquals": {
        "kms:EncryptionContext:LambdaFunctionName": "my-lambda"
      }
    }
  }
}