Skip to content

Instantly share code, notes, and snippets.

@mlebkowski
Created January 29, 2025 07:50
Show Gist options
  • Save mlebkowski/b872e002d4dd76b53c057054cf945467 to your computer and use it in GitHub Desktop.
Save mlebkowski/b872e002d4dd76b53c057054cf945467 to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
if [[ -z "$GITHUB_PRIVATE_KEY" || -z "$GITHUB_APP_ID" ]]; then
echo "Error: Required environment variables are not set." >&2
echo "Ensure GITHUB_PRIVATE_KEY and GITHUB_APP_ID are set." >&2
exit 1
fi
if [[ -f "$GITHUB_PRIVATE_KEY" ]; then
GITHUB_PRIVATE_KEY="$(cat "$GITHUB_PRIVATE_KEY")"
fi
# if you do not provide one, the script will make some assumptions:
GITHUB_INSTALLATION_ID=${GITHUB_INSTALLATION_ID:-}
GITHUB_API_URL=${GITHUB_API_URL:-"https://api.github.com"}
set -euo pipefail
ensure_command() {
declare command="$1"
if ! command -v "$command" >/dev/null 2>&1 ; then
echo "Required command $command is missing on your system" >&2
return 1
fi
}
ensure_many_commands() {
for command in "$@"; do
ensure_command "$command"
done
}
jwt_part() {
openssl base64 -A | tr -d '=' | tr '/+' '_-'
}
generate_jwt() {
local header payload unsigned_token jwt current_time exp_time
current_time=$(date +%s)
exp_time=$((current_time + 600)) # JWT valid for 10 minutes
header="$(jq -nMc '{alg:"RS256",typ:"JWT"}' | jwt_part)"
payload="$(
jq -nMc \
--arg current_time "$current_time" \
--arg exp_time "$exp_time" \
--arg iss "$GITHUB_APP_ID" \
'{iat: $current_time|tonumber, exp: $exp_time|tonumber, iss: $iss|tonumber}' \
| jwt_part
)"
unsigned_token="${header}.${payload}"
jwt="$(
echo -n "$unsigned_token" \
| openssl dgst -sha256 -sign <(echo "$GITHUB_PRIVATE_KEY") \
| jwt_part
)"
echo "${unsigned_token}.${jwt}"
}
get_installation_token() {
declare jwt="$1"
local installation_id=${GITHUB_INSTALLATION_ID}
if [[ -z "$installation_id" ]]; then
# assumes that there is only one installation:
installation_id="$(
curl -s -H "Authorization: Bearer $jwt" \
-H "Accept: application/vnd.github+json" \
"${GITHUB_API_URL}/app/installations" \
| jq '.[0].id'
)"
fi
if [[ -z "$installation_id" || "$installation_id" == "null" ]]; then
echo "Error: Unable to fetch installation ID. Verify app permissions and setup." >&2
return 1
fi
curl -s -X POST -H "Authorization: Bearer $jwt" \
-H "Accept: application/vnd.github+json" \
"${GITHUB_API_URL}/app/installations/${installation_id}/access_tokens" \
| jq -r '.token'
}
main() {
declare target="${1:-.}"
local jwt;
jwt="$(generate_jwt)"
local token
token="$(get_installation_token "$jwt")"
if [[ -z "$token" ]]; then
echo "Error: Unable to retrieve installation token." >&2
return 1
fi
echo "$token"
}
ensure_many_commands jq openssl curl
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment