diff --git a/.github/workflows/terraform-standard-iac-pipeline-aws-global-bootstrap.yaml b/.github/workflows/terraform-standard-iac-pipeline-aws-global-bootstrap.yaml index c574c18d..9d17fcba 100644 --- a/.github/workflows/terraform-standard-iac-pipeline-aws-global-bootstrap.yaml +++ b/.github/workflows/terraform-standard-iac-pipeline-aws-global-bootstrap.yaml @@ -46,17 +46,17 @@ jobs: - name: Init working-directory: ${{ env.TF_WORKDIR }}/${{ matrix.target }} - run: terraform init -upgrade + run: make init - name: Plan if: env.DRY_RUN == 'true' working-directory: ${{ env.TF_WORKDIR }}/${{ matrix.target }} - run: terraform plan -no-color + run: make plan - name: Apply if: env.DRY_RUN == 'false' working-directory: ${{ env.TF_WORKDIR }}/${{ matrix.target }} - run: terraform apply -auto-approve + run: make apply - name: Save Outputs if: env.DRY_RUN == 'false' diff --git a/.github/workflows/terraform-standard-iac-pipeline-aws-global-landingzone-baseline.yaml b/.github/workflows/terraform-standard-iac-pipeline-aws-global-landingzone-baseline.yaml index fd8f0f81..7743f7f1 100644 --- a/.github/workflows/terraform-standard-iac-pipeline-aws-global-landingzone-baseline.yaml +++ b/.github/workflows/terraform-standard-iac-pipeline-aws-global-landingzone-baseline.yaml @@ -25,55 +25,21 @@ env: DEPLOY_ACTION: ${{ github.event.inputs.deploy_action || 'plan' }} DEPLOY_DRY_RUN: ${{ github.event.inputs.deploy_dry_run || 'true' }} + # ------------------------------- + # SMTP settings (明文可接受) + # ------------------------------- + SMTP_HOST: smtp.qq.com + SMTP_PORT: 465 + SMTP_FROM: "XControl Account " + SMTP_REPLY_TO: "no-reply@svc.plus" + TO_EMAIL: "manbuzhe2009@qq.com" + jobs: # ------------------------------------------------------- - # 1. Bootstrap Stage (Matrix) - # ------------------------------------------------------- - bootstrap: - name: "Bootstrap: DynamoDB / S3 / IAM" - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - target: - - bootstrap-dynamodb - - bootstrap-s3 - - bootstrap-iam - - steps: - - uses: actions/checkout@v4 - - - uses: hashicorp/setup-terraform@v3 - with: - terraform_version: 1.9.5 - - - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@v4 - with: - aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - aws-region: ${{ secrets.AWS_REGION }} - - - name: Terraform Init - working-directory: ${{ env.TF_WORKDIR }}/${{ matrix.target }} - run: terraform init -upgrade - - - name: Terraform Plan (bootstrap) - if: env.DEPLOY_DRY_RUN == 'true' - working-directory: ${{ env.TF_WORKDIR }}/${{ matrix.target }} - run: terraform plan -no-color - - - name: Terraform Apply (bootstrap) - if: env.DEPLOY_DRY_RUN == 'false' - working-directory: ${{ env.TF_WORKDIR }}/${{ matrix.target }} - run: terraform apply -auto-approve - - # ------------------------------------------------------- - # 2. Landing Zone Baseline Stage + # 1. Landing Zone Baseline Stage # ------------------------------------------------------- landingzone: name: "Deploy LandingZone Baseline" - needs: bootstrap runs-on: ubuntu-latest steps: @@ -111,7 +77,7 @@ jobs: run: terraform apply -auto-approve # ------------------------------------------------------- - # 3. Validation Stage + # 2. Validation Stage # ------------------------------------------------------- validation: name: "Validate LandingZone Baseline" @@ -129,7 +95,7 @@ jobs: ${{ env.TF_WORKDIR }}/envs/dev-landingzone # ------------------------------------------------------- - # 4. Delivery / Notification Stage + # 3. Delivery / Notification Stage # ------------------------------------------------------- delivery: name: "Delivery: Notify Rollout" @@ -140,7 +106,10 @@ jobs: - uses: actions/checkout@v4 - name: Notify + env: + SMTP_PASSWORD: ${{ secrets.SMTP_PASSWORD }} # <-- 仅密码从 secret + SMTP_USERNAME: "manbuzhe2009@qq.com" run: | echo "📣 Sending LandingZone rollout notification..." chmod +x scripts/notifications/notify-landingzone.sh - scripts/notifications/notify-landingzone.sh + ./scripts/notifications/notify-landingzone.sh diff --git a/scripts/notifications/notify-landingzone.sh b/scripts/notifications/notify-landingzone.sh new file mode 100644 index 00000000..40160f03 --- /dev/null +++ b/scripts/notifications/notify-landingzone.sh @@ -0,0 +1,76 @@ +#!/usr/bin/env bash +set -euo pipefail + +# ----------------------------- +# SMTP CONFIG (from GH secrets) +# ----------------------------- +SMTP_HOST="${SMTP_HOST:-smtp.qq.com}" +SMTP_PORT="${SMTP_PORT:-465}" +SMTP_USERNAME="${SMTP_USERNAME:-manbuzhe2009@qq.com}" +SMTP_PASSWORD="${SMTP_PASSWORD:?SMTP_PASSWORD missing from GitHub secrets}" +SMTP_FROM="${SMTP_FROM:-XControl Account }" +SMTP_REPLY_TO="${SMTP_REPLY_TO:-no-reply@svc.plus}" + +TO_EMAIL="${TO_EMAIL:-manbuzhe2009@qq.com}" +SUBJECT="AWS LandingZone Baseline Deployment Completed" + +# ----------------------------- +# EMAIL BODY (HTML) +# ----------------------------- +BODY_HTML=$(cat < + +

