vault-ops/infra/archiv/05_issue_admin_client_cert.sh
Blade34242 e0b3c80819 Update
2025-11-26 08:56:50 +01:00

81 lines
2.9 KiB
Bash
Executable file

#!/usr/bin/env bash
set -Eeuo pipefail
# 05_issue_admin_client_cert.sh
#
# Purpose:
# Issue an ADMIN mTLS client certificate from the environment's Intermediate PKI in Vault
# and store it under $HOME/vault/tls-admin (for VAULT_CLIENT_CERT/KEY).
#
# Usage:
# VAULT_TOKEN=hvs.XXX \
# ./05_issue_admin_client_cert.sh --env test --config ./config/apps.yaml \
# --cn vault-admin-setup --ttl 180h
if [[ -t 1 ]]; then B=$'\e[1m'; R=$'\e[0m'; G=$'\e[32m'; Y=$'\e[33m'; E=$'\e[31m'; else B= R= G= Y= E=; fi
ok(){ echo -e "🟩 ${G}${B}$*${R}"; }
warn(){ echo -e "🟨 ${Y}${B}$*${R}"; }
die(){ echo -e "🟥 ${E}${B}$*${R}" >&2; exit 1; }
need(){ command -v "$1" >/dev/null || die "missing: $1"; }
need vault; need jq; need python3; need install
: "${VAULT_TOKEN:?Set VAULT_TOKEN (or VAULT_ADMIN_TOKEN)}"
if [[ -z "${VAULT_TOKEN:-}" && -n "${VAULT_ADMIN_TOKEN:-}" ]]; then
export VAULT_TOKEN="$VAULT_ADMIN_TOKEN"
fi
CFG="./config/apps.yaml"; ENV_NAME="test"; CN="vault-admin-setup"; TTL="180h"
while [[ $# -gt 0 ]]; do
case "$1" in
--config) CFG="$2"; shift 2;;
--env) ENV_NAME="$2"; shift 2;;
--cn) CN="$2"; shift 2;;
--ttl) TTL="$2"; shift 2;;
-h|--help) sed -n '1,200p' "$0"; exit 0;;
*) die "Unknown arg: $1";;
esac
done
CFG_ABS="$(readlink -f "$CFG")" || die "cannot resolve $CFG"
CFGJSON="$(python3 - <<PY
import yaml, json; print(json.dumps(yaml.safe_load(open("$CFG_ABS","r",encoding="utf-8"))))
PY
)"
jqenv(){ echo "$CFGJSON" | jq -r ".environments.\"$ENV_NAME\"$1"; }
VAULT_ADDR="$(jqenv '.vault_addr')"
INT_MOUNT="$(jqenv '.pki_mount')"
[[ "$VAULT_ADDR" != "null" && "$INT_MOUNT" != "null" ]] || die "incomplete config: vault_addr/pki_mount"
export VAULT_ADDR
ROLE="admin-client"
ok "Using Vault @ ${VAULT_ADDR} (mount: ${INT_MOUNT}) role=${ROLE} CN=${CN} TTL=${TTL}"
# Tighten for prod if desired (allowed_domains/allowed_uri_sans); default keeps it simple.
vault write "${INT_MOUNT}/roles/${ROLE}" \
server_flag=false client_flag=true \
allow_any_name=true key_usage="DigitalSignature" ext_key_usage="ClientAuth" \
max_ttl="720h" >/dev/null 2>&1 || true
RESP="$(vault write -format=json "${INT_MOUNT}/issue/${ROLE}" common_name="${CN}" ttl="${TTL}")" || die "issue failed"
CERT="$(echo "$RESP" | jq -r .data.certificate)"
KEY="$(echo "$RESP" | jq -r .data.private_key)"
ISSUING_CA="$(vault read -field=certificate "${INT_MOUNT}/cert/ca")"
OUT="$HOME/vault/tls-admin"; mkdir -p "$OUT"
echo "${KEY}" | install -m 0600 /dev/stdin "${OUT}/admin.key"
echo "${CERT}" | install -m 0644 /dev/stdin "${OUT}/admin.crt"
echo "${ISSUING_CA}" | install -m 0644 /dev/stdin "${OUT}/issuing_ca.pem"
ok "Wrote:"
echo " - ${OUT}/admin.key (0600)"
echo " - ${OUT}/admin.crt (0644)"
echo " - ${OUT}/issuing_ca.pem (issuer of admin.crt)"
cat <<EOF
Use:
export VAULT_CLIENT_CERT='${OUT}/admin.crt'
export VAULT_CLIENT_KEY='${OUT}/admin.key'
vault status
EOF