shoc-backend/infra/cdk/README.md
Alexandre Brandizzi 45ffa68dfa
Some checks are pending
Validate and deploy dev / Validate deployable source bundle (push) Waiting to run
Validate and deploy dev / Deploy shoc-backend to Elastic Beanstalk dev (push) Blocked by required conditions
fix: allow Elastic Beanstalk bucket setup check (#36)
2026-07-28 12:51:20 -03:00

5.2 KiB

shoc-backend CDK (dev deployment IAM)

This CDK v2 app owns exactly one thing in the shoc-backend AWS account (396287094661, us-east-1): the GitHub OIDC deploy role used by the dev deployment workflow in .github/workflows/deploy.yml.

Ownership boundary (deliberate)

CDK owns:

  • The IAM role githubdeploy-shoc-backend-dev.
  • Its OIDC trust relationship to arn:aws:iam::396287094661:oidc-provider/token.actions.githubusercontent.com scoped to repo:Sea-Haven-Industries/shoc-backend:environment:dev.
  • Its least-privilege inline permissions policy.

CDK does not own, create, import, replace, or modify any of the following. They are referenced by exact identifier only and remain owned by their original provisioning path:

  • Elastic Beanstalk application shoc-backend
  • Elastic Beanstalk environment shoc-backend-dev
  • DNS, VPC, EC2, RDS, and existing service/instance roles
  • S3 bucket elasticbeanstalk-us-east-1-396287094661
  • Environment configuration / option settings
  • Database schema (migrations are applied by Elastic Beanstalk at deploy time, not by CDK)

The role is retained on stack deletion (DeletionPolicy=Retain, UpdateReplacePolicy=Retain) so an accidental teardown cannot orphan the trust or lock out deployments.

Least-privilege policy summary

The role grants only:

  • The three read-only Elastic Beanstalk actions used by deploy, wait, and rollback (DescribeApplicationVersions, DescribeEnvironments, and DescribeEvents). These use Resource: "*" because Elastic Beanstalk describe actions are not reliably constrained by resource ARN.

  • elasticbeanstalk:CreateApplicationVersion on application shoc-backend.

  • elasticbeanstalk:UpdateEnvironment on environment shoc-backend-dev only.

  • s3:ListBucket on elasticbeanstalk-us-east-1-396287094661 (the official action's ownership-safe HeadBucket check), plus s3:CreateBucket on the same bucket-level ARN. Under the shoc-backend/ object prefix only: s3:PutObject plus s3:GetObject and s3:GetObjectVersion, which the pinned official deployment action requires to validate the CreateApplicationVersion source bundle after upload.

    s3:CreateBucket is part of the pinned aws-actions/aws-elasticbeanstalk-deploy@cfad3e5e... (v1.0.6) IAM contract even though the workflow sets create-s3-bucket-if-not-exists: "false". That input prevents the action's explicit bucket-creation helper; it does not remove the permission required by the subsequent Elastic Beanstalk update path. A live deployment confirmed this boundary: CreateApplicationVersion succeeded, then UpdateEnvironment was denied because the caller lacked s3:CreateBucket on the service bucket. The permission is scoped to that exact bucket-level ARN only (no object prefix, no wildcard resource), so it cannot create any other bucket.

It grants no IAM mutation or PassRole, no RDS / EC2 / Secrets Manager access, and no administrator policy. There are no wildcard mutation surfaces.

Prerequisites

  • Node >= 22.22.1 and npm.
  • AWS credentials authorized to create/inspect CloudFormation, IAM roles, and trust policies in account 396287094661.
  • The GitHub OIDC provider arn:aws:iam::396287094661:oidc-provider/token.actions.githubusercontent.com must already exist in the account (created once, outside this stack).

Commands

npm ci                          # install pinned dependencies
npm run build                   # type-check / compile to dist/
npm run synth                   # synthesize the CloudFormation template
npm run diff                    # diff deployed stack vs local (requires AWS)
npm run deploy                  # deploy the stack (requires AWS)

All commands run from infra/cdk/.

CI integration

npm run synth is the deterministic local/CI validation. After synth, inspect cdk.out/shoc-backend-deploy-dev.template.json and verify the synthesized AWS::IAM::Role:

  • Trust policy StringEquals matches the exact audience and subject above.
  • The inline policy contains no Resource: "*" mutation action and no service outside elasticbeanstalk / s3.

The workflow's AWS_DEPLOY_ROLE_ARN repository secret (environment dev) must hold the ARN output by this stack (GithubDeployRoleArn).

The GitHub dev environment is an external release control and must restrict deployments to the dev branch. Required reviewers should be configured when the repository plan supports environment reviewers. The workflow also checks the exact branch before requesting an OIDC token.

Migration and recovery contract

The deployment bundle applies pending EF Core migrations before the new application starts. Migrations must therefore use an expand/contract sequence:

  • Expand changes must remain backward compatible with the previously deployed application version.
  • Destructive contract changes are deployed only after all application versions relying on the old schema have been retired.
  • A failed deployment restores the previous application version only. Database schema is not downgraded, and schema rollback is not claimed.

This contract preserves the usefulness of application-version recovery without misrepresenting it as a tested database downgrade.