From 396c044efd03fe0f1a8fb4bdfbaf619c6858cf21 Mon Sep 17 00:00:00 2001 From: Arjun Hemrajani Date: Thu, 11 Sep 2025 00:31:26 +0530 Subject: [PATCH] github-ssh-sync --- sync-github-sshkeys/Readme.md | 29 +++++ sync-github-sshkeys/sync-github-sshkeys.sh | 121 +++++++++++++++++++++ 2 files changed, 150 insertions(+) create mode 100644 sync-github-sshkeys/Readme.md create mode 100644 sync-github-sshkeys/sync-github-sshkeys.sh diff --git a/sync-github-sshkeys/Readme.md b/sync-github-sshkeys/Readme.md new file mode 100644 index 0000000..feec58b --- /dev/null +++ b/sync-github-sshkeys/Readme.md @@ -0,0 +1,29 @@ +# Sync GitHub Team SSH Keys to Root + +This tool automatically syncs the SSH public keys of all members of a GitHub team into the `root` user’s `~/.ssh/authorized_keys`. +It is useful for managing server access in organizations where team membership on GitHub defines who should have SSH access. + +--- + +## Features +- Syncs SSH keys from a GitHub team into `root`’s authorized keys +- Backs up old keys automatically +- Installs as a cronjob (runs hourly by default) +- Interactive setup: select your organization and team from GitHub +- Stores your GitHub token securely in `/root/.github-token` + +--- + +## Requirements +- Linux server with root access +- `curl` and `jq` installed +- GitHub [Personal Access Token (PAT)](https://github.com/settings/tokens) with **`read:org`** scope + +--- + +## Quick Install + +Run this as root: + +```bash +curl -s https://raw.githubusercontent.com/excloud-in/examples/main/sync-github-sshkeys/install.sh | bash diff --git a/sync-github-sshkeys/sync-github-sshkeys.sh b/sync-github-sshkeys/sync-github-sshkeys.sh new file mode 100644 index 0000000..66a640b --- /dev/null +++ b/sync-github-sshkeys/sync-github-sshkeys.sh @@ -0,0 +1,121 @@ +#!/bin/bash +# Interactive installer for GitHub SSH key sync + +set -euo pipefail + +SCRIPT_PATH="/usr/local/bin/sync-github-sshkeys.sh" +CRON_LOG="/var/log/sync-github-sshkeys.log" +TOKEN_FILE="/root/.github-token" + +# --- 1. Ask for token --- +if [ ! -f "$TOKEN_FILE" ]; then + echo "To create GitHub Personal Access Token visit https://github.com/settings/tokens" + read -rsp "Enter your GitHub Personal Access Token (with read:org scope): " GITHUB_TOKEN + echo + echo "$GITHUB_TOKEN" > "$TOKEN_FILE" + chmod 600 "$TOKEN_FILE" +else + GITHUB_TOKEN=$(cat "$TOKEN_FILE") +fi + +# --- 2. List orgs --- +echo "Fetching organizations..." +orgs=$(curl -s -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/user/orgs | jq -r '.[].login') + +if [ -z "$orgs" ]; then + echo "❌ No organizations found or token invalid." + exit 1 +fi + +echo "Select an organization:" +select GITHUB_ORG in $orgs; do + [ -n "$GITHUB_ORG" ] && break +done + +# --- 3. List teams --- +echo "Fetching teams for org $GITHUB_ORG..." +teams=$(curl -s -H "Authorization: token $GITHUB_TOKEN" "https://api.github.com/orgs/$GITHUB_ORG/teams" | jq -r '.[].slug') + +if [ -z "$teams" ]; then + echo "❌ No teams found in org $GITHUB_ORG" + exit 1 +fi + +echo "Select a team:" +select GITHUB_TEAM_SLUG in $teams; do + [ -n "$GITHUB_TEAM_SLUG" ] && break +done + +# --- 4. Install sync script --- +cat > "$SCRIPT_PATH" <<"EOF" +#!/bin/bash +# Sync SSH keys for root user from GitHub team members + +set -euo pipefail + +TOKEN_FILE="/root/.github-token" +GITHUB_ORG="{{ORG}}" +GITHUB_TEAM_SLUG="{{TEAM}}" +ROOT_AUTH_KEYS="/root/.ssh/authorized_keys" +TMP_KEYS="/tmp/github_team_keys.$$" + +if [ ! -f "$TOKEN_FILE" ]; then + echo "❌ Missing token file at $TOKEN_FILE" >&2 + exit 1 +fi +GITHUB_TOKEN=$(cat "$TOKEN_FILE") + +if ! command -v jq >/dev/null 2>&1; then + echo "❌ jq is required." >&2 + exit 1 +fi + +# Fetch team members +page=1 +members=() +while :; do + response=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \ + "https://api.github.com/orgs/$GITHUB_ORG/teams/$GITHUB_TEAM_SLUG/members?page=$page&per_page=100") + count=$(echo "$response" | jq length) + [ "$count" -eq 0 ] && break + members+=($(echo "$response" | jq -r '.[].login')) + page=$((page+1)) +done + +# Collect keys +> "$TMP_KEYS" +for user in "${members[@]}"; do + echo "Fetching keys for $user..." + curl -s "https://github.com/$user.keys" >> "$TMP_KEYS" +done + +# Deduplicate +sort -u "$TMP_KEYS" -o "$TMP_KEYS" + +# Backup old keys +if [ -f "$ROOT_AUTH_KEYS" ]; then + cp "$ROOT_AUTH_KEYS" "$ROOT_AUTH_KEYS.bak.$(date +%s)" +fi + +# Replace with new keys +cat "$TMP_KEYS" > "$ROOT_AUTH_KEYS" +chmod 600 "$ROOT_AUTH_KEYS" +rm -f "$TMP_KEYS" + +echo "✅ Keys synced for team $GITHUB_TEAM_SLUG in org $GITHUB_ORG" +EOF + +# Replace placeholders +sed -i "s/{{ORG}}/$GITHUB_ORG/" "$SCRIPT_PATH" +sed -i "s/{{TEAM}}/$GITHUB_TEAM_SLUG/" "$SCRIPT_PATH" + +chmod 700 "$SCRIPT_PATH" + +# --- 5. Install cronjob --- +(crontab -l 2>/dev/null | grep -v "$SCRIPT_PATH" ; echo "0 * * * * $SCRIPT_PATH >> $CRON_LOG 2>&1") | crontab - + +echo "✅ Installed sync script for team '$GITHUB_TEAM_SLUG' in org '$GITHUB_ORG'" +echo "✅ Cronjob set (hourly)" +echo "➡️ Running first sync..." +$SCRIPT_PATH >> $CRON_LOG 2>&1 +echo "✅ First sync done. Check log: $CRON_LOG"