fix(security): isolate workload database identities
All checks were successful
CD Pipeline / workflow-shape (push) Successful in 1s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 2m25s
CD Pipeline / build-and-deploy (push) Successful in 6m42s
CD Pipeline / post-deploy-checks (push) Successful in 1m50s
All checks were successful
CD Pipeline / workflow-shape (push) Successful in 1s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 2m25s
CD Pipeline / build-and-deploy (push) Successful in 6m42s
CD Pipeline / post-deploy-checks (push) Successful in 1m50s
This commit is contained in:
@@ -2145,6 +2145,22 @@ jobs:
|
||||
echo "✅ 所有 Secrets 注入完成"
|
||||
SECRETS
|
||||
|
||||
# AIA-P0-011: record only Secret object pre-existence, never Secret data.
|
||||
# The bootstrap streams CSPRNG credentials directly to PostgreSQL and
|
||||
# kubectl stdin, then proves each identity with a no-write preflight.
|
||||
WORKLOAD_DB_SECRET_PREEXISTENCE_FILE="/tmp/awoooi-workload-db-secret-preexistence"
|
||||
: > "$WORKLOAD_DB_SECRET_PREEXISTENCE_FILE"
|
||||
for secret_name in awoooi-api-db awoooi-worker-db awoooi-broker-db; do
|
||||
secret_existed=$(ssh $SSH_OPTS "wooo@${{ env.K8S_SSH_HOST }}" \
|
||||
"KUBECTL='sudo kubectl --kubeconfig=/etc/rancher/k3s/k3s.yaml --server=${{ env.K8S_API_SERVER }}'; if \$KUBECTL get secret '${secret_name}' -n awoooi-prod >/dev/null 2>&1; then printf 1; else printf 0; fi")
|
||||
printf '%s=%s\n' "$secret_name" "$secret_existed" \
|
||||
>> "$WORKLOAD_DB_SECRET_PREEXISTENCE_FILE"
|
||||
done
|
||||
cat scripts/ops/awoooi-workload-db-identity-bootstrap.sh | \
|
||||
ssh $SSH_OPTS "wooo@${{ env.K8S_SSH_HOST }}" \
|
||||
"AWOOOI_KUBECTL_SUDO=true AWOOOI_KUBECONFIG=/etc/rancher/k3s/k3s.yaml AWOOOI_KUBERNETES_SERVER='${{ env.K8S_API_SERVER }}' AWOOOI_RUN_ID='${GITEA_RUN_NUMBER:-cd}' bash -s -- apply"
|
||||
echo "✅ workload DB identities, Secret projections, and preflights ready"
|
||||
|
||||
# 2026-04-11 Claude Sonnet 4.6 (Sprint B-3 ADR-069):
|
||||
# Deploy 改為 ArgoCD GitOps 模式:更新 kustomization.yaml → git push [skip ci] → ArgoCD sync
|
||||
# 舊做法 (kubectl set image) 與 ArgoCD selfHeal 衝突 — ArgoCD 會 revert 任何直接 kubectl 操作
|
||||
@@ -2187,6 +2203,70 @@ jobs:
|
||||
HARBOR=192.168.0.110:5000
|
||||
|
||||
# ─── Step 1: Apply NetworkPolicy + ConfigMap + ServiceRegistry ───
|
||||
# Preserve only live Deployment specs and Secret object existence.
|
||||
# Secret data is never read or copied into the rollback artifact.
|
||||
WORKLOAD_DB_ROLLBACK_FILE="/tmp/awoooi-workload-db-deployment-rollback.yaml"
|
||||
WORKLOAD_DB_SECRET_PREEXISTENCE_FILE="/tmp/awoooi-workload-db-secret-preexistence"
|
||||
ssh $SSH_OPTS "wooo@${{ env.K8S_SSH_HOST }}" \
|
||||
"KUBECTL='sudo kubectl --kubeconfig=/etc/rancher/k3s/k3s.yaml --server=${{ env.K8S_API_SERVER }}'; \$KUBECTL get deployment awoooi-api awoooi-worker awoooi-ansible-executor-broker -n awoooi-prod -o json" \
|
||||
| python3 -c '
|
||||
import json
|
||||
import sys
|
||||
|
||||
source = json.load(sys.stdin)
|
||||
items = [
|
||||
{
|
||||
"apiVersion": "apps/v1",
|
||||
"kind": "Deployment",
|
||||
"metadata": {
|
||||
"name": item["metadata"]["name"],
|
||||
"namespace": item["metadata"]["namespace"],
|
||||
"labels": item["metadata"].get("labels", {}),
|
||||
},
|
||||
"spec": item["spec"],
|
||||
}
|
||||
for item in source["items"]
|
||||
]
|
||||
json.dump({"apiVersion": "v1", "kind": "List", "items": items}, sys.stdout)
|
||||
' > "$WORKLOAD_DB_ROLLBACK_FILE"
|
||||
test -s "$WORKLOAD_DB_ROLLBACK_FILE"
|
||||
if [ ! -s "$WORKLOAD_DB_SECRET_PREEXISTENCE_FILE" ]; then
|
||||
: > "$WORKLOAD_DB_SECRET_PREEXISTENCE_FILE"
|
||||
for secret_name in awoooi-api-db awoooi-worker-db awoooi-broker-db; do
|
||||
secret_existed=$(ssh $SSH_OPTS "wooo@${{ env.K8S_SSH_HOST }}" \
|
||||
"KUBECTL='sudo kubectl --kubeconfig=/etc/rancher/k3s/k3s.yaml --server=${{ env.K8S_API_SERVER }}'; if \$KUBECTL get secret '${secret_name}' -n awoooi-prod >/dev/null 2>&1; then printf 1; else printf 0; fi")
|
||||
printf '%s=%s\n' "$secret_name" "$secret_existed" \
|
||||
>> "$WORKLOAD_DB_SECRET_PREEXISTENCE_FILE"
|
||||
done
|
||||
fi
|
||||
restore_workload_database_projection() {
|
||||
echo "⏪ restoring previous AWOOOI workload database projection"
|
||||
cat "$WORKLOAD_DB_ROLLBACK_FILE" | \
|
||||
ssh $SSH_OPTS "wooo@${{ env.K8S_SSH_HOST }}" \
|
||||
"KUBECTL='sudo kubectl --kubeconfig=/etc/rancher/k3s/k3s.yaml --server=${{ env.K8S_API_SERVER }}'; \$KUBECTL apply -f -"
|
||||
for deployment_name in awoooi-api awoooi-worker awoooi-ansible-executor-broker; do
|
||||
ssh $SSH_OPTS "wooo@${{ env.K8S_SSH_HOST }}" \
|
||||
"KUBECTL='sudo kubectl --kubeconfig=/etc/rancher/k3s/k3s.yaml --server=${{ env.K8S_API_SERVER }}'; \$KUBECTL rollout status deployment/${deployment_name} -n awoooi-prod --timeout=180s"
|
||||
done
|
||||
|
||||
disable_workloads=()
|
||||
while IFS='=' read -r secret_name secret_existed; do
|
||||
[ "$secret_existed" = "0" ] || continue
|
||||
case "$secret_name" in
|
||||
awoooi-api-db) disable_workloads+=(api) ;;
|
||||
awoooi-worker-db) disable_workloads+=(worker) ;;
|
||||
awoooi-broker-db) disable_workloads+=(broker) ;;
|
||||
esac
|
||||
ssh $SSH_OPTS "wooo@${{ env.K8S_SSH_HOST }}" \
|
||||
"KUBECTL='sudo kubectl --kubeconfig=/etc/rancher/k3s/k3s.yaml --server=${{ env.K8S_API_SERVER }}'; \$KUBECTL delete secret '${secret_name}' -n awoooi-prod --ignore-not-found=true"
|
||||
done < "$WORKLOAD_DB_SECRET_PREEXISTENCE_FILE"
|
||||
if [ "${#disable_workloads[@]}" -gt 0 ]; then
|
||||
cat scripts/ops/awoooi-workload-db-identity-bootstrap.sh | \
|
||||
ssh $SSH_OPTS "wooo@${{ env.K8S_SSH_HOST }}" \
|
||||
"AWOOOI_KUBECTL_SUDO=true AWOOOI_KUBECONFIG=/etc/rancher/k3s/k3s.yaml AWOOOI_KUBERNETES_SERVER='${{ env.K8S_API_SERVER }}' bash -s -- disable ${disable_workloads[*]}"
|
||||
fi
|
||||
}
|
||||
|
||||
# NetworkPolicy is intentionally outside kustomize because commonLabels
|
||||
# mutates nested selectors. Capture production truth before apply; the
|
||||
# checkout is intentionally depth=1, so parent Git history is not a
|
||||
@@ -2238,13 +2318,26 @@ jobs:
|
||||
"KUBECTL='sudo kubectl --kubeconfig=/etc/rancher/k3s/k3s.yaml --server=${{ env.K8S_API_SERVER }}'; \$KUBECTL delete networkpolicy '$BROKER_POLICY_NAME' -n awoooi-prod --ignore-not-found=true"
|
||||
fi
|
||||
}
|
||||
restore_deploy_controls() {
|
||||
set +e
|
||||
restore_workload_database_projection
|
||||
workload_restore_exit=$?
|
||||
restore_network_policy
|
||||
network_restore_exit=$?
|
||||
set -e
|
||||
if [ "$workload_restore_exit" -ne 0 ] \
|
||||
|| [ "$network_restore_exit" -ne 0 ]; then
|
||||
echo "❌ deploy rollback incomplete: workload=${workload_restore_exit} network=${network_restore_exit}" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
cat k8s/awoooi-prod/02-network-policy.yaml | \
|
||||
ssh $SSH_OPTS "wooo@${{ env.K8S_SSH_HOST }}" \
|
||||
"KUBECTL='sudo kubectl --kubeconfig=/etc/rancher/k3s/k3s.yaml --server=${{ env.K8S_API_SERVER }}'; \$KUBECTL apply --dry-run=server -f - >/dev/null"
|
||||
if ! cat k8s/awoooi-prod/02-network-policy.yaml | \
|
||||
ssh $SSH_OPTS "wooo@${{ env.K8S_SSH_HOST }}" \
|
||||
"KUBECTL='sudo kubectl --kubeconfig=/etc/rancher/k3s/k3s.yaml --server=${{ env.K8S_API_SERVER }}'; \$KUBECTL apply -f -"; then
|
||||
restore_network_policy
|
||||
restore_deploy_controls || true
|
||||
exit 1
|
||||
fi
|
||||
echo "✅ NetworkPolicy 已受控更新"
|
||||
@@ -2730,10 +2823,55 @@ jobs:
|
||||
WHERE rolname = current_user
|
||||
"""))
|
||||
row = result.mappings().one()
|
||||
for table_name in (
|
||||
"incidents",
|
||||
"knowledge_entries",
|
||||
"awooop_run_state",
|
||||
):
|
||||
await db.execute(
|
||||
text(f'SELECT count(*) FROM "{table_name}"')
|
||||
)
|
||||
table_gap_count = int((await db.execute(text("""
|
||||
SELECT count(*)
|
||||
FROM pg_class relation
|
||||
JOIN pg_namespace namespace
|
||||
ON namespace.oid = relation.relnamespace
|
||||
WHERE namespace.nspname = 'public'
|
||||
AND relation.relkind IN ('r', 'p', 'v', 'm')
|
||||
AND (
|
||||
(has_table_privilege('awoooi', relation.oid, 'SELECT')
|
||||
AND NOT has_table_privilege(current_user, relation.oid, 'SELECT'))
|
||||
OR (has_table_privilege('awoooi', relation.oid, 'INSERT')
|
||||
AND NOT has_table_privilege(current_user, relation.oid, 'INSERT'))
|
||||
OR (has_table_privilege('awoooi', relation.oid, 'UPDATE')
|
||||
AND NOT has_table_privilege(current_user, relation.oid, 'UPDATE'))
|
||||
OR (has_table_privilege('awoooi', relation.oid, 'DELETE')
|
||||
AND NOT has_table_privilege(current_user, relation.oid, 'DELETE'))
|
||||
)
|
||||
"""))).scalar_one())
|
||||
sequence_gap_count = int((await db.execute(text("""
|
||||
SELECT count(*)
|
||||
FROM pg_class sequence
|
||||
JOIN pg_namespace namespace
|
||||
ON namespace.oid = sequence.relnamespace
|
||||
WHERE namespace.nspname = 'public'
|
||||
AND sequence.relkind = 'S'
|
||||
AND (
|
||||
(has_sequence_privilege('awoooi', sequence.oid, 'USAGE')
|
||||
AND NOT has_sequence_privilege(current_user, sequence.oid, 'USAGE'))
|
||||
OR (has_sequence_privilege('awoooi', sequence.oid, 'SELECT')
|
||||
AND NOT has_sequence_privilege(current_user, sequence.oid, 'SELECT'))
|
||||
OR (has_sequence_privilege('awoooi', sequence.oid, 'UPDATE')
|
||||
AND NOT has_sequence_privilege(current_user, sequence.oid, 'UPDATE'))
|
||||
)
|
||||
"""))).scalar_one())
|
||||
except Exception as exc:
|
||||
print(json.dumps({
|
||||
"role_fingerprint": "",
|
||||
"connection_limit": None,
|
||||
"representative_preflight_passed": False,
|
||||
"table_privilege_gap_count": None,
|
||||
"sequence_privilege_gap_count": None,
|
||||
"error_type": type(exc).__name__,
|
||||
}))
|
||||
return
|
||||
@@ -2742,6 +2880,11 @@ jobs:
|
||||
str(row["role_name"]).encode("utf-8")
|
||||
).hexdigest(),
|
||||
"connection_limit": int(row["connection_limit"]),
|
||||
"representative_preflight_passed": (
|
||||
table_gap_count == 0 and sequence_gap_count == 0
|
||||
),
|
||||
"table_privilege_gap_count": table_gap_count,
|
||||
"sequence_privilege_gap_count": sequence_gap_count,
|
||||
"error_type": None,
|
||||
}))
|
||||
|
||||
@@ -2795,9 +2938,33 @@ jobs:
|
||||
| json_field connection_limit 2>/dev/null || true)
|
||||
BROKER_DB_CONNECTION_LIMIT=$(printf '%s' "$BROKER_DB_IDENTITY" \
|
||||
| json_field connection_limit 2>/dev/null || true)
|
||||
API_DB_REPRESENTATIVE_PREFLIGHT=$(normalize_bool "$(printf '%s' "$API_DB_IDENTITY" \
|
||||
| json_field representative_preflight_passed 2>/dev/null || true)")
|
||||
WORKER_DB_REPRESENTATIVE_PREFLIGHT=$(normalize_bool "$(printf '%s' "$WORKER_DB_IDENTITY" \
|
||||
| json_field representative_preflight_passed 2>/dev/null || true)")
|
||||
BROKER_DB_REPRESENTATIVE_PREFLIGHT=$(normalize_bool "$(printf '%s' "$BROKER_DB_IDENTITY" \
|
||||
| json_field representative_preflight_passed 2>/dev/null || true)")
|
||||
API_DB_TABLE_PRIVILEGE_GAP_COUNT=$(printf '%s' "$API_DB_IDENTITY" \
|
||||
| json_field table_privilege_gap_count 2>/dev/null || true)
|
||||
WORKER_DB_TABLE_PRIVILEGE_GAP_COUNT=$(printf '%s' "$WORKER_DB_IDENTITY" \
|
||||
| json_field table_privilege_gap_count 2>/dev/null || true)
|
||||
BROKER_DB_TABLE_PRIVILEGE_GAP_COUNT=$(printf '%s' "$BROKER_DB_IDENTITY" \
|
||||
| json_field table_privilege_gap_count 2>/dev/null || true)
|
||||
API_DB_SEQUENCE_PRIVILEGE_GAP_COUNT=$(printf '%s' "$API_DB_IDENTITY" \
|
||||
| json_field sequence_privilege_gap_count 2>/dev/null || true)
|
||||
WORKER_DB_SEQUENCE_PRIVILEGE_GAP_COUNT=$(printf '%s' "$WORKER_DB_IDENTITY" \
|
||||
| json_field sequence_privilege_gap_count 2>/dev/null || true)
|
||||
BROKER_DB_SEQUENCE_PRIVILEGE_GAP_COUNT=$(printf '%s' "$BROKER_DB_IDENTITY" \
|
||||
| json_field sequence_privilege_gap_count 2>/dev/null || true)
|
||||
API_DB_CONNECTION_LIMIT=${API_DB_CONNECTION_LIMIT:-0}
|
||||
WORKER_DB_CONNECTION_LIMIT=${WORKER_DB_CONNECTION_LIMIT:-0}
|
||||
BROKER_DB_CONNECTION_LIMIT=${BROKER_DB_CONNECTION_LIMIT:-0}
|
||||
API_DB_TABLE_PRIVILEGE_GAP_COUNT=${API_DB_TABLE_PRIVILEGE_GAP_COUNT:-1}
|
||||
WORKER_DB_TABLE_PRIVILEGE_GAP_COUNT=${WORKER_DB_TABLE_PRIVILEGE_GAP_COUNT:-1}
|
||||
BROKER_DB_TABLE_PRIVILEGE_GAP_COUNT=${BROKER_DB_TABLE_PRIVILEGE_GAP_COUNT:-1}
|
||||
API_DB_SEQUENCE_PRIVILEGE_GAP_COUNT=${API_DB_SEQUENCE_PRIVILEGE_GAP_COUNT:-1}
|
||||
WORKER_DB_SEQUENCE_PRIVILEGE_GAP_COUNT=${WORKER_DB_SEQUENCE_PRIVILEGE_GAP_COUNT:-1}
|
||||
BROKER_DB_SEQUENCE_PRIVILEGE_GAP_COUNT=${BROKER_DB_SEQUENCE_PRIVILEGE_GAP_COUNT:-1}
|
||||
|
||||
API_DB_PROJECTION=$(workload_secret_projection awoooi-api api)
|
||||
WORKER_DB_PROJECTION=$(workload_secret_projection awoooi-worker worker)
|
||||
@@ -2854,14 +3021,27 @@ jobs:
|
||||
&& [ "$DISTINCT_DB_ROLE_FINGERPRINTS" = "true" ]; then
|
||||
DB_IDENTITY_ISOLATED=true
|
||||
fi
|
||||
REPRESENTATIVE_DB_PREFLIGHTS_VERIFIED=false
|
||||
if [ "$API_DB_REPRESENTATIVE_PREFLIGHT" = "true" ] \
|
||||
&& [ "$WORKER_DB_REPRESENTATIVE_PREFLIGHT" = "true" ] \
|
||||
&& [ "$BROKER_DB_REPRESENTATIVE_PREFLIGHT" = "true" ] \
|
||||
&& [ "$API_DB_TABLE_PRIVILEGE_GAP_COUNT" -eq 0 ] \
|
||||
&& [ "$WORKER_DB_TABLE_PRIVILEGE_GAP_COUNT" -eq 0 ] \
|
||||
&& [ "$BROKER_DB_TABLE_PRIVILEGE_GAP_COUNT" -eq 0 ] \
|
||||
&& [ "$API_DB_SEQUENCE_PRIVILEGE_GAP_COUNT" -eq 0 ] \
|
||||
&& [ "$WORKER_DB_SEQUENCE_PRIVILEGE_GAP_COUNT" -eq 0 ] \
|
||||
&& [ "$BROKER_DB_SEQUENCE_PRIVILEGE_GAP_COUNT" -eq 0 ]; then
|
||||
REPRESENTATIVE_DB_PREFLIGHTS_VERIFIED=true
|
||||
fi
|
||||
CONNECTION_BUDGET_VERIFIED=false
|
||||
if [ "$DB_IDENTITY_ISOLATED" = "true" ] \
|
||||
&& [ "$REPRESENTATIVE_DB_PREFLIGHTS_VERIFIED" = "true" ] \
|
||||
&& [ "$API_DB_NULL_POOL" = "true" ] \
|
||||
&& [ "$WORKER_DB_NULL_POOL" = "true" ] \
|
||||
&& [ "$BROKER_DB_NULL_POOL" = "true" ] \
|
||||
&& [ "$API_DB_CONNECTION_LIMIT" -ge 1 ] \
|
||||
&& [ "$WORKER_DB_CONNECTION_LIMIT" -ge 1 ] \
|
||||
&& [ "$BROKER_DB_CONNECTION_LIMIT" -ge 1 ]; then
|
||||
&& [ "$API_DB_CONNECTION_LIMIT" -ge 4 ] \
|
||||
&& [ "$WORKER_DB_CONNECTION_LIMIT" -ge 2 ] \
|
||||
&& [ "$BROKER_DB_CONNECTION_LIMIT" -ge 2 ]; then
|
||||
CONNECTION_BUDGET_VERIFIED=true
|
||||
fi
|
||||
|
||||
@@ -2887,7 +3067,7 @@ jobs:
|
||||
--from-literal=worker_ssh_egress_denied=true \
|
||||
--from-literal=broker_ssh_egress_allowlisted=true \
|
||||
--from-literal=legacy_namespace_egress_allow_absent=true \
|
||||
--from-literal=db_identity_verifier=runtime_role_fingerprint_and_secret_projection_v1 \
|
||||
--from-literal=db_identity_verifier=runtime_role_fingerprint_secret_projection_and_representative_preflight_v2 \
|
||||
--from-literal=api_database_secret_ref="$API_DATABASE_SECRET_REF" \
|
||||
--from-literal=worker_database_secret_ref="$WORKER_DATABASE_SECRET_REF" \
|
||||
--from-literal=broker_database_secret_ref="$BROKER_DATABASE_SECRET_REF" \
|
||||
@@ -2897,9 +3077,19 @@ jobs:
|
||||
--from-literal=api_db_connection_limit="$API_DB_CONNECTION_LIMIT" \
|
||||
--from-literal=worker_db_connection_limit="$WORKER_DB_CONNECTION_LIMIT" \
|
||||
--from-literal=broker_db_connection_limit="$BROKER_DB_CONNECTION_LIMIT" \
|
||||
--from-literal=api_required_connection_budget=1 \
|
||||
--from-literal=worker_required_connection_budget=1 \
|
||||
--from-literal=broker_required_connection_budget=1 \
|
||||
--from-literal=api_required_connection_budget=4 \
|
||||
--from-literal=worker_required_connection_budget=2 \
|
||||
--from-literal=broker_required_connection_budget=2 \
|
||||
--from-literal=api_representative_db_preflight_passed="$API_DB_REPRESENTATIVE_PREFLIGHT" \
|
||||
--from-literal=worker_representative_db_preflight_passed="$WORKER_DB_REPRESENTATIVE_PREFLIGHT" \
|
||||
--from-literal=broker_representative_db_preflight_passed="$BROKER_DB_REPRESENTATIVE_PREFLIGHT" \
|
||||
--from-literal=api_table_privilege_gap_count="$API_DB_TABLE_PRIVILEGE_GAP_COUNT" \
|
||||
--from-literal=worker_table_privilege_gap_count="$WORKER_DB_TABLE_PRIVILEGE_GAP_COUNT" \
|
||||
--from-literal=broker_table_privilege_gap_count="$BROKER_DB_TABLE_PRIVILEGE_GAP_COUNT" \
|
||||
--from-literal=api_sequence_privilege_gap_count="$API_DB_SEQUENCE_PRIVILEGE_GAP_COUNT" \
|
||||
--from-literal=worker_sequence_privilege_gap_count="$WORKER_DB_SEQUENCE_PRIVILEGE_GAP_COUNT" \
|
||||
--from-literal=broker_sequence_privilege_gap_count="$BROKER_DB_SEQUENCE_PRIVILEGE_GAP_COUNT" \
|
||||
--from-literal=representative_db_preflights_verified="$REPRESENTATIVE_DB_PREFLIGHTS_VERIFIED" \
|
||||
--from-literal=api_database_null_pool="$API_DB_NULL_POOL" \
|
||||
--from-literal=worker_database_null_pool="$WORKER_DB_NULL_POOL" \
|
||||
--from-literal=broker_database_null_pool="$BROKER_DB_NULL_POOL" \
|
||||
@@ -2972,9 +3162,15 @@ jobs:
|
||||
last_status = f"fetch_failed:{type(exc).__name__}"
|
||||
else:
|
||||
boundary = payload.get("executor_trust_boundary") or {}
|
||||
database_boundary = (
|
||||
boundary.get("database_identity_boundary") or {}
|
||||
)
|
||||
last_status = str(boundary.get("status") or "missing")
|
||||
if (
|
||||
boundary.get("production_boundary_verified") is True
|
||||
and boundary.get("full_workload_boundary_verified") is True
|
||||
and database_boundary.get("db_identity_isolated") is True
|
||||
and database_boundary.get("connection_budget_verified") is True
|
||||
and str(boundary.get("verified_source_sha") or "").lower()
|
||||
== expected
|
||||
):
|
||||
@@ -2991,12 +3187,23 @@ jobs:
|
||||
ROLLOUT_EXIT=${PIPESTATUS[0]}
|
||||
set -e
|
||||
|
||||
WORKLOAD_DB_VERIFY_EXIT=0
|
||||
cat scripts/ops/awoooi-workload-db-identity-bootstrap.sh | \
|
||||
ssh $SSH_OPTS "wooo@${{ env.K8S_SSH_HOST }}" \
|
||||
"AWOOOI_KUBECTL_SUDO=true AWOOOI_KUBECONFIG=/etc/rancher/k3s/k3s.yaml AWOOOI_KUBERNETES_SERVER='${{ env.K8S_API_SERVER }}' AWOOOI_RUN_ID='${GITEA_RUN_NUMBER:-cd}' bash -s -- verify" \
|
||||
|| WORKLOAD_DB_VERIFY_EXIT=$?
|
||||
if [ "$WORKLOAD_DB_VERIFY_EXIT" -ne 0 ]; then
|
||||
restore_deploy_controls || true
|
||||
echo "❌ workload database post-deploy verifier failed"
|
||||
exit "$WORKLOAD_DB_VERIFY_EXIT"
|
||||
fi
|
||||
|
||||
SECURITY_BOUNDARY_VERIFIED="0"
|
||||
if grep -q '^AWOOOI_SECURITY_BOUNDARY_VERIFIED=1$' "$ROLLOUT_LOG"; then
|
||||
SECURITY_BOUNDARY_VERIFIED="1"
|
||||
fi
|
||||
if [ "$SECURITY_BOUNDARY_VERIFIED" != "1" ]; then
|
||||
restore_network_policy
|
||||
restore_deploy_controls || true
|
||||
echo "❌ executor security boundary did not reach its terminal verifier"
|
||||
if [ "$ROLLOUT_EXIT" -eq 0 ]; then
|
||||
exit 1
|
||||
@@ -3099,6 +3306,7 @@ jobs:
|
||||
PY
|
||||
|
||||
if [ "$DEPLOY_READBACK_EXIT" -ne 0 ]; then
|
||||
restore_deploy_controls || true
|
||||
exit "$DEPLOY_READBACK_EXIT"
|
||||
fi
|
||||
|
||||
|
||||
Reference in New Issue
Block a user