Reviewable governance scaffolding — NOTHING applied to live OpenBAO yet: - policies/: materialize all existing policies as code (faithfully fetched from live) + new `operator` (use engines, no admin) and `auditor` (read-only governance visibility, no secret material) - scripts/apply-policies.sh: idempotent policy-as-code apply, with a read-only --dry-run that diffs files vs live (ignores comments) - scripts/setup-identity.sh: identity-as-code — policy-bound groups (g-admins/operators/auditors/personal) + a human entity/alias; DEFAULT DRY-RUN, --apply to execute - GOVERNANCE.md: the layered model, policy catalog, naming, apply order, and cross-cutting controls (audit device, root offline, AppRole migration) Dry-runs verified read-only: apply-policies shows operator/auditor as NEW, all others unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
56 lines
3.0 KiB
Bash
Executable File
56 lines
3.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Identity-as-code: create governance GROUPS (each bound to a policy) and wire a
|
|
# human ENTITY to a userpass login alias. Demonstrates the full chain:
|
|
# userpass username -> alias -> entity -> group -> policy
|
|
#
|
|
# DEFAULT IS DRY-RUN (prints planned API calls, changes nothing).
|
|
# setup-identity.sh # dry-run, username 'admin'
|
|
# setup-identity.sh --apply # actually create, alias to 'admin'
|
|
# setup-identity.sh --apply lutz # alias to userpass user 'lutz'
|
|
#
|
|
# Auth: $BAO_TOKEN or root from init-output.json. Idempotent (safe to re-run).
|
|
set -euo pipefail
|
|
SELF="$(cd "$(dirname "$0")" && pwd)"; ROOT_DIR="$(cd "$SELF/.." && pwd)"
|
|
INIT="$ROOT_DIR/init-output.json"; ADDR="${BAO_ADDR:-http://127.0.0.1:8200}"
|
|
APPLY=0; USERNAME="admin"
|
|
for a in "$@"; do case "$a" in --apply) APPLY=1;; *) USERNAME="$a";; esac; done
|
|
TOKEN="${BAO_TOKEN:-}"; [ -z "$TOKEN" ] && [ -r "$INIT" ] && TOKEN="$(python3 -c "import json;print(json.load(open('$INIT'))['root_token'])")"
|
|
[ -n "$TOKEN" ] || { echo "no token" >&2; exit 1; }
|
|
api(){ curl -sS -H "X-Vault-Token: $TOKEN" "$@"; }
|
|
|
|
# Groups -> policy. The HUMAN entity goes in g-admins (matches today). Adding it
|
|
# to g-personal/g-operators would compose those policies onto the same login.
|
|
GROUP_MAP="g-admins:admin g-operators:operator g-auditors:auditor g-personal:personal-rw"
|
|
ENTITY="lutz"; MEMBER_OF="g-admins"
|
|
|
|
echo "${APPLY:+}$([ $APPLY = 0 ] && echo '[DRY-RUN] ')target $ADDR username=$USERNAME entity=$ENTITY"
|
|
|
|
run(){ # METHOD PATH [JSON]
|
|
if [ "$APPLY" = 0 ]; then printf ' DRY %s %s %s\n' "$1" "$2" "${3:-}"; return 0; fi
|
|
api -X "$1" ${3:+--data "$3"} "$ADDR/v1/$2"
|
|
}
|
|
|
|
echo "== groups =="
|
|
for gp in $GROUP_MAP; do g="${gp%%:*}"; pol="${gp##*:}"
|
|
echo " $g -> policy:$pol"
|
|
run POST "identity/group" "{\"name\":\"$g\",\"type\":\"internal\",\"policies\":[\"$pol\"]}" >/dev/null
|
|
done
|
|
|
|
echo "== entity =="
|
|
echo " entity:$ENTITY (policies via groups, none direct)"
|
|
run POST "identity/entity" "{\"name\":\"$ENTITY\"}" >/dev/null
|
|
|
|
echo "== alias: $USERNAME@userpass -> entity:$ENTITY =="
|
|
if [ "$APPLY" = 1 ]; then
|
|
ACC="$(api "$ADDR/v1/sys/auth" | python3 -c "import sys,json;print(json.load(sys.stdin)['userpass/']['accessor'])")"
|
|
EID="$(api "$ADDR/v1/identity/entity/name/$ENTITY" | python3 -c "import sys,json;print(json.load(sys.stdin)['data']['id'])")"
|
|
run POST "identity/entity-alias" "{\"name\":\"$USERNAME\",\"canonical_id\":\"$EID\",\"mount_accessor\":\"$ACC\"}" >/dev/null
|
|
GID="$(api "$ADDR/v1/identity/group/name/$MEMBER_OF" | python3 -c "import sys,json;print(json.load(sys.stdin)['data']['id'])")"
|
|
run POST "identity/group/name/$MEMBER_OF" "{\"member_entity_ids\":[\"$EID\"]}" >/dev/null
|
|
echo " added entity:$ENTITY to $MEMBER_OF"
|
|
else
|
|
echo " DRY POST identity/entity-alias {name:$USERNAME, mount_accessor:<userpass>, canonical_id:<entity:$ENTITY>}"
|
|
echo " DRY POST identity/group/name/$MEMBER_OF {member_entity_ids:[<entity:$ENTITY>]}"
|
|
fi
|
|
[ "$APPLY" = 0 ] && echo "(dry-run — nothing changed; re-run with --apply to create)"
|