blob: caff0a7a468c2c03530fea6eb9a241275d79244d [file] [log] [blame]
#!/bin/bash
shopt -s nullglob
# We want to iterate over all system users, check if they are opted-in to ssh
# authorized_keys building, and then construct their keyfile
for user in $(cut -d':' -f1 /etc/passwd); do
home="$(eval echo ~$user)" || continue
link="$(readlink $home/.ssh/authorized_keys 2>/dev/null)" || continue
# Users are only opted-in if they symlink to our well-known directory where
# the final output of this script lives.
if [ "$link" != "/run/authorized_keys/$user" ]; then
echo "Ignoring $user $home/.ssh/authorized_keys" >&2
continue
fi
echo "Updating $link" >&2
declare -A basemap=()
declare -a dirs=(
"/usr/share/authorized_keys.d/$user"
"$home/.ssh/authorized_keys.d"
"/run/authorized_keys.d/$user"
)
# Build a map that can be used for sorting directories by their priority
# and prioritizing the last listed directories over the later ones. We
# append a counter to ensure that there is a stable sorting mechanism for
# duplicate filenames. Duplicate filenames will be overridden by higher
# priority directories.
# Ex.
# /usr/share/authorized_keys.d/root/10-key
# /usr/share/authorized_keys.d/root/15-key
# /run/authorized_keys.d/root/10-key
# /run/authorized_keys.d/root/20-key
# Becomes
# ["10-key"]="/run/authorized_keys.d/root/10-key"
# ["15-key"]="/usr/share/authorized_keys.d/root/15-key"
# ["20-key"]="/run/authorized_keys.d/root/20-key"
for dir in "${dirs[@]}"; do
for file in "$dir"/*; do
basemap["${file##*/}"]="$file"
done
done
rm -f /run/authorized_keys.tmp
touch /run/authorized_keys.tmp
for key in $(printf "%s\n" "${!basemap[@]}" | sort -r); do
echo " Including ${basemap[$key]}" >&2
cat "${basemap[$key]}" >>/run/authorized_keys.tmp
done
mkdir -p /run/authorized_keys
mv /run/authorized_keys.tmp /run/authorized_keys/$user
chown $user /run/authorized_keys/$user
done