autoprovision: Trigger host online webhook

To initiate the automatic host provisioning process, a new machine must
trigger the _POST /host/online_ webhook.  Included in the request are
the hostname of the new machine and its SSH host public keys.
Optionally, the request can also contain the name of a branch in the
configuration policy repository.  For virtual machines, this branch
name can be specified by a QEMU `fw_cfg` option.  The `fw_cfg` values in
sysfs are only readable by root, so the service must run as root, but
it does not need any additional privileges, so we can use systemd
sandbox features to restrict it.

This feature is enabled by default for virtual machines.  I haven't
quite figured out how to do the branch selection for physical machines
yet, but I will enable it for them once I do.
master
Dustin 2025-02-08 17:11:10 -06:00
parent 437ed39ecb
commit 94a9ed900f
2 changed files with 71 additions and 0 deletions

69
autoprovision.ks Normal file
View File

@ -0,0 +1,69 @@
%post
cat > /root/.ssh/authorized_keys <<EOF
expiry-time="$(date -d +1hour +%Y%m%d%H%M)",restrict,pty ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICoOO/ZYMxRgmyvqZwGN3NM5pHyh3NBdC7iZrXIopt93 Host Provisioner
EOF
cat > /usr/local/libexec/notify-online.sh <<'EOF'
#!/bin/sh
set -- \
-F "hostname=$(hostname -f)" \
-F 'sshkeys=<-;type=text/plain'
fw_cfg=/sys/firmware/qemu_fw_cfg/by_name/opt/dch/cfg-branch/raw
if [ -r "${fw_cfg}" ]; then
set -- "$@" -F branch="$(cat "${fw_cfg}")"
fi
cat /etc/ssh/ssh_host_*_key.pub \
| curl -fsS https://webhooks.pyrocufflink.blue/host/online "$@"
EOF
chmod +x /usr/local/libexec/notify-online.sh
cat > /etc/systemd/system/notify-online.service <<'EOF'
[Unit]
Description=Notify infrastructure services that this host is online
ConditionFirstBoot=yes
After=sshd.service
After=network-online.target
Wants=network-online.target
After=systemd-user-sessions.service
[Service]
Type=exec
ExecStart=/usr/local/libexec/notify-online.sh
# Must run as root in order to read QEMU fw_config, so enable maximum
# sandbox restrictions.
CapabilityBoundingSet=
DeviceAllow=
DevicePolicy=closed
LockPersonality=yes
MemoryDenyWriteExecute=yes
NoNewPrivileges=yes
PrivateDevices=yes
PrivateUsers=yes
PrivateTmp=yes
ProcSubset=pid
ProtectClock=yes
ProtectControlGroups=yes
ProtectHome=yes
ProtectHostname=yes
ProtectKernelLogs=yes
ProtectKernelModules=yes
ProtectKernelTunables=yes
ProtectProc=invisible
ProtectSystem=strict
RestrictAddressFamilies=AF_INET AF_INET6
RestrictNamespaces=yes
RestrictRealtime=yes
RestrictSUIDSGID=yes
SystemCallArchitectures=native
SystemCallFilter=@system-service
SystemCallFilter=~@privileged @resources
[Install]
WantedBy=multi-user.target
EOF
systemctl enable --no-reload notify-online.service
%end

View File

@ -13,3 +13,5 @@ reqpart
%packages
qemu-guest-agent
%end
%include https://git.pyrocufflink.net/infra/kickstart/raw/branch/master/autoprovision.ks