diff --git a/.gitea/workflows/cd.yaml b/.gitea/workflows/cd.yaml index 975a9fab..df47b8d4 100644 --- a/.gitea/workflows/cd.yaml +++ b/.gitea/workflows/cd.yaml @@ -829,70 +829,18 @@ jobs: ARGOCD_WAIT # 2026-04-09 Claude Sonnet 4.6: Sprint 5.2 — 同步 ops 腳本到 188 (ollama user) - # DEPLOY_SSH_KEY_188 = gitea-cd-deploy-188 (ed25519,只有 188 authorized_keys) + # 188 deploy key is rotated and must not be read by this disabled step. # 腳本: docker-health-monitor.sh + pg-backup.sh + notify-awoooi-ops.sh # 感知層與備份通知都先走 AWOOI API/AwoooP,Telegram 直發只保留 API 離線 fallback。 - name: Sync Ops Scripts to 188 + # 2026-05-13 Codex T14e/P0: + # Disabled until the 188 ops sync path is moved to a file-secret or + # Ansible-controlled channel. Gitea Actions logs step env values, and + # multiline SSH secrets must not be exposed through CD logs. + if: ${{ false }} continue-on-error: true run: | - mkdir -p ~/.ssh - # 2026-05-13 Codex: do not pass multiline deploy keys through - # step-level env; Gitea Actions prints env values in job logs. - # Keep the secret scoped to this shell and write it directly to disk. - cat > "${HOME}/.ssh/deploy_key_188" <<'DEPLOY_KEY_188' - ${{ secrets.DEPLOY_SSH_KEY_188 }} - DEPLOY_KEY_188 - sed -i 's/^ //' "${HOME}/.ssh/deploy_key_188" - chmod 600 "${HOME}/.ssh/deploy_key_188" - timeout -k 5s 10s ssh-keyscan 192.168.0.188 >> ~/.ssh/known_hosts 2>/dev/null \ - || echo "⚠️ 188 host key scan 失敗,改用 StrictHostKeyChecking=accept-new" - SSH_188_COMMON_OPTS=( - -i "${HOME}/.ssh/deploy_key_188" - -o BatchMode=yes - -o StrictHostKeyChecking=accept-new - -o ConnectTimeout=10 - -o ServerAliveInterval=10 - -o ServerAliveCountMax=3 - -o LogLevel=ERROR - ) - SSH_188_OPTS=( - "${SSH_188_COMMON_OPTS[@]}" - -n - ) - # scp 不支援 ssh 的 -n 參數,避免 188 ops 腳本同步被參數解析擋下。 - SCP_188_OPTS=( - "${SSH_188_COMMON_OPTS[@]}" - ) - - timeout -k 5s 30s ssh "${SSH_188_OPTS[@]}" ollama@192.168.0.188 \ - "mkdir -p ~/awoooi-ops" \ - || echo "⚠️ 188 ops 目錄確認失敗" - - # 同步 docker-health-monitor.sh - timeout -k 5s 60s scp "${SCP_188_OPTS[@]}" \ - scripts/ops/docker-health-monitor.sh \ - ollama@192.168.0.188:~/awoooi-ops/docker-health-monitor.sh \ - && echo "✅ docker-health-monitor.sh 已同步" \ - || echo "⚠️ docker-health-monitor.sh 同步失敗" - - # 同步 pg-backup.sh - timeout -k 5s 60s scp "${SCP_188_OPTS[@]}" \ - scripts/ops/pg-backup.sh \ - ollama@192.168.0.188:~/awoooi-ops/pg-backup.sh \ - && echo "✅ pg-backup.sh 已同步" \ - || echo "⚠️ pg-backup.sh 同步失敗" - - # 同步 ops 通知 helper - timeout -k 5s 60s scp "${SCP_188_OPTS[@]}" \ - scripts/ops/notify-awoooi-ops.sh \ - ollama@192.168.0.188:~/awoooi-ops/notify-awoooi-ops.sh \ - && echo "✅ notify-awoooi-ops.sh 已同步" \ - || echo "⚠️ notify-awoooi-ops.sh 同步失敗" - - # 確保執行權限 - timeout -k 5s 30s ssh "${SSH_188_OPTS[@]}" ollama@192.168.0.188 \ - "chmod +x ~/awoooi-ops/docker-health-monitor.sh ~/awoooi-ops/pg-backup.sh ~/awoooi-ops/notify-awoooi-ops.sh && echo '✅ 權限設定完成'" \ - || echo "⚠️ 權限設定失敗" + echo "188 ops script sync disabled pending secure key rotation path" - name: Notify Pipeline Failure if: failure() diff --git a/docs/LOGBOOK.md b/docs/LOGBOOK.md index 1e492fba..322d4884 100644 --- a/docs/LOGBOOK.md +++ b/docs/LOGBOOK.md @@ -8453,17 +8453,17 @@ by_verdict: - 新觀察:CD job log 會在 step env 區塊顯示 188 deploy key 內容。未在本文件記錄任何 secret 值,但必須列為下一個 P0:輪換 188 deploy key,並改造 workflow,避免 multiline secret 以 env 形式出現在 Gitea Actions logs。 - 目前整體進度更新:約 84%。 -### 2026-05-13 — T14d/P0:Gitea CD 188 deploy key log exposure 止血(workflow pushed) +### 2026-05-13 — T14d/P0:Gitea CD 188 deploy key log exposure 止血(superseded by T14e) **觸發**: - T14c CD log 觀察到 `Sync Ops Scripts to 188` step 會在 Gitea Actions 的 step env 區塊顯示 188 deploy key 內容。 - 未在 repo 或本文件保存任何 secret 值;但已經出現在 CI log,必須視為已暴露。 -**止血變更**: +**止血變更(短暫中繼,已由 T14e 取代)**: - `.gitea/workflows/cd.yaml` 移除 `SSH_KEY_188` step-level env。 -- 改在 shell 內直接寫入 `~/.ssh/deploy_key_188`,避免 multiline deploy key 以 env 形式進入 Gitea Actions log 的 env 區塊。 +- 早期中繼版曾嘗試改成 shell 內寫 key;T14e 已判定仍不適合作為最終安全路徑,並改為整個 188 ops sync step 暫停,不再從 CD 讀取 multiline deploy key。 **verification**: @@ -8475,5 +8475,42 @@ yaml ok 判讀: - 這是 workflow-level 止血,不等於完成安全事件處置。 -- 下一步仍需輪換 188 deploy key,清理/限制歷史 job log 可見性,並用一次受控 workflow_dispatch 確認新 workflow 不再暴露 secret。 +- 下一步仍需輪換 188 deploy key,清理/限制歷史 job log 可見性,並用一次受控 workflow_dispatch 確認新 workflow 不再暴露 secret;這部分由 T14e 接手。 - 目前整體進度更新:約 85%。 + +### 2026-05-13 — T14e/P0:188 deploy key 已輪換,CD 暫停讀取該 secret(awaiting workflow dispatch verification) + +**完成事項**: + +- 產生新的 188 CD deploy ed25519 keypair(public fingerprint:`SHA256:68UY6RnOJTEH4KQNGZJbMFWTUrdpFE0onPd95RDQEBI`)。 +- 新 public key 已加入 `ollama@192.168.0.188:~/.ssh/authorized_keys`,comment:`gitea-cd-deploy-188-20260513`。 +- 使用新 private key SSH 測試成功: + +```text +rotated_key_ok +ollama +ollama +``` + +- Gitea Actions secret `DEPLOY_SSH_KEY_188` 已更新,API 回傳: + +```text +secret_update_status=204 +``` + +- 188 上舊 public key comment `gitea-cd-deploy-188` 已移除;目前只保留新的 `gitea-cd-deploy-188-20260513`。 +- `.gitea/workflows/cd.yaml` 的 `Sync Ops Scripts to 188` step 已暫停,不再讀取 `DEPLOY_SSH_KEY_188`,直到改成 file-secret 或 Ansible-controlled channel。 + +**verification**: + +```text +ruby -e 'require "yaml"; YAML.load_file(".gitea/workflows/cd.yaml"); puts "yaml ok"' +yaml ok +``` + +判讀: + +- 已暴露的舊 188 deploy key 在 188 host 端失效。 +- Gitea secret 已換成新 key,但 CD 暫時不使用它,避免再次透過 Gitea Actions log 暴露 multiline secret。 +- 下一步:推版後用受控 `workflow_dispatch` 跑 CD,確認 `Sync Ops Scripts to 188` 被 skip,且 job log 不再出現 `SSH_KEY_188` / `DEPLOY_SSH_KEY_188` env 內容。 +- 目前整體進度更新:約 86%。 diff --git a/docs/superpowers/specs/2026-04-15-MASTER-ai-autonomous-flywheel-v2.md b/docs/superpowers/specs/2026-04-15-MASTER-ai-autonomous-flywheel-v2.md index 6f3b1dce..d1424d2b 100644 --- a/docs/superpowers/specs/2026-04-15-MASTER-ai-autonomous-flywheel-v2.md +++ b/docs/superpowers/specs/2026-04-15-MASTER-ai-autonomous-flywheel-v2.md @@ -2058,10 +2058,16 @@ Phase 6 完成後 **T14d/P0 Gitea CD 188 deploy key log exposure stopgap(2026-05-13 台北)**: - 觸發:T14c CD log 觀察到 `Sync Ops Scripts to 188` step 以 step-level env 傳入 multiline 188 deploy key,Gitea Actions 會在 job log 的 env 區塊顯示內容。未在 repo / docs 保存任何 secret 值,但應視為已暴露。 -- 止血:`.gitea/workflows/cd.yaml` 移除 `SSH_KEY_188` step env,改在 shell 內直接寫入 `~/.ssh/deploy_key_188`,避免 key 以 env 形式進入 Actions log。 +- 止血:`.gitea/workflows/cd.yaml` 移除 `SSH_KEY_188` step env。早期中繼版曾嘗試改成 shell 內寫 key;T14e 已判定仍不適合作為最終安全路徑,並改為整個 188 ops sync step 暫停,不再從 CD 讀取 multiline deploy key。 - 驗證:`ruby -e 'require "yaml"; YAML.load_file(".gitea/workflows/cd.yaml"); puts "yaml ok"'` 通過。 - 邊界:這不是完整安全事件處置;仍需輪換 188 deploy key、清理/限制歷史 job log 可見性,並以受控 `workflow_dispatch` 驗證新 workflow 不再暴露 secret。 +**T14e/P0 188 deploy key rotated + CD secret path disabled(2026-05-13 台北)**: +- 新 188 CD deploy ed25519 keypair 已產生(public fingerprint:`SHA256:68UY6RnOJTEH4KQNGZJbMFWTUrdpFE0onPd95RDQEBI`),public key 已加入 `ollama@192.168.0.188:~/.ssh/authorized_keys`,comment `gitea-cd-deploy-188-20260513`。 +- Gitea Actions secret `DEPLOY_SSH_KEY_188` 已更新,API 回傳 `204`;188 上舊 public key comment `gitea-cd-deploy-188` 已移除,新 key SSH 測試成功。 +- `.gitea/workflows/cd.yaml` 的 `Sync Ops Scripts to 188` step 已改為 `if: ${{ false }}`,CD 暫時不讀取該 secret,避免再次透過 Actions log 暴露 multiline private key。 +- 邊界:仍需受控 `workflow_dispatch` 驗證 step skip 與 log hygiene;188 ops scripts 自動同步需改成 file-secret 或 Ansible-controlled channel 後再恢復。 + --- ### 2026-04-20 晚 (台北) — C1-C4 全流程串接 — Playbook 鏈路保護(commit de2d34d)