#!/bin/sh

# What the platform handed to systemd as a credential.
#
#   detc.bundle    a bundle, or a single line holding a URL to fetch it from
#   detc.vars      a variables document
#
# This is the one to reach for first, and the reason is that it is not one
# mechanism but five.  systemd already unified them behind one directory, so a
# credential named `detc.bundle` arrives from any of:
#
#   * qemu, through `fw_cfg`: `-fw_cfg name=opt/io.systemd.credentials/detc.bundle,file=...`
#   * SMBIOS type 11: `-smbios type=11,value=io.systemd.credential:detc.bundle=...`
#   * the ESP: `/loader/credentials/detc.bundle.cred`
#   * `systemd-nspawn --load-credential=`
#   * a `.cred` file sealed to the TPM, which is the only one of the lot that a
#     machine can be given without also giving it to whoever can read the disk
#
# Nothing here knows which, and that is the point: one script, and a fleet
# chooses its transport later without changing anything on the node.
#
# `$CREDENTIALS_DIRECTORY` is set by systemd for a unit that asked for
# credentials -- `detc-inject.service` asks with `ImportCredential=detc.*` -- and
# is a `ramfs` that only root can read.  Nothing is set when the unit was given
# none, and this then says nothing, which is the ordinary case on a machine that
# uses one of the other three sources.
#
# A credential is written to a file, and detc takes a file, so the two fit
# without copying.  The one exception is a bundle that is too large to hand over
# whole -- SMBIOS in particular is a few hundred bytes in practice -- and for
# that the credential holds a URL instead, recognised by being one line that
# starts with `http`.  A bundle never does: it is a tar archive, and its first
# bytes are a file name.

set -eu

directory=${CREDENTIALS_DIRECTORY:-}
[ -n "$directory" ] || exit 0
[ -d "$directory" ] || exit 0

bundle=$directory/detc.bundle
if [ -r "$bundle" ]; then
    # `head -c` and not `read`, so that a binary bundle with no newline in its
    # first kilobyte is not read into a variable in its entirety
    case "$(head -c 8 "$bundle" 2>/dev/null || true)" in
      http://*|https://*)
        printf 'bundle\t%s\n' "$(head -n 1 "$bundle")"
        ;;
      *)
        printf 'bundle\t%s\n' "$bundle"
        ;;
    esac
fi

vars=$directory/detc.vars
[ ! -r "$vars" ] || printf 'vars\t%s\n' "$vars"
