• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env bash
2#
3# Request an ACCESS_TOKEN to be used by a GitHub APP
4# Environment variable that need to be set up:
5# * APP_ID, the GitHub's app ID
6# * INSTALL_ID, the Github's app's installation ID
7# * APP_PRIVATE_KEY, the content of GitHub app's private key in PEM format.
8#
9# https://github.com/orgs/community/discussions/24743#discussioncomment-3245300
10#
11
12set -o pipefail
13
14_GITHUB_HOST=${GITHUB_HOST:="github.com"}
15
16# If URL is not github.com then use the enterprise api endpoint
17if [[ ${GITHUB_HOST} = "github.com" ]]; then
18  URI="https://api.${_GITHUB_HOST}"
19else
20  URI="https://${_GITHUB_HOST}/api/v3"
21fi
22
23API_VERSION=v3
24API_HEADER="Accept: application/vnd.github.${API_VERSION}+json"
25CONTENT_LENGTH_HEADER="Content-Length: 0"
26APP_INSTALLATIONS_URI="${URI}/app/installations"
27
28
29# JWT parameters based off
30# https://docs.github.com/en/developers/apps/building-github-apps/authenticating-with-github-apps#authenticating-as-a-github-app
31#
32# JWT token issuance and expiration parameters
33JWT_IAT_DRIFT=60
34JWT_EXP_DELTA=600
35
36JWT_JOSE_HEADER='{
37    "alg": "RS256",
38    "typ": "JWT"
39}'
40
41
42build_jwt_payload() {
43    now=$(date +%s)
44    iat=$((now - JWT_IAT_DRIFT))
45    jq -c \
46        --arg iat_str "${iat}" \
47        --arg exp_delta_str "${JWT_EXP_DELTA}" \
48        --arg app_id_str "${APP_ID}" \
49    '
50        ($iat_str | tonumber) as $iat
51        | ($exp_delta_str | tonumber) as $exp_delta
52        | ($app_id_str | tonumber) as $app_id
53        | .iat = $iat
54        | .exp = ($iat + $exp_delta)
55        | .iss = $app_id
56    ' <<< "{}" | tr -d '\n'
57}
58
59base64url() {
60    base64 | tr '+/' '-_' | tr -d '=\n'
61}
62
63rs256_sign() {
64    openssl dgst -binary -sha256 -sign <(echo "$1")
65}
66
67request_access_token() {
68    jwt_payload=$(build_jwt_payload)
69    encoded_jwt_parts=$(base64url <<<"${JWT_JOSE_HEADER}").$(base64url <<<"${jwt_payload}")
70    encoded_mac=$(echo -n "$encoded_jwt_parts" | rs256_sign "${APP_PRIVATE_KEY}" | base64url)
71    generated_jwt="${encoded_jwt_parts}.${encoded_mac}"
72
73    auth_header="Authorization: Bearer ${generated_jwt}"
74
75    app_installations_response=$(curl -sX POST \
76        -H "${auth_header}" \
77        -H "${API_HEADER}" \
78        --header "X-GitHub-Api-Version: 2022-11-28" \
79        --url "https://api.github.com/app/installations/${INSTALL_ID}/access_tokens" \
80    )
81    echo "$app_installations_response" | jq --raw-output '.token'
82}
83
84request_access_token
85