mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-10-02 22:43:31 +00:00
164 lines
8 KiB
Markdown
164 lines
8 KiB
Markdown
# Backend environment adoption
|
|
|
|
These roots adopt environment-owned infrastructure without taking ownership of
|
|
shared or Elastic Beanstalk-generated infrastructure.
|
|
|
|
## Ownership
|
|
|
|
- `dev/` and `staging/` import the existing EB environment, runtime
|
|
role/profile/policies, deploy role/policy, app-config secret metadata, and API
|
|
record.
|
|
- `tf-poc/` manages the retained rehearsal environment after its completed
|
|
CloudFormation-to-Terraform transfer, excluding the live-only webhook and
|
|
Dynamo policies. It also owns the child zone and DNS-validated ACM
|
|
certificate.
|
|
- `modules/environment-inventory/` reads and pins only shared resources.
|
|
- Org-baseline CloudFormation owns the narrowly scoped HCP Terraform plan/apply
|
|
roles.
|
|
|
|
The shared `shoc-backend` Elastic Beanstalk application and
|
|
`shoc-sqlserver-shared` RDS instance, VPC, subnets, EB service role, shared
|
|
certificate, shared RDS security group, and EB-generated SG/ALB/ASG/CloudFormation
|
|
resources must never enter an environment state. The `shoc_tf_poc` SQL catalog
|
|
is out of band.
|
|
|
|
Secret values are not Terraform resources, variables, outputs, or managed EB
|
|
settings. Terraform manages the app-config secret shell and maps approved JSON
|
|
keys through `aws:elasticbeanstalk:application:environmentsecrets` using
|
|
`secret-arn:json-key` references. Ordinary application environment settings are
|
|
limited to non-secret ASP.NET and webhook configuration. The pinned .NET 8
|
|
AL2023 platform 3.11.3 supports Secrets Manager JSON-key extraction.
|
|
|
|
## Mandatory live secret migration
|
|
|
|
Before importing dev or staging, perform a separately approved production
|
|
mutation from a trusted local session:
|
|
|
|
1. Create a temporary `OptionSettings` JSON file containing the exact
|
|
`environmentsecrets` ARN/key references configured in that root and the five
|
|
non-secret ordinary environment settings.
|
|
2. Create a temporary `OptionsToRemove` JSON file naming the old raw
|
|
secret-valued keys in `aws:elasticbeanstalk:application:environment`.
|
|
3. Run `aws elasticbeanstalk update-environment` for exactly
|
|
`shoc-backend-dev` or `shoc-backend-staging` with
|
|
`--option-settings file://...` and `--options-to-remove file://...`.
|
|
Include the provider-normalized sorted `Subnets` and `ELBSubnets` values in
|
|
this same approved update if live ordering differs.
|
|
4. Delete both files, wait for the replacement environment to become Ready and
|
|
healthy, and run `scripts/smoke-elastic-beanstalk.sh` against the exact API.
|
|
5. Verify the raw ordinary secret settings are absent before generating the
|
|
first Terraform plan.
|
|
|
|
This migration is not performed by Terraform. The first import plan remains
|
|
zero-change only after the migration succeeds.
|
|
|
|
## Mandatory role-boundary attachment
|
|
|
|
After the org baseline creates the dedicated boundary policies, perform a
|
|
separately approved production IAM mutation that attaches:
|
|
|
|
- `shoc-backend-dev-runtime-boundary` to `shoc-backend-dev`
|
|
- `shoc-backend-staging-runtime-boundary` to `shoc-backend-staging`
|
|
- `shoc-backend-dev-deploy-boundary` to `githubdeploy-shoc-backend-dev`
|
|
- `shoc-backend-staging-deploy-boundary` to
|
|
`githubdeploy-shoc-backend-staging`
|
|
|
|
Attach all four boundaries before the SCP and HCP `PutRolePolicy` exceptions
|
|
become effective. In the same approved pre-import phase, add the immutable
|
|
`HcpTerraformWorkspace` tag to each GitHub deploy role:
|
|
|
|
- `githubdeploy-shoc-backend-dev`: `shoc-backend-dev`
|
|
- `githubdeploy-shoc-backend-staging`: `shoc-backend-staging`
|
|
|
|
Verify each exact runtime and deploy boundary ARN and workspace tag from
|
|
`GetRole` before importing. Terraform requires the boundaries to be present
|
|
during `adoption_complete=false`, so the first import remains zero-change.
|
|
Terraform does not perform this pre-import mutation.
|
|
|
|
## Two-phase adoption
|
|
|
|
Each dev/staging root pins `adoption_complete=false` in reviewed code until its
|
|
initial import is proven. It is not an HCP workspace variable. The retained
|
|
tf-poc rehearsal has completed both phases and therefore pins
|
|
`adoption_complete=true`.
|
|
|
|
1. Create the HCP workspace and configure dynamic credentials.
|
|
2. Run the declarative imports.
|
|
3. Export the HCP plan as JSON and run:
|
|
|
|
```bash
|
|
python scripts/check-terraform-import-plan.py plan.json --environment dev
|
|
```
|
|
|
|
The first plan must be a no-op after import. The guard rejects updates,
|
|
creates, deletes, replacements, and managed resource types outside the
|
|
approved environment-owned boundary.
|
|
4. Apply the no-op import only after review.
|
|
5. Change the environment root to `adoption_complete=true` and
|
|
`manage_eb_settings=true` in a reviewed code change, then review the
|
|
controlled in-place role, policy, secret, and Elastic Beanstalk update:
|
|
|
|
```bash
|
|
# Dev example. Omit any address that is not updating.
|
|
python scripts/check-terraform-import-plan.py plan.json --environment dev \
|
|
--allow-update-address module.environment.aws_iam_instance_profile.runtime \
|
|
--allow-update-address module.environment.aws_iam_role.runtime \
|
|
--allow-update-address module.environment.aws_iam_role.github_deploy \
|
|
--allow-update-address module.environment.aws_iam_role_policy.github_deploy \
|
|
--allow-update-address module.environment.aws_secretsmanager_secret.app_config \
|
|
--allow-update-address module.environment.aws_elastic_beanstalk_environment.this
|
|
```
|
|
|
|
6. Apply only when every update address is named on the command line and the
|
|
plan contains no create, delete, or replacement action. The dev direct ALB
|
|
alias remains pinned during this phase and must not update.
|
|
|
|
The same reviewed change prepares the legacy dev CDK stack for ownership
|
|
transfer. Before the Terraform apply, deploy `shoc-backend-deploy-dev` with
|
|
`ManageGithubDeployRole=true` so both the role and generated inline-policy
|
|
resource carry `Retain`. After Terraform succeeds and live verification passes,
|
|
deploy the same reviewed SHA with `ManageGithubDeployRole=false`. This removes
|
|
both resources from CloudFormation ownership without deleting them. Never use
|
|
`ManageGithubDeployRole=true` again after that transfer.
|
|
|
|
The reviewed `adoption_complete=true` change updates ownership tags on IAM
|
|
roles, instance profiles, and app-config secrets, and narrows the dev role to
|
|
the staging-style S3 bucket and application prefix. Elastic Beanstalk
|
|
environment tags remain at their imported values. EB accepts an added
|
|
`ManagedBy` tag request but can fail the asynchronous service-managed
|
|
CloudFormation propagation after Terraform reports success. Terraform still
|
|
manages the declared EB settings. Deploy-role descriptions and immutable
|
|
`HcpTerraformWorkspace` tags remain unchanged. Read-only AWS APIs retain
|
|
`Resource = "*"` only where AWS does not support resource-level permissions.
|
|
|
|
## POC retained identifiers
|
|
|
|
The tf-poc HCP workspace stores the exact retained environment ID, app-config
|
|
secret ARN, child-zone ID, and certificate ARN declared in
|
|
`tf-poc/variables.tf`. The declarative import blocks consumed those identifiers
|
|
during the completed transfer. Do not guess or replace them, and do not put
|
|
credentials or secret values in HCP variables.
|
|
|
|
ACM DNS validation remains part of the Terraform-owned certificate resource;
|
|
its generated validation record is not a separate ownership target. The public
|
|
delegation of `tf-poc.seahaven.com` from `seahaven.com` remains outside this
|
|
Terraform state.
|
|
|
|
## Pinned live identities
|
|
|
|
- Dev: workspace `shoc-backend-dev`; EB environment `shoc-backend-dev`
|
|
(`e-hehnrqjjrt`); .NET 8 AL2023 `3.11.3`; `api.dev.seahaven.com`.
|
|
- Staging: workspace `shoc-backend-staging`; EB environment
|
|
`shoc-backend-staging` (`e-6c9m4vb62z`); .NET 8 AL2023 `3.11.3`;
|
|
`api.staging.seahaven.com`.
|
|
|
|
The environment roots are intentionally not general-purpose modules. Exact
|
|
identifiers make accidental cross-environment reuse fail review and planning.
|
|
|
|
## Safety invariants
|
|
|
|
- Auto-apply remains off.
|
|
- Org baseline owns final HCP plan/apply permissions and manager tags.
|
|
- Every imported Terraform resource has `prevent_destroy`.
|
|
- The tf-poc CloudFormation creator path was removed after its no-op import,
|
|
controlled update, and retained-resource ownership transfer completed.
|