From 5c46775124a728856249da209e560d25ad625a73 Mon Sep 17 00:00:00 2001 From: hermes Date: Mon, 13 Apr 2026 15:49:48 +0800 Subject: [PATCH] feat: initialize ansible-vault secret repository --- .gitignore | 9 +++++ README.md | 19 +++++++++++ docs/secret-vault.md | 55 ++++++++++++++++++++++++++++++ scripts/vault.sh | 79 ++++++++++++++++++++++++++++++++++++++++++++ secrets/vault.yml | 30 +++++++++++++++++ 5 files changed, 192 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 docs/secret-vault.md create mode 100755 scripts/vault.sh create mode 100644 secrets/vault.yml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..579ef28 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +*.log +*.retry +.env +.env.* +__pycache__/ +*.pyc +.DS_Store +.vault_pass.txt +secrets/plaintext/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..0167691 --- /dev/null +++ b/README.md @@ -0,0 +1,19 @@ +# Agent Secret Vault + +這個 repo 專門存放本地 AI agent 開發會用到的機密管理機制。 + +核心設計: +- 使用 `ansible-vault` 作為加密格式 +- 加密檔可進 git +- vault password file 只放在本機 +- 多個 agent 透過統一腳本存取 secrets + +## 內容 +- `scripts/vault.sh`:初始化、檢視、編輯、加密、解密、rekey +- `docs/secret-vault.md`:使用說明與設計原則 +- `secrets/vault.yml`:加密後 secrets 檔 + +## 目標 +- 讓 Hermes / OpenClaw / cron worker / 其他本地 agent 共用同一套 secret storage contract +- 不把明文 secret 留在 repo +- 不讓每個 agent 各自發明一套 credential 管理方式 diff --git a/docs/secret-vault.md b/docs/secret-vault.md new file mode 100644 index 0000000..a9e6574 --- /dev/null +++ b/docs/secret-vault.md @@ -0,0 +1,55 @@ +# Secret Vault + +這個 repo 使用 `ansible-vault` 來保存開發過程中需要的機密資訊。 + +## 設計 +- 加密檔:`secrets/vault.yml` +- 本機 vault password file:`~/.config/continuous-ai-workflow-spec/vault-pass.txt` +- 管理腳本:`scripts/vault.sh` + +## 原則 +- 加密後的 `secrets/vault.yml` 可以進 git +- `vault-pass.txt` 只放在本機,不進 git +- 解密後的暫存 plaintext 檔不要提交 + +## 常用指令 +初始化: +```bash +./scripts/vault.sh init +``` + +檢視: +```bash +./scripts/vault.sh view +``` + +編輯: +```bash +./scripts/vault.sh edit +``` + +把一份 plaintext YAML 加密成 vault: +```bash +./scripts/vault.sh encrypt /tmp/my-secrets.yml +``` + +解密到暫存檔: +```bash +./scripts/vault.sh decrypt /tmp/vault.yml +``` + +重置 vault key: +```bash +./scripts/vault.sh rekey +``` + +## 建議格式 +```yaml +gitea: + base_url: https://gitea.cowbay.org + ssh_url_template: ssh://git@gitea.cowbay.org:2203/{owner}/{repo}.git + account: hermes + email: hermes@ntu.edu.rs + password: ... + api_token: ... +``` diff --git a/scripts/vault.sh b/scripts/vault.sh new file mode 100755 index 0000000..ade523e --- /dev/null +++ b/scripts/vault.sh @@ -0,0 +1,79 @@ +#!/usr/bin/env bash +set -euo pipefail + +REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +VAULT_FILE="${VAULT_FILE:-$REPO_DIR/secrets/vault.yml}" +VAULT_PASS_FILE="${VAULT_PASS_FILE:-$HOME/.config/continuous-ai-workflow-spec/vault-pass.txt}" + +usage() { + cat < "$VAULT_PASS_FILE" +import secrets +print(secrets.token_urlsafe(48)) +PY + chmod 600 "$VAULT_PASS_FILE" + echo "已建立 vault password file: $VAULT_PASS_FILE" + fi +} + +cmd="${1:-}" +case "$cmd" in + init) + ensure_pass + ;; + view) + ensure_pass + ansible-vault view "$VAULT_FILE" --vault-password-file "$VAULT_PASS_FILE" + ;; + edit) + ensure_pass + [ -f "$VAULT_FILE" ] || { echo "找不到 $VAULT_FILE"; exit 1; } + ansible-vault edit "$VAULT_FILE" --vault-password-file "$VAULT_PASS_FILE" + ;; + encrypt) + ensure_pass + src="${2:-}" + [ -n "$src" ] || { usage; exit 1; } + cp "$src" "$VAULT_FILE" + ansible-vault encrypt "$VAULT_FILE" --vault-password-file "$VAULT_PASS_FILE" + ;; + decrypt) + ensure_pass + out="${2:-}" + [ -n "$out" ] || { usage; exit 1; } + ansible-vault decrypt "$VAULT_FILE" --output "$out" --vault-password-file "$VAULT_PASS_FILE" + chmod 600 "$out" || true + ;; + rekey) + ensure_pass + tmp_new="$(mktemp)" + chmod 600 "$tmp_new" + python3 - <<'PY' > "$tmp_new" +import secrets +print(secrets.token_urlsafe(48)) +PY + ansible-vault rekey "$VAULT_FILE" --vault-password-file "$VAULT_PASS_FILE" --new-vault-password-file "$tmp_new" + mv "$tmp_new" "$VAULT_PASS_FILE" + chmod 600 "$VAULT_PASS_FILE" + echo "已更新 vault key: $VAULT_PASS_FILE" + ;; + *) + usage + exit 1 + ;; +esac diff --git a/secrets/vault.yml b/secrets/vault.yml new file mode 100644 index 0000000..099aec2 --- /dev/null +++ b/secrets/vault.yml @@ -0,0 +1,30 @@ +$ANSIBLE_VAULT;1.1;AES256 +35373933393361653231623331383037626334666462366635386261346662316463366264363535 +3263613961616637633466646661396438383231353334360a363330343736613232626333316337 +62376637633062333866343039363862613361353266326532663337663137306130633465383063 +6437316262346635340a653337363536613363613762613362323636316564323433653533343963 +32633532666465613930353636333533336432333261653362633738316333313532366637346265 +35363138306634323462393665336330393731323132356266323037303838306233303832383337 +36613264376538343030353361343638393835613465303665383135326539653434346233663036 +63383536613331346631323835333933636365346465313239363536613532633837383639663832 +32663730626266356364383564386634613463313833363963353832333335393339386164633138 +36343065363965326237633066306137643432333836303561343530356564313465353332353634 +63383338383631343239653563656632393833323033383738373236356563636361373133343065 +66653239353930663633626163653830626434313132396637663635663538326166383335323365 +31333833333261303433393563363266376465303431363031346234313433663737306133613836 +31646134333333303864303836656235623834356131663764666330326538646265636435326266 +36313839393335373231363330343664633364663536376566343964633039663037646133666464 +61623837656633323332646236346362373861653237636461363366333139663531373761373464 +66633536303332633464396333636164613064633462376166666463353138376231376433396361 +61316665386363393163306530633966636638616261653034313430623933363135343236663137 +32363634303063646264663630376532313833393665386433666533613635333432323936616533 +66313031313933303032303435656436343233653966663964333635353832663631363337386539 +63313339313031383964653637373566336134613338346465323235316131396131353535343332 +34643936633864323130353561303933633937626234353233373033333137666565383930626535 +39626561653836633661333736623934393437303934346361313265663736663037626332663534 +37313139623364373235333164313662333933616630626561333061653739613665613865366537 +64643132373130666233383335343361623239363232363133356233633764663435396161363038 +37363962323563343836653965633935316236666434326236623362663536633136346637343637 +66663237333537333738353730306539313533363635343836656262373336646262333733636564 +63633934343264396331363265343166383565373630633432343337306130396464336463643435 +33386332396336653336313438336563663537303364323765633062333163363735