Files
home-ops/vault/mod.just
T
hermes 372e26ece8
Flate / Flate - Filter (pull_request) Successful in 5s
Flate / Flate (pull_request) Successful in 18s
Flate / Flate - Success (pull_request) Canceled after 0s
feat(vault): just vault unseal/status — доли из gitignored файла
2026-09-17 17:17:29 +00:00

101 lines
4.3 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
set no-exit-message
set quiet
set shell := ['bash', '-euo', 'pipefail', '-c']
set script-interpreter := ['bash', '-euo', 'pipefail']
set default-list
set default-script
# Unseal-ключами Vault владеем вручную: файл вне git (см. .gitignore), по одному
# ключу на строку, строки, начинающиеся с '#', игнорируются.
#
# Почему не sops: age-ключ sops лежит в самом кластере (секрет sops-age), поэтому
# любой sops-файл из этого репозитория расшифрует тот, у кого есть доступ к
# кластеру, и смысл ручного unseal (PVC без ключей бесполезен) пропадёт.
# Копии ключей держи в менеджере паролей и на бумаге: они показываются один раз
# при `vault operator init`.
keys_file := env('VAULT_UNSEAL_KEYS', clean(justfile_directory() + '/vault-unseal-keys'))
vault_namespace := env('VAULT_NAMESPACE', 'security')
vault_pod := env('VAULT_POD', 'vault-0')
# Показать состояние Vault.
[doc('Показать состояние Vault (sealed/unsealed и прогресс распечатывания)')]
[group('vault')]
status:
#!/usr/bin/env bash
set -uo pipefail
for cmd in kubectl jq; do
command -v "$cmd" > /dev/null || { echo "vault: не найден $cmd (активируй mise в каталоге репозитория)" >&2; exit 1; }
done
kubectl -n "{{ vault_namespace }}" exec -i "{{ vault_pod }}" -- vault status || true
# Распечатать Vault ключами из файла.
[doc('Распечатать Vault ключами из файла vault-unseal-keys')]
[group('vault')]
unseal:
#!/usr/bin/env bash
set -euo pipefail
keys_file="{{ keys_file }}"
ns="{{ vault_namespace }}"
pod="{{ vault_pod }}"
for cmd in kubectl jq; do
command -v "$cmd" > /dev/null || { echo "vault: не найден $cmd (активируй mise в каталоге репозитория)" >&2; exit 1; }
done
if ! kubectl -n "$ns" get pod "$pod" > /dev/null 2>&1; then
echo "vault: под $ns/$pod недоступен — Vault не запущен или kubeconfig не тот" >&2
exit 1
fi
if [[ ! -f "$keys_file" ]]; then
echo "vault: нет файла с unseal-ключами: $keys_file" >&2
echo "" >&2
echo "Создай его в корне репозитория (в git он не попадёт, см. .gitignore)" >&2
echo "и положи по одному ключу на строку, например:" >&2
echo "" >&2
echo " <ключ 1 из vault operator init>" >&2
echo " <ключ 2 из vault operator init>" >&2
echo " <ключ 3 из vault operator init>" >&2
echo "" >&2
echo "Vault инициализируется с 5 долями и порогом 3, ключи показываются один раз." >&2
exit 1
fi
if find "$keys_file" -perm /077 -print -quit | grep -q .; then
echo "vault: у файла ключей слишком широкие права — сделай chmod 600 $keys_file" >&2
fi
sealed() {
kubectl -n "$ns" exec -i "$pod" -- vault status -format=json 2> /dev/null | jq -r '.sealed | tostring' || true
}
if [[ "$(sealed)" == "false" ]]; then
echo "vault: уже распечатан, ничего не делаю"
exit 0
fi
used=0
while IFS= read -r key || [[ -n "$key" ]]; do
key="$(printf '%s' "$key" | tr -d '[:space:]')"
[[ -z "$key" || "$key" == \#* ]] && continue
used=$((used + 1))
echo "vault: отправляю долю $used"
kubectl -n "$ns" exec -i "$pod" -- vault operator unseal "$key" || true
if [[ "$(sealed)" == "false" ]]; then
echo "vault: распечатан, использовано долей: $used"
break
fi
done < "$keys_file"
if [[ "$(sealed)" != "false" ]]; then
echo "vault: всё ещё запечатан — проверь, что в файле есть порог (3) верных долей" >&2
exit 1
fi
kubectl -n "$ns" exec -i "$pod" -- vault status || true