build_service 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. #!/bin/bash
  2. # Write the systemd unit for this application, and make sure it has a key to
  3. # hand it.
  4. #
  5. # Usage: bin/build_service [domain]
  6. set -u
  7. DOMAIN=${1:-}
  8. REPLACEME=$(dirname "$0")/..
  9. REPLACEME=$(readlink -f "$REPLACEME")
  10. # Make sure we start it with the *right* perl
  11. PERL5BIN=$(perl -V:scriptdir | sed -e "s/^scriptdir=//g;s/[';]//g")":$PATH"
  12. CREDENTIAL=tpsgi-vault
  13. # systemd reads this one, and /run/credstore.encrypted, and /usr/lib/... . The
  14. # override is for a distribution that puts it somewhere else, and for testing
  15. # this without writing to /etc.
  16. CREDSTORE=${TPSGI_CREDSTORE:-/etc/credstore.encrypted}
  17. # An application which keeps secrets needs a key which is not kept where the
  18. # secrets are. systemd's credential store is that place: root owned, decrypted
  19. # into a ramdisk only this service can read, and never anywhere a backup of the
  20. # application would pick it up.
  21. #
  22. # systemd-creds encrypt --with-key=auto seals to the TPM when there is one and
  23. # to the host key when there is not, so there is one command here rather than a
  24. # choice for somebody to get wrong. What differs is how much a stolen disk
  25. # gets you, which is what gets reported below.
  26. #
  27. # Made once and then left alone. Replacing it is the same as losing it: whatever
  28. # was sealed under the old one stops opening, and whoever stored it stores it
  29. # again. That is the deal a key which lives and dies with its machine makes, and
  30. # it is the reason there is nothing here that writes one into $REPLACEME.
  31. setup_credential() {
  32. if ! command -v systemd-creds > /dev/null; then
  33. echo "No systemd-creds here, so no vault key. Applications which wanted one will do without."
  34. return 0
  35. fi
  36. local sealing
  37. case "$(systemd-creds has-tpm2 2> /dev/null)" in
  38. yes) sealing="sealed to this machine's TPM" ;;
  39. *) sealing="encrypted with the host key -- no usable TPM here, so a stolen disk is a stolen key" ;;
  40. esac
  41. sudo mkdir -p "$CREDSTORE" && sudo chmod 700 "$CREDSTORE" || {
  42. echo "Could not make $CREDSTORE; skipping the vault key." >&2
  43. return 1
  44. }
  45. # Asked as root, because the store is 700 and root owned: a plain -e in here
  46. # cannot see into it and says the key is absent every single time. That
  47. # would quietly replace the key on every build_service, which is the same as
  48. # losing it -- everything sealed under the old one stops opening.
  49. if sudo test -e "$CREDSTORE/$CREDENTIAL"; then
  50. echo "Vault key already in $CREDSTORE/$CREDENTIAL; leaving it alone."
  51. return 0
  52. fi
  53. # Straight down a pipe and into systemd-creds: the key is never a file, an
  54. # argument, or a line of scrollback on its way there.
  55. if ! openssl rand -base64 32 \
  56. | sudo systemd-creds encrypt --name="$CREDENTIAL" - "$CREDSTORE/$CREDENTIAL"; then
  57. echo "Could not write $CREDSTORE/$CREDENTIAL; skipping the vault key." >&2
  58. return 1
  59. fi
  60. sudo chmod 600 "$CREDSTORE/$CREDENTIAL"
  61. echo "Wrote $CREDSTORE/$CREDENTIAL, $sealing."
  62. echo "It is not backed up and cannot be recovered. Losing this machine loses what was stored under it."
  63. }
  64. setup_credential
  65. sed -e "s|__REPLACEME__|$REPLACEME|g" \
  66. -e "s|__PERL5BIN__|$PERL5BIN|g" \
  67. -e "s|__DOMAIN__|$DOMAIN|g" \
  68. -e "s|__HOME__|${UHOME:-}|g" \
  69. "$REPLACEME/service/tpsgi.tmpl" > "$REPLACEME/service/tpsgi.service"
  70. echo "Wrote $REPLACEME/service/tpsgi.service"