keycloak: allow groups scope for Veles Gitea

This commit is contained in:
jenkins 2026-06-20 14:50:16 -03:00
parent bb73c65d9f
commit 566eafdfc7
2 changed files with 93 additions and 2 deletions

View File

@ -1,12 +1,12 @@
# services/keycloak/oneoffs/veles-gitea-oidc-secret-ensure-job.yaml
# One-off job for sso/veles-gitea-oidc-secret-ensure-3.
# One-off job for sso/veles-gitea-oidc-secret-ensure-4.
# Purpose: create/update the Veles realm Gitea OIDC client and write the
# matching Gitea auth-source secret to Vault.
# Keep suspended until the Vault policy change has reconciled, then unsuspend once.
apiVersion: batch/v1
kind: Job
metadata:
name: veles-gitea-oidc-secret-ensure-3
name: veles-gitea-oidc-secret-ensure-4
namespace: sso
spec:
suspend: true

View File

@ -145,6 +145,94 @@ ensure_mapper() {
fi
}
ensure_client_scope() {
scope_name="$1"
scopes="$(curl -sS -H "Authorization: Bearer ${ACCESS_TOKEN}" \
"${KC_URL}/admin/realms/${REALM}/client-scopes?search=$(printf '%s' "${scope_name}" | jq -sRr @uri)" || true)"
scope_id="$(echo "$scopes" | jq -r --arg name "$scope_name" '.[]? | select(.name == $name) | .id' | head -n1 || true)"
if [ -n "$scope_id" ] && [ "$scope_id" != "null" ]; then
printf '%s' "$scope_id"
return
fi
scope_payload="$(jq -nc --arg name "$scope_name" '{name:$name,protocol:"openid-connect",attributes:{"include.in.token.scope":"true","display.on.consent.screen":"false"}}')"
status="$(curl -sS -o /tmp/keycloak-client-scope-create.json -w "%{http_code}" -X POST \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H 'Content-Type: application/json' \
-d "${scope_payload}" \
"${KC_URL}/admin/realms/${REALM}/client-scopes")"
if [ "$status" != "201" ] && [ "$status" != "204" ] && [ "$status" != "409" ]; then
echo "Keycloak client scope create failed for ${scope_name} (status ${status})" >&2
cat /tmp/keycloak-client-scope-create.json >&2 || true
exit 1
fi
scopes="$(curl -sS -H "Authorization: Bearer ${ACCESS_TOKEN}" \
"${KC_URL}/admin/realms/${REALM}/client-scopes?search=$(printf '%s' "${scope_name}" | jq -sRr @uri)" || true)"
scope_id="$(echo "$scopes" | jq -r --arg name "$scope_name" '.[]? | select(.name == $name) | .id' | head -n1 || true)"
if [ -z "$scope_id" ] || [ "$scope_id" = "null" ]; then
echo "Keycloak client scope ${scope_name} not found after create" >&2
exit 1
fi
printf '%s' "$scope_id"
}
ensure_scope_mapper() {
scope_id="$1"
mapper_name="$2"
mapper_payload="$3"
mappers="$(curl -sS -H "Authorization: Bearer ${ACCESS_TOKEN}" \
"${KC_URL}/admin/realms/${REALM}/client-scopes/${scope_id}/protocol-mappers/models" || true)"
mapper_id="$(echo "$mappers" | jq -r --arg name "$mapper_name" '.[]? | select(.name == $name) | .id' | head -n1 || true)"
if [ -n "$mapper_id" ] && [ "$mapper_id" != "null" ]; then
mapper_payload="$(echo "$mapper_payload" | jq --arg id "$mapper_id" '. + {id:$id}')"
status="$(curl -sS -o /tmp/keycloak-scope-mapper.json -w "%{http_code}" -X PUT \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H 'Content-Type: application/json' \
-d "${mapper_payload}" \
"${KC_URL}/admin/realms/${REALM}/client-scopes/${scope_id}/protocol-mappers/models/${mapper_id}")"
else
status="$(curl -sS -o /tmp/keycloak-scope-mapper.json -w "%{http_code}" -X POST \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H 'Content-Type: application/json' \
-d "${mapper_payload}" \
"${KC_URL}/admin/realms/${REALM}/client-scopes/${scope_id}/protocol-mappers/models")"
fi
if [ "$status" != "200" ] && [ "$status" != "201" ] && [ "$status" != "204" ]; then
echo "Keycloak client-scope mapper ensure failed for ${mapper_name} (status ${status})" >&2
cat /tmp/keycloak-scope-mapper.json >&2 || true
exit 1
fi
}
ensure_client_optional_scope() {
client_uuid="$1"
scope_id="$2"
scope_name="$3"
default_scopes="$(curl -sS -H "Authorization: Bearer ${ACCESS_TOKEN}" \
"${KC_URL}/admin/realms/${REALM}/clients/${client_uuid}/default-client-scopes" || true)"
optional_scopes="$(curl -sS -H "Authorization: Bearer ${ACCESS_TOKEN}" \
"${KC_URL}/admin/realms/${REALM}/clients/${client_uuid}/optional-client-scopes" || true)"
if echo "$default_scopes" | jq -e --arg name "$scope_name" '.[]? | select(.name == $name)' >/dev/null 2>&1 \
|| echo "$optional_scopes" | jq -e --arg name "$scope_name" '.[]? | select(.name == $name)' >/dev/null 2>&1; then
return
fi
status="$(curl -sS -o /dev/null -w "%{http_code}" -X PUT \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
"${KC_URL}/admin/realms/${REALM}/clients/${client_uuid}/optional-client-scopes/${scope_id}")"
if [ "$status" != "200" ] && [ "$status" != "201" ] && [ "$status" != "204" ]; then
status="$(curl -sS -o /dev/null -w "%{http_code}" -X POST \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
"${KC_URL}/admin/realms/${REALM}/clients/${client_uuid}/optional-client-scopes/${scope_id}")"
if [ "$status" != "200" ] && [ "$status" != "201" ] && [ "$status" != "204" ]; then
echo "Failed to attach ${scope_name} client scope to ${CLIENT_ID} (status ${status})" >&2
exit 1
fi
fi
}
TESTER_GROUP_ID="$(ensure_group "${TESTER_GROUP}")"
TESTER_ROLE="$(ensure_role "${TESTER_GROUP}")"
ensure_group_role "${TESTER_GROUP_ID}" "${TESTER_ROLE}"
@ -197,6 +285,9 @@ roles_mapper_payload="$(jq -nc \
'{name:"roles",protocol:"openid-connect",protocolMapper:"oidc-usermodel-realm-role-mapper",consentRequired:false,config:{"multivalued":"true","id.token.claim":"true","access.token.claim":"true","userinfo.token.claim":"true","claim.name":"roles","jsonType.label":"String"}}')"
ensure_mapper "${CLIENT_UUID}" groups "${groups_mapper_payload}"
ensure_mapper "${CLIENT_UUID}" roles "${roles_mapper_payload}"
GROUPS_SCOPE_ID="$(ensure_client_scope groups)"
ensure_scope_mapper "${GROUPS_SCOPE_ID}" groups "${groups_mapper_payload}"
ensure_client_optional_scope "${CLIENT_UUID}" "${GROUPS_SCOPE_ID}" groups
CLIENT_SECRET="$(curl -sS -H "Authorization: Bearer ${ACCESS_TOKEN}" \
"${KC_URL}/admin/realms/${REALM}/clients/${CLIENT_UUID}/client-secret" | jq -r '.value' 2>/dev/null || true)"