#!/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}."
