mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-09-30 07:13:12 +00:00
118 lines
5.2 KiB
Markdown
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.
|