Last active
July 30, 2024 18:53
-
-
Save SafeEval/a3ae80dacf5297e207c5caec93e69bda to your computer and use it in GitHub Desktop.
Get a Github access token as a Github App in pure bash
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 | |
# Get a Github access token as a Github App in pure bash. | |
# 1. Generate a JWT (CLIENT_ID and PEM) | |
# 2. Obtain the access token (JWT and INSTALLATION_ID) | |
# | |
# https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/generating-a-json-web-token-jwt-for-a-github-app#example-using-bash-to-generate-a-jwt | |
set -o pipefail | |
# Ensure required environment variables are set. | |
function ValidateEnv() { | |
if [ -z $CLIENT_ID ]; then | |
echo "Missing Github App's CLIENT_ID environment variable" >&2; | |
exit 1; | |
fi | |
if [ -z $PEM_FILE ]; then | |
echo "Missing Github App's PEM_FILE environment variable" >&2; | |
exit 1; | |
fi | |
if [ -z $INSTALLATION_ID ]; then | |
echo "Missing Github App's INSTALLATION_ID environment variable" >&2; | |
exit 1; | |
fi | |
} | |
# Base64 encoding for JWT segments. | |
function Base64Enc() { | |
openssl base64 | tr -d '=' | tr '/+' '_-' | tr -d '\n'; | |
} | |
# Generate the signed JWT to get a Github access token. | |
function GenerateJWT() { | |
# Get the app's private key | |
pem="$(cat $PEM_FILE)" | |
# JWT header | |
header_json='{ | |
"typ":"JWT", | |
"alg":"RS256" | |
}' | |
header=$( echo -n "${header_json}" | Base64Enc ) | |
# JWT body | |
now=$(date +%s) | |
iat=$((${now} - 60)) # Issues 60 seconds in the past. | |
exp=$((${now} + 600)) # Expires 10 minutes in the future. | |
payload_json="{\"iat\":${iat}, \"exp\":${exp}, \"iss\":\"${CLIENT_ID}\"}" | |
payload=$( echo -n "${payload_json}" | Base64Enc ) | |
# JWT signature | |
header_payload="${header}"."${payload}" | |
signature=$( | |
openssl dgst -sha256 -sign <(echo -n "${pem}") \ | |
<(echo -n "${header_payload}") | Base64Enc | |
) | |
# Return the assembled JWT | |
JWT="${header_payload}"."${signature}" | |
echo $JWT | |
} | |
# Get an app installation access token as the Github App. | |
function FetchGithubToken() { | |
jwt=$1; | |
result=$(curl -s --request POST \ | |
--header "Authorization: Bearer $jwt" \ | |
--header "Accept: application/vnd.github+json" \ | |
--header "X-GitHub-Api-Version: 2022-11-28" \ | |
--url "https://api.github.com/app/installations/$INSTALLATION_ID/access_tokens") | |
token=$(echo $result | grep -o 'ghs_\w\+') | |
if [ $? -ne 0 ]; then | |
echo "Failed to fetch Github access token" >&2; | |
return 1; | |
fi | |
echo $token | |
} | |
ValidateEnv; | |
jwt=$(GenerateJWT); | |
github_token=$(FetchGithubToken $jwt) || exit 1; | |
echo ${github_token} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment