#!/usr/bin/env bash # bw-git-credential.sh — Git credential helper that sources Gitea tokens from Bitwarden. # # This eliminates the need for per-agent SSH keys or on-disk tokens for git # operations. Each repo has a git identity (user.email) that identifies which # agent is working. This helper reads that identity, fetches the matching # Gitea API token from Bitwarden, and provides it to git. # # Setup (once per environment, in ~/.gitconfig): # [credential "https://git.knownelement.com"] # helper = /path/to/bw-git-credential.sh # # How it works: # - During git push (in an existing repo): reads `git config user.email` # to determine the agent, fetches " Gitea" from Bitwarden. # - During git clone (no repo yet): reads AGENT_CLONE_AS env var, which # clone-as.sh sets before calling git clone. # - If neither is set, exits silently (lets other credential helpers run). set -euo pipefail GITEA_HOST="git.knownelement.com" # --------------------------------------------------------------------------- # Read git credential input from stdin # --------------------------------------------------------------------------- declare -A cred while IFS='=' read -r key value; do # Empty line terminates the credential block [ -z "$key" ] && break cred["$key"]="$value" done host="${cred[protocol]:-}://${cred[host]:-}" # Only handle our Gitea instance if [ "${cred[host]:-}" != "$GITEA_HOST" ]; then exit 0 fi # --------------------------------------------------------------------------- # Determine which agent identity to use # --------------------------------------------------------------------------- agent="" # During clone: clone-as.sh sets this env var if [ -n "${AGENT_CLONE_AS:-}" ]; then agent="$AGENT_CLONE_AS" else # During push/fetch: read the repo's configured identity agent_email=$(git config user.email 2>/dev/null || echo "") if [ -n "$agent_email" ]; then agent=$(echo "$agent_email" | cut -d@ -f1) fi fi if [ -z "$agent" ]; then # No agent identity — let other credential helpers handle it exit 0 fi # --------------------------------------------------------------------------- # Ensure Bitwarden session is active # --------------------------------------------------------------------------- if [ -z "${BW_SESSION:-}" ]; then # Try to establish from the env file bw_env="${HOME}/.config/bw/env" if [ -f "$bw_env" ]; then # shellcheck disable=SC1090 . "$bw_env" fi if [ -n "${BW_CLIENTID:-}" ] && [ -n "${BW_CLIENTSECRET:-}" ]; then bw login --apikey >/dev/null 2>&1 || true export BW_SESSION BW_SESSION=$(BW_PASSWORD="${BW_PASSWORD:-}" bw unlock --raw 2>/dev/null || true) fi fi if [ -z "${BW_SESSION:-}" ]; then echo "bw-git-credential: no BW session — cannot fetch token for $agent" >&2 exit 1 fi # --------------------------------------------------------------------------- # Fetch the Gitea token from Bitwarden # --------------------------------------------------------------------------- item_name="$agent Gitea" token=$(bw get password "$item_name" 2>/dev/null || echo "") if [ -z "$token" ]; then echo "bw-git-credential: no Gitea token in BW for: $item_name" >&2 exit 1 fi # --------------------------------------------------------------------------- # Output credentials for git # --------------------------------------------------------------------------- echo "username=$agent" echo "password=$token"