ci(terraform): update bootstrap & landingzone pipelines and add validation/notification scripts

This commit is contained in:
Haitao Pan 2025-11-17 20:34:11 +08:00
parent 64cb67d4ba
commit 9ae1d2bf84
4 changed files with 192 additions and 50 deletions

View File

@ -46,17 +46,17 @@ jobs:
- name: Init - name: Init
working-directory: ${{ env.TF_WORKDIR }}/${{ matrix.target }} working-directory: ${{ env.TF_WORKDIR }}/${{ matrix.target }}
run: terraform init -upgrade run: make init
- name: Plan - name: Plan
if: env.DRY_RUN == 'true' if: env.DRY_RUN == 'true'
working-directory: ${{ env.TF_WORKDIR }}/${{ matrix.target }} working-directory: ${{ env.TF_WORKDIR }}/${{ matrix.target }}
run: terraform plan -no-color run: make plan
- name: Apply - name: Apply
if: env.DRY_RUN == 'false' if: env.DRY_RUN == 'false'
working-directory: ${{ env.TF_WORKDIR }}/${{ matrix.target }} working-directory: ${{ env.TF_WORKDIR }}/${{ matrix.target }}
run: terraform apply -auto-approve run: make apply
- name: Save Outputs - name: Save Outputs
if: env.DRY_RUN == 'false' if: env.DRY_RUN == 'false'

View File

@ -25,55 +25,21 @@ env:
DEPLOY_ACTION: ${{ github.event.inputs.deploy_action || 'plan' }} DEPLOY_ACTION: ${{ github.event.inputs.deploy_action || 'plan' }}
DEPLOY_DRY_RUN: ${{ github.event.inputs.deploy_dry_run || 'true' }} DEPLOY_DRY_RUN: ${{ github.event.inputs.deploy_dry_run || 'true' }}
# -------------------------------
# SMTP settings (明文可接受)
# -------------------------------
SMTP_HOST: smtp.qq.com
SMTP_PORT: 465
SMTP_FROM: "XControl Account <manbuzhe2009@qq.com>"
SMTP_REPLY_TO: "no-reply@svc.plus"
TO_EMAIL: "manbuzhe2009@qq.com"
jobs: jobs:
# ------------------------------------------------------- # -------------------------------------------------------
# 1. Bootstrap Stage (Matrix) # 1. Landing Zone Baseline Stage
# -------------------------------------------------------
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
# ------------------------------------------------------- # -------------------------------------------------------
landingzone: landingzone:
name: "Deploy LandingZone Baseline" name: "Deploy LandingZone Baseline"
needs: bootstrap
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
@ -111,7 +77,7 @@ jobs:
run: terraform apply -auto-approve run: terraform apply -auto-approve
# ------------------------------------------------------- # -------------------------------------------------------
# 3. Validation Stage # 2. Validation Stage
# ------------------------------------------------------- # -------------------------------------------------------
validation: validation:
name: "Validate LandingZone Baseline" name: "Validate LandingZone Baseline"
@ -129,7 +95,7 @@ jobs:
${{ env.TF_WORKDIR }}/envs/dev-landingzone ${{ env.TF_WORKDIR }}/envs/dev-landingzone
# ------------------------------------------------------- # -------------------------------------------------------
# 4. Delivery / Notification Stage # 3. Delivery / Notification Stage
# ------------------------------------------------------- # -------------------------------------------------------
delivery: delivery:
name: "Delivery: Notify Rollout" name: "Delivery: Notify Rollout"
@ -140,7 +106,10 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Notify - name: Notify
env:
SMTP_PASSWORD: ${{ secrets.SMTP_PASSWORD }} # <-- 仅密码从 secret
SMTP_USERNAME: "manbuzhe2009@qq.com"
run: | run: |
echo "📣 Sending LandingZone rollout notification..." echo "📣 Sending LandingZone rollout notification..."
chmod +x scripts/notifications/notify-landingzone.sh chmod +x scripts/notifications/notify-landingzone.sh
scripts/notifications/notify-landingzone.sh ./scripts/notifications/notify-landingzone.sh

View File

@ -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 <manbuzhe2009@qq.com>}"
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 <<EOF
<html>
<body>
<h2>🚀 AWS LandingZone Baseline Rollout Completed</h2>
<p>The baseline deployment for <b>LandingZone Minimal</b> has successfully finished.</p>
<p><b>Environment:</b> dev-landingzone<br/>
<b>Workdir:</b> iac-template/terraform-standard</p>
<p>This includes:</p>
<ul>
<li>IAM Baseline Group</li>
<li>Deny Root (Partial IAM enforcement)</li>
<li>MFA Enforcement</li>
<li>Disable Console Write</li>
<li>Restrict RI/SP Purchases</li>
</ul>
<p>Regards,<br/>XControl CI/CD</p>
</body>
</html>
EOF
)
# -----------------------------
# BUILD RAW MESSAGE
# -----------------------------
MESSAGE=$(cat <<EOF
From: ${SMTP_FROM}
To: ${TO_EMAIL}
Reply-To: ${SMTP_REPLY_TO}
Subject: ${SUBJECT}
MIME-Version: 1.0
Content-Type: text/html; charset=UTF-8
${BODY_HTML}
EOF
)
# -----------------------------
# SEND VIA IMPLICIT TLS (465)
# -----------------------------
echo "📨 Sending LandingZone Email Notification..."
(
echo "EHLO smtp.qq.com"
echo "AUTH LOGIN"
echo -ne "$(printf '%s' "${SMTP_USERNAME}" | base64)\r\n"
echo -ne "$(printf '%s' "${SMTP_PASSWORD}" | base64)\r\n"
echo "MAIL FROM:<${SMTP_USERNAME}>"
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."

View File

@ -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