From f4292832fe2ada6f10dfdbbd669ced520f121d94 Mon Sep 17 00:00:00 2001 From: Adam Moussa Date: Wed, 5 Aug 2026 12:57:23 -0400 Subject: [PATCH] fix(iam): add plan-role refresh reads for afi terraform state ViewOnlyAccess omits iam:GetRole and events:DescribeRule; without a scoped refresh policy, HCP plans fail after the first partial apply. --- .../terraform-substrate.template.yaml | 64 +++++++++++++++++-- 1 file changed, 60 insertions(+), 4 deletions(-) diff --git a/lib/terraform-substrate/terraform-substrate.template.yaml b/lib/terraform-substrate/terraform-substrate.template.yaml index 5df4dde..7d92126 100644 --- a/lib/terraform-substrate/terraform-substrate.template.yaml +++ b/lib/terraform-substrate/terraform-substrate.template.yaml @@ -377,10 +377,12 @@ Resources: # # First HCP Terraform workload. Trust subs are exact StringEquals on # organization/project/workspace/run_phase — never StringLike, never a - # wildcarded run_phase. Plan role: ViewOnlyAccess only (never ReadOnlyAccess, - # which grants secretsmanager:GetSecretValue). Apply role: attaches the - # shared guardrail plus stack-scoped Lambda / layer / EventBridge / Logs. - # Prod-only (IsProdAccount): this template also deploys to seahaven-dev. + # wildcarded run_phase. Plan role: ViewOnlyAccess (never ReadOnlyAccess, + # which grants secretsmanager:GetSecretValue) PLUS a stack-scoped refresh + # inline policy — ViewOnlyAccess omits iam:GetRole and events:DescribeRule, + # which Terraform needs to refresh state after the first apply. Apply role: + # attaches the shared guardrail plus stack-scoped Lambda / layer / + # EventBridge / Logs / artifact-bucket. Prod-only (IsProdAccount). # --------------------------------------------------------------------------- HcptfAfiBackupMonitorPlanRole: Type: AWS::IAM::Role @@ -400,6 +402,60 @@ Resources: "app.terraform.io:sub": organization:seahaven:project:seahaven-prod:workspace:afi-backup-monitor-prod:run_phase:plan ManagedPolicyArns: - arn:aws:iam::aws:policy/job-function/ViewOnlyAccess + Policies: + - PolicyName: afi-backup-monitor-plan-refresh + PolicyDocument: + Version: "2012-10-17" + Statement: + - Sid: RefreshIamRoles + Effect: Allow + Action: + - iam:GetRole + - iam:GetRolePolicy + - iam:ListRolePolicies + - iam:ListAttachedRolePolicies + Resource: + - !Sub "arn:aws:iam::${AWS::AccountId}:role/tf-managed/afi-*" + - Sid: RefreshManagedPolicies + Effect: Allow + Action: + - iam:GetPolicy + - iam:GetPolicyVersion + Resource: "*" + - Sid: RefreshEventBridge + Effect: Allow + Action: + - events:DescribeRule + - events:ListTargetsByRule + - events:ListTagsForResource + Resource: + - !Sub "arn:aws:events:us-east-1:${AWS::AccountId}:rule/afi-*" + - Sid: RefreshLambda + Effect: Allow + Action: + - lambda:GetFunction + - lambda:GetFunctionConfiguration + - lambda:GetPolicy + - lambda:GetLayerVersion + - lambda:ListVersionsByFunction + - lambda:ListTags + Resource: + - !Sub "arn:aws:lambda:us-east-1:${AWS::AccountId}:function:afi-*" + - !Sub "arn:aws:lambda:us-east-1:${AWS::AccountId}:layer:afi-shared*" + - Sid: RefreshArtifactsBucket + Effect: Allow + Action: + - s3:Get* + - s3:ListBucket + Resource: + - !Sub "arn:aws:s3:::afi-backup-monitor-artifacts-${AWS::AccountId}" + - !Sub "arn:aws:s3:::afi-backup-monitor-artifacts-${AWS::AccountId}/*" + - Sid: RefreshLogs + Effect: Allow + Action: + - logs:DescribeLogGroups + - logs:ListTagsForResource + Resource: "*" HcptfAfiBackupMonitorApplyRole: Type: AWS::IAM::Role