🔄 Automate GitHub Access Checks with Shell Scripting (Real-Life Use Case)

🔄 Automate GitHub Access Checks with Shell Scripting (Real-Life Use Case)

Hey DevOps enthusiasts! 👋 Ever find yourself constantly hopping into GitHub just to double-check who can access your repositories?

Whether you're managing a few projects or overseeing dozens across multiple teams, access control is non-negotiable. But doing it manually? That’s time better spent elsewhere.

Let’s solve this the smart way: a shell script + GitHub API = one-click visibility.


🚨 The Problem

Manually verifying repo access:

  • Eats up your time ⏱️
  • Slows down audits 📉
  • Doesn’t scale across multiple teams or orgs 🚫

Let’s ditch the browser and embrace automation.


🧰 The Tools We’ll Use

There are two main options for interacting with GitHub from the command line:

  • GitHub CLI – Interactive and great for quick tasks
  • GitHub REST API – More flexible and script-friendly ← we’re going with this

API Tip: Think of the API as GitHub’s "back door" that lets us automate almost anything you can do in the UI.

🎯 Our Mission

We want a script that will:

  • Accept a GitHub org and repo name
  • Authenticate via your GitHub credentials
  • Pull a list of users with read-only access
  • Help you identify and remove unneeded collaborators


🔑 Set Up GitHub Authentication

To access GitHub programmatically, you need:

  • Your GitHub username
  • A Personal Access Token (PAT)

🔧 How to Get a PAT:

  1. Go to GitHub > Settings > Developer Settings > Personal Access Tokens
  2. Click “Generate new token”
  3. Grant it repo scope
  4. Copy and save the token (you won’t see it again)

Then, in your terminal:

Article content

🧾 The Script: list-users.sh

The heart of the automation is this bash script. It does all the heavy lifting:

#!/bin/bash

##########################################################
# Script Name : list-users.sh
# Author      : Swasti
# Version     : v1.2
# Date        : 13-May-2025
#
# Purpose     : Lists GitHub collaborators with read access
#               using GitHub REST API and jq parser.
#
# Requirements:
#   - jq installed (sudo apt install jq)
#   - Export GitHub credentials:
#       export username="your_username"
#       export token="your_token"
#
# Usage:
#   ./list-users.sh <org_name> <repo_name>
##########################################################

API_URL="https://api.github.com"
USERNAME=$username
TOKEN=$token
REPO_OWNER=$1
REPO_NAME=$2

