#!/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
while read -r user; 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 < <(cut -d':' -f1 /etc/passwd)
