Hi folks,
I would like to propose a proof-of-concept for better SecureBoot support in Foreman.
SecureBoot expects to follow a chain of trust from the start of the host to the loading of Linux kernel modules. The very first shim that is loaded basically determines which distribution is allowed to be booted or kexec’ed until next reboot.
We assume host systems with enabled SecureBoot (user mode) and default MS certificates in db.
The existing “Grub2 UEFI SecureBoot” is not sufficiant as it limits the possible provisioning to the vendor of the Foreman host system. Simply speaking, if your Foreman/Smart Proxy host operating system is for example CentOS, you can only provisioning CentOS OS to your hosts (see puppet-foreman_proxy/netboot.pp at master · theforeman/puppet-foreman_proxy · GitHub).
Example (as of today):
- Foreman Smart Proxy host OS is CentOS7
- shim in (/var/lib/tftpboot/grub2/shimx64.efi) is signed by MS and contains CentOS certificate (vendor key)
- GRUB2 in (/var/lib/tftpboot/grub2/grubx64.efi) is signed by CentOS
- a host fetches shim, shim fetches GRUB2, GRUB2 fetches its configuration instructing GRUB2 to boot Ubuntu 22.04 installation kernel
- GRUB2 fetches kernel+initrd
- GRUB2 calls shim for signature verification
- booting of Ubuntu 22.024 installation kernel fails with “Invalid signature”
We could solve this through a more fine configurable way to specify a host’s Network Bootstrap Program (NBP) and its provisioning. Foreman knows the to-be-installed OS at the moment when a host goes into build mode. Having this, Foreman can prepare and provide all required files on TFTP server and make corresponding DHCP configuration.
The following patchset is a proof-of-concept:
To make this POC working you need to provide all shim and GRUB2 binaries manually under /usr/local/share/bootloader-universe/<os>/. Don’t forget to set read permissions for foreman-proxy user. You need to set SELinux to permissive when testing.
Example (working):
- Foreman host OS is CentOS7
- Start Ubuntu 22.04 provisioning for a host
- host enters build mode, shim+GRUB2 are copied from /usr/local/share/bootloader-universe/ubuntu/ to /var/lib/tftpboot/grub2/00-11-22-33-44-55, shim is signed by MS and contains Ubuntu certificate (vendor key)
- GRUB2 in (/var/lib/tftpboot/grub2/00-11-22-33-44-55/grubx64.efi) is signed by Ubuntu
- host fetches shim, shim fetches GRUB2 (from same directory path), GRUB2 fetches its configuration (from same directory path: $prefix) instructing GRUB2 to boot Ubuntu 22.04 installation kernel
- GRUB2 fetches kernel+initrd
- GRUB2 calls shim for signature verification
- booting of Ubuntu 22.24 installation kernel succeeds
To-be-implemented:
- auto-extract of binaries out of corresponding installation media
- SELinux policy to allow file creation
- DELETE method for Smart Proxy
- various checks and code improvements
- …
Considerations:
- always boot from network: shim chainloading does not work (network shim chainloads disk shim), but network shim chainloading GRUB2 from disk works
- some distribution GRUB2 are only trying to fetch grub.cfg (and not grub.cfg-<mac>) from $prefix (here TFTP), therefor we provide same GRUB2 configuration in three different files
What do you guys think? Would this be a useful feature for Foreman?