1
0
Files
terraform.examples/modules/security_identity_compliance/SecretRotationReminder/main.tf
T
2026-02-13 15:44:24 +08:00

144 lines
4.2 KiB
Terraform

/**
* # SecretRotationReminder
* Deploy lambda function which takes secret rotation event from secretsmanager
* and send reminders to users using SNS.
* This function can be used by any number of secrets
* Secret ARN is obtained from the secretsmanager event
*
* This function overrides the blueprint function from AWS. Instead of rotating the secret value,
* it sends a reminder to user who will manually rotate the secret.
*/
resource "aws_sns_topic" "reminder" {
name = "${var.prefix}-SecretRotationReminder"
kms_master_key_id = var.sns-cmk-arn
}
resource "aws_sns_topic_subscription" "reminder" {
for_each = toset(var.rotation-reminder-recipients)
topic_arn = aws_sns_topic.reminder.arn
protocol = "email"
endpoint = each.value
}
data "archive_file" "payload" {
type = "zip"
source_file = "${path.module}/rotation_reminder.py"
output_path = "payload.zip"
}
data "aws_subnet" "this" {
id = var.lambda-subnet-ids[0]
}
resource "aws_security_group" "rotation-reminder" {
name = "${var.prefix}-SecretRotationReminder"
description = "Allow access to VPC endpoint"
vpc_id = data.aws_subnet.this.vpc_id
egress {
description = "Access to VPC endpoints"
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_lambda_function" "rotation-reminder" {
function_name = "${var.prefix}-SecretRotationReminder"
description = "Sends secret rotation reminder"
role = aws_iam_role.lambda.arn
handler = "rotation_reminder.lambda_handler"
filename = data.archive_file.payload.output_path
source_code_hash = data.archive_file.payload.output_base64sha256
runtime = "python3.13"
timeout = 180
vpc_config {
subnet_ids = var.lambda-subnet-ids
security_group_ids = [aws_security_group.rotation-reminder.id]
}
environment {
variables = {
SNS_TOPIC_ARN = aws_sns_topic.reminder.arn
}
}
}
resource "aws_lambda_permission" "rotation-reminder" {
statement_id = "SecretRotationReminderPermission"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.rotation-reminder.function_name
principal = "secretsmanager.amazonaws.com"
# this function should be allowed to send reminders for all secrets # source_arn = module.mock-secret.secret_arn
}
resource "aws_cloudwatch_log_group" "rotation-reminder" {
name = "/aws/lambda/whk1-bea-icc-obk-SecretRotationReminder"
retention_in_days = 400 # intentionally set to longer than 1 year as rotation may happen yearly
kms_key_id = var.logs-cmk-arn
}
resource "aws_iam_role" "lambda" {
name = "${var.prefix}-SecretRotationReminderFunctionRole"
assume_role_policy = data.aws_iam_policy_document.assume_role.json
}
resource "aws_iam_role_policy_attachment" "lambda" {
for_each = { for k, v in [
"arn:aws:iam::aws:policy/AWSLambdaExecute",
aws_iam_policy.lambda.arn
] : k => v }
role = aws_iam_role.lambda.name
policy_arn = each.value
}
resource "aws_iam_policy" "lambda" {
name_prefix = "SecretRotationPolicy"
policy = jsonencode(
{
"Version" : "2012-10-17",
"Statement" : [
{
"Sid" : "AllowAccessToSecretSnsVpc",
"Effect" : "Allow",
"Action" : [
"SNS:Publish",
"secretsmanager:DescribeSecret",
"secretsmanager:ListSecretVersionIds",
"secretsmanager:UpdateSecretVersionStage",
"secretsmanager:GetSecretValue",
"secretsmanager:PutSecretValue",
"ec2:CreateNetworkInterface",
"ec2:DescribeNetworkInterfaces",
"ec2:DescribeSubnets",
"ec2:DeleteNetworkInterface",
"ec2:AssignPrivateIpAddresses",
"ec2:UnassignPrivateIpAddresses",
"ec2:DescribeSecurityGroups",
"ec2:DescribeSubnets",
"ec2:DescribeVpcs",
"ec2:GetSecurityGroupsForVpc"
],
"Resource" : "*"
}
]
}
)
}
data "aws_iam_policy_document" "assume_role" {
statement {
effect = "Allow"
principals {
type = "Service"
identifiers = ["lambda.amazonaws.com"]
}
actions = ["sts:AssumeRole"]
}
}