Skip to content

chore(infra): scope down gh-actions-deploy-prod role to least privilege #52

@mikanmarusan

Description

@mikanmarusan

Goal

Tighten the IAM permissions of the gh-actions-deploy-prod OIDC role from six *FullAccess AWS managed policies (including IAMFullAccess) down to a least-privilege custom policy sufficient for sam deploy of template.yml plus the post-deploy steps in deploy-production.yml.

Your Task

  1. Choose approach:
    • (Preferred) Use IAM Access Analyzer policy generation. Run a few real deploys to populate CloudTrail, then aws accessanalyzer start-policy-generation to derive an actual-usage policy as a starting point.
    • (Fallback) Hand-craft from a known SAM deploy policy template.
  2. Resource-scope the new policy to this stack only:
    • CloudFormation: arn:aws:cloudformation:ap-northeast-1:470021024556:stack/transitmikanmarusan/*
    • Lambda: arn:aws:lambda:ap-northeast-1:470021024556:function:transitmikanmarusan-*
    • S3: the SAM managed bucket aws-sam-cli-managed-default-samclisourcebucket-esq8nlny65pu + the frontend bucket transitmikanmarusan-frontend-470021024556
    • CloudFront: the distribution currently in use (see CloudFrontDistributionId stack output)
    • API Gateway: the REST API created by the stack
    • IAM: arn:aws:iam::470021024556:role/transitmikanmarusan-* only, with iam:PassRole further restricted via Condition to the Lambda execution role created by the stack
  3. Detach the six *FullAccess policies once the scoped policy is verified end-to-end.
  4. Verify with Deploy to Production dry-run=true and then dry-run=false.
  5. Document the final policy JSON in docs/architecture.md so the security posture is auditable from the repo.

Context

The OIDC migration in #42 / #51 created the IAM Role gh-actions-deploy-prod (ARN arn:aws:iam::470021024556:role/gh-actions-deploy-prod) and migrated the six managed policies the old lambda-function-transit-prod-deploy IAM user had, verbatim:

AmazonAPIGatewayAdministrator
AmazonS3FullAccess
AWSCloudFormationFullAccess
AWSLambda_FullAccess
CloudFrontFullAccess
IAMFullAccess

This preserved deploy behavior with zero behavioral risk during the OIDC cutover. It is not the long-term policy posture.

Concerns:

  1. IAMFullAccess is privilege-escalation territory. A compromised workflow step could attach AdministratorAccess to the role itself, create new roles for persistence, or alter the OIDC trust setup. OIDC short-lived credentials limit the leak window, but they do not bound what the assumed identity can do during that window.
  2. Cross-resource blast radius. The role can read/write S3 buckets, Lambda functions, CloudFront distributions, etc. that have nothing to do with the transitmikanmarusan stack.

Acceptance

  • No *FullAccess AWS managed policy is attached to gh-actions-deploy-prod.
  • IAMFullAccess (or any policy granting iam:*) is gone.
  • Deploy to Production dry-run=true and dry-run=false both succeed end-to-end (sam deploy, S3 sync, CloudFront invalidation, both health checks including the three security headers).
  • Resulting policy JSON documented in docs/architecture.md.

Related

Warning

  • Out of scope: changing the OIDC trust policy or the role ARN.
  • Out of scope: anything outside this deploy role's permissions.
  • A too-narrow scoped policy will fail mid-deploy and may leave the stack in UPDATE_ROLLBACK_FAILED, requiring manual intervention. Iterate against a non-prod stack first if available, or be ready to revert by re-attaching the six managed policies temporarily.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions