Files
diskless-workstation/files/ssh-hostcert/ssh-hostcert.service
T
2026-07-11 16:20:21 +09:30

52 lines
2.0 KiB
Desktop File

[Unit]
Description=Fleet SSH host-certificate acquisition (TPM-authenticated, fleet SSH CA)
Documentation=https://git.bitasylum.org/audiobuzz/diskless-workstation/docs/ssh-host-certificate-design.md
# Needs the network up (dials step-ca) and sshd's per-boot host key to exist.
# sshd-keygen generates the host key before sshd starts, so ordering After sshd
# guarantees the key is present; sshd itself serves the bare key until we install
# the cert and reload it. All soft ordering (After, not Requires) — this unit is
# FAIL-OPEN: if the CA is unreachable or the host isn't enrolled yet, it exits
# non-zero WITHOUT touching sshd, and the timer retries.
After=network-online.target sshd.service
Wants=network-online.target
# Don't run in the throwaway build VM (no TPM, no enrolment, no network CA).
ConditionPathExists=/dev/tpmrm0
[Service]
Type=oneshot
EnvironmentFile=/etc/ssh-hostcert/ssh-hostcert.env
ExecStart=/usr/local/bin/fleet-ssh-hostcert
# Runs as root — unlike the DynamicUser agent — because it writes root-owned
# files under /etc/ssh and reloads sshd. Kept tightly sandboxed otherwise. The
# TPM private key never leaves the chip; root only drives signing through it.
User=root
# STIG-friendly sandbox. /etc/ssh must be writable (the cert + drop-in); the rest
# of the filesystem is read-only.
ProtectSystem=strict
ReadWritePaths=/etc/ssh
ProtectHome=yes
PrivateTmp=yes
DeviceAllow=/dev/tpmrm0 rw
NoNewPrivileges=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectKernelLogs=yes
ProtectControlGroups=yes
ProtectClock=yes
ProtectHostname=yes
RestrictNamespaces=yes
RestrictRealtime=yes
RestrictSUIDSGID=yes
LockPersonality=yes
MemoryDenyWriteExecute=yes
SystemCallArchitectures=native
SystemCallFilter=@system-service
SystemCallFilter=~@privileged @resources
# INET egress to step-ca; AF_UNIX for the journal + talking to systemd (reload
# sshd); AF_NETLINK for Go's interface/source-address selection.
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX AF_NETLINK
UMask=0022
# Triggered by ssh-hostcert.timer (boot + periodic renewal), not enabled directly.