Created
January 29, 2025 07:50
-
-
Save mlebkowski/b872e002d4dd76b53c057054cf945467 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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