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

118 lines
5.2 KiB
Markdown

# 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
```bash
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.