Skip to content

Commit a5fd552

Browse files
New Scripts for interacting with GitHub Apps and determining rate limits (#80)
* feat: initial version of script * feat: Added 3 scripts related to GitHub Apps, updated ReadMe
1 parent 23f2713 commit a5fd552

File tree

4 files changed

+345
-0
lines changed

4 files changed

+345
-0
lines changed

api/README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# api
22

3+
## checking-github-app-rate-limits.sh
4+
5+
This script checks the GitHub App's rate limit status by generating a JWT (JSON Web Token), obtaining an installation access token, and then querying the GitHub API for the rate limit information. It is useful for developers and administrators to monitor and manage their GitHub App's API usage.
6+
37
## create-repo.sh
48

59
Create an internal repo in an organization
@@ -37,3 +41,12 @@ Download a workflow artifact (e.g.: downloading the artifact from the build work
3741
Enables actions on a repository - similar to [gh cli example](./../api/enable-actions-on-repository.sh), but using `curl`
3842

3943
[Documentation](https://docs.github.com/en/rest/reference/actions#set-github-actions-permissions-for-a-repository)
44+
45+
## generate-jwt-from-github-app-and-find-org-installation-ids.sh
46+
47+
This script generates a JWT (JSON Web Token) for a GitHub App and uses it to list the installations of the App. It is useful for developers and administrators who need to authenticate as a GitHub App to access GitHub API.
48+
49+
## get-repo-info-using-github-app-and-show-api-rate-limit-info.sh
50+
51+
This script is designed to generate a JWT (JSON Web Token) for authenticating as a GitHub App. It then uses this token to perform GitHub API requests, specifically to retrieve information about a specified repository
52+
and display the current API rate limit status. This is particularly useful for developers and administrators who need to monitor their GitHub App's API usage and ensure it stays within the GitHub API rate limits.
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
#!/bin/bash
2+
3+
# v1.0.0
4+
5+
# This script checks the GitHub App's rate limit status by generating a JWT (JSON Web Token),
6+
# obtaining an installation access token, and then querying the GitHub API for the rate limit information.
7+
# It is useful for developers and administrators to monitor and manage their GitHub App's API usage.
8+
9+
# Inputs:
10+
# 1. APP_ID: The unique identifier for the GitHub App. This should be passed as the first argument.
11+
# 2. PRIVATE_KEY_PATH: The file path to the private key of the GitHub App. This should be passed as the second argument.
12+
# 3. INSTALLATION_ID: The installation ID of the GitHub App. This should be passed as the third argument.
13+
# 4. --debug (optional): A flag that can be included to enable debug output. This can be placed anywhere in the command line.
14+
15+
# How to call:
16+
# ./checking-github-app-rate-limits.sh [APP_ID] [PRIVATE_KEY_PATH] [INSTALLATION_ID]
17+
# ./checking-github-app-rate-limits.sh --debug [APP_ID] [PRIVATE_KEY_PATH] [INSTALLATION_ID]
18+
# ./checking-github-app-rate-limits.sh [APP_ID] [PRIVATE_KEY_PATH] [INSTALLATION_ID] --debug
19+
20+
# Important Notes:
21+
# - The script requires `openssl`, `curl`, and `jq` to be installed on the system.
22+
# - The JWT generated by this script is valid for 10 minutes from its creation time.
23+
# - The script outputs the remaining API call count, which helps in understanding the current rate limit status.
24+
# - Ensure that the private key file path is correct and the file has appropriate read permissions.
25+
# - The `--debug` flag is useful for troubleshooting and understanding the script's flow.
26+
27+
28+
# Initialize debug mode to off
29+
DEBUG_MODE=0
30+
31+
# Function to handle debug messages
32+
debug() {
33+
if [ "$DEBUG_MODE" -eq 1 ]; then
34+
echo "DEBUG: $*"
35+
fi
36+
}
37+
38+
# Initialize an array to hold the remaining arguments after removing recognized flags
39+
REMAINING_ARGS=()
40+
41+
# Process each argument
42+
while [ "$#" -gt 0 ]; do
43+
case "$1" in
44+
--debug)
45+
DEBUG_MODE=1
46+
shift # Remove --debug from the list of arguments
47+
;;
48+
*)
49+
# Collect unrecognized arguments
50+
REMAINING_ARGS+=("$1")
51+
shift # Move to the next argument
52+
;;
53+
esac
54+
done
55+
56+
# Check if we have at least three remaining arguments for APP_ID, PRIVATE_KEY_PATH, and INSTALLATION_ID
57+
if [ "${#REMAINING_ARGS[@]}" -lt 3 ]; then
58+
echo "Usage: $0 [--debug] APP_ID PRIVATE_KEY_PATH INSTALLATION_ID"
59+
exit 1
60+
fi
61+
62+
# Assign the remaining arguments
63+
# GitHub App's ID
64+
APP_ID="${REMAINING_ARGS[0]}"
65+
# Path to your GitHub App's private key
66+
PRIVATE_KEY_PATH="${REMAINING_ARGS[1]}"
67+
# The installation ID of the GitHub App
68+
INSTALLATION_ID="${REMAINING_ARGS[2]}"
69+
70+
# Generate JWT Header
71+
header=$(echo -n '{"alg":"RS256","typ":"JWT"}' | openssl base64 -e -A | tr '+/' '-_' | tr -d '=')
72+
debug "Header: $header"
73+
74+
# Generate JWT Payload with issued at time and expiration time
75+
iat=$(date +%s)
76+
debug "Issued At Time: $iat"
77+
78+
exp=$((iat + 600)) # JWT expiration time (10 minutes from now)
79+
debug "Expiration Time: $exp"
80+
81+
payload=$(echo -n "{\"iat\":$iat,\"exp\":$exp,\"iss\":\"$APP_ID\"}" | openssl base64 -e -A | tr '+/' '-_' | tr -d '=')
82+
debug "Payload: $payload"
83+
84+
# Sign the Header and Payload
85+
signature=$(echo -n "$header.$payload" | openssl dgst -binary -sha256 -sign "$PRIVATE_KEY_PATH" | openssl base64 -e -A | tr '+/' '-_' | tr -d '=')
86+
debug "Signature: $signature"
87+
88+
# Concatenate Header, Payload, and Signature to form the JWT
89+
jwt_token="$header.$payload.$signature"
90+
debug "JWT Token: $jwt_token"
91+
92+
# GitHub API URL to obtain an installation access token
93+
access_token_url="https://api.github.com/app/installations/$INSTALLATION_ID/access_tokens"
94+
debug "Access Token URL: $access_token_url"
95+
96+
# Obtain an installation access token
97+
response=$(curl -X POST -s -H "Authorization: Bearer ${jwt_token}" -H "Accept: application/vnd.github.v3+json" "${access_token_url}")
98+
debug "Response: $response"
99+
100+
# Extract the token from the response
101+
installation_token=$(echo "${response}" | jq -r '.token')
102+
103+
# Use the installation token for API calls
104+
debug "Installation Token: ${installation_token}"
105+
106+
# Correct GitHub API URL for checking the app's rate limit
107+
api_url="https://api.github.com/rate_limit"
108+
debug "API URL: $api_url"
109+
110+
# Make a request to the GitHub API to get the rate limit status
111+
response=$(curl -s -H "Authorization: Bearer ${installation_token}" -H "Accept: application/vnd.github.machine-man-preview+json" "${api_url}")
112+
debug "Response: $response"
113+
114+
# Parse the JSON response to get the remaining rate limit
115+
remaining_calls=$(echo "${response}" | jq '.resources.core.remaining')
116+
117+
# Output the remaining API call count
118+
echo "Remaining API calls: ${remaining_calls}"
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
#!/bin/bash
2+
3+
# v1.0.0
4+
5+
# This script generates a JWT (JSON Web Token) for a GitHub App and uses it to list the installations of the App.
6+
# It is useful for developers and administrators who need to authenticate as a GitHub App to access GitHub API.
7+
8+
# Inputs:
9+
# 1. APP_ID: The unique identifier for the GitHub App. This should be passed as the first argument.
10+
# 2. PRIVATE_KEY_PATH: The file path to the private key of the GitHub App. This should be passed as the second argument.
11+
# 3. --debug (optional): A flag that can be included to enable debug output. This can be placed anywhere in the command line.
12+
13+
# How to call:
14+
# ./generate-jwt-from-github-app-and-find-installation-tokens.sh [APP_ID] [PRIVATE_KEY_PATH]
15+
# ./generate-jwt-from-github-app-and-find-installation-tokens.sh --debug [APP_ID] [PRIVATE_KEY_PATH]
16+
# ./generate-jwt-from-github-app-and-find-installation-tokens.sh [APP_ID] [PRIVATE_KEY_PATH] --debug
17+
18+
# Important Notes:
19+
# - The script requires `openssl` and `curl` to be installed on the system.
20+
# - The JWT generated by this script is valid for 10 minutes from its creation time.
21+
# - The script outputs the generated JWT and the response from the GitHub API listing the installations.
22+
# - Ensure that the private key file path is correct and the file has appropriate read permissions.
23+
24+
# Initialize debug mode to off
25+
DEBUG_MODE=0
26+
27+
# Function to handle debug messages
28+
debug() {
29+
if [ "$DEBUG_MODE" -eq 1 ]; then
30+
echo "DEBUG: $*"
31+
fi
32+
}
33+
34+
# Initialize an array to hold the remaining arguments after removing recognized flags
35+
REMAINING_ARGS=()
36+
37+
# Process each argument
38+
while [ "$#" -gt 0 ]; do
39+
case "$1" in
40+
--debug)
41+
DEBUG_MODE=1
42+
shift # Remove --debug from the list of arguments
43+
;;
44+
*)
45+
# Collect unrecognized arguments
46+
REMAINING_ARGS+=("$1")
47+
shift # Move to the next argument
48+
;;
49+
esac
50+
done
51+
52+
# Check if we have at least two remaining arguments for APP_ID and PRIVATE_KEY_PATH
53+
if [ "${#REMAINING_ARGS[@]}" -lt 2 ]; then
54+
echo "Usage: $0 [--debug] APP_ID PRIVATE_KEY_PATH"
55+
exit 1
56+
fi
57+
58+
# Assign the remaining arguments
59+
# GitHub App's ID
60+
APP_ID="${REMAINING_ARGS[0]}"
61+
# Path to your GitHub App's private key
62+
PRIVATE_KEY_PATH="${REMAINING_ARGS[1]}"
63+
64+
# Generate JWT Header
65+
header=$(echo -n '{"alg":"RS256","typ":"JWT"}' | openssl base64 -e -A | tr '+/' '-_' | tr -d '=')
66+
67+
# Generate JWT Payload with issued at time and expiration time
68+
iat=$(date +%s)
69+
exp=$((iat + 600)) # JWT expiration time (10 minutes from now)
70+
payload=$(echo -n "{\"iat\":$iat,\"exp\":$exp,\"iss\":\"$APP_ID\"}" | openssl base64 -e -A | tr '+/' '-_' | tr -d '=')
71+
72+
# Sign the Header and Payload
73+
signature=$(echo -n "$header.$payload" | openssl dgst -binary -sha256 -sign "$PRIVATE_KEY_PATH" | openssl base64 -e -A | tr '+/' '-_' | tr -d '=')
74+
75+
# Concatenate Header, Payload, and Signature to form the JWT
76+
jwt="$header.$payload.$signature"
77+
78+
echo $jwt
79+
80+
# GitHub API URL to list installations
81+
api_url="https://api.github.com/app/installations"
82+
83+
# Make a request to list installations
84+
response=$(curl -s -H "Authorization: Bearer ${jwt}" -H "Accept: application/vnd.github.machine-man-preview+json" "${api_url}")
85+
86+
# Print the response
87+
echo "Installations: $response"
88+
89+
debug "I am a debug statement, testing the debug switch. I should only appear if --debug is provided."
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
#!/bin/bash
2+
3+
# v1.0.0
4+
5+
# This script is designed to generate a JWT (JSON Web Token) for authenticating as a GitHub App.
6+
# It then uses this token to perform GitHub API requests, specifically to retrieve information about a specified repository
7+
# and display the current API rate limit status. This is particularly useful for developers and administrators
8+
# who need to monitor their GitHub App's API usage and ensure it stays within the GitHub API rate limits.
9+
10+
# Inputs:
11+
# 1. APP_ID: The unique identifier for the GitHub App. This should be passed as the first argument.
12+
# 2. PRIVATE_KEY_PATH: The file path to the private key of the GitHub App. This should be passed as the second argument.
13+
# 3. INSTALLATION_ID: The installation ID of the GitHub App. This should be passed as the third argument.
14+
# 4. ORG_NAME: The name of the organization that owns the repository. This should be passed as the fourth argument.
15+
# 5. REPO_NAME: The name of the repository to retrieve information for. This should be passed as the fifth argument.
16+
# 6. --debug (optional): A flag that can be included to enable debug output. This can be placed anywhere in the command line.
17+
18+
# How to call:
19+
# ./get-repo-info-using-github-app-and-show-api-rate-limit-info.sh [APP_ID] [PRIVATE_KEY_PATH] [INSTALLATION_ID] [ORG_NAME] [REPO_NAME]
20+
# ./get-repo-info-using-github-app-and-show-api-rate-limit-info.sh --debug [APP_ID] [PRIVATE_KEY_PATH] [INSTALLATION_ID] [ORG_NAME] [REPO_NAME]
21+
# ./get-repo-info-using-github-app-and-show-api-rate-limit-info.sh [APP_ID] [PRIVATE_KEY_PATH] [INSTALLATION_ID] [ORG_NAME] [REPO_NAME] --debug
22+
23+
# Important Notes:
24+
# - The script requires `openssl` to generate the JWT and `curl` to make API requests.
25+
# - The JWT generated by this script is valid for 10 minutes from its creation time.
26+
# - Debug mode can be enabled to output detailed information about each step of the JWT creation and API request process.
27+
# - Ensure that the private key file path is correct and the file has appropriate read permissions.
28+
# - The script is intended for use with GitHub Apps and requires the APP_ID, PRIVATE_KEY_PATH, ORG_NAME, REPO_NAME, and INSTALLATION_ID to function correctly.
29+
30+
# Initialize debug mode to off
31+
DEBUG_MODE=0
32+
33+
# Function to handle debug messages
34+
debug() {
35+
if [ "$DEBUG_MODE" -eq 1 ]; then
36+
echo "DEBUG: $*"
37+
fi
38+
}
39+
40+
# Initialize an array to hold the remaining arguments after removing recognized flags
41+
REMAINING_ARGS=()
42+
43+
# Process each argument
44+
while [ "$#" -gt 0 ]; do
45+
case "$1" in
46+
--debug)
47+
DEBUG_MODE=1
48+
shift # Remove --debug from the list of arguments
49+
;;
50+
*)
51+
# Collect unrecognized arguments
52+
REMAINING_ARGS+=("$1")
53+
shift # Move to the next argument
54+
;;
55+
esac
56+
done
57+
58+
# Check if we have at least four remaining arguments for APP_ID, PRIVATE_KEY_PATH, ORG_NAME, and REPO_NAME
59+
if [ "${#REMAINING_ARGS[@]}" -lt 4 ]; then
60+
echo "Usage: $0 [--debug] APP_ID PRIVATE_KEY_PATH ORG_NAME REPO_NAME"
61+
exit 1
62+
fi
63+
64+
# Assign the remaining arguments
65+
APP_ID="${REMAINING_ARGS[0]}"
66+
PRIVATE_KEY_PATH="${REMAINING_ARGS[1]}"
67+
INSTALLATION_ID="${REMAINING_ARGS[2]}"
68+
ORG_NAME="${REMAINING_ARGS[3]}"
69+
REPO_NAME="${REMAINING_ARGS[4]}"
70+
71+
# Generate JWT Header
72+
header=$(echo -n '{"alg":"RS256","typ":"JWT"}' | openssl base64 -e -A | tr '+/' '-_' | tr -d '=')
73+
debug "Header: $header"
74+
75+
# Generate JWT Payload with issued at time and expiration time
76+
iat=$(date +%s)
77+
debug "Issued At Time: $iat"
78+
79+
exp=$((iat + 600)) # JWT expiration time (10 minutes from now)
80+
debug "Expiration Time: $exp"
81+
82+
payload=$(echo -n "{\"iat\":$iat,\"exp\":$exp,\"iss\":\"$APP_ID\"}" | openssl base64 -e -A | tr '+/' '-_' | tr -d '=')
83+
debug "Payload: $payload"
84+
85+
# Sign the Header and Payload
86+
signature=$(echo -n "$header.$payload" | openssl dgst -binary -sha256 -sign "$PRIVATE_KEY_PATH" | openssl base64 -e -A | tr '+/' '-_' | tr -d '=')
87+
debug "Signature: $signature"
88+
89+
# Concatenate Header, Payload, and Signature to form the JWT
90+
jwt_token="$header.$payload.$signature"
91+
debug "JWT Token: $jwt_token"
92+
93+
# GitHub API URL to obtain an installation access token
94+
access_token_url="https://api.github.com/app/installations/$INSTALLATION_ID/access_tokens"
95+
debug "Access Token URL: $access_token_url"
96+
97+
# Obtain an installation access token
98+
response=$(curl -X POST -s -H "Authorization: Bearer ${jwt_token}" -H "Accept: application/vnd.github.v3+json" "${access_token_url}")
99+
debug "Response: $response"
100+
101+
# Extract the token from the response
102+
installation_token=$(echo "${response}" | jq -r '.token')
103+
104+
# Use the installation token for API calls
105+
debug "Installation Token: ${installation_token}"
106+
107+
api_url="https://api.github.com/repos/$ORG_NAME/$REPO_NAME"
108+
echo "API URL: $api_url"
109+
110+
# Make API Call and save response and headers
111+
response=$(curl -i -s -H "Authorization: token ${installation_token}" -H "Accept: application/vnd.github.v3+json" "${api_url}")
112+
113+
# Separate headers and body
114+
headers=$(echo "$response" | grep -Pzo '(?s)^.*?\r\n\r\n' | tr -d '\0')
115+
body=$(echo "$response" | sed -n '/^\r$/,$p' | tail -n +2)
116+
117+
# Extract and echo rate limit information
118+
echo "x-ratelimit-limit: $(echo "$headers" | grep 'x-ratelimit-limit' | awk '{print $2}')"
119+
echo "x-ratelimit-remaining: $(echo "$headers" | grep 'x-ratelimit-remaining' | awk '{print $2}')"
120+
echo "x-ratelimit-used: $(echo "$headers" | grep 'x-ratelimit-used' | awk '{print $2}')"
121+
echo "x-ratelimit-reset: $(echo "$headers" | grep 'x-ratelimit-reset' | awk '{print $2}')"
122+
echo "x-ratelimit-resource: $(echo "$headers" | grep 'x-ratelimit-resource' | awk '{print $2}')"
123+
124+
# Print the body of the response
125+
echo "Repository Info: $body"

0 commit comments

Comments
 (0)