2026-09-16 13:41:47 -04:00
# Per-workload Lambda permissions boundary. Created on the first (bootstrap)
# apply. The scoped apply role denies iam:CreatePolicy / CreatePolicyVersion,
# so later edits to this document need the hcptf-bootstrap window.
data " aws_iam_policy_document " " lambda_boundary " {
# checkov:skip=CKV_AWS_111: AWS requires Resource=* for logs:DescribeLogGroups, xray Put*, and EC2 ENI lifecycle used by VPC Lambdas. Secrets, table, CMK, buckets, DLQ, and invoke are ARN-pinned.
statement {
sid = " CloudWatchLogsWrite "
effect = " Allow "
actions = [
" logs:CreateLogGroup " ,
" logs:CreateLogStream " ,
" logs:PutLogEvents " ,
" logs:DescribeLogStreams " ,
]
resources = [
" arn:aws:logs: ${ var . aws_region } : ${ local . account_id } :log-group:/aws/lambda* " ,
]
}
statement {
sid = " CloudWatchLogsDescribe "
effect = " Allow "
actions = [ " logs:DescribeLogGroups " ]
resources = [ " * " ]
}
statement {
sid = " XRay "
effect = " Allow "
actions = [
" xray:PutTraceSegments " ,
" xray:PutTelemetryRecords " ,
]
resources = [ " * " ]
}
statement {
sid = " Ec2Eni "
effect = " Allow "
actions = [
" ec2:CreateNetworkInterface " ,
" ec2:DescribeNetworkInterfaces " ,
" ec2:DeleteNetworkInterface " ,
" ec2:DescribeSubnets " ,
" ec2:DescribeSecurityGroups " ,
" ec2:DescribeVpcs " ,
]
resources = [ " * " ]
}
statement {
sid = " PaymentsSecrets "
effect = " Allow "
actions = [
" secretsmanager:GetSecretValue " ,
]
resources = [ for arn in local . secret_arns : arn ]
}
statement {
sid = " PaymentsDynamoDB "
effect = " Allow "
actions = [
" dynamodb:GetItem " ,
" dynamodb:PutItem " ,
" dynamodb:UpdateItem " ,
" dynamodb:DeleteItem " ,
" dynamodb:Query " ,
" dynamodb:Scan " ,
" dynamodb:BatchGetItem " ,
" dynamodb:BatchWriteItem " ,
" dynamodb:DescribeTable " ,
" dynamodb:ConditionCheckItem " ,
]
resources = [
" arn:aws:dynamodb: ${ var . aws_region } : ${ local . account_id } :table/ ${ local . table_name } " ,
" arn:aws:dynamodb: ${ var . aws_region } : ${ local . account_id } :table/ ${ local . table_name } /* " ,
]
}
statement {
sid = " PaymentsCmk "
effect = " Allow "
actions = [
" kms:Decrypt " ,
" kms:GenerateDataKey " ,
" kms:DescribeKey " ,
]
2026-09-16 13:58:33 -04:00
resources = [ local . dynamodb_cmk_arn ]
2026-09-16 13:41:47 -04:00
condition {
test = " StringEquals "
variable = " kms:ViaService "
values = [ " dynamodb. ${ var . aws_region } .amazonaws.com " ]
}
}
statement {
sid = " PaymentsCsvRead "
effect = " Allow "
actions = [
" s3:GetObject " ,
" s3:GetObjectVersion " ,
]
resources = [ " arn:aws:s3::: ${ local . csv_bucket_name } /* " ]
}
statement {
sid = " PaymentsBoaRawPut "
effect = " Allow "
actions = [
" s3:PutObject " ,
]
resources = [ " arn:aws:s3::: ${ local . boa_raw_bucket_name } /* " ]
}
statement {
sid = " PaymentsDlqSend "
effect = " Allow "
actions = [
" sqs:SendMessage " ,
]
resources = [
" arn:aws:sqs: ${ var . aws_region } : ${ local . account_id } :payments-processPaymentCsv-async-dlq " ,
]
}
statement {
sid = " PaymentsInvokeExpenseProcessor "
effect = " Allow "
actions = [
" lambda:InvokeFunction " ,
]
resources = [
" arn:aws:lambda: ${ var . aws_region } : ${ local . account_id } :function:payments-expenseProcessor " ,
]
}
}
resource " aws_iam_policy " " lambda_boundary " {
# checkov:skip=CKV_AWS_111: AWS requires Resource=* for logs:DescribeLogGroups, xray Put*, and EC2 ENI lifecycle used by VPC Lambdas. Secrets, table, CMK, buckets, DLQ, and invoke are ARN-pinned.
name = " payments-dashboard-lambda-boundary "
path = " /tf-managed/ "
description = " Per-workload Lambda permissions boundary for payments-dashboard (PLAT-79). "
policy = data . aws_iam_policy_document . lambda_boundary . json
}