mkarchiso: Add buildmode to export netboot artifacts

archiso/mkarchiso:
Implement a buildmode to export artifacts required for netboot with IPXE.
When providing the buildmode 'netboot' via profiledef.sh or the `-m` option, all targets necessary to create an ISO
medium are built, but the components required for netboot are exported to the output dir.
Optionally, it is possible to provide a set of certificates for codsigning using the `-c` option, where the first file
is considered as the signer certificate and the second as the key.

Add `_export_netboot_artifacts()` to copy build artifacts to the output directory.
Add `_sign_netboot_artifacts()` to codesign the netboot artifacts in the work directory.
Add `_validate_requirements_buildmode_netboot()` to check for openssl.
Add `_build_iso_base()` to implement common function calls between the 'iso' and the 'netboot' buildmodes.
Add `_build_buildmode_netboot()` to make use of `_build_iso_base()`, (optionally) `_sign_netboot_artifacts()` and
`_export_netboot_artifacts()`.
Change `_build_buildmode_iso()` to make use of `_build_iso_base()`.
Add `-c` as an option to mkarchiso to read in a list of file names.
Unify the output of `_usage()` by using the same definition style for lists of strings provided to options that accept
them (e.g. `-c`, `-m`, `-p`).

Closes #128
This commit is contained in:
David Runge 2021-05-06 00:56:02 +02:00
parent 1fed84c795
commit d54bf635cd
No known key found for this signature in database
GPG Key ID: 7258734B41C31549

View File

