From 1cd0bfb9f2c1f0b48705019ece6b70c234562533 Mon Sep 17 00:00:00 2001 From: hermes Date: Thu, 14 May 2026 15:45:16 +0800 Subject: [PATCH] Add non-interactive vault pass install modes --- README.md | 9 ++++ docs/agent-install-runbook.md | 29 ++++++++++++ docs/human-guide.md | 18 ++++++++ scripts/install-vault-pass.sh | 87 +++++++++++++++++++++++++---------- 4 files changed, 119 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 98d2cbf..37f82d2 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,15 @@ - Agent 整合補充:[`docs/agent-integration.md`](docs/agent-integration.md) - Vault 基礎說明:[`docs/secret-vault.md`](docs/secret-vault.md) +## 全自動 agent 安裝 + +```bash +# 例:用一次性 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 +``` + ## 常用指令 ```bash diff --git a/docs/agent-install-runbook.md b/docs/agent-install-runbook.md index 0ec52b9..e6d8548 100644 --- a/docs/agent-install-runbook.md +++ b/docs/agent-install-runbook.md @@ -120,6 +120,35 @@ export VAULT_PASS_FILE=/path/to/vault-pass.txt ./scripts/install-vault-pass.sh ``` + +### Agent 全自動安裝(避免卡在互動密碼) + +若安裝由 AI agent / CI 執行,不要走互動 prompt。用以下任一非互動方式: + +```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 密碼放在本機安全檔案 +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 diff --git a/docs/human-guide.md b/docs/human-guide.md index 4f3c2cd..410bd35 100644 --- a/docs/human-guide.md +++ b/docs/human-guide.md @@ -66,6 +66,24 @@ git push 腳本會要求互動輸入 zip 密碼。這個 zip 密碼不要寫進 repo、chat 或 log;交給安裝者時用另外的安全渠道。 +## 給 agent 的全自動安裝方式 + +如果目標是「AI agent 直接安裝,不要卡在互動輸入密碼」,請不要讓 agent 選互動 zip 解壓。改用環境變數指定方法: + +```bash +# 一次性 URL 下載 +INSTALL_VAULT_PASS_METHOD=url \ +VAULT_PASS_URL="https://example.com/one-time/vault-pass.txt" \ +./scripts/install-vault-pass.sh + +# 或:zip 密碼放在本機安全檔案 +INSTALL_VAULT_PASS_METHOD=archive \ +VAULT_PASS_ZIP_PASSWORD_FILE=/secure/path/zip-password.txt \ +./scripts/install-vault-pass.sh +``` + +不要把 zip 密碼或 vault-pass 內容貼在聊天裡;應由目標機器的 secret manager、一次性 URL 或本機安全檔提供。 + ## 常用人工操作 ### 查看 vault diff --git a/scripts/install-vault-pass.sh b/scripts/install-vault-pass.sh index f52f754..5070873 100755 --- a/scripts/install-vault-pass.sh +++ b/scripts/install-vault-pass.sh @@ -5,6 +5,12 @@ REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" DEST="${VAULT_PASS_FILE:-$HOME/.config/vault-pass.txt}" ARCHIVE="${1:-$REPO_DIR/secrets/vault-pass.txt.zip}" VAULT_FILE="${VAULT_FILE:-$REPO_DIR/secrets/vault.yml}" +# Optional non-interactive controls: +# INSTALL_VAULT_PASS_METHOD=create|manual|url|archive +# VAULT_PASS_CONTENT= (for method=manual) +# VAULT_PASS_URL= (for method=url) +# VAULT_PASS_ZIP_PASSWORD= (for method=archive; avoid chat/log) +# VAULT_PASS_ZIP_PASSWORD_FILE= (for method=archive; safer than env) usage() { cat < "$DEST" + else + cat <&2 - exit 4 + read -r -s pass + printf '\n' + if [ -z "$pass" ]; then + echo "Empty password is not allowed." >&2 + exit 4 + fi + umask 077 + printf '%s\n' "$pass" > "$DEST" fi - umask 077 - printf '%s\n' "$pass" > "$DEST" secure_dest echo "Installed manually provided vault password file: $DEST" } download_from_url() { ensure_dest_dir - printf 'Enter vault-pass.txt URL: ' - read -r url + url="${VAULT_PASS_URL:-}" + if [ -z "$url" ]; then + printf 'Enter vault-pass.txt URL: ' + read -r url + fi if [ -z "$url" ]; then echo "URL is required." >&2 exit 4 @@ -161,8 +180,19 @@ ERR cleanup() { rm -rf "$tmpdir"; } trap cleanup EXIT - # unzip will prompt for the archive password interactively. - unzip -q "$ARCHIVE" -d "$tmpdir" + if [ -n "${VAULT_PASS_ZIP_PASSWORD_FILE:-}" ]; then + if [ ! -f "$VAULT_PASS_ZIP_PASSWORD_FILE" ]; then + echo "Missing VAULT_PASS_ZIP_PASSWORD_FILE: $VAULT_PASS_ZIP_PASSWORD_FILE" >&2 + exit 4 + fi + zip_pass="$(cat "$VAULT_PASS_ZIP_PASSWORD_FILE")" + unzip -P "$zip_pass" -q "$ARCHIVE" -d "$tmpdir" + elif [ -n "${VAULT_PASS_ZIP_PASSWORD:-}" ]; then + unzip -P "$VAULT_PASS_ZIP_PASSWORD" -q "$ARCHIVE" -d "$tmpdir" + else + # unzip will prompt for the archive password interactively. + unzip -q "$ARCHIVE" -d "$tmpdir" + fi src="$tmpdir/vault-pass.txt" if [ ! -f "$src" ]; then @@ -185,6 +215,16 @@ verify_vault_readable_if_possible() { fi } +run_method() { + case "$1" in + create|1) create_new_password ;; + manual|2) manual_create ;; + url|3) download_from_url ;; + archive|4) extract_from_archive ;; + *) echo "Invalid setup method: $1" >&2; exit 4 ;; + esac +} + if [ "${1:-}" = "-h" ] || [ "${1:-}" = "--help" ]; then usage exit 0 @@ -195,6 +235,12 @@ if verify_existing; then exit 0 fi +if [ -n "${INSTALL_VAULT_PASS_METHOD:-}" ]; then + run_method "$INSTALL_VAULT_PASS_METHOD" + verify_vault_readable_if_possible || true + exit 0 +fi + cat <&2; exit 4 ;; -esac - +run_method "$choice" verify_vault_readable_if_possible || true