titan-iac/services/vault/scripts/vault_oidc_configure.sh

114 lines
3.5 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
log() { echo "[vault-oidc] $*"; }
status_json="$(vault status -format=json || true)"
if [[ -z "${status_json}" ]]; then
log "vault status failed; check VAULT_ADDR and VAULT_TOKEN"
exit 1
fi
if ! grep -q '"initialized":true' <<<"${status_json}"; then
log "vault not initialized; skipping"
exit 0
fi
if grep -q '"sealed":true' <<<"${status_json}"; then
log "vault sealed; skipping"
exit 0
fi
: "${VAULT_OIDC_DISCOVERY_URL:?set VAULT_OIDC_DISCOVERY_URL}"
: "${VAULT_OIDC_CLIENT_ID:?set VAULT_OIDC_CLIENT_ID}"
: "${VAULT_OIDC_CLIENT_SECRET:?set VAULT_OIDC_CLIENT_SECRET}"
default_role="${VAULT_OIDC_DEFAULT_ROLE:-admin}"
scopes="${VAULT_OIDC_SCOPES:-openid profile email groups}"
user_claim="${VAULT_OIDC_USER_CLAIM:-preferred_username}"
groups_claim="${VAULT_OIDC_GROUPS_CLAIM:-groups}"
redirect_uris="${VAULT_OIDC_REDIRECT_URIS:-https://secret.bstein.dev/ui/vault/auth/oidc/oidc/callback}"
bound_audiences="${VAULT_OIDC_BOUND_AUDIENCES:-${VAULT_OIDC_CLIENT_ID}}"
bound_claims_type="${VAULT_OIDC_BOUND_CLAIMS_TYPE:-string}"
admin_group="${VAULT_OIDC_ADMIN_GROUP:-admin}"
admin_policies="${VAULT_OIDC_ADMIN_POLICIES:-default,vault-admin}"
dev_group="${VAULT_OIDC_DEV_GROUP:-dev}"
dev_policies="${VAULT_OIDC_DEV_POLICIES:-default,dev-kv}"
user_group="${VAULT_OIDC_USER_GROUP:-${dev_group}}"
user_policies="${VAULT_OIDC_USER_POLICIES:-${VAULT_OIDC_TOKEN_POLICIES:-${dev_policies}}}"
if ! vault auth list -format=json | grep -q '"oidc/"'; then
log "enabling oidc auth method"
vault auth enable oidc
fi
log "configuring oidc auth"
vault write auth/oidc/config \
oidc_discovery_url="${VAULT_OIDC_DISCOVERY_URL}" \
oidc_client_id="${VAULT_OIDC_CLIENT_ID}" \
oidc_client_secret="${VAULT_OIDC_CLIENT_SECRET}" \
default_role="${default_role}"
vault auth tune -listing-visibility=unauth oidc >/dev/null
build_bound_claims() {
local claim="$1"
local groups="$2"
local json
local first=1
json="{\"${claim}\":["
IFS=',' read -r -a group_items <<<"${groups}"
for item in "${group_items[@]}"; do
item="${item#"${item%%[![:space:]]*}"}"
item="${item%"${item##*[![:space:]]}"}"
if [[ -z "${item}" ]]; then
continue
fi
if [[ ${first} -eq 0 ]]; then
json+=","
fi
json+="\"${item}\""
first=0
done
json+="]}"
printf '%s' "${json}"
}
configure_role() {
local role_name="$1"
local role_groups="$2"
local role_policies="$3"
if [[ -z "${role_name}" || -z "${role_groups}" || -z "${role_policies}" ]]; then
log "skipping role ${role_name} (missing groups or policies)"
return
fi
local claims
claims="$(build_bound_claims "${groups_claim}" "${role_groups}")"
local role_args=(
"user_claim=${user_claim}"
"oidc_scopes=${scopes}"
"token_policies=${role_policies}"
"bound_audiences=${bound_audiences}"
"bound_claims=${claims}"
"bound_claims_type=${bound_claims_type}"
)
if [[ -n "${groups_claim}" ]]; then
role_args+=("groups_claim=${groups_claim}")
fi
IFS=',' read -r -a redirect_items <<<"${redirect_uris}"
for uri in "${redirect_items[@]}"; do
trimmed="${uri#"${uri%%[![:space:]]*}"}"
trimmed="${trimmed%"${trimmed##*[![:space:]]}"}"
if [[ -n "${trimmed}" ]]; then
role_args+=("allowed_redirect_uris=${trimmed}")
fi
done
log "configuring oidc role ${role_name}"
vault write "auth/oidc/role/${role_name}" "${role_args[@]}"
}
configure_role "admin" "${admin_group}" "${admin_policies}"
configure_role "dev" "${dev_group}" "${dev_policies}"
configure_role "user" "${user_group}" "${user_policies}"