function helper {
    if [ $# -ne 2 ]; then
        echo "Usage: ./list-users.sh <org_name> <repo_name>"
        exit 1
    fi
    if [[ -z "$USERNAME" || -z "$TOKEN" ]]; then
        echo "Please export 'username' and 'token' first."
        exit 1
    fi
    if ! command -v jq &>/dev/null; then
        echo "'jq' is required. Install using: sudo apt install jq"
        exit 1
    fi
}

helper "$@"

function github_api_get {
    local endpoint="$1"
    curl -s -u "${USERNAME}:${TOKEN}" "${API_URL}/${endpoint}"
}

function list_users_with_read_access {
    local endpoint="repos/${REPO_OWNER}/${REPO_NAME}/collaborators"
    collaborators=$(github_api_get "$endpoint" | jq -r '.[] | select(.permissions.pull == true) | .login')

    if [[ -z "$collaborators" ]]; then
        echo "No users with read access found."
    else
        echo "Users with read access to ${REPO_OWNER}/${REPO_NAME}:"
        echo "$collaborators"
    fi
}

echo "🔍 Checking collaborators for ${REPO_OWNER}/${REPO_NAME}..."
list_users_with_read_access
        

🛠️ Before You Run It

Make sure you have:

  • ✅ Installed jq: sudo apt install jq
  • ✅ Exported your credentials with export username=... and export token=...
  • ✅ Made the script executable:

Article content

Then run it:

Article content

Detailed Script Explanation – list-users.sh

This script is a practical tool to fetch a list of GitHub users who have read (pull) access to a repository. Let’s dissect it step by step:

##########################################################
# Script Name : list-users.sh
# Author      : Swasti
# Version     : v1.2
# Date        : 13-May-2025
#
# Purpose     : Lists GitHub collaborators with read access
#               using GitHub REST API and jq parser.
#
# Requirements:
#   - jq installed (sudo apt install jq)
#   - Export GitHub credentials:
#       export username="your_username"
#       export token="your_token"
#
# Usage:
#   ./list-users.sh <org_name> <repo_name>
##########################################################
        

✅ Purpose:

This block acts as a header comment. It's considered good scripting practice, especially in production or shared environments.

  • It tells anyone reading the script what it does
  • Includes authorship and version control
  • Describes prerequisites
  • Provides usage instructions

This ensures maintainability and clarity for future readers or collaborators.

🔐 2. Environment Variables and Inputs

API_URL="https://api.github.com"
USERNAME=$username
TOKEN=$token
REPO_OWNER=$1
REPO_NAME=$2        

✅ Purpose:

  • API_URL defines the GitHub REST API base.
  • $username and $token are read from environment variables. This avoids hardcoding secrets into the script.
  • $1 and $2 capture positional command-line arguments — the organization and repository names.

🔐 Security note: Never hardcode credentials. Exporting them from your shell session is safer.

🧩 3. Input Validation with Helper Function

function helper {
    if [ $# -ne 2 ]; then
        echo "Usage: ./list-users.sh <org_name> <repo_name>"
        exit 1
    fi
    if [[ -z "$USERNAME" || -z "$TOKEN" ]]; then
        echo "Please export 'username' and 'token' first."
        exit 1
    fi
    if ! command -v jq &>/dev/null; then
        echo "'jq' is required. Install using: sudo apt install jq"
        exit 1
    fi
}

helper "$@"        

✅ Purpose:

Before doing anything else, the script:

  • Checks that exactly two arguments were passed
  • Confirms that credentials are set
  • Verifies that jq is installed (used to parse JSON)

Failing any of these, it exits early and tells the user what to fix.

🧠 This is called "fail fast" logic — a defensive programming technique that saves debugging time later.

🌐 4. GitHub API Wrapper Function

function github_api_get {
    local endpoint="$1"
    curl -s -u "${USERNAME}:${TOKEN}" "${API_URL}/${endpoint}"
}        

✅ Purpose:

This helper function:

  • Takes an API endpoint as input (like repos/org/repo/collaborators)
  • Uses curl to send an authenticated GET request
  • Returns the raw JSON from GitHub’s API

💡 Reusability: You could expand this to support POST, PUT, DELETE for a complete GitHub automation toolkit.

📋 5. Main Logic – List Users With Read Access

function list_users_with_read_access {
    local endpoint="repos/${REPO_OWNER}/${REPO_NAME}/collaborators"
    collaborators=$(github_api_get "$endpoint" | jq -r '.[] | select(.permissions.pull == true) | .login')

    if [[ -z "$collaborators" ]]; then
        echo "No users with read access found."
    else
        echo "Users with read access to ${REPO_OWNER}/${REPO_NAME}:"
        echo "$collaborators"
    fi
}        

✅ Purpose:

This function does the core work:

  1. Constructs the full endpoint for the collaborators API
  2. Calls the API with github_api_get
  3. Parses the response using jq:
  4. Displays them nicely.

🧠 jq is a powerful tool for filtering, transforming, and formatting JSON — perfect for shell scripts working with APIs.

▶️ 6. Script Execution

echo "🔍 Checking collaborators for ${REPO_OWNER}/${REPO_NAME}..."
list_users_with_read_access        

✅ Purpose:

The script ends with a friendly message and a call to the list_users_with_read_access function.

This is the "main" part of the script, akin to a main() function in other programming languages.

🧠 How It Works (In Plain English)

✔️ Input Validation

Checks for missing arguments, credentials, or missing jq. You get a helpful error if something's wrong.

✔️ GitHub API Call

Uses curl and your credentials to talk to GitHub securely.

✔️ Data Parsing with jq

Filters the API response to show only users with "pull" (read) access.

✔️ Clean Output

Prints usernames in a clean, readable list — perfect for auditing or reporting.


🔁 Real-World Scenario

Let’s say you support 20+ teams, each with their own GitHub repo. You want to:

  • List out everyone with access
  • Spot users who shouldn't be there
  • Clean things up

Instead of opening every repo manually, just run this script across your org's repos. Automate it with a cron job, GitHub Actions, or your internal CI/CD system.

Time saved = hours.

To view or add a comment, sign in

More articles by Swastideepa Dash

Others also viewed

Explore content categories