Skip to content

Instantly share code, notes, and snippets.

@longlostnick
Last active October 30, 2017 05:40
Show Gist options
  • Save longlostnick/5b0080cb0e658ab39884be785bfbf83b to your computer and use it in GitHub Desktop.
Save longlostnick/5b0080cb0e658ab39884be785bfbf83b to your computer and use it in GitHub Desktop.
Simple set of bash scripts for uploading public keys to remote servers via GitHub usernames

authorized_keys

A method for managing and giving team members access to remote servers without needing to pass around the master .pem key. Generates and sends authorized key files to a list of hosts based on a set of permissions.

fetch_keys_from_github.sh

Generates a new keys/*.txt file for each user defined in permissions.txt when one doesn't already exist. Gets the list by calling out to https://github.com/<user>.keys. After first fetching a set of keys, the list can be paired down if necessary before running upload_keys.sh.

./fetch_keys_from_github.sh

upload_keys.sh

  1. Runs through each group defined in hosts/. ex:
  2. Reads the permissions.txt file to find out which users have permission to that host
  3. Generates a master authorized keys file for those users using their keys from keys/<user>.txt
  4. Uploads it to ~/.ssh/authorized_keys_sh for each host in that group. This avoids overwriting the server default authorized_keys file.
./upload_keys.sh

permissions.txt

Specifies each user and which groups of hosts they should have permissions for. The format for each line is a GitHub username followed by a dash, then a comma-delimited list of groups they belong to. Each group should correspond to a file with a list of servers in hosts/. Example below:

ifightcrime - web,mygroup,othergroup

keys/*.txt

This directory houses a user specific set of keys for each user defined in permissions.txt.

hosts/*.txt

Each file (group) contains a list of associated hosts that we want to push the keys to. A separate user@host is defined on each line.

Adding support for new hosts

Modify the host's /etc/ssh/sshd_config file to add support for our new authorized_keys_sh file. Change the AuthorizedKeysFile directive to match the following (and uncomment if commented):

AuthorizedKeysFile     %h/.ssh/authorized_keys %h/.ssh/authorized_keys_sh

Don't forget to reload ssh after you make the change.

/etc/init.d/ssh reload
#!/bin/bash
function fetch_keys_from_github () {
for user in $(awk '{print $1}' permissions.txt); do
file="keys/${user}.txt"
# only fetch if the file doesn't exist
if [[ ! -f $file ]] ; then
echo "Fetching ssh keys for ${user}..."
curl -sf https://github.com/${user}.keys > $file
fi
done
}
fetch_keys_from_github
#!/bin/bash
readonly REMOTE_KEY_PATH="~/.ssh/authorized_keys_sh"
function users_for_group () {
# group must start after '-' with space/comma, and end with comma/newline
users=$(grep "\-.*\(\s\|,\)${1}\(,\|$\)" permissions.txt | awk '{print $1;}')
if [[ -z $users ]]; then
echo -e " \e[31mno permissions defined for this group\e[0m" 1>&2
fi
echo $users
}
function generate_key_file () {
key_file=""
for user in $(users_for_group $1); do
file="keys/${user}.txt"
if [[ ! -f $file ]]; then
# skip this user if they have no key file
echo -e " \e[31mkeys for user '${user}' are missing\e[0m" 1>&2
else
key_file="${key_file}\n# ${user}"
key_file="${key_file}\n$(cat $file)\n"
fi
done
# -e and quotes to preserve line breaks
echo -e "$key_file"
}
function send_keys_to_hosts () {
for file in hosts/*.txt; do
group=$(basename ${file%.txt})
echo "Generating key file for '${group}'..."
key_file=$(mktemp /tmp/${group}_${host}.XXXXXX)
echo -e "$(generate_key_file $group)" > $key_file
if [[ -z $(cat $key_file) ]]; then
# generated file is empty, which means there are no keys to send
echo -e " \e[31mno keys generated for this group, skipping...\e[0m" 1>&2
else
for host in $(<${file}); do
echo " uploading to '${host}'"
scp -i ~/.ssh/upcounsel20130307.pem ${key_file} ${host}:${REMOTE_KEY_PATH} > /dev/null
done
fi
rm $key_file
done
}
send_keys_to_hosts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment