From 71b0a6081ca12030a8f34730f2f90d0c1bb437d8 Mon Sep 17 00:00:00 2001 From: nourshoreibah Date: Sun, 6 Sep 2026 17:49:31 -0400 Subject: [PATCH 1/3] feat(infra): grant DSQL IAM access Groundwork for the Aurora DSQL migration, split out so the PR that adds the cluster does not also have to change IAM. branch-ci-plan carries AWS-managed ReadOnlyAccess, which does not reliably cover dsql:*. Without AmazonAuroraDSQLReadOnlyAccess, the PR introducing an aws_dsql_cluster fails its own terraform plan. branch-lambda-role gets dsql:DbConnectAdmin because DSQL authenticates with an IAM token rather than a password. The role is shared with every preview lambda, so previews are covered too. Resource is "*" until the cluster exists. Co-Authored-By: Claude Opus 5 (1M context) --- infrastructure/aws/lambda.tf | 18 ++++++++++++++++++ infrastructure/aws/oidc.tf | 7 +++++++ 2 files changed, 25 insertions(+) diff --git a/infrastructure/aws/lambda.tf b/infrastructure/aws/lambda.tf index 0f350199..5888b821 100644 --- a/infrastructure/aws/lambda.tf +++ b/infrastructure/aws/lambda.tf @@ -109,6 +109,24 @@ resource "aws_iam_role_policy" "lambda_ses_send" { }) } +# Aurora DSQL authenticates with an IAM token instead of a password. Granted +# ahead of the cluster so the migration PR does not also have to change IAM. +# Resource is "*" until the cluster exists; scope it to the cluster ARN then. +resource "aws_iam_role_policy" "lambda_dsql_connect" { + name = "branch-lambda-dsql-connect" + role = aws_iam_role.lambda_role.id + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [{ + Sid = "LambdaDsqlConnect" + Effect = "Allow" + Action = ["dsql:DbConnectAdmin"] + Resource = "*" + }] + }) +} + # Get AWS account ID for unique bucket naming data "aws_caller_identity" "current" {} diff --git a/infrastructure/aws/oidc.tf b/infrastructure/aws/oidc.tf index a164cf57..10ad16c6 100644 --- a/infrastructure/aws/oidc.tf +++ b/infrastructure/aws/oidc.tf @@ -45,6 +45,13 @@ resource "aws_iam_role_policy_attachment" "ci_plan_readonly" { policy_arn = "arn:aws:iam::aws:policy/ReadOnlyAccess" } +# ReadOnlyAccess does not reliably cover dsql:*, and a plan that cannot read a +# resource it manages fails. +resource "aws_iam_role_policy_attachment" "ci_plan_dsql_readonly" { + role = aws_iam_role.ci_plan.name + policy_arn = "arn:aws:iam::aws:policy/AmazonAuroraDSQLReadOnlyAccess" +} + resource "aws_iam_role_policy" "ci_plan_state_lock" { name = "tfstate-lock" role = aws_iam_role.ci_plan.id From 029bb2eb7ae6ebfd076b7f305b7146ce87ecce61 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 6 Sep 2026 21:50:26 +0000 Subject: [PATCH 2/3] chore: auto-format terraform and update documentation - Auto-formatted .tf files with terraform fmt - Updated README.md with terraform-docs Co-authored-by: nourshoreibah --- infrastructure/aws/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/infrastructure/aws/README.md b/infrastructure/aws/README.md index 844bc58f..6f23dbab 100644 --- a/infrastructure/aws/README.md +++ b/infrastructure/aws/README.md @@ -65,9 +65,11 @@ | [aws_iam_role_policy.ci_plan_state_lock](https://registry.terraform.io/providers/hashicorp/aws/6.14.1/docs/resources/iam_role_policy) | resource | | [aws_iam_role_policy.ci_preview](https://registry.terraform.io/providers/hashicorp/aws/6.14.1/docs/resources/iam_role_policy) | resource | | [aws_iam_role_policy.lambda_cognito_admin](https://registry.terraform.io/providers/hashicorp/aws/6.14.1/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy.lambda_dsql_connect](https://registry.terraform.io/providers/hashicorp/aws/6.14.1/docs/resources/iam_role_policy) | resource | | [aws_iam_role_policy.lambda_s3_objects](https://registry.terraform.io/providers/hashicorp/aws/6.14.1/docs/resources/iam_role_policy) | resource | | [aws_iam_role_policy.lambda_ses_send](https://registry.terraform.io/providers/hashicorp/aws/6.14.1/docs/resources/iam_role_policy) | resource | | [aws_iam_role_policy_attachment.ci_apply_admin](https://registry.terraform.io/providers/hashicorp/aws/6.14.1/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.ci_plan_dsql_readonly](https://registry.terraform.io/providers/hashicorp/aws/6.14.1/docs/resources/iam_role_policy_attachment) | resource | | [aws_iam_role_policy_attachment.ci_plan_readonly](https://registry.terraform.io/providers/hashicorp/aws/6.14.1/docs/resources/iam_role_policy_attachment) | resource | | [aws_iam_role_policy_attachment.lambda_basic](https://registry.terraform.io/providers/hashicorp/aws/6.14.1/docs/resources/iam_role_policy_attachment) | resource | | [aws_lambda_function.functions](https://registry.terraform.io/providers/hashicorp/aws/6.14.1/docs/resources/lambda_function) | resource | From 5feae9716c30aaa11ab5179b8c76f55b702104a7 Mon Sep 17 00:00:00 2001 From: nourshoreibah Date: Sun, 6 Sep 2026 17:50:46 -0400 Subject: [PATCH 3/3] chore: trim comments Co-Authored-By: Claude Opus 5 (1M context) --- infrastructure/aws/lambda.tf | 4 +--- infrastructure/aws/oidc.tf | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/infrastructure/aws/lambda.tf b/infrastructure/aws/lambda.tf index 5888b821..959534d5 100644 --- a/infrastructure/aws/lambda.tf +++ b/infrastructure/aws/lambda.tf @@ -109,9 +109,7 @@ resource "aws_iam_role_policy" "lambda_ses_send" { }) } -# Aurora DSQL authenticates with an IAM token instead of a password. Granted -# ahead of the cluster so the migration PR does not also have to change IAM. -# Resource is "*" until the cluster exists; scope it to the cluster ARN then. +# Resource "*" until the DSQL cluster exists; scope to its ARN then. resource "aws_iam_role_policy" "lambda_dsql_connect" { name = "branch-lambda-dsql-connect" role = aws_iam_role.lambda_role.id diff --git a/infrastructure/aws/oidc.tf b/infrastructure/aws/oidc.tf index 10ad16c6..3820a3f4 100644 --- a/infrastructure/aws/oidc.tf +++ b/infrastructure/aws/oidc.tf @@ -45,8 +45,7 @@ resource "aws_iam_role_policy_attachment" "ci_plan_readonly" { policy_arn = "arn:aws:iam::aws:policy/ReadOnlyAccess" } -# ReadOnlyAccess does not reliably cover dsql:*, and a plan that cannot read a -# resource it manages fails. +# Plan needs dsql read access; ReadOnlyAccess is not guaranteed to include it. resource "aws_iam_role_policy_attachment" "ci_plan_dsql_readonly" { role = aws_iam_role.ci_plan.name policy_arn = "arn:aws:iam::aws:policy/AmazonAuroraDSQLReadOnlyAccess"