Skip to content

Instantly share code, notes, and snippets.

@magnetikonline
Last active December 29, 2023 13:47
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save magnetikonline/391a8632c664c2a9f7940bf9f957e83d to your computer and use it in GitHub Desktop.
Save magnetikonline/391a8632c664c2a9f7940bf9f957e83d to your computer and use it in GitHub Desktop.
Import all GPG keys for GitHub organisation users.

Import all GPG keys for GitHub organisation users

Script to fetch a GitHub organisation member list and gpg --import the public GPG key(s) for each member with GPG key(s) associated against their profile.

Requires curl for GitHub API calls, jq for parsing GitHub REST API responses and (obviously) gpg.

Usage

Create a GitHub personal access token (classic or fine-grained) with read access to organisation members:

  • Classic token: read:org scope.
  • Fine-grained token: Members Read-only organization permission.

Next, run the script:

export GITHUB_TOKEN="INSERT_TOKEN_VALUE_HERE"
ORG_NAME="INSERT_GITHUB_ORG" ./import-github-gpg.sh

Done!

#!/bin/bash -e
function exitError {
echo "Error: $1" >&2
exit 1
}
function main {
local IFS=$'\n'
if [[ ! -x $(command -v jq) ]]; then
exitError "unable to locate jq"
fi
if [[ -z $GITHUB_TOKEN ]]; then
exitError "expected GITHUB_TOKEN not found"
fi
if [[ -z $ORG_NAME ]]; then
exitError "expected ORG_NAME not found"
fi
local fetchPage=1
local hasResult=:
while [[ $hasResult ]]; do
# pull list page of members for GitHub organisation
local response=$(
curl \
--header "Accept: application/vnd.github+json" \
--header "Authorization: Bearer $GITHUB_TOKEN"\
--silent \
"https://api.github.com/orgs/$ORG_NAME/members?page=$fetchPage"
)
# for each member profile URL, attempt to pull and import public GPG key(s)
hasResult=
local profileUrl
for profileUrl in $(echo "$response" | jq --raw-output ".[].html_url"); do
hasResult=:
local response=$(curl --silent "$profileUrl.gpg")
if [[ $response =~ Note:\ This\ user\ hasn\'t\ uploaded\ any\ GPG\ keys\. ]]; then
echo "$profileUrl - skipping (no GPG key)"
else
echo "$profileUrl - importing key"
echo "$response" | gpg --import
echo
fi
done
fetchPage=$((fetchPage+1))
done
echo
echo "Finished"
}
main
@falsefalse
Copy link

excellent, works like a charm in 2023, thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment