From 82011a0c67073184e4a9ee08270c3c71a9afa161 Mon Sep 17 00:00:00 2001 From: thanhnv Date: Wed, 1 Jul 2026 21:44:20 +0900 Subject: [PATCH] fix(ci): eliminate audit-signature flake + self-heal deploy docker access MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two comprehensive CI fixes: 1. Adversarial harness flake (PASS=42 FAIL=2, state-dependent): governance-check.sh re-exported audit-public.pem only when GENERATING a new signing key. On a CI runner where the off-repo private key PERSISTS across runs, the checked-out (Vault-signed) audit-public.pem drifted out of sync with the local re-signing key, so verify-audit-chain.sh rejected a genuine head ("H5/H2 verifies the genuine signed chain"). Now always re-export the public key matching the signing key — mirrors the same fix already applied to tool-audit-lib.sh (c31987c). Reproduced the exact FAIL=2 locally with a drifted persisted key; now deterministically 44/44. 2. Deploy docker.sock permission denied: Added a self-healing preflight to deploy-okr that ensures the deploy user is in the docker group on the web VPS (idempotent, passwordless sudo) and proves a fresh SSH session can reach the daemon before streaming images. Co-Authored-By: Claude Opus 4.8 (1M context) --- .gitea/workflows/ci.yml | 18 ++++++++++++++++++ .../.specify/scripts/bash/governance-check.sh | 6 +++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index 09f6dbb..f3116b6 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -170,6 +170,24 @@ jobs: ssh-keyscan -H 161.33.139.73 >> ~/.ssh/known_hosts 2>/dev/null echo "SSH ready: $(ssh-keygen -l -f ~/.ssh/deploy_key 2>&1)" + - name: Ensure docker access on web VPS (self-heal group membership) + run: | + # The deploy user must be in the 'docker' group to reach + # /var/run/docker.sock (root:docker, mode 660). Idempotent; self-heals + # a rebuilt web VPS. Each subsequent step opens a fresh SSH session, so + # the new group membership takes effect without a reboot. + ssh -i ~/.ssh/deploy_key -o StrictHostKeyChecking=no $WEB_VPS ' + if id -nG "$USER" | tr " " "\n" | grep -qx docker; then + echo "docker group: already a member" + else + echo "docker group: adding $USER" + sudo usermod -aG docker "$USER" + fi + ' + # Prove a NEW session can reach the docker daemon before streaming ~GBs. + ssh -i ~/.ssh/deploy_key -o StrictHostKeyChecking=no $WEB_VPS \ + 'docker version --format "server={{.Server.Version}}"' + - name: Build backend image (node:20-slim + Prisma MySQL) run: docker build -t okr-backend:latest -f Dockerfile.backend . diff --git a/AINative_OKR_CASAN5/.specify/scripts/bash/governance-check.sh b/AINative_OKR_CASAN5/.specify/scripts/bash/governance-check.sh index 949cc11..88cf005 100755 --- a/AINative_OKR_CASAN5/.specify/scripts/bash/governance-check.sh +++ b/AINative_OKR_CASAN5/.specify/scripts/bash/governance-check.sh @@ -157,8 +157,12 @@ if command -v openssl >/dev/null 2>&1; then if [[ ! -f "$AUDIT_PRIV" ]]; then openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out "$AUDIT_PRIV" 2>/dev/null chmod 600 "$AUDIT_PRIV" - openssl rsa -in "$AUDIT_PRIV" -pubout -out "$AUDIT_PUB" 2>/dev/null fi + # Always re-export the public key so it matches the private key we sign with. + # Without this, a private key that PERSISTS on a CI runner drifts out of sync + # with a freshly checked-out audit-public.pem (e.g. one committed after a + # Vault-KMS signing), and verify-audit-chain.sh would reject a genuine head. + openssl rsa -in "$AUDIT_PRIV" -pubout -out "$AUDIT_PUB" 2>/dev/null || true printf '%s' "$RECORD_HASH" > "$AUDIT_DIR/audit-head.txt" openssl dgst -sha256 -sign "$AUDIT_PRIV" -out "$AUDIT_DIR/audit-head.sig" "$AUDIT_DIR/audit-head.txt" 2>/dev/null || true fi