#!/usr/bin/env bash # Policy-as-code: apply every policies/*.hcl to OpenBAO. Idempotent. # apply-policies.sh --dry-run # read-only: show NEW/CHANGED/unchanged, change nothing # apply-policies.sh # apply (writes policies that are NEW or CHANGED) # # Auth: needs a token allowed to write sys/policies/acl/* (root or admin). # Uses $BAO_TOKEN if set, else falls back to the root token in init-output.json. # Built-in `default`/`root` policies have no file here and are never touched. set -euo pipefail SELF="$(cd "$(dirname "$0")" && pwd)"; ROOT_DIR="$(cd "$SELF/.." && pwd)" DIR="$ROOT_DIR/policies"; INIT="$ROOT_DIR/init-output.json" ADDR="${BAO_ADDR:-http://127.0.0.1:8200}" DRY=0; [ "${1:-}" = "--dry-run" ] && DRY=1 TOKEN="${BAO_TOKEN:-}" [ -z "$TOKEN" ] && [ -r "$INIT" ] && TOKEN="$(python3 -c "import json;print(json.load(open('$INIT'))['root_token'])")" [ -n "$TOKEN" ] || { echo "no token (set BAO_TOKEN or provide init-output.json)" >&2; exit 1; } # functional comparison: ignore comments and blank lines norm(){ grep -vE '^[[:space:]]*#' | grep -vE '^[[:space:]]*$' | sed 's/[[:space:]]*$//'; } echo "${DRY:+[dry-run] }policies under $DIR -> $ADDR" for f in "$DIR"/*.hcl; do name="$(basename "$f" .hcl)"; filetxt="$(cat "$f")" live="$(curl -sS -H "X-Vault-Token: $TOKEN" "$ADDR/v1/sys/policies/acl/$name" \ | python3 -c "import sys,json;d=json.load(sys.stdin);print(d.get('data',{}).get('policy','') if 'data' in d else '')" 2>/dev/null || true)" if [ -z "$live" ]; then status="NEW" elif [ "$(printf '%s' "$filetxt" | norm)" = "$(printf '%s' "$live" | norm)" ]; then status="unchanged" else status="CHANGED"; fi if [ "$DRY" = 1 ] || [ "$status" = unchanged ]; then printf ' %-10s %s\n' "$status" "$name"; continue fi code="$(printf '%s' "$filetxt" | python3 -c 'import json,sys;print(json.dumps({"policy":sys.stdin.read()}))' \ | curl -sS -o /dev/null -w '%{http_code}' -H "X-Vault-Token: $TOKEN" --data @- "$ADDR/v1/sys/policies/acl/$name")" printf ' %-10s %s (HTTP %s)\n' "applied[$status]" "$name" "$code" done [ "$DRY" = 1 ] && echo "(dry-run — nothing changed)" || true