fix: first-boot security updates read Debian's security.sources #34

Merged
marcos-mendez merged 2 commits from fix/secupdates-debian-security into master 2026-10-02 14:53:38 -03:00
marcos-mendez commented 2026-10-02 10:08:14 -03:00 (Migrated from github.com)

Summary

  • 95secupdates ran its dist-upgrade with Dir::Etc::sourcelist=/etc/apt/sources.list.d/security.sources.sources. common's bootstrap wrote that file with an enabled archive.turnkeylinux.org stanza in it, so the first boot of a Keel image fetched from the TurnKey archive. Keel-Linux/common#30 now writes security.sources with Debian's security archive alone, and the hook reads that name. SEC_UPDATES_SOURCES overrides the path for the tests.
  • A missing security source now fails the hook. The failure is logged and written to the hook's log. Before, apt read a missing sourcelist as empty, so the upgrade succeeded having installed nothing. That is exactly what an old common combined with a new hook (or the reverse) would have done silently.
  • secupdates-ask.py checks that it can resolve security.debian.org, where the updates come from, instead of archive.turnkeylinux.org. archive.turnkeylinux.org is removed from the branding test's ALLOWED list.
  • Changelog: 2.3.6+keel17. This must land together with Keel-Linux/common#30.

Review fixes (second commit)

  • set -o pipefail. dist-upgrade, dpkg --configure and apt-get update all pipe into tee, so a failure ended as tee's success. The listing of /lib/modules and /boot now tolerates a missing /boot, as in containers, which would otherwise fail under pipefail.
  • Offline, the first boot goes on. Before installing, the hook fetches the InRelease of the security source with curl (curl added to Depends). If that fails, or apt-get update fails, it logs cannot reach ... or apt-get update failed to syslog and to the hook's log, names turnkey-install-security-updates, and exits 0. Before, an offline apt-get update stopped the hook under -e with nothing logged.
  • force is recorded only after a successful install, on both the preseeded and the screen path. A failed install, or one that never ran because the machine was offline, leaves no record.
  • Interactive path offline. secupdates-ask.py still checks DNS for security.debian.org and shows its error dialog, which fails the hook. That is unchanged here and can be aligned in a follow-up if wanted.

Verification

On the step8 Web image in an LXC container, with common#30 applied: turnkey-install-security-updates (SEC_UPDATES=FORCE) read only security.debian.org trixie-security. With libpng16-16t64 rolled back to the trixie version, the hook fetched 1.6.48-1+deb13u6 from security.debian.org and installed it. Hook exit 0, and /var/lib/inithooks/sec-updates says force.

Test plan

  • bats tests/test-secupdates.bats: 20 pass (11 new, RED first); kcov 98.6 percent of 95secupdates
  • pytest tests/: 383 pass
  • shellcheck firstboot.d/95secupdates
  • CI green
## Summary - 95secupdates ran its dist-upgrade with `Dir::Etc::sourcelist=/etc/apt/sources.list.d/security.sources.sources`. common's bootstrap wrote that file with an enabled archive.turnkeylinux.org stanza in it, so the first boot of a Keel image fetched from the TurnKey archive. Keel-Linux/common#30 now writes `security.sources` with Debian's security archive alone, and the hook reads that name. `SEC_UPDATES_SOURCES` overrides the path for the tests. - A missing security source now fails the hook. The failure is logged and written to the hook's log. Before, apt read a missing sourcelist as empty, so the upgrade succeeded having installed nothing. That is exactly what an old common combined with a new hook (or the reverse) would have done silently. - secupdates-ask.py checks that it can resolve `security.debian.org`, where the updates come from, instead of archive.turnkeylinux.org. `archive.turnkeylinux.org` is removed from the branding test's ALLOWED list. - Changelog: 2.3.6+keel17. This must land together with Keel-Linux/common#30. ## Review fixes (second commit) - **`set -o pipefail`.** `dist-upgrade`, `dpkg --configure` and `apt-get update` all pipe into `tee`, so a failure ended as tee's success. The listing of `/lib/modules` and `/boot` now tolerates a missing `/boot`, as in containers, which would otherwise fail under pipefail. - **Offline, the first boot goes on.** Before installing, the hook fetches the InRelease of the security source with curl (`curl` added to Depends). If that fails, or `apt-get update` fails, it logs `cannot reach ...` or `apt-get update failed` to syslog and to the hook's log, names `turnkey-install-security-updates`, and exits 0. Before, an offline `apt-get update` stopped the hook under -e with nothing logged. - **`force` is recorded only after a successful install**, on both the preseeded and the screen path. A failed install, or one that never ran because the machine was offline, leaves no record. - **Interactive path offline.** `secupdates-ask.py` still checks DNS for security.debian.org and shows its error dialog, which fails the hook. That is unchanged here and can be aligned in a follow-up if wanted. ## Verification On the step8 Web image in an LXC container, with common#30 applied: `turnkey-install-security-updates` (SEC_UPDATES=FORCE) read only security.debian.org trixie-security. With libpng16-16t64 rolled back to the trixie version, the hook fetched `1.6.48-1+deb13u6` from security.debian.org and installed it. Hook exit 0, and `/var/lib/inithooks/sec-updates` says `force`. ## Test plan - [x] `bats tests/test-secupdates.bats`: 20 pass (11 new, RED first); kcov 98.6 percent of 95secupdates - [x] `pytest tests/`: 383 pass - [x] shellcheck firstboot.d/95secupdates - [ ] CI green
Sign in to join this conversation.
No description provided.