titan-iac/scripts/gitea_cred_sync.sh

93 lines
3.2 KiB
Bash
Executable File

#!/usr/bin/env bash
# Sync Keycloak users into Gitea local accounts (for CLI + tokens).
# Requires: curl, jq, kubectl. Expects a Keycloak client with realm-management
# permissions (manage-users) and a Gitea admin token stored in a secret.
set -euo pipefail
require() { command -v "$1" >/dev/null 2>&1 || { echo "missing required binary: $1" >&2; exit 1; }; }
require curl; require jq; require kubectl
: "${KEYCLOAK_URL:=https://sso.bstein.dev}"
: "${KEYCLOAK_REALM:=atlas}"
: "${KEYCLOAK_CLIENT_ID:?set KEYCLOAK_CLIENT_ID or export via secret}"
: "${KEYCLOAK_CLIENT_SECRET:?set KEYCLOAK_CLIENT_SECRET or export via secret}"
: "${GITEA_BASE_URL:=https://scm.bstein.dev}"
: "${GITEA_NAMESPACE:=gitea}"
: "${GITEA_TOKEN_SECRET_NAME:=gitea-admin-token}"
: "${GITEA_TOKEN_SECRET_KEY:=token}"
: "${DEFAULT_PASSWORD:=TempSsoPass!2025}"
fetch_token() {
curl -fsS -X POST \
-d "grant_type=client_credentials" \
-d "client_id=${KEYCLOAK_CLIENT_ID}" \
-d "client_secret=${KEYCLOAK_CLIENT_SECRET}" \
"${KEYCLOAK_URL}/realms/${KEYCLOAK_REALM}/protocol/openid-connect/token" \
| jq -r '.access_token'
}
pull_users() {
local token="$1"
curl -fsS -H "Authorization: Bearer ${token}" \
"${KEYCLOAK_URL}/admin/realms/${KEYCLOAK_REALM}/users?max=500" \
| jq -r '.[] | select(.enabled == true) | select(.username | startswith("service-account-") | not) | [.username, (.email // ""), (.firstName // ""), (.lastName // "")] | @tsv'
}
get_gitea_token() {
if [[ -n "${GITEA_ADMIN_TOKEN:-}" ]]; then
echo "${GITEA_ADMIN_TOKEN}"
return
fi
kubectl -n "${GITEA_NAMESPACE}" get secret "${GITEA_TOKEN_SECRET_NAME}" -o "jsonpath={.data.${GITEA_TOKEN_SECRET_KEY}}" \
| base64 -d
}
user_exists() {
local token="$1" username="$2"
local code
code=$(curl -s -o /dev/null -w '%{http_code}' \
-H "Authorization: token ${token}" \
"${GITEA_BASE_URL}/api/v1/admin/users/${username}")
[[ "${code}" == "200" ]]
}
create_user() {
local token="$1" username="$2" email="$3" fname="$4" lname="$5"
local body status fullname
fullname="$(echo "${fname} ${lname}" | xargs)"
if [[ -z "${email}" ]]; then
email="${username}@example.local"
fi
body=$(jq -n --arg u "${username}" --arg e "${email}" --arg p "${DEFAULT_PASSWORD}" \
--arg fn "${fullname}" '{username:$u, email:$e, password:$p, must_change_password:false, full_name:$fn}')
status=$(curl -s -o /dev/null -w '%{http_code}' \
-H "Authorization: token ${token}" \
-H "Content-Type: application/json" \
-X POST \
-d "${body}" \
"${GITEA_BASE_URL}/api/v1/admin/users")
if [[ "${status}" == "201" ]]; then
echo "created gitea user ${username}"
elif [[ "${status}" == "409" ]]; then
echo "gitea user ${username} already exists (409)" >&2
else
echo "failed to create gitea user ${username} (status ${status})" >&2
fi
}
main() {
local kc_token gitea_token
kc_token="$(fetch_token)"
gitea_token="$(get_gitea_token)"
while IFS=$'\t' read -r username email fname lname; do
if user_exists "${gitea_token}" "${username}"; then
continue
fi
create_user "${gitea_token}" "${username}" "${email}" "${fname}" "${lname}"
done < <(pull_users "${kc_token}")
}
main "$@"