#!/bin/bash

# v1.0.0

# 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.

# Inputs:
# 1. APP_ID: The unique identifier for the GitHub App. This should be passed as the first argument.
# 2. PRIVATE_KEY_PATH: The file path to the private key of the GitHub App. This should be passed as the second argument.
# 3. --debug (optional): A flag that can be included to enable debug output. This can be placed anywhere in the command line.

# How to call:
# ./generate-jwt-from-github-app-and-find-installation-tokens.sh [APP_ID] [PRIVATE_KEY_PATH]
# ./generate-jwt-from-github-app-and-find-installation-tokens.sh --debug [APP_ID] [PRIVATE_KEY_PATH]
# ./generate-jwt-from-github-app-and-find-installation-tokens.sh [APP_ID] [PRIVATE_KEY_PATH] --debug

# Important Notes:
# - The script requires `openssl` and `curl` to be installed on the system.
# - The JWT generated by this script is valid for 10 minutes from its creation time.
# - The script outputs the generated JWT and the response from the GitHub API listing the installations.
# - Ensure that the private key file path is correct and the file has appropriate read permissions.

# Initialize debug mode to off
DEBUG_MODE=0

# Function to handle debug messages
debug() {
    if [ "$DEBUG_MODE" -eq 1 ]; then
        echo "DEBUG: $*"
    fi
}

# Initialize an array to hold the remaining arguments after removing recognized flags
REMAINING_ARGS=()

# Process each argument
while [ "$#" -gt 0 ]; do
    case "$1" in
        --debug)
            DEBUG_MODE=1
            shift # Remove --debug from the list of arguments
            ;;
        *)
            # Collect unrecognized arguments
            REMAINING_ARGS+=("$1")
            shift # Move to the next argument
            ;;
    esac
done

# Check if we have at least two remaining arguments for APP_ID and PRIVATE_KEY_PATH
if [ "${#REMAINING_ARGS[@]}" -lt 2 ]; then
    echo "Usage: $0 [--debug] APP_ID PRIVATE_KEY_PATH"
    exit 1
fi

# Assign the remaining arguments
# GitHub App's ID
APP_ID="${REMAINING_ARGS[0]}"
# Path to your GitHub App's private key
PRIVATE_KEY_PATH="${REMAINING_ARGS[1]}"

# Generate JWT Header
header=$(echo -n '{"alg":"RS256","typ":"JWT"}' | openssl base64 -e -A | tr '+/' '-_' | tr -d '=')

# Generate JWT Payload with issued at time and expiration time
iat=$(date +%s)
exp=$((iat + 600)) # JWT expiration time (10 minutes from now)
payload=$(echo -n "{\"iat\":$iat,\"exp\":$exp,\"iss\":\"$APP_ID\"}" | openssl base64 -e -A | tr '+/' '-_' | tr -d '=')

# Sign the Header and Payload
signature=$(echo -n "$header.$payload" | openssl dgst -binary -sha256 -sign "$PRIVATE_KEY_PATH" | openssl base64 -e -A | tr '+/' '-_' | tr -d '=')

# Concatenate Header, Payload, and Signature to form the JWT
jwt="$header.$payload.$signature"

echo $jwt

# GitHub API URL to list installations
api_url="https://api.github.com/app/installations"

# Make a request to list installations
response=$(curl -s -H "Authorization: Bearer ${jwt}" -H "Accept: application/vnd.github.machine-man-preview+json" "${api_url}")

# Print the response
echo "Installations: $response"

debug "I am a debug statement, testing the debug switch. I should only appear if --debug is provided."