Skip to content

Instantly share code, notes, and snippets.

@fawkesley
Last active November 6, 2018 17:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fawkesley/ff1a33025955a582ea6ace3a2dd7ae49 to your computer and use it in GitHub Desktop.
Save fawkesley/ff1a33025955a582ea6ace3a2dd7ae49 to your computer and use it in GitHub Desktop.
fksync
#!/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