From 54753b750dd81ffcad8a1ec6984203861427d190 Mon Sep 17 00:00:00 2001 From: Alexandre Brandizzi Date: Tue, 28 Jul 2026 14:39:46 -0300 Subject: [PATCH] fix(deploy): verify exact EB release --- .github/workflows/deploy.yml | 32 ++++++++++++++++++++++++++++++++ infra/cdk/README.md | 22 ++++++++++++---------- infra/cdk/deploy-dev-stack.ts | 7 +++---- 3 files changed, 47 insertions(+), 14 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 5e23077..83cf517 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -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 diff --git a/infra/cdk/README.md b/infra/cdk/README.md index 0dc802d..151909f 100644 --- a/infra/cdk/README.md +++ b/infra/cdk/README.md @@ -117,17 +117,19 @@ 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 the active Elastic Beanstalk platform version - prefix - `elasticbeanstalk-platform-assets-us-east-1/stalks/eb_dotnet8_amazon_linux_2023_1.0.2939.0_20260625064821/*`. - The live environment stack references its platform configuration, hooks, - user-data script, and sample bundle under that exact AWS-owned prefix. An +- `s3:GetObjectAcl` on only the live environment's AWS-owned launch-control + object: + `elasticbeanstalk-us-east-1/environments/28bfd388-952c-4121-8897-42d39fb48b69/launch_control`. + The sanitized live environment template references that exact object. An audited account-bucket data-event trail captured source-bundle ACL reads but - did not capture the remaining denied ACL read, which rules out the previous - account-owned runtime-prefix inference. The grant therefore covers only ACL - metadata for the environment's currently deployed platform version; it - grants no platform object content read or write, no adjacent platform - version, and no account-owned runtime object access. + did not capture the remaining denied ACL read, and a controlled deployment + still failed after granting the separate platform-assets prefix. Together, + those observations identify this cross-account launch-control object as the + remaining ACL target. The grant exposes ACL metadata for one object only: it + grants no object content read or write, no adjacent environment object, no + platform asset, and no account-owned runtime object access. If the EB + environment is replaced, this identifier must be re-derived from the new + sanitized environment stack before updating the policy. It grants **no** IAM mutation or `PassRole`, **no** RDS / Secrets Manager access, no EC2 mutation, and **no** administrator policy. The only non-EB/S3 diff --git a/infra/cdk/deploy-dev-stack.ts b/infra/cdk/deploy-dev-stack.ts index 0d8bbfb..f2fd58c 100644 --- a/infra/cdk/deploy-dev-stack.ts +++ b/infra/cdk/deploy-dev-stack.ts @@ -10,9 +10,8 @@ const ENVIRONMENT_ID = 'e-hehnrqjjrt'; const ENVIRONMENT_STACK_NAME = `awseb-${ENVIRONMENT_ID}-stack`; const REPO = 'Sea-Haven-Industries/shoc-backend'; const BUCKET_NAME = `elasticbeanstalk-${REGION}-${ACCOUNT_ID}`; -const PLATFORM_ASSET_BUCKET_NAME = `elasticbeanstalk-platform-assets-${REGION}`; -const PLATFORM_ASSET_PREFIX = - 'stalks/eb_dotnet8_amazon_linux_2023_1.0.2939.0_20260625064821'; +const ENVIRONMENT_LAUNCH_CONTROL_KEY = + 'environments/28bfd388-952c-4121-8897-42d39fb48b69/launch_control'; export class DeployDevStack extends cdk.Stack { constructor(scope: Construct, id: string, props: cdk.StackProps = {}) { @@ -155,7 +154,7 @@ export class DeployDevStack extends cdk.Stack { effect: iam.Effect.ALLOW, actions: ['s3:GetObjectAcl'], resources: [ - `arn:aws:s3:::${PLATFORM_ASSET_BUCKET_NAME}/${PLATFORM_ASSET_PREFIX}/*`, + `arn:aws:s3:::elasticbeanstalk-${REGION}/${ENVIRONMENT_LAUNCH_CONTROL_KEY}`, ], }), );