refactor: 폴더 구조 변경
This commit is contained in:
Executable
+187
@@ -0,0 +1,187 @@
|
||||
#!/usr/bin/env bash
|
||||
# Configure operator authentication for Vault.
|
||||
#
|
||||
# Adds a `userpass` auth method + `vault-admin` policy + one or more admin users.
|
||||
# Operators use these credentials instead of the root token for day-to-day work.
|
||||
# The root token stays offline and is only used for break-glass / rekey.
|
||||
#
|
||||
# Required env:
|
||||
# REPO_ROOT — repo root (for vault-init-keys.json path)
|
||||
#
|
||||
# Interactive inputs (대화형 TTY 에서 자동 프롬프트):
|
||||
# VAULT_ADMIN_USERNAME — login name (비면 프롬프트)
|
||||
# VAULT_ADMIN_PASSWORD — 초기 비밀번호 (비면 무음 입력 프롬프트)
|
||||
#
|
||||
# Non-interactive 시 (CI 등): 위 두 개를 env var 로 전달해야 함.
|
||||
#
|
||||
# Optional env:
|
||||
# VAULT_ADMIN_TTL — token TTL per login (default: 8h)
|
||||
# VAULT_ADMIN_MAX_TTL — maximum TTL (default: 24h)
|
||||
#
|
||||
# 입력 검증:
|
||||
# - username: 영문/숫자/._- 만 허용, 1..64 자
|
||||
# - TTL/MAX_TTL: 숫자+단위(s|m|h|d), 1..16 자
|
||||
# 이 값들은 Vault API 경로/파라미터에 쓰이는데, 과거 구현은 `sh -c` 문자열에
|
||||
# 직접 보간했다. allowlist 를 통과시키면 쉘 메타문자 주입 경로가 닫히고,
|
||||
# 아래 `vault write` 호출은 `sh -c` 없이 kubectl exec 로 직접 실행한다.
|
||||
|
||||
set -Eeuo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=../lib/common.sh
|
||||
. "$SCRIPT_DIR/../lib/common.sh"
|
||||
# shellcheck source=../lib/vault.sh
|
||||
. "$SCRIPT_DIR/../lib/vault.sh"
|
||||
|
||||
USERNAME_RE='^[A-Za-z0-9._-]{1,64}$'
|
||||
TTL_RE='^[0-9]+[smhd]?$'
|
||||
|
||||
validate_inputs() {
|
||||
[[ "$VAULT_ADMIN_USERNAME" =~ $USERNAME_RE ]] \
|
||||
|| die "VAULT_ADMIN_USERNAME 형식 불일치 (영문/숫자/._- 만 허용, 1..64자): '$VAULT_ADMIN_USERNAME'"
|
||||
[[ "$ADMIN_TTL" =~ $TTL_RE ]] \
|
||||
|| die "VAULT_ADMIN_TTL 형식 불일치 (예: 8h, 3600, 30m): '$ADMIN_TTL'"
|
||||
[[ "$ADMIN_MAX_TTL" =~ $TTL_RE ]] \
|
||||
|| die "VAULT_ADMIN_MAX_TTL 형식 불일치 (예: 24h, 86400): '$ADMIN_MAX_TTL'"
|
||||
((${#ADMIN_TTL} <= 16 && ${#ADMIN_MAX_TTL} <= 16)) \
|
||||
|| die "TTL 값이 너무 깁니다."
|
||||
}
|
||||
|
||||
prompt_username_if_missing() {
|
||||
[[ -n "${VAULT_ADMIN_USERNAME:-}" ]] && return 0
|
||||
if [[ ! -t 0 ]]; then
|
||||
die "VAULT_ADMIN_USERNAME 환경 변수가 비어있습니다 (비대화 환경)."
|
||||
fi
|
||||
read -r -p "운영자 username (e.g. alice): " VAULT_ADMIN_USERNAME
|
||||
[[ -n "$VAULT_ADMIN_USERNAME" ]] || die "username 이 비어있습니다."
|
||||
}
|
||||
|
||||
prompt_password_if_missing() {
|
||||
[[ -n "${VAULT_ADMIN_PASSWORD:-}" ]] && return 0
|
||||
if [[ ! -t 0 ]]; then
|
||||
die "VAULT_ADMIN_PASSWORD 환경 변수가 비어있습니다 (비대화 환경)."
|
||||
fi
|
||||
read -r -s -p "${VAULT_ADMIN_USERNAME} 초기 비밀번호: " VAULT_ADMIN_PASSWORD
|
||||
echo >&2
|
||||
[[ -n "$VAULT_ADMIN_PASSWORD" ]] || die "비밀번호가 비어있습니다."
|
||||
|
||||
local confirm
|
||||
read -r -s -p "비밀번호 한 번 더 입력: " confirm
|
||||
echo >&2
|
||||
[[ "$VAULT_ADMIN_PASSWORD" == "$confirm" ]] \
|
||||
|| die "비밀번호가 일치하지 않습니다."
|
||||
unset confirm
|
||||
}
|
||||
|
||||
enable_userpass() {
|
||||
if vault_auth_method_enabled "userpass"; then
|
||||
log "auth method 'userpass/' 이미 활성화됨"
|
||||
else
|
||||
log "userpass auth method 활성화"
|
||||
vault_exec auth enable userpass
|
||||
fi
|
||||
}
|
||||
|
||||
write_admin_policy() {
|
||||
# sudo capability 는 sys/* 일부 엔드포인트 (seal/audit/generate-root) 때문에 필요.
|
||||
# 권한이 강하므로 인프라 담당자에게만 부여.
|
||||
log "policy 'vault-admin' 작성"
|
||||
vault_exec_sh 'cat <<"EOF" | vault policy write vault-admin -
|
||||
# KV v2 — 전 경로 관리
|
||||
path "secret/*" {
|
||||
capabilities = ["create", "read", "update", "delete", "list"]
|
||||
}
|
||||
path "secret/data/*" {
|
||||
capabilities = ["create", "read", "update", "delete", "list"]
|
||||
}
|
||||
path "secret/metadata/*" {
|
||||
capabilities = ["create", "read", "update", "delete", "list"]
|
||||
}
|
||||
|
||||
# Auth method / identity 관리
|
||||
path "auth/*" {
|
||||
capabilities = ["create", "read", "update", "delete", "list", "sudo"]
|
||||
}
|
||||
path "identity/*" {
|
||||
capabilities = ["create", "read", "update", "delete", "list"]
|
||||
}
|
||||
|
||||
# policy 관리 (자기 자신 포함)
|
||||
path "sys/policies/*" {
|
||||
capabilities = ["create", "read", "update", "delete", "list"]
|
||||
}
|
||||
path "sys/policy/*" {
|
||||
capabilities = ["create", "read", "update", "delete", "list"]
|
||||
}
|
||||
|
||||
# 상태 / 감사 장치 / mount 관리
|
||||
path "sys/health" { capabilities = ["read"] }
|
||||
path "sys/seal-status" { capabilities = ["read"] }
|
||||
path "sys/mounts" { capabilities = ["read", "list"] }
|
||||
path "sys/mounts/*" {
|
||||
capabilities = ["create", "read", "update", "delete", "list", "sudo"]
|
||||
}
|
||||
path "sys/audit" { capabilities = ["read", "list"] }
|
||||
path "sys/audit/*" {
|
||||
capabilities = ["create", "read", "update", "delete", "sudo"]
|
||||
}
|
||||
EOF
|
||||
' >/dev/null
|
||||
}
|
||||
|
||||
# 사용자 생성/갱신 — `sh -c` 를 쓰지 않는다.
|
||||
#
|
||||
# 비밀번호는 `vault write -` 의 JSON stdin 으로 전달해 argv / 쉘 히스토리 노출이
|
||||
# 전혀 없다. 나머지 파라미터 (username / TTL) 는 allowlist 를 통과한 값만
|
||||
# kubectl exec argv 로 직접 전달된다 (쉘 해석 없음).
|
||||
create_or_update_user() {
|
||||
log "userpass user '${VAULT_ADMIN_USERNAME}' 생성/갱신 (ttl=${ADMIN_TTL} max_ttl=${ADMIN_MAX_TTL})"
|
||||
printf '%s\0%s\0%s\0' "$VAULT_ADMIN_PASSWORD" "$ADMIN_TTL" "$ADMIN_MAX_TTL" \
|
||||
| jq -Rs '
|
||||
split("\u0000") |
|
||||
{
|
||||
password: .[0],
|
||||
token_policies: "vault-admin",
|
||||
token_ttl: .[1],
|
||||
token_max_ttl: .[2]
|
||||
}
|
||||
' \
|
||||
| kubectl exec -i -n "$VAULT_NAMESPACE" "$VAULT_POD" -- \
|
||||
vault write "auth/userpass/users/${VAULT_ADMIN_USERNAME}" - >/dev/null
|
||||
unset VAULT_ADMIN_PASSWORD
|
||||
}
|
||||
|
||||
print_next_steps() {
|
||||
log "vault-setup-admin 태스크 완료"
|
||||
log ""
|
||||
log "다음 단계:"
|
||||
log " 1) 운영자는 다음 명령으로 로그인 (root token 사용 중단)"
|
||||
log " vault login -method=userpass username=${VAULT_ADMIN_USERNAME}"
|
||||
log " 2) 각 운영자는 첫 로그인 후 비밀번호를 변경"
|
||||
log " vault write auth/userpass/users/${VAULT_ADMIN_USERNAME}/password password='<new>'"
|
||||
log " 3) root token 은 오프라인 금고로 이동 후 vault-init-keys.json 에서 삭제 검토"
|
||||
log " (재발급은 \"vault operator generate-root -init\" 으로 가능)"
|
||||
}
|
||||
|
||||
main() {
|
||||
require_cmd kubectl jq
|
||||
require_env REPO_ROOT
|
||||
|
||||
prompt_username_if_missing
|
||||
prompt_password_if_missing
|
||||
|
||||
ADMIN_TTL="${VAULT_ADMIN_TTL:-8h}"
|
||||
ADMIN_MAX_TTL="${VAULT_ADMIN_MAX_TTL:-24h}"
|
||||
validate_inputs
|
||||
|
||||
local keys_file="${VAULT_KEYS_FILE:-$REPO_ROOT/vault-init-keys.json}"
|
||||
vault_login_root_from_keyfile "$keys_file"
|
||||
|
||||
enable_userpass
|
||||
write_admin_policy
|
||||
create_or_update_user
|
||||
print_next_steps
|
||||
}
|
||||
|
||||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||
main "$@"
|
||||
fi
|
||||
Reference in New Issue
Block a user