Add non-interactive vault pass install modes

This commit is contained in:
2026-05-14 15:45:16 +08:00
parent ea1bb0979f
commit 1cd0bfb9f2
4 changed files with 119 additions and 24 deletions

View File

@@ -17,6 +17,15 @@
- Agent 整合補充:[`docs/agent-integration.md`](docs/agent-integration.md) - Agent 整合補充:[`docs/agent-integration.md`](docs/agent-integration.md)
- Vault 基礎說明:[`docs/secret-vault.md`](docs/secret-vault.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 ```bash

View File

@@ -120,6 +120,35 @@ export VAULT_PASS_FILE=/path/to/vault-pass.txt
./scripts/install-vault-pass.sh ./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. 驗證安裝 ## 4. 驗證安裝
```bash ```bash

View File

@@ -66,6 +66,24 @@ git push
腳本會要求互動輸入 zip 密碼。這個 zip 密碼不要寫進 repo、chat 或 log交給安裝者時用另外的安全渠道。 腳本會要求互動輸入 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 ### 查看 vault

View File

@@ -5,6 +5,12 @@ REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
DEST="${VAULT_PASS_FILE:-$HOME/.config/vault-pass.txt}" DEST="${VAULT_PASS_FILE:-$HOME/.config/vault-pass.txt}"
ARCHIVE="${1:-$REPO_DIR/secrets/vault-pass.txt.zip}" ARCHIVE="${1:-$REPO_DIR/secrets/vault-pass.txt.zip}"
VAULT_FILE="${VAULT_FILE:-$REPO_DIR/secrets/vault.yml}" VAULT_FILE="${VAULT_FILE:-$REPO_DIR/secrets/vault.yml}"
# Optional non-interactive controls:
# INSTALL_VAULT_PASS_METHOD=create|manual|url|archive
# VAULT_PASS_CONTENT=<content> (for method=manual)
# VAULT_PASS_URL=<https-url> (for method=url)
# VAULT_PASS_ZIP_PASSWORD=<password> (for method=archive; avoid chat/log)
# VAULT_PASS_ZIP_PASSWORD_FILE=<path> (for method=archive; safer than env)
usage() { usage() {
cat <<USAGE cat <<USAGE
@@ -13,7 +19,7 @@ Usage: scripts/install-vault-pass.sh [archive.zip]
Installs the Ansible Vault password file to: Installs the Ansible Vault password file to:
${VAULT_PASS_FILE:-$HOME/.config/vault-pass.txt} ${VAULT_PASS_FILE:-$HOME/.config/vault-pass.txt}
Behavior: Interactive behavior:
1. If the password file already exists, keep it and verify permissions. 1. If the password file already exists, keep it and verify permissions.
2. If missing, prompt the user to choose one of four setup methods: 2. If missing, prompt the user to choose one of four setup methods:
[1] Create a new vault password and initialize/re-encrypt vault.yml [1] Create a new vault password and initialize/re-encrypt vault.yml
@@ -21,6 +27,13 @@ Behavior:
[3] Download vault-pass.txt from a user-provided URL [3] Download vault-pass.txt from a user-provided URL
[4] Extract vault-pass.txt from a password-protected zip archive [4] Extract vault-pass.txt from a password-protected zip archive
Non-interactive agent mode:
INSTALL_VAULT_PASS_METHOD=create ./scripts/install-vault-pass.sh
VAULT_PASS_CONTENT='...' INSTALL_VAULT_PASS_METHOD=manual ./scripts/install-vault-pass.sh
VAULT_PASS_URL='https://...' INSTALL_VAULT_PASS_METHOD=url ./scripts/install-vault-pass.sh
VAULT_PASS_ZIP_PASSWORD_FILE=/secure/pass INSTALL_VAULT_PASS_METHOD=archive ./scripts/install-vault-pass.sh
VAULT_PASS_ZIP_PASSWORD='...' INSTALL_VAULT_PASS_METHOD=archive ./scripts/install-vault-pass.sh
Default archive path for method [4]: Default archive path for method [4]:
$REPO_DIR/secrets/vault-pass.txt.zip $REPO_DIR/secrets/vault-pass.txt.zip
USAGE USAGE
@@ -32,9 +45,7 @@ ensure_dest_dir() {
chmod 700 "$(dirname "$DEST")" || true chmod 700 "$(dirname "$DEST")" || true
} }
secure_dest() { secure_dest() { chmod 600 "$DEST"; }
chmod 600 "$DEST"
}
verify_existing() { verify_existing() {
if [ -f "$DEST" ]; then if [ -f "$DEST" ]; then
@@ -98,6 +109,10 @@ YAML
manual_create() { manual_create() {
ensure_dest_dir ensure_dest_dir
if [ -n "${VAULT_PASS_CONTENT:-}" ]; then
umask 077
printf '%s\n' "$VAULT_PASS_CONTENT" > "$DEST"
else
cat <<MSG cat <<MSG
Paste/type the vault password content now, then press Enter. Paste/type the vault password content now, then press Enter.
Input is hidden. The content will be written to: Input is hidden. The content will be written to:
@@ -111,14 +126,18 @@ MSG
fi fi
umask 077 umask 077
printf '%s\n' "$pass" > "$DEST" printf '%s\n' "$pass" > "$DEST"
fi
secure_dest secure_dest
echo "Installed manually provided vault password file: $DEST" echo "Installed manually provided vault password file: $DEST"
} }
download_from_url() { download_from_url() {
ensure_dest_dir ensure_dest_dir
url="${VAULT_PASS_URL:-}"
if [ -z "$url" ]; then
printf 'Enter vault-pass.txt URL: ' printf 'Enter vault-pass.txt URL: '
read -r url read -r url
fi
if [ -z "$url" ]; then if [ -z "$url" ]; then
echo "URL is required." >&2 echo "URL is required." >&2
exit 4 exit 4
@@ -161,8 +180,19 @@ ERR
cleanup() { rm -rf "$tmpdir"; } cleanup() { rm -rf "$tmpdir"; }
trap cleanup EXIT trap cleanup EXIT
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 will prompt for the archive password interactively.
unzip -q "$ARCHIVE" -d "$tmpdir" unzip -q "$ARCHIVE" -d "$tmpdir"
fi
src="$tmpdir/vault-pass.txt" src="$tmpdir/vault-pass.txt"
if [ ! -f "$src" ]; then if [ ! -f "$src" ]; then
@@ -185,6 +215,16 @@ verify_vault_readable_if_possible() {
fi 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 if [ "${1:-}" = "-h" ] || [ "${1:-}" = "--help" ]; then
usage usage
exit 0 exit 0
@@ -195,6 +235,12 @@ if verify_existing; then
exit 0 exit 0
fi fi
if [ -n "${INSTALL_VAULT_PASS_METHOD:-}" ]; then
run_method "$INSTALL_VAULT_PASS_METHOD"
verify_vault_readable_if_possible || true
exit 0
fi
cat <<MENU cat <<MENU
Vault password file does not exist: Vault password file does not exist:
$DEST $DEST
@@ -208,12 +254,5 @@ MENU
printf 'Enter choice [1-4]: ' printf 'Enter choice [1-4]: '
read -r choice read -r choice
case "$choice" in run_method "$choice"
1) create_new_password ;;
2) manual_create ;;
3) download_from_url ;;
4) extract_from_archive ;;
*) echo "Invalid choice: $choice" >&2; exit 4 ;;
esac
verify_vault_readable_if_possible || true verify_vault_readable_if_possible || true