Handling Environment Variables in Lambda: The Right Way
The article emphasizes distinguishing between configurable values and sensitive secrets when managing data in AWS Lambda. It advocates for using Lambda Environment Variables for non-sensitive configurations and AWS Secrets Manager for all sensitive data.
Lambda Function Environment Variables
- What they are: Environment variables are key-value pairs built directly into the Lambda function’s UI. They define the “DNA” or ecosystem of your code’s runtime environment.
- Purpose: Ideal for non-sensitive, configurable values that change between environments (e.g., development, production). Examples include API endpoints, database table names (like
dev_table
vs.prod_table
), or form IDs. - Access in code (Python example)
import os
my_config_value = os.environ.get("MY_CONFIG_KEY")
- Best Practice: If a variable’s value needs to change when moving between environments (Dev, Prod), set it as an Environment variable instead of hardcoding it. This allows you to deploy the exact same code to different Lambda instances and merely change the environment variables for each environment.
Securely Storing Secrets with AWS Secrets Manager
- Why not just Environment Variables for secrets? While you could put an API key directly into environment variables, it’s not as secure. Secrets Manager provides a dedicated, more robust solution for sensitive data.
- Purpose: For actual secrets like API keys, database credentials, or other sensitive information, store their actual values in AWS Secrets Manager.
- Interaction with Lambda Environment Variables: The “right way” involves a double layer of indirection:
- Lambda Environment Variable: Store the name of the secret (the
SecretId
) that’s in Secrets Manager, not the secret’s actual value. - Lambda Code: Use
os.environ.get()
to retrieve the secret’s name, and then use the AWS SDK (Boto3 in Python) to make an API call to Secrets Manager to fetch the actual secret value.
- Lambda Environment Variable: Store the name of the secret (the
- Example
get_secret
function (Python): This function retrieves a secret from AWS Secrets Manager using the secret’s name, which is pulled from a Lambda environment variable.
import boto3
import json
import os
def get_secret(secret_name_env_var_key):
# Get the actual secret name from Lambda's environment variables
secret_name = os.environ[secret_name_env_var_key]
# Assumes AWS_REGION is set in Lambda env
region_name = os.environ['AWS_REGION']
client = boto3.client('secretsmanager', region_name=region_name)
try:
response = client.get_secret_value(SecretId=secret_name)
secret = response['SecretString']
return json.loads(secret) # Assuming your secret is stored as a JSON string
except Exception as e:
print(f"Error retrieving secret: {e}")
return None
- How it works:
- Your Lambda’s environment variable (e.g.,
MY_API_SECRET_NAME
) holds the string name of the secret (e.g.,"prod/my-service/api-key"
). - Your code calls
get_secret('MY_API_SECRET_NAME')
. get_secret
uses this name to fetch the actual key-value pair (e.g.,{"api_key": "xyz123"}
) from Secrets Manager.
- Your Lambda’s environment variable (e.g.,
- Benefits of this approach: Enhanced security by not exposing secrets directly in environment variables, dynamic secret rotation capabilities of Secrets Manager, and a cleaner Dev/Prod deployment process.
By combining Environment Variables for configurable values and AWS Secrets Manager for sensitive credentials, you build a more secure, flexible, and maintainable application deployment ecosystem in AWS Lambda.