A Terraform module that provisions a baseline AWS Lambda setup, including:
- A CloudWatch log group (with configurable retention)
- Zero or more Secrets Manager secrets
- A least-privilege IAM execution role scoped to both
- The Lambda function itself, wired to all of the above
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Lambda Function β
β runtime: var.lambda_runtime handler: index.handler β
β env: <KEY>_SECRET_ARN=<arn>, ... β
ββββββββββββββββββββ¬βββββββββββββββββββββββββββββ¬βββββββββββββββββββ
β assumes β writes logs (JSON)
βΌ βΌ
βββββββββββββββββ βββββββββββββββββββββββββββββββ
β IAM Role β β CloudWatch Log Group β
β + CW policy β β /aws/lambda/<prefix>-lambda β
β + SM policy β βββββββββββββββββββββββββββββββ
β + extra ARNs β
βββββββββ¬ββββββββ
β GetSecretValue (scoped to each provisioned secret ARN)
βΌ
βββββββββββββββββ
β Secrets β
β Manager β
β (0 .. n) β
βββββββββββββββββ
All resources are named using the prefix {environment}-{name}.
module "my_lambda" {
source = "github.com/your-org/terraform-aws-lambda-baseline"
name = "payments-processor"
environment = "prod"
lambda_zip_path = "${path.module}/dist/function.zip"
secrets = {
api_key = {
value = var.payments_api_key
description = "Payments API key"
}
db_password = {
value = var.db_password
description = "Database password"
}
}
environment_variables = {
LOG_LEVEL = "INFO"
}
lambda_runtime = "python3.12"
lambda_memory_mb = 512
lambda_timeout_seconds = 30
log_retention_days = 30
extra_iam_policy_arns = [
"arn:aws:iam::aws:policy/AmazonSQSReadOnlyAccess",
]
tags = {
Team = "platform"
Service = "payments"
}
}| Name | Version |
|---|---|
| terraform | >= 1.6.0 |
| aws | ~> 6.0 |
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
name |
string |
β | yes | Base name for all resources, e.g. payments-processor |
environment |
string |
β | yes | Deployment environment: dev, staging, or prod |
lambda_zip_path |
string |
β | yes | Local path to the zipped Lambda deployment package |
secrets |
map(object({value=string, description=string})) |
{} |
no | Secrets to create in Secrets Manager; key becomes part of the secret name |
environment_variables |
map(string) |
{} |
no | Plain-text env vars passed to the Lambda |
lambda_runtime |
string |
"python3.12" |
no | Lambda runtime identifier |
lambda_memory_mb |
number |
512 |
no | Memory (MB) allocated to the Lambda |
lambda_timeout_seconds |
number |
30 |
no | Maximum execution time in seconds |
lambda_tracing_mode |
string |
"PassThrough" |
no | X-Ray tracing mode: PassThrough or Active |
lambda_reserved_concurrency |
number |
-1 |
no | Reserved concurrency; -1 = unreserved, 0 = disabled |
log_retention_days |
number |
30 |
no | Days to retain CloudWatch logs |
secret_recovery_window_days |
number |
30 |
no | Days before a deleted secret is permanently removed; 0 disables recovery |
extra_iam_policy_arns |
list(string) |
[] |
no | Additional managed policy ARNs to attach to the execution role |
tags |
map(string) |
{} |
no | Tags applied to every resource |
| Name | Description |
|---|---|
lambda_arn |
ARN of the Lambda function |
lambda_name |
Name of the Lambda function |
secret_arns |
Map of secret_key β ARN for all provisioned secrets |
log_group_name |
Name of the CloudWatch log group |
iam_role_arn |
ARN of the Lambda IAM execution role |
The repo ships a full integration test suite that runs Terraform against MiniStack β a free, MIT-licensed AWS emulator (drop-in LocalStack alternative) that supports Lambda, IAM, Secrets Manager, and CloudWatch Logs out of the box.
Prerequisites: Docker (Colima, Docker Desktop, etc.), docker-compose,
terraform, aws CLI, python3, zip.
./scripts/test-ministack.shThe script will:
- Build a minimal Lambda zip from
tests/ministack/fixture/ - Start MiniStack on port 4566 (stopped automatically on exit)
- Run
terraform applyagainst it - Assert every resource β Lambda config, IAM trust policy, CloudWatch retention, Secrets Manager values, secret ARN env vars, and a live Lambda invocation
terraform destroyand stop MiniStack
To reuse an already-running MiniStack container:
MINISTACK_RUNNING=1 ./scripts/test-ministack.shTo run against a remote MiniStack (e.g. in CI with the container on a different host):
MINISTACK_ENDPOINT=http://ministack:4566 MINISTACK_RUNNING=1 ./scripts/test-ministack.sh- Handler: hardcoded to
index.handler. Ensure your deployment package exposes this entrypoint. - Secret injection: each secret's ARN is injected as
<KEY>_SECRET_ARN(key uppercased). For the example above:API_KEY_SECRET_ARNandDB_PASSWORD_SECRET_ARN. Read these at runtime to fetch values from Secrets Manager. - Least-privilege IAM: the execution role is granted CloudWatch Logs write access scoped to the provisioned log group, and
secretsmanager:GetSecretValuescoped to the specific secret ARNs provisioned by this module β no wildcards. - Log format: logs are written in JSON format to
/aws/lambda/{environment}-{name}-lambdawith the configured retention policy applied. - Sensitive values:
secretsis marked sensitive and will not appear in Terraform plan output. - Dev/test tip: set
secret_recovery_window_days = 0to allow immediate recreation of secrets with the same name after aterraform destroy.