keycloak: add Hermes automation identity

This commit is contained in:
jenkins 2026-08-13 17:45:09 -03:00
parent 521d1190c6
commit aa376c0ee9
2 changed files with 86 additions and 2 deletions

View File

@ -1,9 +1,9 @@
# services/keycloak/bootstrap-jobs/hermes-access-oidc-client-job.yaml # services/keycloak/bootstrap-jobs/hermes-access-oidc-client-job.yaml
# Purpose: create isolated chat, Brad-only agent, and Brad-only triage clients. # Purpose: create Hermes browser clients and its automation identity.
apiVersion: batch/v1 apiVersion: batch/v1
kind: Job kind: Job
metadata: metadata:
name: hermes-access-oidc-client-ensure-6 name: hermes-access-oidc-client-ensure-7
namespace: sso namespace: sso
spec: spec:
backoffLimit: 3 backoffLimit: 3

View File

@ -208,6 +208,89 @@ ensure_proxy_client() {
echo "Hermes OIDC client ${client_id} is ready" echo "Hermes OIDC client ${client_id} is ready"
} }
ensure_service_account_client() {
client_id="$1"
vault_path="$2"
payload="$(jq -nc \
--arg client_id "${client_id}" \
'{
clientId:$client_id,
name:"Hermes Automation",
description:"Machine identity for Hermes development and delivery integrations",
enabled:true,
protocol:"openid-connect",
publicClient:false,
bearerOnly:false,
clientAuthenticatorType:"client-secret",
standardFlowEnabled:false,
implicitFlowEnabled:false,
directAccessGrantsEnabled:false,
serviceAccountsEnabled:true,
fullScopeAllowed:false,
attributes:{"access.token.lifespan":"1200"}
}')"
query="$(curl -sS -H "Authorization: Bearer ${ACCESS_TOKEN}" \
"${KC_URL}/admin/realms/atlas/clients?clientId=${client_id}" || true)"
internal_id="$(printf '%s' "${query}" | jq -r '.[0].id' 2>/dev/null || true)"
if [ -z "${internal_id}" ] || [ "${internal_id}" = "null" ]; then
status="$(curl -sS -o /dev/null -w '%{http_code}' -X POST \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H 'Content-Type: application/json' \
-d "${payload}" \
"${KC_URL}/admin/realms/atlas/clients")"
if [ "${status}" != "201" ] && [ "${status}" != "204" ] && [ "${status}" != "409" ]; then
echo "Keycloak service account client ${client_id} create failed (status ${status})" >&2
exit 1
fi
query="$(curl -sS -H "Authorization: Bearer ${ACCESS_TOKEN}" \
"${KC_URL}/admin/realms/atlas/clients?clientId=${client_id}" || true)"
internal_id="$(printf '%s' "${query}" | jq -r '.[0].id' 2>/dev/null || true)"
fi
if [ -z "${internal_id}" ] || [ "${internal_id}" = "null" ]; then
echo "Keycloak service account client ${client_id} was not found after create" >&2
exit 1
fi
status="$(curl -sS -o /dev/null -w '%{http_code}' -X PUT \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H 'Content-Type: application/json' \
-d "${payload}" \
"${KC_URL}/admin/realms/atlas/clients/${internal_id}")"
if [ "${status}" != "204" ]; then
echo "Keycloak service account client ${client_id} update failed (status ${status})" >&2
exit 1
fi
client_secret="$(curl -sS -H "Authorization: Bearer ${ACCESS_TOKEN}" \
"${KC_URL}/admin/realms/atlas/clients/${internal_id}/client-secret" \
| jq -r '.value' 2>/dev/null || true)"
if [ -z "${client_secret}" ] || [ "${client_secret}" = "null" ]; then
echo "Keycloak service account client ${client_id} secret was not returned" >&2
exit 1
fi
issuer="https://sso.bstein.dev/realms/atlas"
token_url="${KC_URL}/realms/atlas/protocol/openid-connect/token"
state_file="/tmp/hermes-$(printf '%s' "${client_id}" | tr -c 'a-zA-Z0-9' '-').json"
vault_payload="$(jq -nc \
--arg client_id "${client_id}" \
--arg client_secret "${client_secret}" \
--arg issuer "${issuer}" \
--arg token_url "${token_url}" \
'{data:{client_id:$client_id,client_secret:$client_secret,issuer:$issuer,token_url:$token_url}}')"
write_status="$(curl -sS -o "${state_file}" -w '%{http_code}' -X POST \
-H "X-Vault-Token: ${vault_token}" \
-H 'Content-Type: application/json' \
-d "${vault_payload}" \
"${VAULT_ADDR}/v1/kv/data/atlas/${vault_path}")"
if [ "${write_status}" != "200" ] && [ "${write_status}" != "204" ]; then
echo "Vault ${vault_path} write failed (status ${write_status})" >&2
exit 1
fi
echo "Hermes machine identity ${client_id} is ready"
}
ensure_telegram_config() { ensure_telegram_config() {
vault_path="hermes/chat-telegram" vault_path="hermes/chat-telegram"
state_file="/tmp/hermes-chat-telegram.json" state_file="/tmp/hermes-chat-telegram.json"
@ -247,4 +330,5 @@ ensure_hermes_owner
ensure_proxy_client "hermes-chat-proxy" "https://chat.hermes.bstein.dev" "hermes/chat-oidc" ensure_proxy_client "hermes-chat-proxy" "https://chat.hermes.bstein.dev" "hermes/chat-oidc"
ensure_proxy_client "hermes-agent-proxy" "https://agent.hermes.bstein.dev" "hermes/agent-oidc" ensure_proxy_client "hermes-agent-proxy" "https://agent.hermes.bstein.dev" "hermes/agent-oidc"
ensure_proxy_client "hermes-triage-proxy" "https://triage.hermes.bstein.dev" "hermes/triage-oidc" ensure_proxy_client "hermes-triage-proxy" "https://triage.hermes.bstein.dev" "hermes/triage-oidc"
ensure_service_account_client "hermes-automation" "hermes/developer-keycloak"
ensure_telegram_config ensure_telegram_config