🚀 AWS LandingZone Baseline Rollout Completed

+

The baseline deployment for LandingZone Minimal has successfully finished.

+

Environment: dev-landingzone
+ Workdir: iac-template/terraform-standard

+ +

This includes:

+
    +
  • IAM Baseline Group
  • +
  • Deny Root (Partial IAM enforcement)
  • +
  • MFA Enforcement
  • +
  • Disable Console Write
  • +
  • Restrict RI/SP Purchases
  • +
+ +

Regards,
XControl CI/CD

+ + +EOF +) + +# ----------------------------- +# BUILD RAW MESSAGE +# ----------------------------- +MESSAGE=$(cat <" + echo "RCPT TO:<${TO_EMAIL}>" + echo "DATA" + echo "${MESSAGE}" + echo "." + echo "QUIT" +) | openssl s_client -quiet -crlf -connect "${SMTP_HOST}:${SMTP_PORT}" + +echo "✅ Notification sent." diff --git a/scripts/validation/validate-landingzone.sh b/scripts/validation/validate-landingzone.sh new file mode 100644 index 00000000..1c501d8f --- /dev/null +++ b/scripts/validation/validate-landingzone.sh @@ -0,0 +1,97 @@ +#!/usr/bin/env bash +set -euo pipefail + +TARGET_ENV_PATH="$1" + +echo "🔍 Validating AWS LandingZone Baseline..." +echo "Target path: $TARGET_ENV_PATH" +echo "Region: ${AWS_REGION}" + +# ------------------------- +# Check 1: IAM Group Exists +# ------------------------- +echo -n "Checking IAM group LandingZoneBaseline... " +if aws iam get-group --group-name LandingZoneBaseline >/dev/null 2>&1; then + echo "OK" +else + echo "FAILED" + exit 1 +fi + +# ----------------------------- +# Check 2: Required Policies +# ----------------------------- +REQUIRED_POLICIES=( + "landingzone-deny-root" + "landingzone-deny-no-mfa" + "landingzone-deny-console-write" + "landingzone-deny-ri-sp" +) + +echo "Checking IAM baseline policies..." +for p in "${REQUIRED_POLICIES[@]}"; do + echo -n " - $p ... " + if aws iam list-policies --scope Local --query "Policies[?PolicyName=='$p']" --output text | grep "$p" >/dev/null; then + echo "OK" + else + echo "FAILED" + exit 1 + fi +done + +# ----------------------------- +# Check 3: Policy Attachments +# ----------------------------- +echo "Checking policy attachments..." +for p in "${REQUIRED_POLICIES[@]}"; do + ARN=$(aws iam list-policies --scope Local --query "Policies[?PolicyName=='$p'].Arn" --output text) + + echo -n " - $p attached ... " + if aws iam list-attached-group-policies \ + --group-name LandingZoneBaseline \ + --query "AttachedPolicies[?PolicyArn=='$ARN']" \ + --output text | grep "$p" >/dev/null; then + echo "OK" + else + echo "FAILED" + exit 1 + fi +done + +# ----------------------------- +# Check 4: Terraform State Exists +# ----------------------------- +echo -n "Checking Terraform state presence... " +if test -f "${TARGET_ENV_PATH}/terraform.tfstate"; then + echo "OK" +else + echo "OK (remote backend)" +fi + +# ----------------------------- +# Check 5: root AccessKey +# ----------------------------- +echo -n "Checking root AccessKey... " +ROOT_KEYS=$(aws iam list-access-keys --user-name root 2>/dev/null || true) + +if [[ -z "$ROOT_KEYS" ]]; then + echo "OK (none)" +else + echo "FAILED (root has access keys!)" + exit 1 +fi + +# ----------------------------- +# Check 6: MFA Enforcement (Account Summary) +# ----------------------------- +echo -n "Checking MFA requirement... " +MFA=$(aws iam get-account-summary --query "SummaryMap.AccountMFAEnabled" --output text) + +if [[ "$MFA" == "1" ]]; then + echo "OK" +else + echo "WARNING (Account MFA not enforced globally)" +fi + +echo "✅ LandingZone baseline validation PASSED" +exit 0