#!/usr/bin/env bash set -euo pipefail project_id="${GOOGLE_CLOUD_PROJECT:-${BURROW_GOOGLE_PROJECT_ID:-project-88c23ce9-918a-470a-b33}}" project_number="${BURROW_GOOGLE_PROJECT_NUMBER:-416198671487}" pool_id="${BURROW_GOOGLE_WIF_POOL_ID:-burrow-authentik}" provider_id="${BURROW_GOOGLE_WIF_PROVIDER_ID:-forgejo-runners}" service_account="${BURROW_GOOGLE_WIF_SERVICE_ACCOUNT:-burrow-forgejo-runner@project-88c23ce9-918a-470a-b33.iam.gserviceaccount.com}" authentik_issuer="${BURROW_AUTHENTIK_WIF_ISSUER:-https://auth.burrow.net/application/o/google-cloud/}" authentik_token_endpoint="${BURROW_AUTHENTIK_WIF_TOKEN_ENDPOINT:-}" authentik_audience="${BURROW_AUTHENTIK_WIF_AUDIENCE:-google-wif.burrow.net}" authentik_client_id="${BURROW_AUTHENTIK_WIF_CLIENT_ID:-${AUTHENTIK_GOOGLE_WIF_CLIENT_ID:-google-wif.burrow.net}}" authentik_client_secret="${BURROW_AUTHENTIK_WIF_CLIENT_SECRET:-${AUTHENTIK_GOOGLE_WIF_CLIENT_SECRET:-}}" authentik_token_file="${BURROW_AUTHENTIK_WIF_TOKEN_FILE:-}" authentik_token="${BURROW_AUTHENTIK_WIF_TOKEN:-}" work_dir="${RUNNER_TEMP:-${TMPDIR:-/tmp}}/burrow-google-wif" emit_env=1 usage() { cat <<'EOF' Usage: Scripts/ci/google-wif-auth.sh [--no-emit-env] Authenticates gcloud to the Burrow Google project through Authentik-issued OIDC and Google Workload Identity Federation. No Google service-account JSON key is used or written. Inputs: GOOGLE_CLOUD_PROJECT / BURROW_GOOGLE_PROJECT_ID BURROW_GOOGLE_PROJECT_NUMBER BURROW_GOOGLE_WIF_POOL_ID BURROW_GOOGLE_WIF_PROVIDER_ID BURROW_GOOGLE_WIF_SERVICE_ACCOUNT BURROW_AUTHENTIK_WIF_ISSUER BURROW_AUTHENTIK_WIF_TOKEN_ENDPOINT BURROW_AUTHENTIK_WIF_AUDIENCE BURROW_AUTHENTIK_WIF_TOKEN or BURROW_AUTHENTIK_WIF_TOKEN_FILE If no token is supplied, the script requests one from Authentik using BURROW_AUTHENTIK_WIF_CLIENT_ID and BURROW_AUTHENTIK_WIF_CLIENT_SECRET. EOF } while [[ "$#" -gt 0 ]]; do case "$1" in --no-emit-env) emit_env=0 ;; -h|--help) usage exit 0 ;; *) echo "unknown argument: $1" >&2 exit 64 ;; esac shift done require_command() { if ! command -v "$1" >/dev/null 2>&1; then echo "$1 is required for Google WIF authentication" >&2 exit 127 fi } require_command gcloud require_command curl require_command jq resolve_token_endpoint() { if [[ -n "$authentik_token_endpoint" ]]; then printf '%s\n' "$authentik_token_endpoint" return fi local issuer_no_slash="${authentik_issuer%/}" local discovered="" if discovered="$( curl -fsS "${issuer_no_slash}/.well-known/openid-configuration" 2>/dev/null \ | jq -r '.token_endpoint // empty' 2>/dev/null )" && [[ -n "$discovered" ]]; then printf '%s\n' "$discovered" return fi case "$issuer_no_slash" in */application/o/*) printf '%s/application/o/token/\n' "${issuer_no_slash%%/application/o/*}" ;; *) printf '%s/token/\n' "$issuer_no_slash" ;; esac } mkdir -p "$work_dir" chmod 0700 "$work_dir" token_path="$work_dir/authentik-oidc-token.jwt" credential_config="$work_dir/google-wif-credentials.json" if [[ -n "$authentik_token_file" ]]; then if [[ ! -s "$authentik_token_file" ]]; then echo "Authentik WIF token file is empty or missing: $authentik_token_file" >&2 exit 1 fi cp "$authentik_token_file" "$token_path" elif [[ -n "$authentik_token" ]]; then printf '%s' "$authentik_token" > "$token_path" else if [[ -z "$authentik_client_secret" ]]; then echo "missing Authentik WIF token. Set BURROW_AUTHENTIK_WIF_TOKEN, BURROW_AUTHENTIK_WIF_TOKEN_FILE, or BURROW_AUTHENTIK_WIF_CLIENT_SECRET." >&2 exit 1 fi token_endpoint="$(resolve_token_endpoint)" curl -fsS \ -d grant_type=client_credentials \ -d client_id="$authentik_client_id" \ -d client_secret="$authentik_client_secret" \ -d scope="openid profile email groups" \ -d audience="$authentik_audience" \ "$token_endpoint" \ | jq -r '.id_token // .access_token // empty' > "$token_path" fi chmod 0600 "$token_path" if [[ ! -s "$token_path" ]]; then echo "Authentik did not return an OIDC token for Google WIF" >&2 exit 1 fi provider_resource="projects/${project_number}/locations/global/workloadIdentityPools/${pool_id}/providers/${provider_id}" gcloud iam workload-identity-pools create-cred-config "$provider_resource" \ --service-account "$service_account" \ --subject-token-type="urn:ietf:params:oauth:token-type:jwt" \ --credential-source-file "$token_path" \ --output-file "$credential_config" chmod 0600 "$credential_config" export CLOUDSDK_CORE_PROJECT="$project_id" export GOOGLE_CLOUD_PROJECT="$project_id" gcloud auth login --cred-file="$credential_config" --brief { echo "GOOGLE_APPLICATION_CREDENTIALS=$credential_config" echo "CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE=$credential_config" echo "CLOUDSDK_CORE_PROJECT=$project_id" echo "GOOGLE_CLOUD_PROJECT=$project_id" } > "$work_dir/google-wif.env" if [[ "$emit_env" == "1" && -n "${GITHUB_ENV:-}" ]]; then cat "$work_dir/google-wif.env" >> "$GITHUB_ENV" fi echo "Authenticated gcloud through Authentik WIF as ${service_account} in ${project_id}."