Compare commits

...

3 commits

Author SHA1 Message Date
Alexandre Brandizzi
f645b89997 docs(deploy): record unresolved EB ACL gate 2026-07-28 14:48:47 -03:00
Alexandre Brandizzi
54753b750d fix(deploy): verify exact EB release 2026-07-28 14:39:46 -03:00
Alexandre Brandizzi
400ba09770 fix(cdk): scope EB platform ACL read 2026-07-28 14:30:48 -03:00
3 changed files with 46 additions and 17 deletions

View file

@ -119,6 +119,38 @@ jobs:
wait-for-deployment: "true"
wait-for-environment-recovery: "true"
- name: Verify exact application version is active
run: |
set -euo pipefail
expected="${{ github.sha }}-${{ github.run_id }}-${{ github.run_attempt }}"
status="Unknown"
current="Unknown"
health="Unknown"
for _ in $(seq 1 80); do
read -r status current health < <(
aws elasticbeanstalk describe-environments \
--environment-names shoc-backend-dev \
--region us-east-1 \
--query 'Environments[0].[Status,VersionLabel,Health]' \
--output text
)
echo "environment status: $status; version: $current; health: $health"
if [ "$status" = "Ready" ]; then
if [ "$current" = "$expected" ] && { [ "$health" = "Green" ] || [ "$health" = "Yellow" ]; }; then
echo "Expected application version is Ready and healthy."
exit 0
fi
echo "Environment became Ready without activating expected version $expected." >&2
exit 1
fi
sleep 15
done
echo "Expected application version did not become Ready within the deployment window." >&2
exit 1
- name: Post-deploy smoke
run: bash scripts/smoke-elastic-beanstalk.sh https://api.dev.seahaven.com

View file

@ -117,15 +117,6 @@ The role grants only:
Elastic Beanstalk emitted this read during the same attempt while validating
the uploaded application bundle. It grants no bucket-wide or cross-prefix
object access.
- `s3:GetObjectAcl` on only
`resources/environments/e-hehnrqjjrt/_runtime/*` in the same bucket. A
successful break-glass deployment showed that EB copies each immutable
application version, its embedded extensions, and its manifest under that
exact environment runtime prefix. The failed OIDC path already allowed the
source object, so the remaining ACL validation is limited to that proven
runtime boundary. This grant exposes ACL metadata only; it does not grant
runtime content reads or writes.
It grants **no** IAM mutation or `PassRole`, **no** RDS / Secrets Manager
access, no EC2 mutation, and **no** administrator policy. The only non-EB/S3
mutations are the three deployment-process Auto Scaling calls, restricted to
@ -169,6 +160,20 @@ All commands run from `infra/cdk/`.
The workflow's `AWS_DEPLOY_ROLE_ARN` repository secret (environment `dev`) must
hold the ARN output by this stack (`GithubDeployRoleArn`).
The OIDC deployment is currently fail-closed, not repaired. Elastic Beanstalk
still reports a generic `s3:GetObjectAcl` denial after the account-owned source
prefix and every exact cross-account object referenced by the sanitized live
stack were tested independently. The runtime-prefix, platform-assets, and
launch-control hypotheses were disproved and are intentionally absent from the
policy. Do not broaden `GetObjectAcl` without an exact principal/action/resource
record from AWS Support or the AWS-owned bucket's diagnostic owner.
The pinned deployment action can return success after Elastic Beanstalk emits a
fatal deployment event. The following workflow step therefore verifies that
the exact immutable version label is active and healthy before smoke testing.
Any mismatch fails and invokes rollback. This guard prevents false success; it
does not make the unresolved OIDC deployment path release-ready.
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

View file

@ -147,14 +147,6 @@ export class DeployDevStack extends cdk.Stack {
}),
);
deployRole.addToPolicy(
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ['s3:GetObjectAcl'],
resources: [`${bucketArn}/resources/environments/${ENVIRONMENT_ID}/_runtime/*`],
}),
);
new cdk.CfnOutput(this, 'GithubDeployRoleArn', {
value: deployRole.roleArn,
description: 'ARN of the GitHub OIDC deploy role for shoc-backend dev.',