meta-google: authorized-keys-comp: Add package

This adds a startup routine that compiles an authorized_keys file from
multiple locations in the filesystem, allowing for multiple providers
without clashing.

Change-Id: Ib26e04af42f29d42410154fdd809aa3a525fc9d5
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/meta-google/recipes-google/ssh/authorized-keys-comp.bb b/meta-google/recipes-google/ssh/authorized-keys-comp.bb
new file mode 100644
index 0000000..81ee868
--- /dev/null
+++ b/meta-google/recipes-google/ssh/authorized-keys-comp.bb
@@ -0,0 +1,34 @@
+SUMMARY = "Compiles a set of authorized_keys files into a single file"
+PR = "r1"
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
+
+inherit systemd
+
+SRC_URI += " \
+  file://authorized-keys-comp.service \
+  file://authorized-keys-comp.sh \
+  "
+
+S = "${WORKDIR}"
+
+RDEPENDS_${PN} += "bash"
+
+SYSTEMD_SERVICE_${PN} += "authorized-keys-comp.service"
+
+FILES_${PN} += "/home"
+
+AUTHORIZED_KEYS_COMP_USERS ?= "root"
+
+do_install_append() {
+  install -d -m0755 ${D}${libexecdir}
+  install -m0755 authorized-keys-comp.sh ${D}${libexecdir}/
+
+  install -d -m0755 ${D}${systemd_system_unitdir}
+  install -m0644 authorized-keys-comp.service ${D}${systemd_system_unitdir}/
+
+  for user in ${AUTHORIZED_KEYS_COMP_USERS}; do
+    install -d -m0755 ${D}/home/$user/.ssh
+    ln -sv /run/authorized_keys/$user ${D}/home/$user/.ssh/authorized_keys
+  done
+}
diff --git a/meta-google/recipes-google/ssh/authorized-keys-comp/authorized-keys-comp.service b/meta-google/recipes-google/ssh/authorized-keys-comp/authorized-keys-comp.service
new file mode 100644
index 0000000..92f9b26
--- /dev/null
+++ b/meta-google/recipes-google/ssh/authorized-keys-comp/authorized-keys-comp.service
@@ -0,0 +1,6 @@
+[Service]
+Type=oneshot
+ExecStart=/usr/libexec/authorized-keys-comp.sh
+
+[Install]
+WantedBy=multi-user.target
diff --git a/meta-google/recipes-google/ssh/authorized-keys-comp/authorized-keys-comp.sh b/meta-google/recipes-google/ssh/authorized-keys-comp/authorized-keys-comp.sh
new file mode 100644
index 0000000..caff0a7
--- /dev/null
+++ b/meta-google/recipes-google/ssh/authorized-keys-comp/authorized-keys-comp.sh
@@ -0,0 +1,51 @@
+#!/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
diff --git a/meta-google/recipes-phosphor/images/obmc-phosphor-image.bbappend b/meta-google/recipes-phosphor/images/obmc-phosphor-image.bbappend
index 0dc37fd..042bb08 100644
--- a/meta-google/recipes-phosphor/images/obmc-phosphor-image.bbappend
+++ b/meta-google/recipes-phosphor/images/obmc-phosphor-image.bbappend
@@ -7,6 +7,7 @@
 OBMC_IMAGE_EXTRA_INSTALL_append_gbmc = " iproute2 iproute2-ss"
 OBMC_IMAGE_EXTRA_INSTALL_append_gbmc = " gbmc-systemd-config"
 OBMC_IMAGE_EXTRA_INSTALL_append_gbmc = " gbmc-iperf3"
+OBMC_IMAGE_EXTRA_INSTALL_append_gbmc = " authorized-keys-comp"
 OBMC_IMAGE_EXTRA_INSTALL_append_gbmc = \
   '${@"" if not d.getVar("GBMC_NCSI_IF_NAME") else " gbmc-ncsi-config"}'
 OBMC_IMAGE_EXTRA_INSTALL_append_gbmc = \