From ca179bbdf6e4839a6b0c427ea2586c4ba407e37d Mon Sep 17 00:00:00 2001 From: Adam Moussa <166072409+amoussa1229@users.noreply.github.com> Date: Mon, 28 Sep 2026 15:56:04 -0400 Subject: [PATCH] chore(terraform-substrate): forget imported prod hcptf pairs (PLAT-147) (#164) The six pairs are already in HCP state and DeletionPolicy is Retain, so CloudFormation drops the logical IDs without deleting the roles. --- README.md | 30 +- .../terraform-substrate.template.yaml | 1791 +---------------- 2 files changed, 18 insertions(+), 1803 deletions(-) diff --git a/README.md b/README.md index 1f5214e..98fb62b 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ are noted): | `seahaven-backup-offsite` | 328440206208 | us-west-2 | Governance-locked offsite copy vault (C-7) | | `seahaven-org-governance` | 328440206208 | us-east-1 | AWS Organizations OU tree + SCPs (incl. the cdk-imported external-dev guardrails) | | `seahaven-external-dev-baseline` | 396287094661 | us-east-1 | Member-account baseline: Config, GuardDuty, Security Hub (FSBP + CIS v3.0), Access Analyzer, flow logs, budget | -| `seahaven-terraform-substrate` | 011934824531, 710827005802 | us-east-1 | Prod/dev HCP substrate: OIDC + shared IAM manager + eight existing `hcptf-*` pairs (DeletionPolicy Retain). Pending PLAT-147 delete after consumer imports. New prod/dev HCP IAM is not added here. | +| `seahaven-terraform-substrate` | 011934824531, 710827005802 | us-east-1 | Prod/dev HCP substrate: OIDC + shared IAM manager. The six imported prod pairs are forgotten with `DeletionPolicy: Retain` (PLAT-147). Stacks stay until the delete. New prod/dev HCP IAM is not added here. | | `seahaven-site-hcptf` | 011934824531 | us-east-1 | Imported `hcptf-seahaven-site` apply and plan roles (PLAT-225). On the prod deploy job. Do not create. | | `seahaven-terraform-substrate` | 396287094661 | us-east-1 | Staged manually for SHOC backend/frontend adoption; exact HCP roles and deploy boundaries referencing the existing OIDC provider. Stays (PLAT-148). | | `seahaven-security-baseline` | 001520130573 | us-east-1 | Member-account baseline for the delegated security-admin account (same construct set) | @@ -255,7 +255,7 @@ Prod/dev still carry, until PLAT-147 deletes those two stacks: future `hcptf-*` role), - the `seahaven-hcptf-iam-management` guardrail policy (enumerated `seahaven-lambda-execution-boundary-*` allow-list; frozen, do not append), -- the eight existing prod `hcptf-` pairs with `DeletionPolicy: Retain`. +- no prod `hcptf-` pairs. The six imported pairs are Retain-removed. `seahaven-site` is `seahaven-site-hcptf`. `sh-openswe-traces` is gone. External-dev still carries: @@ -301,10 +301,10 @@ org-level control for the same class is `protect-privileged-roles` on prod and nonprod (PLAT-145), covering `hcptf-bootstrap*` plus the break-glass / CDK / `githubdeploy-*` set already on the security OU. -The eight existing prod/dev per-workspace pairs are imported into the owning -app, not recreated. After import they are Retain-removed from this template -and the prod/dev stacks are deleted. See the first-apply and import runbooks -below. Do not batch those consumer PRs; pilot is `afi-backup-monitor`. +The six live prod pairs are imported into the owning app, not recreated, then +Retain-removed from this template. `seahaven-site` is `seahaven-site-hcptf`. +`sh-openswe-traces` is not imported. The prod/dev stacks are deleted after +that forget. See the first-apply and import runbooks below. **External-dev SHOC role adoption is a staged CloudFormation import, not a normal first deploy.** Six roles exist today: @@ -594,13 +594,12 @@ plan-refresh sidecar. Apply role: scoped IAM statements from `lib/hcptf-bootstrap/scoped-apply-iam.json.tmpl` plus prefix-scoped service wildcards. Do not enumerate provider Get* APIs. -**Import runbook (existing eight prod stacks, PLAT-146).** Import, do not -recreate. Role names and `TFC_AWS_*_ROLE_ARN` stay the same. Pilot is -`afi-backup-monitor` only; do not batch the remaining seven. - -Repos that must change: `afi-backup-monitor`, `front-integrations`, -`paychex-integrations`, `sh-openswe-traces`, `procurement-ingest`, -`seahaven-site`, `meal-order-manager`, `seahaven-door-unlock-api`. +**Import runbook (PLAT-146).** Import, do not recreate. Role names and +`TFC_AWS_*_ROLE_ARN` stay the same. The six live prod pairs are in HCP +state: `afi-backup-monitor`, `front-integrations`, `paychex-integrations`, +`procurement-ingest`, `meal-order-manager`, `seahaven-door-unlock-api`. +`sh-openswe-traces` was decommissioned (PLAT-196) and is not imported. +`seahaven-site` is stack `seahaven-site-hcptf` (PLAT-225), not this template. Repos that do not change: SHOC (`shoc-backend`, `shoc-frontend-new`), remaining SAM / unmigrated stacks. @@ -617,13 +616,14 @@ revoke the extra trust. Lambda `permissions_boundary` may keep pointing at `seahaven-lambda-execution-boundary-` in deploy-substrate for this pass. -**Prod/dev substrate delete (PLAT-147).** After all eight imports: +**Prod/dev substrate delete (PLAT-147).** After the six imports: 1. Inventory `seahaven-hcptf-iam-management` attachments (`scripts/delete-terraform-substrate-prod-dev.sh --account prod --inventory`). None may remain. -2. Remove the eight prod role pairs from the template (they already have +2. Remove the six prod role pairs from the template (they already have `DeletionPolicy: Retain`) so CloudFormation forgets them without deleting. + `sh-openswe-traces` and `seahaven-site` are not in this list. 3. Remove `terraform-substrate-prod` and `terraform-substrate-dev` from `bin/app.ts` and `.github/workflows/deploy.yaml`. Keep `terraform-substrate-external-dev`. diff --git a/lib/terraform-substrate/terraform-substrate.template.yaml b/lib/terraform-substrate/terraform-substrate.template.yaml index 4c7ccbb..2fecce8 100644 --- a/lib/terraform-substrate/terraform-substrate.template.yaml +++ b/lib/terraform-substrate/terraform-substrate.template.yaml @@ -75,10 +75,9 @@ Description: >- # # PER-WORKSPACE ROLE ACCUMULATOR — CLOSED FOR PROD/DEV # Do not append new hcptf- pairs for prod or dev. App Terraform owns -# those roles (PLAT-144/PLAT-146). Six prod pairs stay here with -# DeletionPolicy: Retain until the Retain-remove, then the prod/dev stacks -# delete (PLAT-147). hcptf-sh-openswe-traces and -plan are omitted: the IAM -# roles are already gone (PLAT-196), so this update forgets the logical IDs. +# those roles (PLAT-144/PLAT-146). The six imported prod pairs are removed +# here. Their previous DeletionPolicy is Retain, so CloudFormation forgets +# them (PLAT-147). hcptf-sh-openswe-traces was already forgotten. # seahaven-site lives in seahaven-site-hcptf. External-dev # SHOC roles below remain in this template (PLAT-148). All remaining subs are # exact StringEquals (never StringLike, never a wildcarded run_phase). @@ -396,1790 +395,6 @@ Resources: StringEquals: "iam:PassedToService": "lambda.amazonaws.com" - # --------------------------------------------------------------------------- - # Per-workspace role pattern (required for every future hcptf-* append) - # and first workload: afi-backup-monitor-prod (PLAT-56). - # - # Copy this shape — do not invent enumerated Get* allow-lists. - # - # Plan role (every stack): - # - Managed: ViewOnlyAccess (never ReadOnlyAccess — it grants - # secretsmanager:GetSecretValue / s3:GetObject / kms:Decrypt to - # speculative PR plans). - # - PLUS a stack-scoped plan-refresh sidecar. ViewOnly alone omits - # iam:GetRole, events:DescribeRule, and provider Lambda/S3 reads - # needed after a partial first apply. - # - # Apply role (Lambda / EventBridge stacks): - # - Attach seahaven-hcptf-iam-management. - # - Service grants: prefix-scoped lambda:* on function:-* and - # layer:-*, events:* on rule/-*, and bucket-scoped - # s3:* on the stack artifact bucket. Enumerating provider Get* - # (GetFunctionCodeSigningConfig, GetBucketAcl, …) lags and fails - # first apply (PLAT-56). - # - # Trust: exact StringEquals on organization/project/workspace/run_phase — - # never StringLike, never a wildcarded run_phase. Prod-only for this - # pair (IsProdAccount). See README "Migration checklist". - # --------------------------------------------------------------------------- - HcptfAfiBackupMonitorPlanRole: - Type: AWS::IAM::Role - Condition: IsProdAccount - DeletionPolicy: Retain - UpdateReplacePolicy: Retain - Properties: - RoleName: hcptf-afi-backup-monitor-plan - AssumeRolePolicyDocument: - Version: "2012-10-17" - Statement: - - Effect: Allow - Principal: - Federated: !Sub "arn:aws:iam::${AWS::AccountId}:oidc-provider/app.terraform.io" - Action: sts:AssumeRoleWithWebIdentity - Condition: - StringEquals: - "app.terraform.io:aud": aws.workload.identity - "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:* - 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 - Condition: IsProdAccount - DeletionPolicy: Retain - UpdateReplacePolicy: Retain - Properties: - RoleName: hcptf-afi-backup-monitor - AssumeRolePolicyDocument: - Version: "2012-10-17" - Statement: - - Effect: Allow - Principal: - Federated: !Sub "arn:aws:iam::${AWS::AccountId}:oidc-provider/app.terraform.io" - Action: sts:AssumeRoleWithWebIdentity - Condition: - StringEquals: - "app.terraform.io:aud": aws.workload.identity - "app.terraform.io:sub": organization:seahaven:project:seahaven-prod:workspace:afi-backup-monitor-prod:run_phase:apply - ManagedPolicyArns: - - !Ref HcptfIamManagementPolicy - Policies: - - PolicyName: afi-backup-monitor-services - PolicyDocument: - Version: "2012-10-17" - Statement: - # lambda:*/events:* on stack prefixes — AWS provider reads many - # Get* attributes (e.g. GetFunctionCodeSigningConfig) that lag any - # enumerated allow-list (PLAT-56 first-apply misses). - - Sid: LambdaAll - Effect: Allow - Action: - - lambda:* - 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: LambdaList - Effect: Allow - Action: - - lambda:ListFunctions - - lambda:ListLayers - - lambda:GetAccountSettings - Resource: "*" - - Sid: EventBridgeRules - Effect: Allow - Action: - - events:* - Resource: - - !Sub "arn:aws:events:us-east-1:${AWS::AccountId}:rule/afi-*" - - Sid: CloudWatchLogs - Effect: Allow - Action: - - logs:CreateLogGroup - - logs:DeleteLogGroup - - logs:PutRetentionPolicy - - logs:DeleteRetentionPolicy - - logs:TagResource - - logs:UntagResource - - logs:ListTagsForResource - Resource: - - !Sub "arn:aws:logs:us-east-1:${AWS::AccountId}:log-group:/aws/lambda/afi-*" - # logs:DescribeLogGroups is a collection action — AWS authorises it - # against "*" only. Scoping it to a log-group ARN is a silent no-op - # grant (same pitfall documented on LambdaExecutionBoundary). - - Sid: CloudWatchLogsDescribe - Effect: Allow - Action: - - logs:DescribeLogGroups - Resource: "*" - # Artifact bucket for HCP plan/apply split: zip bytes travel in the - # plan via aws_s3_object content_base64 (local archive_file paths - # from the plan worker are not on the apply worker). Action set is - # s3:* on this bucket only — the AWS provider reads many GetBucket* - # attributes (e.g. GetBucketAcl) after CreateBucket; enumerating - # them lags provider upgrades (PLAT-56 first-apply miss). - - Sid: LambdaArtifactsBucket - Effect: Allow - Action: - - s3:* - Resource: - - !Sub "arn:aws:s3:::afi-backup-monitor-artifacts-${AWS::AccountId}" - - !Sub "arn:aws:s3:::afi-backup-monitor-artifacts-${AWS::AccountId}/*" - - # --------------------------------------------------------------------------- - # front-integrations (PLAT-72) — plan + apply roles for workspace - # front-integrations-prod. Copy shape from afi-backup-monitor above; extend - # for DynamoDB table front-sla-alerts, CloudWatch alarms, and site-alerts SNS. - # --------------------------------------------------------------------------- - HcptfFrontIntegrationsPlanRole: - Type: AWS::IAM::Role - Condition: IsProdAccount - DeletionPolicy: Retain - UpdateReplacePolicy: Retain - Properties: - RoleName: hcptf-front-integrations-plan - AssumeRolePolicyDocument: - Version: "2012-10-17" - Statement: - - Effect: Allow - Principal: - Federated: !Sub "arn:aws:iam::${AWS::AccountId}:oidc-provider/app.terraform.io" - Action: sts:AssumeRoleWithWebIdentity - Condition: - StringEquals: - "app.terraform.io:aud": aws.workload.identity - "app.terraform.io:sub": organization:seahaven:project:seahaven-prod:workspace:front-integrations-prod:run_phase:plan - ManagedPolicyArns: - - arn:aws:iam::aws:policy/job-function/ViewOnlyAccess - Policies: - - PolicyName: front-integrations-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/front-*" - - 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/front-*" - - Sid: RefreshLambda - Effect: Allow - Action: - # Read-only refresh for plan; mutate APIs stay on the apply role. - - lambda:Get* - - lambda:List* - Resource: - - !Sub "arn:aws:lambda:us-east-1:${AWS::AccountId}:function:front-*" - - Sid: RefreshArtifactsBucket - Effect: Allow - Action: - - s3:Get* - - s3:ListBucket - Resource: - - !Sub "arn:aws:s3:::front-integrations-artifacts-${AWS::AccountId}" - - !Sub "arn:aws:s3:::front-integrations-artifacts-${AWS::AccountId}/*" - - Sid: RefreshDynamoDB - Effect: Allow - Action: - - dynamodb:DescribeTable - - dynamodb:DescribeTimeToLive - - dynamodb:DescribeContinuousBackups - - dynamodb:ListTagsOfResource - Resource: - - !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/front-sla-alerts" - - Sid: RefreshCloudWatchAlarms - Effect: Allow - Action: - - cloudwatch:DescribeAlarms - - cloudwatch:ListTagsForResource - Resource: - - !Sub "arn:aws:cloudwatch:us-east-1:${AWS::AccountId}:alarm:front-*" - - Sid: RefreshLogs - Effect: Allow - Action: - - logs:DescribeLogGroups - - logs:ListTagsForResource - Resource: "*" - - HcptfFrontIntegrationsApplyRole: - Type: AWS::IAM::Role - Condition: IsProdAccount - DeletionPolicy: Retain - UpdateReplacePolicy: Retain - Properties: - RoleName: hcptf-front-integrations - AssumeRolePolicyDocument: - Version: "2012-10-17" - Statement: - - Effect: Allow - Principal: - Federated: !Sub "arn:aws:iam::${AWS::AccountId}:oidc-provider/app.terraform.io" - Action: sts:AssumeRoleWithWebIdentity - Condition: - StringEquals: - "app.terraform.io:aud": aws.workload.identity - "app.terraform.io:sub": organization:seahaven:project:seahaven-prod:workspace:front-integrations-prod:run_phase:apply - ManagedPolicyArns: - - !Ref HcptfIamManagementPolicy - Policies: - - PolicyName: front-integrations-services - PolicyDocument: - Version: "2012-10-17" - Statement: - - Sid: LambdaAll - Effect: Allow - Action: - - lambda:* - Resource: - - !Sub "arn:aws:lambda:us-east-1:${AWS::AccountId}:function:front-*" - - Sid: LambdaList - Effect: Allow - Action: - - lambda:ListFunctions - - lambda:ListLayers - - lambda:GetAccountSettings - Resource: "*" - - Sid: EventBridgeRules - Effect: Allow - Action: - - events:* - Resource: - - !Sub "arn:aws:events:us-east-1:${AWS::AccountId}:rule/front-*" - - Sid: CloudWatchLogs - Effect: Allow - Action: - - logs:CreateLogGroup - - logs:DeleteLogGroup - - logs:PutRetentionPolicy - - logs:DeleteRetentionPolicy - - logs:TagResource - - logs:UntagResource - - logs:ListTagsForResource - Resource: - - !Sub "arn:aws:logs:us-east-1:${AWS::AccountId}:log-group:/aws/lambda/front-*" - - Sid: CloudWatchLogsDescribe - Effect: Allow - Action: - - logs:DescribeLogGroups - Resource: "*" - - Sid: LambdaArtifactsBucket - Effect: Allow - Action: - - s3:* - Resource: - - !Sub "arn:aws:s3:::front-integrations-artifacts-${AWS::AccountId}" - - !Sub "arn:aws:s3:::front-integrations-artifacts-${AWS::AccountId}/*" - - Sid: DynamoDBTable - Effect: Allow - Action: - - dynamodb:* - Resource: - - !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/front-sla-alerts" - - !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/front-sla-alerts/index/*" - - Sid: DynamoDBList - Effect: Allow - Action: - - dynamodb:ListTables - Resource: "*" - - Sid: CloudWatchAlarms - Effect: Allow - Action: - - cloudwatch:* - Resource: - - !Sub "arn:aws:cloudwatch:us-east-1:${AWS::AccountId}:alarm:front-*" - - Sid: SiteAlertsSns - Effect: Allow - Action: - - sns:Publish - - sns:GetTopicAttributes - Resource: - - !Sub "arn:aws:sns:us-east-1:${AWS::AccountId}:site-alerts" - - # --------------------------------------------------------------------------- - # paychex-integrations (PLAT-120/123) — plan + apply roles for workspace - # paychex-integrations-prod. Copy shape from front-integrations. Secret - # Get/Put value stays off the apply role. Lambda execution boundary pins - # minted secret ARNs and table paychex-worker-ledger. - # --------------------------------------------------------------------------- - HcptfPaychexIntegrationsPlanRole: - Type: AWS::IAM::Role - Condition: IsProdAccount - DeletionPolicy: Retain - UpdateReplacePolicy: Retain - Properties: - RoleName: hcptf-paychex-integrations-plan - AssumeRolePolicyDocument: - Version: "2012-10-17" - Statement: - - Effect: Allow - Principal: - Federated: !Sub "arn:aws:iam::${AWS::AccountId}:oidc-provider/app.terraform.io" - Action: sts:AssumeRoleWithWebIdentity - Condition: - StringEquals: - "app.terraform.io:aud": aws.workload.identity - "app.terraform.io:sub": organization:seahaven:project:seahaven-prod:workspace:paychex-integrations-prod:run_phase:plan - ManagedPolicyArns: - - arn:aws:iam::aws:policy/job-function/ViewOnlyAccess - Policies: - - PolicyName: paychex-integrations-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/paychex-*" - - Sid: RefreshManagedPolicies - Effect: Allow - Action: - - iam:GetPolicy - - iam:GetPolicyVersion - Resource: "*" - - Sid: RefreshLambda - Effect: Allow - Action: - - lambda:Get* - Resource: - - !Sub "arn:aws:lambda:us-east-1:${AWS::AccountId}:function:paychex-*" - # Collection/list APIs authorize only against Resource "*". - - Sid: RefreshLambdaList - Effect: Allow - Action: - - lambda:ListFunctions - - lambda:GetAccountSettings - Resource: "*" - - Sid: RefreshArtifactsBucket - Effect: Allow - Action: - - s3:Get* - - s3:ListBucket - Resource: - - !Sub "arn:aws:s3:::paychex-integrations-artifacts-${AWS::AccountId}" - - !Sub "arn:aws:s3:::paychex-integrations-artifacts-${AWS::AccountId}/*" - - Sid: RefreshCloudWatchAlarms - Effect: Allow - Action: - - cloudwatch:DescribeAlarms - - cloudwatch:ListTagsForResource - Resource: - - !Sub "arn:aws:cloudwatch:us-east-1:${AWS::AccountId}:alarm:paychex-*" - - Sid: RefreshLogs - Effect: Allow - Action: - - logs:DescribeLogGroups - - logs:ListTagsForResource - Resource: "*" - - Sid: RefreshSecrets - Effect: Allow - Action: - - secretsmanager:DescribeSecret - - secretsmanager:GetResourcePolicy - - secretsmanager:ListSecretVersionIds - Resource: - - !Sub "arn:aws:secretsmanager:us-east-1:${AWS::AccountId}:secret:paychex-integrations/*" - - Sid: RefreshDynamoDB - Effect: Allow - Action: - - dynamodb:DescribeTable - - dynamodb:DescribeTimeToLive - - dynamodb:DescribeContinuousBackups - - dynamodb:ListTagsOfResource - Resource: - - !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/paychex-worker-ledger" - - HcptfPaychexIntegrationsApplyRole: - Type: AWS::IAM::Role - Condition: IsProdAccount - DeletionPolicy: Retain - UpdateReplacePolicy: Retain - Properties: - RoleName: hcptf-paychex-integrations - AssumeRolePolicyDocument: - Version: "2012-10-17" - Statement: - - Effect: Allow - Principal: - Federated: !Sub "arn:aws:iam::${AWS::AccountId}:oidc-provider/app.terraform.io" - Action: sts:AssumeRoleWithWebIdentity - Condition: - StringEquals: - "app.terraform.io:aud": aws.workload.identity - "app.terraform.io:sub": organization:seahaven:project:seahaven-prod:workspace:paychex-integrations-prod:run_phase:apply - ManagedPolicyArns: - - !Ref HcptfIamManagementPolicy - Policies: - - PolicyName: paychex-integrations-services - PolicyDocument: - Version: "2012-10-17" - Statement: - - Sid: LambdaAll - Effect: Allow - Action: - - lambda:* - Resource: - - !Sub "arn:aws:lambda:us-east-1:${AWS::AccountId}:function:paychex-*" - - Sid: LambdaList - Effect: Allow - Action: - - lambda:ListFunctions - - lambda:ListLayers - - lambda:GetAccountSettings - Resource: "*" - - Sid: CloudWatchLogs - Effect: Allow - Action: - - logs:CreateLogGroup - - logs:DeleteLogGroup - - logs:PutRetentionPolicy - - logs:DeleteRetentionPolicy - - logs:TagResource - - logs:UntagResource - - logs:ListTagsForResource - Resource: - - !Sub "arn:aws:logs:us-east-1:${AWS::AccountId}:log-group:/aws/lambda/paychex-*" - - Sid: CloudWatchLogsDescribe - Effect: Allow - Action: - - logs:DescribeLogGroups - Resource: "*" - - Sid: LambdaArtifactsBucket - Effect: Allow - Action: - - s3:* - Resource: - - !Sub "arn:aws:s3:::paychex-integrations-artifacts-${AWS::AccountId}" - - !Sub "arn:aws:s3:::paychex-integrations-artifacts-${AWS::AccountId}/*" - - Sid: CloudWatchAlarms - Effect: Allow - Action: - - cloudwatch:* - Resource: - - !Sub "arn:aws:cloudwatch:us-east-1:${AWS::AccountId}:alarm:paychex-*" - - Sid: SiteAlertsSns - Effect: Allow - Action: - - sns:Publish - - sns:GetTopicAttributes - Resource: - - !Sub "arn:aws:sns:us-east-1:${AWS::AccountId}:site-alerts" - - Sid: PaychexSecretShell - Effect: Allow - Action: - - secretsmanager:DeleteSecret - - secretsmanager:DescribeSecret - - secretsmanager:GetResourcePolicy - - secretsmanager:PutResourcePolicy - - secretsmanager:DeleteResourcePolicy - - secretsmanager:TagResource - - secretsmanager:UntagResource - Resource: - - !Sub "arn:aws:secretsmanager:us-east-1:${AWS::AccountId}:secret:paychex-integrations/*" - - Sid: PaychexSecretCreate - Effect: Allow - Action: - - secretsmanager:CreateSecret - Resource: "*" - Condition: - StringEquals: - "secretsmanager:Name": - - paychex-integrations/oauth-client - - paychex-integrations/webhook-api-key - - paychex-integrations/google-service-account - - paychex-integrations/slack-bot-token - - paychex-integrations/front-inboxes-write - - paychex-integrations/3cx-system-admin - - Sid: DynamoDBTable - Effect: Allow - Action: - - dynamodb:* - Resource: - - !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/paychex-worker-ledger" - - !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/paychex-worker-ledger/index/*" - - Sid: DynamoDBList - Effect: Allow - Action: - - dynamodb:ListTables - Resource: "*" - - # --------------------------------------------------------------------------- - # procurement-ingest (PLAT-86) — plan + apply roles for workspace - # procurement-ingest-prod. Import-in-place of three former CDK stacks - # (po-ingest, WorkorderIngestStack, procurement-api). Copy shape from - # front-integrations; extend for S3 email buckets, SQS, SES receipt rules, - # API Gateway, KMS (SHOC + DynamoDB CMK manage), Secrets Manager shell/ - # rotation, DynamoDB streams, and prefix-scoped Lambda/alarms/log groups. - # --------------------------------------------------------------------------- - HcptfProcurementIngestPlanRole: - Type: AWS::IAM::Role - Condition: IsProdAccount - DeletionPolicy: Retain - UpdateReplacePolicy: Retain - Properties: - RoleName: hcptf-procurement-ingest-plan - AssumeRolePolicyDocument: - Version: "2012-10-17" - Statement: - - Effect: Allow - Principal: - Federated: !Sub "arn:aws:iam::${AWS::AccountId}:oidc-provider/app.terraform.io" - Action: sts:AssumeRoleWithWebIdentity - Condition: - StringEquals: - "app.terraform.io:aud": aws.workload.identity - "app.terraform.io:sub": organization:seahaven:project:seahaven-prod:workspace:procurement-ingest-prod:run_phase:plan - ManagedPolicyArns: - - arn:aws:iam::aws:policy/job-function/ViewOnlyAccess - Policies: - - PolicyName: procurement-ingest-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/po-*" - - !Sub "arn:aws:iam::${AWS::AccountId}:role/tf-managed/workorder-*" - - !Sub "arn:aws:iam::${AWS::AccountId}:role/tf-managed/procurement-api" - - Sid: RefreshManagedPolicies - Effect: Allow - Action: - - iam:GetPolicy - - iam:GetPolicyVersion - Resource: "*" - - Sid: RefreshLambda - Effect: Allow - Action: - - lambda:Get* - Resource: - - !Sub "arn:aws:lambda:us-east-1:${AWS::AccountId}:function:po-*" - - !Sub "arn:aws:lambda:us-east-1:${AWS::AccountId}:function:workorder-*" - - !Sub "arn:aws:lambda:us-east-1:${AWS::AccountId}:function:procurement-api" - # Collection/list APIs authorize only against Resource "*". - # GetEventSourceMapping is authorized on the UUID mapping ARN - # (no FunctionArn in the request context), so it cannot share - # the apply-role FunctionArn condition. - - Sid: RefreshLambdaList - Effect: Allow - Action: - - lambda:ListFunctions - - lambda:ListEventSourceMappings - - lambda:GetEventSourceMapping - - lambda:GetAccountSettings - Resource: "*" - - Sid: RefreshArtifactsBucket - Effect: Allow - Action: - - s3:Get* - - s3:ListBucket - Resource: - - !Sub "arn:aws:s3:::procurement-ingest-artifacts-${AWS::AccountId}" - - !Sub "arn:aws:s3:::procurement-ingest-artifacts-${AWS::AccountId}/*" - - Sid: RefreshEmailBuckets - Effect: Allow - Action: - - s3:Get* - - s3:ListBucket - - s3:GetBucketNotification - - s3:GetBucketPolicy - - s3:GetEncryptionConfiguration - - s3:GetBucketTagging - - s3:GetBucketVersioning - - s3:GetBucketPublicAccessBlock - Resource: - - !Sub "arn:aws:s3:::po-ingest-emails-${AWS::AccountId}" - - !Sub "arn:aws:s3:::po-ingest-emails-${AWS::AccountId}/*" - - !Sub "arn:aws:s3:::workorder-ingest-emails-${AWS::AccountId}" - - !Sub "arn:aws:s3:::workorder-ingest-emails-${AWS::AccountId}/*" - - Sid: RefreshDynamoDB - Effect: Allow - Action: - - dynamodb:DescribeTable - - dynamodb:DescribeTimeToLive - - dynamodb:DescribeContinuousBackups - - dynamodb:DescribeStream - - dynamodb:ListTagsOfResource - Resource: - - !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/purchase-orders" - - !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/purchase-orders/*" - - !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/verified-sites" - - !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/pending-site-review" - - !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/work-orders" - - !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/work-orders/*" - - !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/work-order-comments" - - !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/work-order-comments/*" - - Sid: RefreshDynamoDBList - Effect: Allow - Action: - - dynamodb:ListStreams - - dynamodb:ListTables - Resource: "*" - - Sid: RefreshSqs - Effect: Allow - Action: - - sqs:GetQueueAttributes - - sqs:GetQueueUrl - - sqs:ListQueueTags - Resource: - - !Sub "arn:aws:sqs:us-east-1:${AWS::AccountId}:po-ingest-*" - - !Sub "arn:aws:sqs:us-east-1:${AWS::AccountId}:WorkorderIngestStack-*" - - !Sub "arn:aws:sqs:us-east-1:${AWS::AccountId}:workorder-shoc-emitter-*" - - Sid: RefreshCloudWatchAlarms - Effect: Allow - Action: - - cloudwatch:DescribeAlarms - - cloudwatch:ListTagsForResource - Resource: - - !Sub "arn:aws:cloudwatch:us-east-1:${AWS::AccountId}:alarm:po-*" - - !Sub "arn:aws:cloudwatch:us-east-1:${AWS::AccountId}:alarm:workorder-*" - - !Sub "arn:aws:cloudwatch:us-east-1:${AWS::AccountId}:alarm:procurement-api-*" - - !Sub "arn:aws:cloudwatch:us-east-1:${AWS::AccountId}:alarm:purchase-orders-*" - - !Sub "arn:aws:cloudwatch:us-east-1:${AWS::AccountId}:alarm:verified-sites-*" - - !Sub "arn:aws:cloudwatch:us-east-1:${AWS::AccountId}:alarm:pending-site-review-*" - - !Sub "arn:aws:cloudwatch:us-east-1:${AWS::AccountId}:alarm:work-orders-*" - - !Sub "arn:aws:cloudwatch:us-east-1:${AWS::AccountId}:alarm:work-order-comments-*" - - Sid: RefreshApiGateway - Effect: Allow - Action: - - apigateway:GET - Resource: - - !Sub "arn:aws:apigateway:us-east-1::/restapis/mvul1efda2" - - !Sub "arn:aws:apigateway:us-east-1::/restapis/mvul1efda2/*" - - arn:aws:apigateway:us-east-1::/domainnames/procurement-api.seahaven.com - - arn:aws:apigateway:us-east-1::/domainnames/procurement-api.seahaven.com/* - - Sid: RefreshKms - Effect: Allow - Action: - - kms:DescribeKey - - kms:GetKeyPolicy - - kms:GetKeyRotationStatus - - kms:ListResourceTags - Resource: - - !Sub "arn:aws:kms:us-east-1:${AWS::AccountId}:key/*" - - !Sub "arn:aws:kms:us-east-1:${AWS::AccountId}:alias/workorder-ingest-shoc-webhook-kms" - # ListAliases/ListKeys are collection APIs (Resource "*"). - - Sid: RefreshKmsList - Effect: Allow - Action: - - kms:ListAliases - - kms:ListKeys - Resource: "*" - - Sid: RefreshSecrets - Effect: Allow - Action: - - secretsmanager:DescribeSecret - - secretsmanager:GetResourcePolicy - - secretsmanager:ListSecretVersionIds - Resource: - - !Sub "arn:aws:secretsmanager:us-east-1:${AWS::AccountId}:secret:workorder-ingest/shoc-webhook-hmac-*" - - !Sub "arn:aws:secretsmanager:us-east-1:${AWS::AccountId}:secret:procurement-ingest/web-ui-auth-token-*" - # OOB SSM pins used by data.aws_ssm_parameter (not in ViewOnlyAccess). - - Sid: RefreshSsm - Effect: Allow - Action: - - ssm:GetParameter - - ssm:GetParameters - Resource: - - !Sub "arn:aws:ssm:us-east-1:${AWS::AccountId}:parameter/seahaven/dynamodb/cmk-arn" - - !Sub "arn:aws:ssm:us-east-1:${AWS::AccountId}:parameter/procurement-api/custom-domain/certificate-arn" - - Sid: RefreshSes - Effect: Allow - Action: - - ses:DescribeReceiptRule - - ses:DescribeReceiptRuleSet - Resource: "*" - - Sid: RefreshLogs - Effect: Allow - Action: - - logs:DescribeLogGroups - - logs:DescribeMetricFilters - - logs:ListTagsForResource - Resource: "*" - - HcptfProcurementIngestApplyRole: - Type: AWS::IAM::Role - Condition: IsProdAccount - DeletionPolicy: Retain - UpdateReplacePolicy: Retain - Properties: - RoleName: hcptf-procurement-ingest - AssumeRolePolicyDocument: - Version: "2012-10-17" - Statement: - - Effect: Allow - Principal: - Federated: !Sub "arn:aws:iam::${AWS::AccountId}:oidc-provider/app.terraform.io" - Action: sts:AssumeRoleWithWebIdentity - Condition: - StringEquals: - "app.terraform.io:aud": aws.workload.identity - "app.terraform.io:sub": organization:seahaven:project:seahaven-prod:workspace:procurement-ingest-prod:run_phase:apply - ManagedPolicyArns: - - !Ref HcptfIamManagementPolicy - Policies: - - PolicyName: procurement-ingest-services - PolicyDocument: - Version: "2012-10-17" - Statement: - - Sid: LambdaAll - Effect: Allow - Action: - - lambda:* - Resource: - - !Sub "arn:aws:lambda:us-east-1:${AWS::AccountId}:function:po-*" - - !Sub "arn:aws:lambda:us-east-1:${AWS::AccountId}:function:workorder-*" - - !Sub "arn:aws:lambda:us-east-1:${AWS::AccountId}:function:procurement-api" - # Event source mapping ARNs are UUID-keyed; AWS authorises Create against - # FunctionArn. Mutating Get/Update/Delete also take the mapping ARN. - # GetEventSourceMapping by UUID does not carry FunctionArn in the - # request context, so read is unconditioned on "*"; mutate stays - # FunctionArn-constrained. - - Sid: LambdaEventSourceMappingRead - Effect: Allow - Action: - - lambda:GetEventSourceMapping - - lambda:ListTags - # Tag/Untag on ESM UUID ARNs do not carry FunctionArn in the - # request context (provider default_tags on import). - - lambda:TagResource - - lambda:UntagResource - Resource: "*" - - Sid: LambdaEventSourceMappings - Effect: Allow - Action: - - lambda:CreateEventSourceMapping - - lambda:DeleteEventSourceMapping - - lambda:UpdateEventSourceMapping - Resource: "*" - Condition: - "ForAnyValue:StringLike": - "lambda:FunctionArn": - - !Sub "arn:aws:lambda:us-east-1:${AWS::AccountId}:function:po-*" - - !Sub "arn:aws:lambda:us-east-1:${AWS::AccountId}:function:workorder-*" - - !Sub "arn:aws:lambda:us-east-1:${AWS::AccountId}:function:procurement-api" - - Sid: LambdaList - Effect: Allow - Action: - - lambda:ListFunctions - - lambda:ListEventSourceMappings - - lambda:GetAccountSettings - Resource: "*" - - Sid: SsmRead - Effect: Allow - Action: - - ssm:GetParameter - - ssm:GetParameters - Resource: - - !Sub "arn:aws:ssm:us-east-1:${AWS::AccountId}:parameter/seahaven/dynamodb/cmk-arn" - - !Sub "arn:aws:ssm:us-east-1:${AWS::AccountId}:parameter/procurement-api/custom-domain/certificate-arn" - - Sid: CloudWatchLogs - Effect: Allow - Action: - - logs:CreateLogGroup - - logs:DeleteLogGroup - - logs:PutRetentionPolicy - - logs:DeleteRetentionPolicy - - logs:TagResource - - logs:UntagResource - - logs:ListTagsForResource - - logs:PutMetricFilter - - logs:DeleteMetricFilter - - logs:DescribeMetricFilters - Resource: - - !Sub "arn:aws:logs:us-east-1:${AWS::AccountId}:log-group:/aws/lambda/po-*" - - !Sub "arn:aws:logs:us-east-1:${AWS::AccountId}:log-group:/aws/lambda/workorder-*" - - !Sub "arn:aws:logs:us-east-1:${AWS::AccountId}:log-group:/aws/lambda/procurement-api*" - - Sid: CloudWatchLogsDescribe - Effect: Allow - Action: - - logs:DescribeLogGroups - Resource: "*" - - Sid: ArtifactsBucket - Effect: Allow - Action: - - s3:* - Resource: - - !Sub "arn:aws:s3:::procurement-ingest-artifacts-${AWS::AccountId}" - - !Sub "arn:aws:s3:::procurement-ingest-artifacts-${AWS::AccountId}/*" - - Sid: EmailBuckets - Effect: Allow - Action: - - s3:* - Resource: - - !Sub "arn:aws:s3:::po-ingest-emails-${AWS::AccountId}" - - !Sub "arn:aws:s3:::po-ingest-emails-${AWS::AccountId}/*" - - !Sub "arn:aws:s3:::workorder-ingest-emails-${AWS::AccountId}" - - !Sub "arn:aws:s3:::workorder-ingest-emails-${AWS::AccountId}/*" - - Sid: DynamoDBTables - Effect: Allow - Action: - - dynamodb:* - Resource: - - !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/purchase-orders" - - !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/purchase-orders/*" - - !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/verified-sites" - - !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/verified-sites/*" - - !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/pending-site-review" - - !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/pending-site-review/*" - - !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/work-orders" - - !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/work-orders/*" - - !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/work-order-comments" - - !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/work-order-comments/*" - - Sid: DynamoDBList - Effect: Allow - Action: - - dynamodb:ListTables - - dynamodb:ListStreams - Resource: "*" - - Sid: SqsQueues - Effect: Allow - Action: - - sqs:* - Resource: - - !Sub "arn:aws:sqs:us-east-1:${AWS::AccountId}:po-ingest-*" - - !Sub "arn:aws:sqs:us-east-1:${AWS::AccountId}:WorkorderIngestStack-*" - - !Sub "arn:aws:sqs:us-east-1:${AWS::AccountId}:workorder-shoc-emitter-*" - - Sid: CloudWatchAlarms - Effect: Allow - Action: - - cloudwatch:* - Resource: - - !Sub "arn:aws:cloudwatch:us-east-1:${AWS::AccountId}:alarm:po-*" - - !Sub "arn:aws:cloudwatch:us-east-1:${AWS::AccountId}:alarm:workorder-*" - - !Sub "arn:aws:cloudwatch:us-east-1:${AWS::AccountId}:alarm:procurement-api-*" - - !Sub "arn:aws:cloudwatch:us-east-1:${AWS::AccountId}:alarm:purchase-orders-*" - - !Sub "arn:aws:cloudwatch:us-east-1:${AWS::AccountId}:alarm:verified-sites-*" - - !Sub "arn:aws:cloudwatch:us-east-1:${AWS::AccountId}:alarm:pending-site-review-*" - - !Sub "arn:aws:cloudwatch:us-east-1:${AWS::AccountId}:alarm:work-orders-*" - - !Sub "arn:aws:cloudwatch:us-east-1:${AWS::AccountId}:alarm:work-order-comments-*" - - Sid: SiteAlertsSns - Effect: Allow - Action: - - sns:Publish - - sns:GetTopicAttributes - - sns:ListTagsForResource - Resource: - - !Sub "arn:aws:sns:us-east-1:${AWS::AccountId}:site-alerts" - - Sid: ApiGateway - Effect: Allow - Action: - - apigateway:* - Resource: - - !Sub "arn:aws:apigateway:us-east-1::/restapis/mvul1efda2" - - !Sub "arn:aws:apigateway:us-east-1::/restapis/mvul1efda2/*" - - arn:aws:apigateway:us-east-1::/domainnames/procurement-api.seahaven.com - - arn:aws:apigateway:us-east-1::/domainnames/procurement-api.seahaven.com/* - # TagResource/UntagResource authorize against /tags/. - - arn:aws:apigateway:us-east-1::/tags/* - - Sid: SesReceiptRules - Effect: Allow - Action: - - ses:CreateReceiptRule - - ses:UpdateReceiptRule - - ses:DeleteReceiptRule - - ses:DescribeReceiptRule - - ses:SetReceiptRulePosition - Resource: - - !Sub "arn:aws:ses:us-east-1:${AWS::AccountId}:receipt-rule-set/INBOUND_MAIL:receipt-rule/ExistingRuleSetPoEmailRuleAC8E9C87-qwGDj9lBoL1G" - - !Sub "arn:aws:ses:us-east-1:${AWS::AccountId}:receipt-rule-set/INBOUND_MAIL:receipt-rule/ExistingRuleSetWorkorderEmailRuleEA29F845-PKtaDBvIg61a" - - Sid: SesDescribeRuleSet - Effect: Allow - Action: - - ses:DescribeReceiptRuleSet - Resource: "*" - # Key management only on the live SHOC CMK — no kms:* (excludes - # unconstrained key-policy/destructive ops on other keys and - # avoids data-plane Encrypt/Decrypt on the apply role). - - Sid: ShocKms - Effect: Allow - Action: - - kms:DescribeKey - - kms:GetKeyPolicy - - kms:GetKeyRotationStatus - - kms:ListResourceTags - - kms:PutKeyPolicy - - kms:EnableKeyRotation - - kms:DisableKeyRotation - - kms:ScheduleKeyDeletion - - kms:CancelKeyDeletion - - kms:TagResource - - kms:UntagResource - - kms:EnableKey - - kms:DisableKey - Resource: - - !Sub "arn:aws:kms:us-east-1:${AWS::AccountId}:key/d10fd1f0-a61a-4405-8568-85e9fd11ba18" - - Sid: KmsList - Effect: Allow - Action: - - kms:ListAliases - - kms:ListKeys - Resource: "*" - - Sid: ShocKmsAlias - Effect: Allow - Action: - - kms:CreateAlias - - kms:DeleteAlias - - kms:UpdateAlias - Resource: - - !Sub "arn:aws:kms:us-east-1:${AWS::AccountId}:alias/workorder-ingest-shoc-webhook-kms" - - !Sub "arn:aws:kms:us-east-1:${AWS::AccountId}:key/d10fd1f0-a61a-4405-8568-85e9fd11ba18" - # Shell lifecycle only — no CreateSecret / UpdateSecret so apply - # never writes SecretString into HCP state or run logs. Create is - # isolated in ShocSecretCreate with an exact Name pin. - - Sid: ShocSecretShell - Effect: Allow - Action: - - secretsmanager:DeleteSecret - - secretsmanager:DescribeSecret - - secretsmanager:GetResourcePolicy - - secretsmanager:PutResourcePolicy - - secretsmanager:DeleteResourcePolicy - - secretsmanager:TagResource - - secretsmanager:UntagResource - - secretsmanager:RotateSecret - - secretsmanager:CancelRotateSecret - - secretsmanager:UpdateSecretVersionStage - Resource: - - !Sub "arn:aws:secretsmanager:us-east-1:${AWS::AccountId}:secret:workorder-ingest/shoc-webhook-hmac-*" - - Sid: ShocSecretCreate - Effect: Allow - Action: - - secretsmanager:CreateSecret - Resource: "*" - Condition: - StringEquals: - "secretsmanager:Name": workorder-ingest/shoc-webhook-hmac - - Sid: WebUiSecretDescribe - Effect: Allow - Action: - - secretsmanager:DescribeSecret - - secretsmanager:GetResourcePolicy - Resource: - - !Sub "arn:aws:secretsmanager:us-east-1:${AWS::AccountId}:secret:procurement-ingest/web-ui-auth-token-*" - - # seahaven-site-prod exec roles moved to stack seahaven-site-hcptf (PLAT-225). - # DeletionPolicy on the removed resources was Retain, so dropping them here - # keeps the live roles for that stack to import. - - # --------------------------------------------------------------------------- - # meal-order-manager-prod (PLAT-70, imported to the app workspace in PLAT-146). - # Live plan/apply IAM is terraform/hcp_iam.tf in meal-order-manager (ECS/ALB - # as of PLAT-215). Do not mutate these CFN role policies; they are Retain - # leftovers. githubdeploy-meal-order-manager OIDC lives in that app module. - # --------------------------------------------------------------------------- - # Original shape: HttpApi + Lambdas + DynamoDB + S3 + CloudFront. - # Plan role: ViewOnly + plan-refresh sidecar. Apply role: HcptfIamManagement - # + prefix-scoped service wildcards (no enumerated Get* lists). - # --------------------------------------------------------------------------- - HcptfMealOrderManagerPlanRole: - Type: AWS::IAM::Role - Condition: IsProdAccount - DeletionPolicy: Retain - UpdateReplacePolicy: Retain - Properties: - RoleName: hcptf-meal-order-manager-plan - AssumeRolePolicyDocument: - Version: "2012-10-17" - Statement: - - Effect: Allow - Principal: - Federated: !Sub "arn:aws:iam::${AWS::AccountId}:oidc-provider/app.terraform.io" - Action: sts:AssumeRoleWithWebIdentity - Condition: - StringEquals: - "app.terraform.io:aud": aws.workload.identity - "app.terraform.io:sub": organization:seahaven:project:seahaven-prod:workspace:meal-order-manager-prod:run_phase:plan - ManagedPolicyArns: - - arn:aws:iam::aws:policy/job-function/ViewOnlyAccess - Policies: - - PolicyName: meal-order-manager-plan-refresh - PolicyDocument: - Version: "2012-10-17" - Statement: - - Sid: RefreshIamRoles - Effect: Allow - Action: - - iam:GetRole - - iam:GetRolePolicy - - iam:ListRolePolicies - - iam:ListAttachedRolePolicies - - iam:ListRoleTags - Resource: - - !Sub "arn:aws:iam::${AWS::AccountId}:role/tf-managed/meal-order-manager-*" - - !Sub "arn:aws:iam::${AWS::AccountId}:role/tf-managed/githubdeploy-meal-order-manager*" - - 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/meal-order-manager-*" - - Sid: RefreshLambda - Effect: Allow - Action: - # Read-only refresh for plan; mutate APIs stay on the apply role. - - lambda:Get* - - lambda:List* - Resource: - - !Sub "arn:aws:lambda:us-east-1:${AWS::AccountId}:function:meal-order-manager-*" - - !Sub "arn:aws:lambda:us-east-1:${AWS::AccountId}:layer:meal-order-manager-*" - - Sid: RefreshBuckets - Effect: Allow - Action: - - s3:Get* - - s3:ListBucket - Resource: - - !Sub "arn:aws:s3:::meal-order-manager-artifacts-${AWS::AccountId}" - - !Sub "arn:aws:s3:::meal-order-manager-artifacts-${AWS::AccountId}/*" - - !Sub "arn:aws:s3:::meal-order-manager-form-${AWS::AccountId}" - - !Sub "arn:aws:s3:::meal-order-manager-form-${AWS::AccountId}/*" - - !Sub "arn:aws:s3:::meal-order-manager-reports-${AWS::AccountId}" - - !Sub "arn:aws:s3:::meal-order-manager-reports-${AWS::AccountId}/*" - - Sid: RefreshDynamoDB - Effect: Allow - Action: - - dynamodb:DescribeTable - - dynamodb:DescribeTimeToLive - - dynamodb:DescribeContinuousBackups - - dynamodb:ListTagsOfResource - Resource: - - !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/meal-order-manager-orders" - - Sid: RefreshLogs - Effect: Allow - Action: - - logs:DescribeLogGroups - - logs:ListTagsForResource - Resource: "*" - - Sid: RefreshCloudFront - Effect: Allow - Action: - - cloudfront:Get* - - cloudfront:List* - Resource: "*" - - Sid: RefreshAcm - Effect: Allow - Action: - - acm:DescribeCertificate - - acm:ListCertificates - - acm:ListTagsForCertificate - - acm:GetCertificate - Resource: "*" - - Sid: RefreshAppWebAclSsm - Effect: Allow - Action: - - ssm:GetParameter - - ssm:GetParameters - # aws_ssm_parameter refresh lists tags on managed parameters. - - ssm:ListTagsForResource - Resource: - - !Sub "arn:aws:ssm:us-east-1:${AWS::AccountId}:parameter/seahaven/waf/app-web-acl-arn" - - !Sub "arn:aws:ssm:us-east-1:${AWS::AccountId}:parameter/meal-order-manager/*" - # aws_ssm_parameter refresh uses DescribeParameters (collection API; - # resource-level parameter ARNs are a silent no-op for this action). - - Sid: RefreshSsmDescribeParameters - Effect: Allow - Action: - - ssm:DescribeParameters - Resource: "*" - - Sid: RefreshWafWebAcl - Effect: Allow - Action: - - wafv2:GetWebACL - - wafv2:ListWebACLs - Resource: "*" - - Sid: RefreshHttpApi - Effect: Allow - Action: - - apigateway:GET - Resource: - - !Sub "arn:aws:apigateway:us-east-1::/apis/*" - - !Sub "arn:aws:apigateway:us-east-1::/tags/*" - - Sid: RefreshAlarms - Effect: Allow - Action: - - cloudwatch:DescribeAlarms - - cloudwatch:ListTagsForResource - Resource: "*" - - HcptfMealOrderManagerApplyRole: - Type: AWS::IAM::Role - Condition: IsProdAccount - DeletionPolicy: Retain - UpdateReplacePolicy: Retain - Properties: - RoleName: hcptf-meal-order-manager - AssumeRolePolicyDocument: - Version: "2012-10-17" - Statement: - - Effect: Allow - Principal: - Federated: !Sub "arn:aws:iam::${AWS::AccountId}:oidc-provider/app.terraform.io" - Action: sts:AssumeRoleWithWebIdentity - Condition: - StringEquals: - "app.terraform.io:aud": aws.workload.identity - "app.terraform.io:sub": organization:seahaven:project:seahaven-prod:workspace:meal-order-manager-prod:run_phase:apply - ManagedPolicyArns: - - !Ref HcptfIamManagementPolicy - Policies: - - PolicyName: meal-order-manager-services - PolicyDocument: - Version: "2012-10-17" - Statement: - - Sid: LambdaAll - Effect: Allow - Action: - - lambda:* - Resource: - - !Sub "arn:aws:lambda:us-east-1:${AWS::AccountId}:function:meal-order-manager-*" - - !Sub "arn:aws:lambda:us-east-1:${AWS::AccountId}:layer:meal-order-manager-*" - - Sid: LambdaList - Effect: Allow - Action: - - lambda:ListFunctions - - lambda:ListLayers - - lambda:GetAccountSettings - Resource: "*" - - Sid: EventBridgeRules - Effect: Allow - Action: - - events:* - Resource: - - !Sub "arn:aws:events:us-east-1:${AWS::AccountId}:rule/meal-order-manager-*" - - Sid: CloudWatchLogs - Effect: Allow - Action: - - logs:CreateLogGroup - - logs:DeleteLogGroup - - logs:PutRetentionPolicy - - logs:DeleteRetentionPolicy - - logs:TagResource - - logs:UntagResource - - logs:ListTagsForResource - - logs:PutMetricFilter - - logs:DeleteMetricFilter - - logs:DescribeMetricFilters - Resource: - - !Sub "arn:aws:logs:us-east-1:${AWS::AccountId}:log-group:/aws/lambda/meal-order-manager-*" - - !Sub "arn:aws:logs:us-east-1:${AWS::AccountId}:log-group:/aws/apigateway/meal-order-manager*" - - Sid: CloudWatchLogsDescribe - Effect: Allow - Action: - - logs:DescribeLogGroups - Resource: "*" - # HTTP API stage access_log_settings uses Log Delivery APIs - # (account-level Resource "*"). PutResourcePolicy is intentionally - # omitted: MealOrderApiAccessLogResourcePolicy below pre-grants - # delivery.logs.amazonaws.com on the meal-order API log group so - # the apply role cannot mutate account-wide log resource policies. - - Sid: MealOrderApiGwAccessLogDelivery - Effect: Allow - Action: - - logs:CreateLogDelivery - - logs:GetLogDelivery - - logs:UpdateLogDelivery - - logs:DeleteLogDelivery - - logs:ListLogDeliveries - - logs:DescribeResourcePolicies - Resource: "*" - - Sid: StackBuckets - Effect: Allow - Action: - - s3:* - Resource: - - !Sub "arn:aws:s3:::meal-order-manager-artifacts-${AWS::AccountId}" - - !Sub "arn:aws:s3:::meal-order-manager-artifacts-${AWS::AccountId}/*" - - !Sub "arn:aws:s3:::meal-order-manager-form-${AWS::AccountId}" - - !Sub "arn:aws:s3:::meal-order-manager-form-${AWS::AccountId}/*" - - !Sub "arn:aws:s3:::meal-order-manager-reports-${AWS::AccountId}" - - !Sub "arn:aws:s3:::meal-order-manager-reports-${AWS::AccountId}/*" - - Sid: DynamoDBTable - Effect: Allow - Action: - - dynamodb:* - Resource: - - !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/meal-order-manager-orders" - - !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/meal-order-manager-orders/*" - - Sid: DynamoDBList - Effect: Allow - Action: - - dynamodb:ListTables - Resource: "*" - - Sid: HttpApiManage - Effect: Allow - Action: - - apigateway:* - Resource: - - !Sub "arn:aws:apigateway:us-east-1::/apis" - - !Sub "arn:aws:apigateway:us-east-1::/apis/*" - - !Sub "arn:aws:apigateway:us-east-1::/tags/*" - - !Sub "arn:aws:apigateway:us-east-1::/vpclinks" - - !Sub "arn:aws:apigateway:us-east-1::/vpclinks/*" - - Sid: CloudFrontManage - Effect: Allow - Action: - - cloudfront:* - Resource: "*" - - Sid: AcmCreate - Effect: Allow - Action: - - acm:RequestCertificate - Resource: "*" - Condition: - StringEquals: - "aws:RequestTag/Project": meal-order-manager - - Sid: AcmList - Effect: Allow - Action: - - acm:ListCertificates - - acm:ListTagsForCertificate - Resource: "*" - - Sid: AcmManageTagged - Effect: Allow - Action: - - acm:DescribeCertificate - - acm:GetCertificate - - acm:DeleteCertificate - - acm:AddTagsToCertificate - - acm:RemoveTagsFromCertificate - - acm:RenewCertificate - Resource: "*" - Condition: - StringEquals: - "aws:ResourceTag/Project": meal-order-manager - - Sid: ReadAppWebAclSsm - Effect: Allow - Action: - - ssm:GetParameter - - ssm:GetParameters - Resource: - - !Sub "arn:aws:ssm:us-east-1:${AWS::AccountId}:parameter/seahaven/waf/app-web-acl-arn" - - Sid: MealOrderSsm - Effect: Allow - Action: - - ssm:GetParameter - - ssm:GetParameters - - ssm:PutParameter - - ssm:DeleteParameter - - ssm:AddTagsToResource - - ssm:RemoveTagsFromResource - - ssm:ListTagsForResource - Resource: - - !Sub "arn:aws:ssm:us-east-1:${AWS::AccountId}:parameter/meal-order-manager/*" - # Collection API required for aws_ssm_parameter refresh/import. - - Sid: MealOrderSsmDescribeParameters - Effect: Allow - Action: - - ssm:DescribeParameters - Resource: "*" - # API Gateway Lambda authorizer requires PassRole to - # apigateway.amazonaws.com. Shared HcptfIamManagementPolicy only - # grants PassRole to lambda.amazonaws.com (see IAMPassRole comment). - - Sid: MealOrderPassRoleApiGateway - Effect: Allow - Action: - - iam:PassRole - Resource: - - !Sub "arn:aws:iam::${AWS::AccountId}:role/tf-managed/meal-order-manager-*" - Condition: - StringEquals: - "iam:PassedToService": "apigateway.amazonaws.com" - - Sid: ReadWafWebAcl - Effect: Allow - Action: - - wafv2:GetWebACL - - wafv2:GetWebACLForResource - - wafv2:ListWebACLs - - wafv2:ListResourcesForWebACL - Resource: "*" - - Sid: CloudWatchAlarms - Effect: Allow - Action: - - cloudwatch:PutMetricAlarm - - cloudwatch:DeleteAlarms - - cloudwatch:DescribeAlarms - - cloudwatch:TagResource - - cloudwatch:UntagResource - - cloudwatch:ListTagsForResource - Resource: - - !Sub "arn:aws:cloudwatch:us-east-1:${AWS::AccountId}:alarm:meal-order-manager-*" - - Sid: SnsPublishSiteAlerts - Effect: Allow - Action: - - sns:Publish - - sns:GetTopicAttributes - - sns:ListTagsForResource - Resource: - - !Sub "arn:aws:sns:us-east-1:${AWS::AccountId}:site-alerts" - - Sid: SesIdentityRead - Effect: Allow - Action: - - ses:GetIdentityVerificationAttributes - - ses:GetSendQuota - Resource: "*" - - # Pre-grant delivery.logs write to the meal-order API access log group so - # hcptf-meal-order-manager does not need logs:PutResourcePolicy (account-wide). - # Deployed by CDK CFN exec on substrate update (PLAT-99). - MealOrderApiAccessLogResourcePolicy: - Type: AWS::Logs::ResourcePolicy - Condition: IsProdAccount - DeletionPolicy: Retain - UpdateReplacePolicy: Retain - Properties: - PolicyName: MealOrderManagerApiAccessLogDelivery - PolicyDocument: !Sub | - { - "Version": "2012-10-17", - "Statement": [ - { - "Sid": "AWSLogDeliveryWrite", - "Effect": "Allow", - "Principal": { "Service": "delivery.logs.amazonaws.com" }, - "Action": [ - "logs:CreateLogStream", - "logs:PutLogEvents" - ], - "Resource": [ - "arn:aws:logs:us-east-1:${AWS::AccountId}:log-group:/aws/apigateway/meal-order-manager", - "arn:aws:logs:us-east-1:${AWS::AccountId}:log-group:/aws/apigateway/meal-order-manager:*" - ], - "Condition": { - "StringEquals": { - "aws:SourceAccount": "${AWS::AccountId}" - } - } - } - ] - } - - # --------------------------------------------------------------------------- - # seahaven-door-unlock-api-prod (PLAT-76) — HttpApi + 5 Lambdas + EventBridge - # + ACM custom domain + alarms. Plan role: ViewOnly + plan-refresh sidecar. - # Apply role: HcptfIamManagement + prefix-scoped service wildcards. - # --------------------------------------------------------------------------- - HcptfDoorUnlockApiPlanRole: - Type: AWS::IAM::Role - Condition: IsProdAccount - DeletionPolicy: Retain - UpdateReplacePolicy: Retain - Properties: - RoleName: hcptf-seahaven-door-unlock-api-plan - AssumeRolePolicyDocument: - Version: "2012-10-17" - Statement: - - Effect: Allow - Principal: - Federated: !Sub "arn:aws:iam::${AWS::AccountId}:oidc-provider/app.terraform.io" - Action: sts:AssumeRoleWithWebIdentity - Condition: - StringEquals: - "app.terraform.io:aud": aws.workload.identity - "app.terraform.io:sub": organization:seahaven:project:seahaven-prod:workspace:seahaven-door-unlock-api-prod:run_phase:plan - ManagedPolicyArns: - - arn:aws:iam::aws:policy/job-function/ViewOnlyAccess - Policies: - - PolicyName: seahaven-door-unlock-api-plan-refresh - PolicyDocument: - Version: "2012-10-17" - Statement: - - Sid: RefreshIamRoles - Effect: Allow - Action: - - iam:GetRole - - iam:GetRolePolicy - - iam:ListRolePolicies - - iam:ListAttachedRolePolicies - - iam:ListRoleTags - Resource: - - !Sub "arn:aws:iam::${AWS::AccountId}:role/tf-managed/door-unlock-api-*" - - 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/door-unlock-api-*" - - Sid: RefreshLambda - Effect: Allow - Action: - - lambda:Get* - - lambda:List* - Resource: - - !Sub "arn:aws:lambda:us-east-1:${AWS::AccountId}:function:door-unlock-api-*" - - Sid: RefreshBuckets - Effect: Allow - Action: - - s3:Get* - - s3:ListBucket - Resource: - - !Sub "arn:aws:s3:::door-unlock-api-artifacts-${AWS::AccountId}" - - !Sub "arn:aws:s3:::door-unlock-api-artifacts-${AWS::AccountId}/*" - - Sid: RefreshLogs - Effect: Allow - Action: - - logs:DescribeLogGroups - - logs:ListTagsForResource - Resource: "*" - - Sid: RefreshAcm - Effect: Allow - Action: - - acm:DescribeCertificate - - acm:ListCertificates - - acm:ListTagsForCertificate - - acm:GetCertificate - Resource: "*" - # String door-id only. SecureString auth-token / elements-api-key - # stay off the plan role so speculative runs cannot render them. - - Sid: RefreshDoorUnlockSsm - Effect: Allow - Action: - - ssm:GetParameter - - ssm:GetParameters - Resource: - - !Sub "arn:aws:ssm:us-east-1:${AWS::AccountId}:parameter/seahaven/door-unlock/door-id" - - Sid: RefreshDoorUnlockSsmTags - Effect: Allow - Action: - - ssm:ListTagsForResource - Resource: - - !Sub "arn:aws:ssm:us-east-1:${AWS::AccountId}:parameter/seahaven/door-unlock/*" - - Sid: RefreshSsmDescribeParameters - Effect: Allow - Action: - - ssm:DescribeParameters - Resource: "*" - - Sid: RefreshHttpApi - Effect: Allow - Action: - - apigateway:GET - Resource: - - !Sub "arn:aws:apigateway:us-east-1::/apis/*" - - arn:aws:apigateway:us-east-1::/domainnames/doorunlock.seahaven.com - - arn:aws:apigateway:us-east-1::/domainnames/doorunlock.seahaven.com/* - - !Sub "arn:aws:apigateway:us-east-1::/tags/*" - - Sid: RefreshAlarms - Effect: Allow - Action: - - cloudwatch:DescribeAlarms - - cloudwatch:ListTagsForResource - Resource: "*" - - Sid: RefreshThreeCxSecrets - Effect: Allow - Action: - - secretsmanager:DescribeSecret - - secretsmanager:GetResourcePolicy - - secretsmanager:ListSecretVersionIds - Resource: - - arn:aws:secretsmanager:us-east-1:011934824531:secret:afterhours-shift-manager/3cx-domain-TPwqWP - - arn:aws:secretsmanager:us-east-1:011934824531:secret:afterhours-shift-manager/3cx-client-id-jzyQXb - - arn:aws:secretsmanager:us-east-1:011934824531:secret:afterhours-shift-manager/3cx-client-secret-jpO476 - - HcptfDoorUnlockApiApplyRole: - Type: AWS::IAM::Role - Condition: IsProdAccount - DeletionPolicy: Retain - UpdateReplacePolicy: Retain - Properties: - RoleName: hcptf-seahaven-door-unlock-api - AssumeRolePolicyDocument: - Version: "2012-10-17" - Statement: - - Effect: Allow - Principal: - Federated: !Sub "arn:aws:iam::${AWS::AccountId}:oidc-provider/app.terraform.io" - Action: sts:AssumeRoleWithWebIdentity - Condition: - StringEquals: - "app.terraform.io:aud": aws.workload.identity - "app.terraform.io:sub": organization:seahaven:project:seahaven-prod:workspace:seahaven-door-unlock-api-prod:run_phase:apply - ManagedPolicyArns: - - !Ref HcptfIamManagementPolicy - Policies: - - PolicyName: seahaven-door-unlock-api-services - PolicyDocument: - Version: "2012-10-17" - Statement: - - Sid: LambdaAll - Effect: Allow - Action: - - lambda:* - Resource: - - !Sub "arn:aws:lambda:us-east-1:${AWS::AccountId}:function:door-unlock-api-*" - - Sid: LambdaList - Effect: Allow - Action: - - lambda:ListFunctions - - lambda:GetAccountSettings - Resource: "*" - - Sid: EventBridgeRules - Effect: Allow - Action: - - events:* - Resource: - - !Sub "arn:aws:events:us-east-1:${AWS::AccountId}:rule/door-unlock-api-*" - - Sid: CloudWatchLogs - Effect: Allow - Action: - - logs:CreateLogGroup - - logs:DeleteLogGroup - - logs:PutRetentionPolicy - - logs:DeleteRetentionPolicy - - logs:TagResource - - logs:UntagResource - - logs:ListTagsForResource - Resource: - - !Sub "arn:aws:logs:us-east-1:${AWS::AccountId}:log-group:/aws/lambda/door-unlock-api-*" - - !Sub "arn:aws:logs:us-east-1:${AWS::AccountId}:log-group:/aws/apigateway/door-unlock-api*" - - Sid: CloudWatchLogsDescribe - Effect: Allow - Action: - - logs:DescribeLogGroups - Resource: "*" - - Sid: DoorUnlockApiGwAccessLogDelivery - Effect: Allow - Action: - - logs:CreateLogDelivery - - logs:GetLogDelivery - - logs:UpdateLogDelivery - - logs:DeleteLogDelivery - - logs:ListLogDeliveries - - logs:DescribeResourcePolicies - Resource: "*" - - Sid: StackBuckets - Effect: Allow - Action: - - s3:* - Resource: - - !Sub "arn:aws:s3:::door-unlock-api-artifacts-${AWS::AccountId}" - - !Sub "arn:aws:s3:::door-unlock-api-artifacts-${AWS::AccountId}/*" - # HTTP API ids are allocated at create (same as meal-order). - # Custom domain is hostname-pinned like procurement-api. - # CreateDomainName POSTs to /domainnames and cannot be hostname-pinned; - # mgmt still holds doorunlock.seahaven.com, so the domain is attached - # at DNS cutover rather than granted as an unscoped collection POST. - - Sid: HttpApiManage - Effect: Allow - Action: - - apigateway:* - Resource: - - !Sub "arn:aws:apigateway:us-east-1::/apis" - - !Sub "arn:aws:apigateway:us-east-1::/apis/*" - - !Sub "arn:aws:apigateway:us-east-1::/tags/*" - - Sid: HttpApiDomain - Effect: Allow - Action: - - apigateway:* - Resource: - - arn:aws:apigateway:us-east-1::/domainnames/doorunlock.seahaven.com - - arn:aws:apigateway:us-east-1::/domainnames/doorunlock.seahaven.com/* - - Sid: AcmCreate - Effect: Allow - Action: - - acm:RequestCertificate - Resource: "*" - Condition: - StringEquals: - "aws:RequestTag/Project": seahaven-door-unlock-api - - Sid: AcmList - Effect: Allow - Action: - - acm:ListCertificates - - acm:ListTagsForCertificate - Resource: "*" - - Sid: AcmManageTagged - Effect: Allow - Action: - - acm:DescribeCertificate - - acm:GetCertificate - - acm:DeleteCertificate - - acm:AddTagsToCertificate - - acm:RemoveTagsFromCertificate - - acm:RenewCertificate - Resource: "*" - Condition: - StringEquals: - "aws:ResourceTag/Project": seahaven-door-unlock-api - # HCP reads the String door-id data source only. Lambda execution - # roles (not this apply role) GetParameter the SecureStrings. - - Sid: DoorUnlockSsm - Effect: Allow - Action: - - ssm:GetParameter - - ssm:GetParameters - Resource: - - !Sub "arn:aws:ssm:us-east-1:${AWS::AccountId}:parameter/seahaven/door-unlock/door-id" - - Sid: DoorUnlockSsmTags - Effect: Allow - Action: - - ssm:ListTagsForResource - Resource: - - !Sub "arn:aws:ssm:us-east-1:${AWS::AccountId}:parameter/seahaven/door-unlock/*" - - Sid: DoorUnlockSsmDescribeParameters - Effect: Allow - Action: - - ssm:DescribeParameters - Resource: "*" - - Sid: DescribeThreeCxSecrets - Effect: Allow - Action: - - secretsmanager:DescribeSecret - - secretsmanager:GetResourcePolicy - - secretsmanager:ListSecretVersionIds - Resource: - - arn:aws:secretsmanager:us-east-1:011934824531:secret:afterhours-shift-manager/3cx-domain-TPwqWP - - arn:aws:secretsmanager:us-east-1:011934824531:secret:afterhours-shift-manager/3cx-client-id-jzyQXb - - arn:aws:secretsmanager:us-east-1:011934824531:secret:afterhours-shift-manager/3cx-client-secret-jpO476 - - Sid: DoorUnlockPassRoleApiGateway - Effect: Allow - Action: - - iam:PassRole - Resource: - - !Sub "arn:aws:iam::${AWS::AccountId}:role/tf-managed/door-unlock-api-*" - Condition: - StringEquals: - "iam:PassedToService": "apigateway.amazonaws.com" - - Sid: CloudWatchAlarms - Effect: Allow - Action: - - cloudwatch:PutMetricAlarm - - cloudwatch:DeleteAlarms - - cloudwatch:DescribeAlarms - - cloudwatch:TagResource - - cloudwatch:UntagResource - - cloudwatch:ListTagsForResource - Resource: - - !Sub "arn:aws:cloudwatch:us-east-1:${AWS::AccountId}:alarm:door-unlock-api-*" - - Sid: SnsPublishSiteAlerts - Effect: Allow - Action: - - sns:Publish - - sns:GetTopicAttributes - - sns:ListTagsForResource - Resource: - - !Sub "arn:aws:sns:us-east-1:${AWS::AccountId}:site-alerts" - - DoorUnlockApiAccessLogResourcePolicy: - Type: AWS::Logs::ResourcePolicy - Condition: IsProdAccount - DeletionPolicy: Retain - UpdateReplacePolicy: Retain - Properties: - PolicyName: DoorUnlockApiAccessLogDelivery - PolicyDocument: !Sub | - { - "Version": "2012-10-17", - "Statement": [ - { - "Sid": "AWSLogDeliveryWrite", - "Effect": "Allow", - "Principal": { "Service": "delivery.logs.amazonaws.com" }, - "Action": [ - "logs:CreateLogStream", - "logs:PutLogEvents" - ], - "Resource": [ - "arn:aws:logs:us-east-1:${AWS::AccountId}:log-group:/aws/apigateway/door-unlock-api", - "arn:aws:logs:us-east-1:${AWS::AccountId}:log-group:/aws/apigateway/door-unlock-api:*" - ], - "Condition": { - "StringEquals": { - "aws:SourceAccount": "${AWS::AccountId}" - } - } - } - ] - } - # --------------------------------------------------------------------------- # SHOC backend GitHub deployment permissions boundaries (external-dev only) #