commit ae55be8be9d9bf61bcbea739a79648502a6d2458 Author: Max Weiss Date: Sat Apr 17 05:51:41 2021 -0700 Initial commit diff --git a/buildbot/x86_iso_build.sh b/buildbot/x86_iso_build.sh new file mode 100755 index 0000000..5a5a764 --- /dev/null +++ b/buildbot/x86_iso_build.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + + +# By this point, the dependencies are installed, so we just need to download +# IPXE and build our ISO + +git clone git://git.ipxe.org/ipxe.git +cd ipxe + +# Do we want to specify a specific commit to lock in?? +git checkout HEAD +cd src + +# Enable required IPXE features +sed -i 's/^\/\/\#define\ DOWNLOAD_PROTO_HTTPS/\#define\ DOWNLOAD_PROTO_HTTPS/g' config/general.h +sed -i 's/^\/\/\#define\ NSLOOKUP_CMD/\#define\ NSLOOKUP_CMD/g' config/general.h +sed -i 's/^\/\/\#define\ TIME_CMD/\#define\ TIME_CMD/g' config/general.h +sed -i 's/^\/\/\#define\ DIGEST_CMD/\#define\ DIGEST_CMD/g' config/general.h +sed -i 's/^\/\/\#define\ REBOOT_CMD/\#define\ REBOOT_CMD/g' config/general.h +sed -i 's/^\/\/\#define\ POWEROFF_CMD/\#define\ POWEROFF_CMD/g' config/general.h +sed -i 's/^\/\/\#define\ IMAGE_TRUST_CMD/\#define\ IMAGE_TRUST_CMD/g' config/general.h +sed -i 's/^\/\/\#define\ NTP_CMD/\#define\ NTP_CMD/g' config/general.h +sed -i 's/^\/\/\#define\ CERT_CMD/\#define\ CERT_CMD/g' config/general.h + +sed -i 's/^\#undef\ DOWNLOAD_PROTO_HTTPS/\#define\ DOWNLOAD_PROTO_HTTPS/g' config/general.h +sed -i 's/^\#undef\ NSLOOKUP_CMD/\#define\ NSLOOKUP_CMD/g' config/general.h +sed -i 's/^\#undef\ TIME_CMD/\#define\ TIME_CMD/g' config/general.h +sed -i 's/^\#undef\ DIGEST_CMD/\#define\ DIGEST_CMD/g' config/general.h +sed -i 's/^\#undef\ REBOOT_CMD/\#define\ REBOOT_CMD/g' config/general.h +sed -i 's/^\#undef\ POWEROFF_CMD/\#define\ POWEROFF_CMD/g' config/general.h +sed -i 's/^\#undef\ IMAGE_TRUST_CMD/\#define\ IMAGE_TRUST_CMD/g' config/general.h +sed -i 's/^\#undef\ NTP_CMD/\#define\ NTP_CMD/g' config/general.h +sed -i 's/^\#undef\ CERT_CMD/\#define\ CERT_CMD/g' config/general.h + + +IPXE_EMBED_FILE_LOC="$(realpath $(dirname $(realpath $0))/../embed.ipxe)" + +make bin/ipxe.iso EMBED="${IPXE_EMBED_FILE_LOC}" \ + CERT="${IPXE_SIGNING_CERT},${IPXE_SIGNING_CA_CRT}" \ + TRUST="${IPXE_SIGNING_CA_CRT}" + diff --git a/embed.ipxe b/embed.ipxe new file mode 100644 index 0000000..aa3ed04 --- /dev/null +++ b/embed.ipxe @@ -0,0 +1,182 @@ +#!ipxe + + +# I've assume IPv4 for this script, so if we need IPv6, it may need +# modifications. + + +# Require only verified images to boot +imgtrust --permanent + + +# For the "focal" part of the URL string, in case that changes in the future. +set ubuntu-variant focal + +goto get_arch + + +################# +### This section is at the top, so it's easier to modify. +:static_ip_boot_setup + +# Open all network interface devices, so we aren't restricted to just the first +ifopen +sleep 1 + +# Currently we just configure IP info by MAC address. So we iterate over +# MAC addresses and set the variables. To ensure we use the desired +# device, we iterate over all devices and simply find matches by +# MAC address. +set idx:int32 0 +set successful f +:loop +isset ${net${idx}/mac} || goto loop_done + +######################## SET STATIC IP INFO HERE ############################# +# Just copy/paste an entire line to add more + +iseq ${net${idx}/mac:string} "00:01:02:A0:B1:C1" && set ip-dev-name eth0 && set ip-addr "192.168.1.5" && set ip-gateway "192.168.1.1" && set ip-netmask "255.255.255.0" && set ip-dns "1.1.1.1" && set successful t && goto loop_done || +iseq ${net${idx}/mac:string} "03:04:05:D4:E5:F6" && set ip-dev-name eth0 && set ip-addr "192.168.99.2" && set ip-gateway "192.168.99.1" && set ip-netmask "255.255.255.0" && set ip-dns "1.1.1.1" && set successful t && goto loop_done || +############################################################################## +inc idx && goto loop + +:loop_done +# If we have not successfully found a MAC match, then we error, because we +# also failed DHCP. So there's nothing we can do but fail. +iseq successful f && goto error_handler + +# If on the other hand we're successful, then we construct the kernel ip= line +set ip-info ${ip-addr}::${ip-gateway}:${ip-netmask}::${ip-dev-name}:off:${ip-dns} + +# And setup IPXE networking. + +# First, set device info +set net${idx}/ip ${ip-addr} +set net${idx}/gateway ${ip-gateway} +set net${idx}/netmask ${ip-netmask} +set net${idx}/dns ${ip-dns} + +# Now we close all net devices and enable only the one we need. +# Sleep a little between, so we don't error by continuing too fast before the +# device is actually ready +sleep 1 +ifclose +sleep 1 +ifopen net${idx} +sleep 1 + +# Set settings again in case the ifdown/ifup cleared them +set net${idx}/ip ${ip-addr} +set net${idx}/gateway ${ip-gateway} +set net${idx}/netmask ${ip-netmask} +set net${idx}/dns ${ip-dns} +sleep 1 + +# Now we have the ip= line and the IPXE network configured, so we can +# download and boot. +goto boot_all +### +################# + + +# In case we want to... log?? Or do something else. +:error_handler +echo "###########################################################" +echo "An unspecified error has occurred." +echo "The system will sleep for two minutes and then reboot." +echo "###########################################################" +sleep 60 +sleep 60 +reboot +# Should not occur, but just in case... +sleep 5 +exit + + + +# Get relevant CPU arch. +:get_arch +iseq ${buildarch} arm32 && goto start_arm32 || +iseq ${buildarch} arm64 && goto start_arm64 || +iseq ${buildarch} i386 && goto start_i386 || +iseq ${buildarch} x86_64 && goto start_amd64 || +goto error_handler + + +# Builds may be done on 32-bit, but machines will always be 64-bit. +# Keep this section just in case we want to use 32-bit machines in the future. +:start_arm32 +goto start_arm64 + +:start_i386 +goto start_amd64 + + +# Set arch info and determine if we can use DHCP for network. +# Then either boot or goto static IP setup. +:start_arm64 +set arch-info arm64 +dhcp || goto static_ip_boot_arm64 +sleep 1 +set ip-info dhcp +goto boot_all + +:start_amd64 +set arch-info amd64 +dhcp || goto static_ip_boot_amd64 +sleep 1 +set ip-info dhcp +goto boot_all + + +# This process should be the same for arm and x86, but I'll leave this section +# intact in case it turns out it's not the same +:static_ip_boot_arm64 +goto static_ip_boot_setup + +:static_ip_boot_amd64 +goto static_ip_boot_setup + + + +:boot_all + +# We use HTTP because IPXE's HTTPS implementation is lacking. So we delegate +# integrity and validation to imgverify. + + +# Naming the squashfs download "/squashfs" is required, otherwise the boot +# kernel fails to load it in the "root=" part of the kernel cmdline. +# However, note that imgverify will fail if you refer to it as "/squashfs" +# instead of "squashfs". + +imgfetch http://images.sysdeploy.org/${ubuntu-variant}/${arch-info}/squashfs /squashfs || goto error_handler +imgverify --signer images.sysdeploy.org squashfs http://images.sysdeploy.org/${ubuntu-variant}/${arch-info}/squashfs.sig || goto error_handler + +# "--signer" validates against the subject common name field of the signing +# certificate. That signing cert must have both the digital signature key +# usage set and the code-signing key usage extension set. + +# By default, IPXE trusts the default Mozilla global root CA list, so +# make sure you pick a common name with a FQDN you control, even if you're +# using a custom CA that you import during build. + + +initrd http://images.sysdeploy.org/${ubuntu-variant}/${arch-info}/boot-initrd || goto error_handler +imgverify --signer images.sysdeploy.org boot-initrd http://images.sysdeploy.org/${ubuntu-variant}/${arch-info}/boot-initrd.sig || goto error_handler + +kernel http://images.sysdeploy.org/${ubuntu-variant}/${arch-info}/boot-kernel || goto error_handler +imgverify --signer images.sysdeploy.org boot-kernel http://images.sysdeploy.org/${ubuntu-variant}/${arch-info}/boot-kernel.sig || goto error_handler + + +# Get accurate time so we can set the clock in kernel boot cmdline +ntp pool.ntp.org || goto error_handler + + +boot boot-kernel initrd=boot-initrd rootfstype=squashfs root=/squashfs ip=${ip-info} overlayroot=tmpfs:recurse=0 systemd.clock-usec=${unixtime:int32}000000 ds=nocloud-net;s=https://cloud-init.sysdeploy.org/ || goto error_handler + +# unixtime variable must be used with int32, because that's the only way it +# will display as decimal digits. unit32 and string both display as hex. +# Therefore this will stop working in 2038. + +