144 lines
4.2 KiB
Terraform
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"]
|
|
}
|
|
}
|