# 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", ] resources = [data.aws_ssm_parameter.dynamodb_cmk.value] 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 }