@ -34,6 +34,8 @@ buildmodes=()
bootmodes=()
airootfs_image_type=""
airootfs_image_tool_options=()
cert_list=()
sign_netboot_artifacts=""
declare -A file_permissions=()
@ -96,13 +98,17 @@ usage: ${app_name} [options] <profile_dir>
Default: '${iso_label}'
-P <publisher> Set the ISO publisher
Default: '${iso_publisher}'
-c [cert ..] Provide certificates for codesigning of netboot artifacts
Multiple files are provided as quoted, space delimited list.
The first file is considered as the signing certificate,
the second as the key.
-g <gpg_key> Set the PGP key ID to be used for signing the rootfs image
-h This message
-m [build modes] Build modes to use (valid modes are: 'bootstrap' and 'iso').
-m [mode ..] Build mode(s) to use (valid modes are: 'bootstrap', 'iso' and 'netboot').
Multiple build modes are provided as quoted, space delimited list.
-o <out_dir> Set the output directory
Default: '${out_dir}'
-p PACKAGE(S) Package(s) to install.
-p [package ..] Package(s) to install.
Multiple packages are provided as quoted, space delimited list.
-v Enable verbose output
-w <work_dir> Set the working directory
@ -127,6 +133,7 @@ _show_config() {
_msg_info " Current build mode: ${buildmode}"
_msg_info " Build modes: ${buildmodes[*]}"
_msg_info " GPG key: ${gpg_key:-None}"
_msg_info "Code signing certificates: ${cert_list[*]}"
_msg_info " Profile: ${profile}"
_msg_info "Pacman configuration file: ${pacman_conf}"
_msg_info " Image file name: ${image_name:-None}"
@ -650,6 +657,34 @@ _prepare_airootfs_image() {
fi
}
# export build artifacts for netboot
_export_netboot_artifacts() {
_msg_info "Exporting netboot artifacts..."
install -d -m 0755 "${out_dir}"
cp -a -- "${isofs_dir}/${install_dir}/" "${out_dir}/"
_msg_info "Done!"
du -h -- "${out_dir}/${install_dir}"
}
# sign build artifacts for netboot
_sign_netboot_artifacts() {
local _file _dir
_msg_info "Signing netboot artifacts..."
_dir="${isofs_dir}/${install_dir}/"
for _file in "${_dir}/boot/"*ucode.img "${_dir}/boot/${arch}/vmlinuz-"* "${_dir}/boot/${arch}/initramfs-"*.img; do
openssl cms \
-sign \
-binary \
-noattr \
-in "${_file}" \
-signer "${cert_list[0]}" \
-inkey "${cert_list[1]}" \
-outform DER \
-out "${_file}".ipxe.sig
done
_msg_info "Done!"
}
_validate_requirements_airootfs_image_type_squashfs() {
if ! command -v mksquashfs &> /dev/null; then
(( validation_error=validation_error+1 ))
@ -703,6 +738,14 @@ _validate_requirements_buildmode_iso() {
fi
}
_validate_requirements_buildmode_netboot() {
_validate_requirements_buildmode_all
if ! command -v openssl &> /dev/null; then
(( validation_error=validation_error+1 ))
_msg_error "Validating build mode '${_buildmode}': openssl is not available on this host. Install 'openssl'!" 0
fi
}
# SYSLINUX El Torito
_add_xorrisofs_options_bios.syslinux.eltorito() {
xorrisofs_options+=(
@ -884,9 +927,10 @@ _read_profile() {
# Validate set options
_validate_options() {
local validation_error=0 bootmode _buildmode
local validation_error=0 bootmode _cert _buildmode
local pkg_list_from_file=()
local bootstrap_pkg_list_from_file=()
local _override_cert_list=()
_msg_info "Validating options..."
# Check if the package list file exists and read packages from it
@ -917,7 +961,23 @@ _validate_options() {
_msg_error "Bootstrap packages file '${bootstrap_packages}' does not exist." 0
fi
fi
if [[ "${sign_netboot_artifacts}" == "y" ]]; then
# Check if the certificate files exist
for _cert in "${cert_list[@]}"; do
if [[ -e "${_cert}" ]]; then
_override_cert_list+=("$(realpath -- "${_cert}")")
else
(( validation_error=validation_error+1 ))
_msg_error "File '${_cert}' does not exist." 0
fi
done
cert_list=("${_override_cert_list[@]}")
# Check if there are at least two certificate files
if (( "${#cert_list[@]}" < 2 )); then
(( validation_error=validation_error+1 ))
_msg_error "Two certificates are required for codesigning, but '${cert_list[*]}' is provided." 0
fi
fi
# Check if pacman configuration file exists
if [[ ! -e "${pacman_conf}" ]]; then
(( validation_error=validation_error+1 ))
@ -1017,6 +1077,10 @@ _set_overrides() {
install_dir="${app_name}"
fi
[[ ! -v override_gpg_key ]] || gpg_key="$override_gpg_key"
if [[ -v override_cert_list ]]; then
sign_netboot_artifacts="y"
fi
[[ ! -v override_cert_list ]] || cert_list+=("${override_cert_list[@]}")
if [[ -v override_quiet ]]; then
quiet="$override_quiet"
elif [[ -z "$quiet" ]]; then
@ -1079,38 +1143,15 @@ _make_pkglist() {
_msg_info "Done!"
}
_build_buildmode_bootstrap() {
local image_name="${iso_name}-bootstrap-${iso_version}-${arch}.tar.gz"
local run_once_mode="${buildmode}"
local buildmode_packages="${bootstrap_packages}"
local buildmode_pkg_list=()
# Set the package list to use
buildmode_pkg_list=("${bootstrap_pkg_list[@]}")
# Set up essential directory paths
pacstrap_dir="${work_dir}/${arch}/bootstrap/root.${arch}"
[[ -d "${work_dir}" ]] || install -d -- "${work_dir}"
install -d -m 0755 -o 0 -g 0 -- "${pacstrap_dir}"
[[ "${quiet}" == "y" ]] || _show_config
_run_once _make_pacman_conf
_run_once _make_packages
_run_once _make_version
_run_once _make_pkglist
_run_once _cleanup_pacstrap_dir
_run_once _build_bootstrap_image
}
_build_buildmode_iso() {
local image_name="${iso_name}-${iso_version}-${arch}.iso"
local run_once_mode="${buildmode}"
# build the base for an ISO and/or a netboot target
_build_iso_base() {
local run_once_mode="base"
local buildmode_packages="${packages}"
local buildmode_pkg_list=()
# Set the package list to use
local buildmode_pkg_list=("${pkg_list[@]}")
# Set up essential directory paths
pacstrap_dir="${work_dir}/${arch}/airootfs"
isofs_dir="${work_dir}/iso"
# Set the package list to use
buildmode_pkg_list=("${pkg_list[@]}")
# Create working directory
[[ -d "${work_dir}" ]] || install -d -- "${work_dir}"
@ -1132,6 +1173,46 @@ _build_buildmode_iso() {
_make_bootmodes
_run_once _cleanup_pacstrap_dir
_run_once _prepare_airootfs_image
}
# Build the bootstrap buildmode
_build_buildmode_bootstrap() {
local image_name="${iso_name}-bootstrap-${iso_version}-${arch}.tar.gz"
local run_once_mode="${buildmode}"
local buildmode_packages="${bootstrap_packages}"
# Set the package list to use
local buildmode_pkg_list=("${bootstrap_pkg_list[@]}")
# Set up essential directory paths
pacstrap_dir="${work_dir}/${arch}/bootstrap/root.${arch}"
[[ -d "${work_dir}" ]] || install -d -- "${work_dir}"
install -d -m 0755 -o 0 -g 0 -- "${pacstrap_dir}"
[[ "${quiet}" == "y" ]] || _show_config
_run_once _make_pacman_conf
_run_once _make_packages
_run_once _make_version
_run_once _make_pkglist
_run_once _cleanup_pacstrap_dir
_run_once _build_bootstrap_image
}
# Build the netboot buildmode
_build_buildmode_netboot() {
local run_once_mode="${buildmode}"
_run_once _build_iso_base
if [[ -v cert_list ]]; then
_run_once _sign_netboot_artifacts
fi
_run_once _export_netboot_artifacts
}
# Build the ISO buildmode
_build_buildmode_iso() {
local image_name="${iso_name}-${iso_version}-${arch}.iso"
local run_once_mode="${buildmode}"
_run_once _build_iso_base
_run_once _build_iso_image
}
@ -1145,7 +1226,7 @@ _build() {
done
}
while getopts 'p:C:L:P:A:D:w:m:o:g:vh?' arg; do
while getopts 'c:p:C:L:P:A:D:w:m:o:g:vh?' arg; do
case "${arg}" in
p) read -r -a override_pkg_list <<< "${OPTARG}" ;;
C) override_pacman_conf="${OPTARG}" ;;
@ -1153,6 +1234,7 @@ while getopts 'p:C:L:P:A:D:w:m:o:g:vh?' arg; do
P) override_iso_publisher="${OPTARG}" ;;
A) override_iso_application="${OPTARG}" ;;
D) override_install_dir="${OPTARG}" ;;
c) read -r -a override_cert_list <<< "${OPTARG}" ;;
w) override_work_dir="${OPTARG}" ;;
m) read -r -a override_buildmodes <<< "${OPTARG}" ;;
o) override_out_dir="${OPTARG}" ;;