mirror of
https://github.com/openglow-org/forgefirm.git
synced 2026-09-27 08:41:13 -07:00
The rootfs mounted read-write, so a slot ran with its own files open to change, and the factory-slot mounts rode along on the release image. Both images now carry the read-only-rootfs feature: the ro root line and the rcS default, the volatile links made at rootfs time, a writable copy of /var/lib at boot, a build failure for a post-install that needs the machine, and the removal of shadow, base-passwd, update-rc.d and update-alternatives. What must last or change at run time is handled file by file: - forgefirm-users renders the four account files from the record into /run/forgefirm/accounts and bind-mounts each copy over its /etc file (useradd and the rest are gone with shadow); a render writes through the mount, and the image's own files apply until the first render. - forgefirm-banner bind-mounts a copy of /etc/issue and writes the address block through it. - sshd keeps its host keys under /data/forgefirm/ssh, so the fingerprint survives updates; both sshd configs carry the same HostKey lines. - forgefirm-logging passes logrotate a state file under /var/run (logrotate refuses to run without one). - forgefirm-persist points the boot timestamp and the random seed at /data/forgefirm. The dev image appends the /factory slot mounts, without nofail (busybox mount hands it to the kernel, which rejects it). The rootfs command entries lose their semicolons: on scarthgap the value is the task's vardeps, split on whitespace, so "name;" left the function body out of the signature and a changed body did not remake the rootfs; with the bodies tracked, the dev image's DATETIME string needs a vardepsexclude. release.sh gains the read-only gate (root ro, no /factory line, ROOTFS_READ_ONLY=yes, host keys on /data). image.health checks the mounts, the account binds, the banner bind, the host keys and the dev-only /factory mounts. Proven on the bench reference (dev image 20260909140901): / ro, /data rw, /var/lib a tmpfs copy, the four account files and /etc/issue bound from tmpfs, the host keys in /data/forgefirm/ssh, no "Read-only file system" line in any log; forgectrl.auth and commission.account-login (a temporary account rendered, logged in over HTTPS and removed again), kernel.latch-locked-idle and motion.liveness-probe PASS; logrotate runs with the volatile state. forgetest unit tests 335 OK; both images build clean, and debugfs on the built rootfs shows every setting above.
53 lines
2.6 KiB
Plaintext
53 lines
2.6 KiB
Plaintext
# ForgeFIRM SSH policy, set in the installed files so the release image
|
|
# carries it as built:
|
|
# PermitRootLogin no root logs in at the serial console only
|
|
# PermitEmptyPasswords no an account without a password cannot log in
|
|
# PasswordAuthentication yes operator accounts log in with a password
|
|
# The dev image's debug-tweaks turns PermitRootLogin and
|
|
# PermitEmptyPasswords back to yes at rootfs time (ssh_allow_root_login
|
|
# and ssh_allow_empty_password in rootfs-postcommands.bbclass match the
|
|
# active lines too), so the bench keeps root over SSH.
|
|
#
|
|
# The init script starts sshd only when the control panel has turned it
|
|
# on (/run/forgefirm/ssh-enabled, tmpfs, gone at reboot) or on the dev
|
|
# image (/etc/forgefirm-dev). The guard sits in check_for_no_start, which
|
|
# start, reload and restart call; stop is never gated.
|
|
#
|
|
# The host keys live under /data/forgefirm/ssh: sshd_check_keys makes
|
|
# them at the first start (it reads the HostKey paths from the config),
|
|
# and they stay across updates, so the machine's fingerprint does not
|
|
# change with a release. The rootfs is read-only, and the
|
|
# read-only-rootfs image feature, finding no key in the image, selects
|
|
# sshd_config_readonly at rootfs time; both configs carry the same
|
|
# HostKey lines, so that selection changes nothing.
|
|
|
|
do_install:append() {
|
|
for config in sshd_config sshd_config_readonly; do
|
|
f=${D}${sysconfdir}/ssh/$config
|
|
[ -e "$f" ] || continue
|
|
sed -i \
|
|
-e 's/^[#[:space:]]*PermitRootLogin .*/PermitRootLogin no/' \
|
|
-e 's/^[#[:space:]]*PermitEmptyPasswords .*/PermitEmptyPasswords no/' \
|
|
-e 's/^[#[:space:]]*PasswordAuthentication .*/PasswordAuthentication yes/' \
|
|
-e '/^[#[:space:]]*HostKey /d' \
|
|
"$f"
|
|
for t in rsa ecdsa ed25519; do
|
|
echo "HostKey /data/forgefirm/ssh/ssh_host_${t}_key" >> "$f"
|
|
done
|
|
grep -q '^PermitRootLogin no$' "$f" \
|
|
&& grep -q '^PermitEmptyPasswords no$' "$f" \
|
|
&& grep -q '^PasswordAuthentication yes$' "$f" \
|
|
&& [ "$(grep -c '^HostKey /data/forgefirm/ssh/' "$f")" = 3 ] \
|
|
|| bbfatal "$config: the ForgeFIRM policy lines did not land"
|
|
done
|
|
|
|
init=${D}${sysconfdir}/init.d/sshd
|
|
sed -i '/^check_for_no_start() {$/a\
|
|
[ -e /run/forgefirm/ssh-enabled ] || [ -e /etc/forgefirm-dev ] || {\
|
|
echo "sshd: not enabled (turn it on from the ForgeFIRM control panel)"\
|
|
exit 0\
|
|
}' "$init"
|
|
grep -q 'forgefirm/ssh-enabled' "$init" \
|
|
|| bbfatal "init.d/sshd: the check_for_no_start anchor was not found"
|
|
}
|