Last active
November 6, 2018 17:19
-
-
Save fawkesley/ff1a33025955a582ea6ace3a2dd7ae49 to your computer and use it in GitHub Desktop.
fksync
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh -eu | |
# fksync | |
# | |
# This scripts keeps your PGP keys in sync with your team by: | |
# | |
# 1. periodically uploading your key to the keyservers | |
# 2. periodically downloading their keys from the keyservesr | |
# | |
# Note: it can't handle *new* team members. You'll need to get their key the | |
# first time. | |
# | |
# *** INSTALLATION *** | |
# | |
# 0. Save this file as $HOME/bin/fksync | |
# | |
# 1. Set the DOMAIN variable below | |
# | |
# 2. Make it executable: | |
# > chmod +x $HOME/bin/fksync | |
# | |
# 3. Add it to your crontab: | |
# > crontab -e | |
# @hourly ~/bin/fksync | |
DOMAIN="@fluidkeys.com" | |
# --------------------------------------------------------------------------- | |
PATH=$PATH:/bin:/usr/bin:/usr/local/MacGPG2/bin | |
CACHE_DIR="$HOME/.cache/fksync" | |
# 3 hours = 10,800 | |
# 6 hours = 21,600 seconds | |
REFRESH_SECONDS=10800 | |
find_team_fingerprints() { | |
TEAM_FINGERPRINTS="$(gpg2 --with-colons --list-keys "${DOMAIN}" | grep '^fpr' | cut -d':' -f10)" | |
} | |
find_my_fingerprints() { | |
MY_FINGERPRINTS="$(gpg2 --with-colons --list-secret-keys "${DOMAIN}" | grep --after=1 '^sec' | grep '^fpr' | cut -d':' -f10)" | |
} | |
upload_my_keys() { | |
for FINGERPRINT in ${MY_FINGERPRINTS}; do | |
if is_upload_overdue "${FINGERPRINT}" ; then | |
upload_fingerprint "${FINGERPRINT}" && record_fingerprint_uploaded "${FINGERPRINT}" | |
fi | |
done | |
} | |
download_team_keys() { | |
for FINGERPRINT in ${TEAM_FINGERPRINTS}; do | |
if is_download_overdue "${FINGERPRINT}" ; then | |
download_fingerprint "${FINGERPRINT}" && record_fingerprint_downloaded "${FINGERPRINT}" | |
fi | |
done | |
} | |
upload_fingerprint() { | |
FINGERPRINT=$1 | |
run_with_retry "gpg2 --keyserver keyserver.paulfurley.com --send-key "${FINGERPRINT}"" | |
return $? | |
} | |
download_fingerprint() { | |
FINGERPRINT=$1 | |
run_with_retry "gpg2 --keyserver keyserver.paulfurley.com --recv-key "${FINGERPRINT}"" | |
return $? | |
} | |
run_with_retry() { | |
COMMAND="$1" | |
MAX_ATTEMPTS="5" | |
ATTEMPT=1 | |
until [ "$ATTEMPT" -ge "${MAX_ATTEMPTS}" ] | |
do | |
$COMMAND > $TMP_OUTPUT 2>&1 && return 0 | |
ATTEMPT=$(($ATTEMPT+1)) | |
sleep 30 | |
done | |
echo "Command failed. Giving up after $MAX_ATTEMPTS attempts:" | |
echo | |
echo "> $COMMAND" | |
echo | |
cat "${TMP_OUTPUT}" | |
echo | |
# 1 = unsuccessful | |
return 1 | |
} | |
make_cache_directory() { | |
mkdir -p "${CACHE_DIR}" | |
} | |
make_tmp_output() { | |
TMP_OUTPUT=$(mktemp) | |
} | |
is_upload_overdue() { | |
FINGERPRINT=$1 | |
is_overdue "upload" "${FINGERPRINT}" && return 0 || return 1 | |
} | |
is_download_overdue() { | |
FINGERPRINT=$1 | |
is_overdue "download" "${FINGERPRINT}" && return 0 || return 1 | |
} | |
record_fingerprint_uploaded() { | |
FINGERPRINT=$1 | |
record_fingerprint "upload" "${FINGERPRINT}" | |
} | |
record_fingerprint_downloaded() { | |
FINGERPRINT=$1 | |
record_fingerprint "download" "${FINGERPRINT}" | |
} | |
is_overdue() { | |
DIRECTION=$1 | |
FINGERPRINT=$2 | |
CACHE_FILENAME="${CACHE_DIR}/${DIRECTION}.${FINGERPRINT}" | |
if [ ! -f "${CACHE_FILENAME}" ]; then | |
# 0 = "yes, overdue" | |
return 0 | |
else | |
AGE_SECONDS=$(( ($(date +%s) - $(stat -L --format %Y $CACHE_FILENAME)) )) | |
if [ $AGE_SECONDS -gt "${REFRESH_SECONDS}" ]; then | |
# 0 = "yes, overdue" | |
return 0 | |
fi | |
fi | |
# 1 = "not overdue" | |
return 1 | |
} | |
record_fingerprint() { | |
DIRECTION=$1 | |
FINGERPRINT=$2 | |
CACHE_FILENAME="${CACHE_DIR}/${DIRECTION}.${FINGERPRINT}" | |
touch "${CACHE_FILENAME}" | |
} | |
find_team_fingerprints | |
find_my_fingerprints | |
make_cache_directory | |
make_tmp_output | |
upload_my_keys | |
download_team_keys |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment