256 lines
7.7 KiB
Markdown
256 lines
7.7 KiB
Markdown
# Agent 安裝 Runbook:agent-secret-vault
|
||
|
||
這份文件給 AI agent / cron worker / automation 使用。目標:把 `agent-secret-vault` 安裝好、缺檔時建立 placeholder、並能安全讀取 secrets。
|
||
|
||
## 安全規則
|
||
|
||
- 不要把 secret value、vault password、token、private key 印到 chat / log / 工單 comment。
|
||
- 不要 dump 整份解密後的 `secrets/vault.yml`。
|
||
- 只讀取任務所需的單一欄位。
|
||
- 所有暫存解密檔用完立即刪除。
|
||
|
||
## 目標路徑
|
||
|
||
- Repo:`~/projects/agent-secret-vault`
|
||
- Vault 檔:`~/projects/agent-secret-vault/secrets/vault.yml`
|
||
- Vault password file:`~/.config/vault-pass.txt`
|
||
- 可覆寫環境變數:`VAULT_PASS_FILE=/custom/path`
|
||
|
||
## 1. 安裝系統依賴
|
||
|
||
```bash
|
||
sudo apt update
|
||
sudo apt install -y git ansible unzip
|
||
```
|
||
|
||
驗證:
|
||
|
||
```bash
|
||
command -v git
|
||
command -v ansible-vault
|
||
command -v unzip
|
||
```
|
||
|
||
## 2. Clone repo
|
||
|
||
```bash
|
||
mkdir -p ~/projects
|
||
cd ~/projects
|
||
if [ ! -d agent-secret-vault/.git ]; then
|
||
git clone ssh://git@gitea.cowbay.org:2203/hermes/agent-secret-vault.git
|
||
fi
|
||
cd agent-secret-vault
|
||
```
|
||
|
||
若 clone 失敗,建立 placeholder 讓後續步驟可明確回報缺什麼:
|
||
|
||
```bash
|
||
mkdir -p ~/projects/agent-secret-vault/{scripts,secrets,docs}
|
||
cat > ~/projects/agent-secret-vault/README.PLACEHOLDER.md <<'PLACEHOLDER'
|
||
# Placeholder
|
||
|
||
agent-secret-vault repo 尚未成功 clone。
|
||
需要 Gitea SSH 權限:ssh://git@gitea.cowbay.org:2203/hermes/agent-secret-vault.git
|
||
PLACEHOLDER
|
||
```
|
||
|
||
然後回報人類:需要把此 agent / 機器的 SSH public key 加到 Gitea 或 deploy key。
|
||
|
||
## 2.5 設定 installer env
|
||
|
||
Repo 內提供兩個 env 檔:
|
||
|
||
```text
|
||
install.env.example # 範本
|
||
install.env # 安裝用 placeholder
|
||
```
|
||
|
||
安裝前必須先設定 `install.env`(或指定 `INSTALL_ENV_FILE`),不要跳過這一步:
|
||
|
||
```bash
|
||
cd ~/projects/agent-secret-vault
|
||
cp -n install.env.example install.env
|
||
editor install.env
|
||
```
|
||
|
||
常用設定:
|
||
|
||
```bash
|
||
# 一次性 URL 下載 vault-pass.txt
|
||
INSTALL_VAULT_PASS_METHOD="url"
|
||
VAULT_PASS_URL="https://example.com/one-time/vault-pass.txt"
|
||
|
||
# 或:zip 密碼放在本機安全檔案
|
||
INSTALL_VAULT_PASS_METHOD="archive"
|
||
VAULT_PASS_ZIP_PASSWORD_FILE="/secure/path/zip-password.txt"
|
||
```
|
||
|
||
注意:`VAULT_PASS_ZIP_PASSWORD_FILE` 必須指向「只包含 zip 密碼的一行純文字檔」。不要把它指到 `secrets/vault-pass.txt.zip`(zip 壓縮檔本身)、`~/.config/vault-pass.txt`(Ansible Vault password file)、私鑰、或任何二進位檔。若 installer 報告檔案含 NUL bytes,通常就是路徑指錯了;請改成正確的 zip 密碼文字檔,或改用 `VAULT_PASS_ZIP_PASSWORD` / `url` / `manual` 方法。
|
||
|
||
若需要使用另一個 env 檔:
|
||
|
||
```bash
|
||
INSTALL_ENV_FILE=install.local.env ./scripts/install-vault-pass.sh
|
||
```
|
||
|
||
不要把含真實密碼/token 的 env 檔 commit。
|
||
|
||
執行安裝前可先檢查 env 是否足夠非互動安裝:
|
||
|
||
```bash
|
||
./scripts/install-vault-pass.sh --check-env
|
||
```
|
||
|
||
若輸出顯示 env 不足,先補齊 env;只有人類在本機 terminal 操作時才允許進入互動提示。AI agent / CI 不應直接進互動流程。
|
||
|
||
## 3. 安裝 vault password file
|
||
|
||
標準位置:
|
||
|
||
```text
|
||
~/.config/vault-pass.txt
|
||
```
|
||
|
||
執行 installer 前再次確認 env,然後安裝:
|
||
|
||
```bash
|
||
cd ~/projects/agent-secret-vault
|
||
./scripts/install-vault-pass.sh --check-env
|
||
./scripts/install-vault-pass.sh
|
||
```
|
||
|
||
installer 會先判斷 `~/.config/vault-pass.txt` 是否已存在:
|
||
|
||
- 若已存在:保留現有檔案、修正權限為 `600`,並嘗試驗證能否解開 `secrets/vault.yml`。
|
||
- 若不存在:提示使用者選擇 4 種建立方式。
|
||
|
||
### 缺檔時的 4 種方式
|
||
|
||
1. **建立新密碼並初始化 placeholder vault**
|
||
- 適合全新 repo / 全新環境。
|
||
- installer 會產生新的 `~/.config/vault-pass.txt`。
|
||
- 若 `secrets/vault.yml` 不存在,會建立加密 placeholder。
|
||
- 若既有 `secrets/vault.yml` 無法用新密碼解開,installer 不會覆蓋它,避免破壞既有 secrets。
|
||
|
||
2. **使用者自行輸入 vault-pass.txt 內容**
|
||
- installer 會用 hidden input 讀取一行密碼內容。
|
||
- 寫入 `~/.config/vault-pass.txt`,權限設為 `600`。
|
||
|
||
3. **使用者輸入 vault-pass.txt URL,自動下載**
|
||
- installer 會提示輸入 `http://` 或 `https://` URL。
|
||
- 用 `curl` 或 `wget` 下載到 `~/.config/vault-pass.txt`。
|
||
- 只適合可信的一次性下載 URL。
|
||
|
||
4. **解壓 repo 內既有密碼保護 zip**
|
||
- 預設讀取:`secrets/vault-pass.txt.zip`。
|
||
- zip 內必須包含檔名:`vault-pass.txt`。
|
||
- installer 會要求使用者在自己的 terminal 手動輸入 zip 密碼。
|
||
|
||
### 若壓縮檔不存在
|
||
|
||
建立 placeholder,不要自行編造密碼:
|
||
|
||
```bash
|
||
mkdir -p ~/projects/agent-secret-vault/secrets
|
||
cat > ~/projects/agent-secret-vault/secrets/vault-pass.txt.zip.PLACEHOLDER <<'PLACEHOLDER'
|
||
Missing file: secrets/vault-pass.txt.zip
|
||
Purpose: password-protected archive containing vault-pass.txt
|
||
Action: ask human maintainer to provide this archive or use installer method 1/2/3.
|
||
PLACEHOLDER
|
||
```
|
||
|
||
然後回報人類:缺 `secrets/vault-pass.txt.zip`,或請人類選擇 installer 方法 1/2/3。
|
||
|
||
### 若要用非預設路徑
|
||
|
||
```bash
|
||
export VAULT_PASS_FILE=/path/to/vault-pass.txt
|
||
./scripts/install-vault-pass.sh
|
||
```
|
||
|
||
|
||
### Agent 全自動安裝(避免卡在互動密碼)
|
||
|
||
若安裝由 AI agent / CI 執行,不要走互動 prompt。優先把設定寫進 `install.env` 或 `install.local.env`,也可用以下任一非互動方式:
|
||
|
||
```bash
|
||
# 方式 A:從安全 URL 下載 vault-pass.txt
|
||
INSTALL_VAULT_PASS_METHOD=url \
|
||
VAULT_PASS_URL="https://example.com/one-time/vault-pass.txt" \
|
||
./scripts/install-vault-pass.sh
|
||
|
||
# 方式 B:從密碼保護 zip 解壓,zip 密碼放在本機安全檔案
|
||
# /secure/path/zip-password.txt 必須是純文字,內容只有 zip 密碼本身;
|
||
# 不可指到 secrets/vault-pass.txt.zip 或 ~/.config/vault-pass.txt。
|
||
INSTALL_VAULT_PASS_METHOD=archive \
|
||
VAULT_PASS_ZIP_PASSWORD_FILE=/secure/path/zip-password.txt \
|
||
./scripts/install-vault-pass.sh
|
||
|
||
# 方式 C:從密碼保護 zip 解壓,zip 密碼用環境變數帶入(避免寫入 chat/log)
|
||
INSTALL_VAULT_PASS_METHOD=archive \
|
||
VAULT_PASS_ZIP_PASSWORD="..." \
|
||
./scripts/install-vault-pass.sh
|
||
|
||
# 方式 D:直接提供 vault-pass.txt 內容(只適合安全 runtime,不可印 log)
|
||
INSTALL_VAULT_PASS_METHOD=manual \
|
||
VAULT_PASS_CONTENT="..." \
|
||
./scripts/install-vault-pass.sh
|
||
```
|
||
|
||
推薦順序:URL 一次性下載 > `VAULT_PASS_ZIP_PASSWORD_FILE` > `VAULT_PASS_ZIP_PASSWORD` > `VAULT_PASS_CONTENT`。
|
||
|
||
## 4. 驗證安裝
|
||
|
||
```bash
|
||
cd ~/projects/agent-secret-vault
|
||
ansible-vault view secrets/vault.yml --vault-password-file ~/.config/vault-pass.txt >/dev/null
|
||
```
|
||
|
||
成功:exit code 0。失敗時只回報錯誤摘要,不要輸出密碼或 vault 內容。
|
||
|
||
## 5. 讀取單一 secret
|
||
|
||
```bash
|
||
cd ~/projects/agent-secret-vault
|
||
./scripts/get-secret.sh <dot.path>
|
||
```
|
||
|
||
範例:
|
||
|
||
```bash
|
||
./scripts/get-secret.sh gitea.api_token
|
||
./scripts/get-secret.sh openclaw_alice.http_nodes.gitea.password
|
||
```
|
||
|
||
把輸出直接交給需要 secret 的動作使用;不要貼到 chat / log。
|
||
|
||
## 6. Worker 需要 env 時
|
||
|
||
```bash
|
||
cd ~/projects/agent-secret-vault
|
||
umask 077
|
||
./scripts/render-env.sh gitea > /tmp/gitea.env
|
||
set -a
|
||
. /tmp/gitea.env
|
||
set +a
|
||
rm -f /tmp/gitea.env
|
||
```
|
||
|
||
使用完如果擔心環境被 dump,執行 `unset` 清掉相關變數。
|
||
|
||
## 7. 更新 secret 的 agent 流程
|
||
|
||
只有在人類明確要求更新 secrets 時才做:
|
||
|
||
```bash
|
||
cd ~/projects/agent-secret-vault
|
||
git pull --ff-only
|
||
./scripts/vault.sh edit
|
||
ansible-vault view secrets/vault.yml --vault-password-file ~/.config/vault-pass.txt >/dev/null
|
||
git add secrets/vault.yml
|
||
git commit -m "Update secret <key-name>"
|
||
git push
|
||
```
|
||
|
||
回報只包含 key 名稱、commit hash、驗證方式;不要包含 secret value。
|