Skip to content

Instantly share code, notes, and snippets.

@Raiu
Last active October 1, 2023 16:40
Show Gist options
  • Save Raiu/23418eac4e78856167121b4f02c13db7 to your computer and use it in GitHub Desktop.
Save Raiu/23418eac4e78856167121b4f02c13db7 to your computer and use it in GitHub Desktop.
This script automatically adds SSH keys from a GitHub user to the authorized_keys file on a local machine while keeping all manually added keys.
#!/usr/bin/env sh
: '
This script helps you download your ssh keys from Github while keeping any existing keys.
Usage:
./add_github_keys.sh [OPTIONS] USERNAME
Without downloading:
curl -fsSL https://gist.githubusercontent.com/Raiu/23418eac4e78856167121b4f02c13db7/raw | sh -s -- USERNAME
Options:
-c, --comment COMMENT Identifier for GH keys (default: GH-Key) [optional]
-p, --path PATH Path to authorized_keys (default: ~/.ssh/authorized_keys) [optional]
-h, --help Show this help message and exit
'
_exist() { command -v "$@" >/dev/null 2>&1; }
! _exist 'curl' && printf 'Install: curl' && exit 1
! _exist 'ssh-keygen' && printf 'Install: ssh-keygen' && exit 1
# Set default values
key_comment="GH-Key"
auth_keys="${HOME}/.ssh/authorized_keys"
# Verify and validate SSH keys function
verify_key() {
printf '%s\n' "$1" | ssh-keygen -l -f - > /dev/null 2>&1
}
# Verify Github username function
verify_username() {
printf '%s\n' "$1" | grep -qE '^[a-zA-Z0-9]([-a-zA-Z0-9]{0,37}[a-zA-Z0-9])?$'
}
# Validate option has an argument
validate_option() {
if [ -z "$2" ] || [ "${2#-}" != "$2" ]; then
printf 'Error: option requires an argument -- %s\n' "$1" >&2
help >&2
exit 1
fi
}
# Help function
help() {
cat <<EOF
Usage: ${0##*/} [options] <username>
Options:
-c, --comment <comment> Set comment for the key (default: GH-Key)
-p, --path <path> Set path to authorized_keys file (default: ~/.ssh/authorized_keys)
-h, --help Show this help message and exit
EOF
}
# Parse arguments
while [ $# -gt 0 ]; do
case "$1" in
-c|--comment)
validate_option "$@"
key_comment="$2"
shift 2
;;
-p|--path)
validate_option "$@"
auth_keys="$2"
shift 2
;;
-h|--help)
help
exit 0
;;
-*)
printf 'Error: unrecognized option -- %s\n' "$1" >&2
help >&2
exit 1
;;
*)
break
;;
esac
done
# Verify username
! verify_username "$1" && printf '%s is not a valid username\n' "$1" && help && exit 1
username=$1
# Create authorized_keys file if it doesn't exist and set correct permissions.
if [ ! -f "${auth_keys}" ]; then
mkdir -p "${auth_keys%/*}"
chmod 700 "${auth_keys%/*}"
touch "${auth_keys}"
chmod 600 "${auth_keys}"
fi
# Read content from authorized_keys into a temporary file.
temp_file=$(mktemp)
while read -r line; do
if ! printf '%s\n' "${line}" | grep -q "${key_comment}$"; then
if verify_key "${line}"; then
printf '%s\n' "${line}" >> "${temp_file}"
fi
fi
done < "${auth_keys}"
# try to grab ssh keys from GH
printf '\n# Github keys\n' >> "${temp_file}"
curl -s "https://github.com/${username}.keys" | while read -r key; do
if verify_key "${key}"; then
printf '%s %s\n' "${key}" "${key_comment}" >> "${temp_file}"
fi
done
# If the old file and new file is the same, skip writing.
if ! cmp "${temp_file}" "${auth_keys}" > /dev/null 2>&1; then
cat "${temp_file}" > "${auth_keys}"
fi
rm "${temp_file}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment