burrow/Scripts/ci/google-wif-auth.sh
Conrad Kramer 8180c3c35a
Some checks failed
Build Rust / Cargo Test (push) Successful in 4m8s
Build Site / Next.js Build (push) Failing after 4s
Lint Governance / BEP Metadata (push) Successful in 1s
Fix Authentik WIF token endpoint
2026-06-07 12:33:39 -07:00

154 lines
5 KiB
Bash
Executable file

#!/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 \
-u "${authentik_client_id}:${authentik_client_secret}" \
-d grant_type=client_credentials \
-d scope="openid profile email groups" \
-d audience="$authentik_audience" \
"$token_endpoint" \
| jq -r '.id_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"
gcloud auth login --cred-file="$credential_config" --brief
gcloud config set project "$project_id" >/dev/null
{
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}."