Skip to content

Instantly share code, notes, and snippets.

@SafeEval
Last active July 30, 2024 18:53
Show Gist options
  • Save SafeEval/a3ae80dacf5297e207c5caec93e69bda to your computer and use it in GitHub Desktop.
Save SafeEval/a3ae80dacf5297e207c5caec93e69bda to your computer and use it in GitHub Desktop.
Get a Github access token as a Github App in pure bash
#!/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