-
Notifications
You must be signed in to change notification settings - Fork 118
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add custom ipxe firmware building support
This commit adds the following: - Support for detecting iPXE certificates - When iPXE certs are detected, the iPXE services and conigs will be advertised with https addresses - Enforce chainloading of the iPXE firmware provided by the user even if the client machine comes with an iPXE firmware by default - Adds modular iPXE apache2 config file to enable separate iPXE specific virtual host (port) where TLS is enforced - Adds ipxe builder script that can be run as an entry point to standalone container or as a K8s pod init container - iPXE build script provides options to enable IPV6 and TLS support - option to embed a script to the iPXE firmware is added but for now it is only used to break chainloading - custom iPXE config file template has been added thus Ironic can generate node specific iPXE config files that use the custom iPXE firmware - a set of environment variable that control the new iPXE related features - option to build ipxe from a cache specified as a file path or pulling remote iPXE repo and building that
- Loading branch information
Showing
14 changed files
with
296 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
Listen {{ env.IPXE_TLS_PORT }} | ||
|
||
<VirtualHost *:{{ env.IPXE_TLS_PORT }}> | ||
ErrorLog /dev/stderr | ||
LogLevel debug | ||
CustomLog /dev/stdout combined | ||
|
||
SSLEngine on | ||
SSLProtocol {{ env.IPXE_SSL_PROTOCOL }} | ||
SSLCertificateFile {{ env.IPXE_CERT_FILE }} | ||
SSLCertificateKeyFile {{ env.IPXE_KEY_FILE }} | ||
|
||
<Directory "/shared/html"> | ||
Order Allow,Deny | ||
Allow from all | ||
</Directory> | ||
<Directory "/shared/html/(redfish|ilo|images)/"> | ||
Order Deny,Allow | ||
Deny from all | ||
</Directory> | ||
</VirtualHost> | ||
|
||
<Location ~ "^/grub.*/"> | ||
SSLRequireSSL | ||
</Location> | ||
<Location ~ "^/pxelinux.cfg/"> | ||
SSLRequireSSL | ||
</Location> | ||
<Location ~ "^/.*\.conf/"> | ||
SSLRequireSSL | ||
</Location> | ||
<Location ~ "^/(([0-9]|[a-z]).*-){4}([0-9]|[a-z]).*/"> | ||
SSLRequireSSL | ||
</Location> | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
#!ipxe | ||
|
||
set attempts:int32 10 | ||
set i:int32 0 | ||
|
||
goto deploy | ||
|
||
:deploy | ||
imgfree | ||
{%- if pxe_options.deployment_aki_path %} | ||
{%- set aki_path_https_elements = pxe_options.deployment_aki_path.split(':') %} | ||
{%- set aki_port_and_path = aki_path_https_elements[2].split('/') %} | ||
{%- set aki_afterport = aki_port_and_path[1:]|join('/') %} | ||
{%- set aki_path_https = ['https:', aki_path_https_elements[1], ':8084/', aki_afterport]|join %} | ||
{%- endif %} | ||
{%- if pxe_options.deployment_ari_path %} | ||
{%- set ari_path_https_elements = pxe_options.deployment_ari_path.split(':') %} | ||
{%- set ari_port_and_path = ari_path_https_elements[2].split('/') %} | ||
{%- set ari_afterport = ari_port_and_path[1:]|join('/') %} | ||
{%- set ari_path_https = ['https:', ari_path_https_elements[1], ':8084/', ari_afterport]|join %} | ||
{%- endif %} | ||
kernel {% if pxe_options.ipxe_timeout > 0 %}--timeout {{ pxe_options.ipxe_timeout }} {% endif %}{{ aki_path_https }} selinux=0 troubleshoot=0 text {{ pxe_options.pxe_append_params|default("", true) }} BOOTIF=${mac} initrd={{ pxe_options.initrd_filename|default("deploy_ramdisk", true) }} || goto retry | ||
|
||
initrd {% if pxe_options.ipxe_timeout > 0 %}--timeout {{ pxe_options.ipxe_timeout }} {% endif %}{{ ari_path_https }} || goto retry | ||
boot | ||
|
||
:retry | ||
iseq ${i} ${attempts} && goto fail || | ||
inc i | ||
echo No response, retrying in ${i} seconds. | ||
sleep ${i} | ||
goto deploy | ||
|
||
:fail | ||
echo Failed to get a response after ${attempts} attempts | ||
echo Powering off in 30 seconds. | ||
sleep 30 | ||
poweroff | ||
|
||
:boot_anaconda | ||
imgfree | ||
kernel {% if pxe_options.ipxe_timeout > 0 %}--timeout {{ pxe_options.ipxe_timeout }} {% endif %}{{ aki_path_https }} text {{ pxe_options.pxe_append_params|default("", true) }} inst.ks={{ pxe_options.ks_cfg_url }} {% if pxe_options.repo_url %}inst.repo={{ pxe_options.repo_url }}{% else %}inst.stage2={{ pxe_options.stage2_url }}{% endif %} initrd=ramdisk || goto boot_anaconda | ||
initrd {% if pxe_options.ipxe_timeout > 0 %}--timeout {{ pxe_options.ipxe_timeout }} {% endif %}{{ ari_path_https }} || goto boot_anaconda | ||
boot | ||
|
||
:boot_ramdisk | ||
imgfree | ||
{%- if pxe_options.boot_iso_url %} | ||
sanboot {{ pxe_options.boot_iso_url }} | ||
{%- else %} | ||
kernel {% if pxe_options.ipxe_timeout > 0 %}--timeout {{ pxe_options.ipxe_timeout }} {% endif %}{{ aki_path_https }} root=/dev/ram0 text {{ pxe_options.pxe_append_params|default("", true) }} {{ pxe_options.ramdisk_opts|default('', true) }} initrd=ramdisk || goto boot_ramdisk | ||
initrd {% if pxe_options.ipxe_timeout > 0 %}--timeout {{ pxe_options.ipxe_timeout }} {% endif %}{{ ari_path_https }} || goto boot_ramdisk | ||
boot | ||
{%- endif %} | ||
|
||
{%- if pxe_options.boot_from_volume %} | ||
|
||
:boot_iscsi | ||
imgfree | ||
{% if pxe_options.username %}set username {{ pxe_options.username }}{% endif %} | ||
{% if pxe_options.password %}set password {{ pxe_options.password }}{% endif %} | ||
{% if pxe_options.iscsi_initiator_iqn %}set initiator-iqn {{ pxe_options.iscsi_initiator_iqn }}{% endif %} | ||
sanhook --drive 0x80 {{ pxe_options.iscsi_boot_url }} || goto fail_iscsi_retry | ||
{%- if pxe_options.iscsi_volumes %}{% for i, volume in enumerate(pxe_options.iscsi_volumes) %} | ||
set username {{ volume.username }} | ||
set password {{ volume.password }} | ||
{%- set drive_id = 129 + i %} | ||
sanhook --drive {{ '0x%x' % drive_id }} {{ volume.url }} || goto fail_iscsi_retry | ||
{%- endfor %}{% endif %} | ||
{% if pxe_options.iscsi_volumes %}set username {{ pxe_options.username }}{% endif %} | ||
{% if pxe_options.iscsi_volumes %}set password {{ pxe_options.password }}{% endif %} | ||
sanboot --no-describe || goto fail_iscsi_retry | ||
|
||
:fail_iscsi_retry | ||
echo Failed to attach iSCSI volume(s), retrying in 10 seconds. | ||
sleep 10 | ||
goto boot_iscsi | ||
{%- endif %} | ||
|
||
:boot_whole_disk | ||
sanboot --no-describe || exit 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
#!/usr/bin/bash | ||
|
||
set -euxo pipefail | ||
# ENV VARIABLE CONFIG # | ||
# shellcheck disable=SC1091 | ||
. /bin/tls-common.sh | ||
. /bin/ironic-common.sh | ||
|
||
# This script should be used as an init container's entry point thus | ||
# it is expected that the user would like to build the ipxe when this script | ||
# is started. By default the script will try to build from cache and fails | ||
# if the cache is unavailable. | ||
export IPXE_BUILD_FROM_CACHE="${IPXE_BUILD_FROM_CACHE:-true}" | ||
export IPXE_BUILD_FROM_REPO="${IPXE_BUILD_FROM_REPO:-false}" | ||
export IPXE_SHARED_FIRMWARE_SOURCE="${IPXE_SHARED_FIRMWARE_SOURCE:-/shared/ipxe-source}" | ||
export IPXE_EMBED_SCRIPT="${IPXE_EMBED_SCRIPT:-/bin/embed.ipxe}" | ||
export IPXE_EMBED_SCRIPT_TEMPLATE="${IPXE_EMBED_SCRIPT_TEMPLATE:-/bin/embed.ipxe.j2}" | ||
export IPXE_RELEASE_BRANCH="${IPXE_RELEASE_BRANCH:-v1.21.1}" | ||
export IPXE_ENABLE_IPV6="${IPXE_ENABLE_IPV6:-false}" | ||
export IPXE_ENABLE_HTTPS="${IPXE_ENABLE_TLS:-false}" | ||
# BUILD_OPTIONS are not configurable directly | ||
export IPXE_BUILD_OPTIONS="NO_WERROR=1 EMBED=${IPXE_EMBED_SCRIPT}" | ||
# PREPARE SOURCE # | ||
|
||
# Create debug folder | ||
mkdir -p "/shared/ipxe-debug" | ||
|
||
# In case building ipxe firmware from shared volume | ||
if [[ "${IPXE_BUILD_FROM_CACHE}" == "true" ]]; then | ||
if [[ -r "${IPXE_SHARED_FIRMWARE_SOURCE}" ]]; then | ||
cp -r "${IPXE_SHARED_FIRMWARE_SOURCE}" "/tmp" | ||
ls -all "/tmp/ipxe-source" | ||
else | ||
>&2 echo "ERROR: can't build ipxe from cache, there is no path!" | ||
exit 1 | ||
fi | ||
fi | ||
|
||
# In case building ipxe firmware from upstream git repo directly | ||
# Requires Internet access! | ||
if [[ "${IPXE_BUILD_FROM_CACHE}" == "false" ]] \ | ||
&& [[ "${IPXE_BUILD_FROM_REPO}" == "true" ]]; then | ||
git clone --depth 1 --branch "${IPXE_RELEASE_BRANCH}" \ | ||
"https://github.com/ipxe/ipxe.git" \ | ||
"/tmp/ipxe-source" | ||
fi | ||
|
||
if [[ ! -r "/tmp/ipxe-source" ]]; then | ||
>&2 echo "ERROR: The ipxe firmware source is missing, check the env vars!" | ||
exit 1 | ||
fi | ||
|
||
# BUILD # | ||
ARCH=$(uname -m | sed 's/aarch/arm/') | ||
# NOTE(elfosardo): warning should not be treated as errors by default | ||
cd "/tmp/ipxe-source/src" | ||
if [[ "${IPXE_ENABLE_IPV6}" == "true" ]]; then | ||
sed -i 's/^\/\/#define[ \t]NET_PROTO_IPV6/#define\tNET_PROTO_IPV6/g' \ | ||
"config/general.h" | ||
fi | ||
if [[ "${IPXE_ENABLE_TLS}" == "true" ]]; then | ||
if [[ ! -r "${IPXE_CERT_FILE}" ]]; then | ||
>&2 echo "ERROR: iPXE TLS support is enabled but cert is missing!" | ||
exit 1 | ||
fi | ||
sed -i 's/^#define[ \t]DOWNLOAD_PROTO_HTTP/#undef\tDOWNLOAD_PROTO_HTTP/g' \ | ||
"config/general.h" | ||
sed -i 's/^#undef[ \t]DOWNLOAD_PROTO_HTTPS/#define\tDOWNLOAD_PROTO_HTTPS/g' \ | ||
"config/general.h" | ||
echo "IPXE BUILD OPTIONS ARE EXTENDED WITH CERTS!!!" | ||
render_j2_config "${IPXE_EMBED_SCRIPT_TEMPLATE}" "${IPXE_EMBED_SCRIPT}" | ||
export IPXE_BUILD_OPTIONS="${IPXE_BUILD_OPTIONS} CERT=${IPXE_CERT_FILE} TRUST=${IPXE_CERT_FILE}" | ||
fi | ||
|
||
sed -i 's/^\/\/#define[ \t]CONSOLE_SERIAL/#define\tCONSOLE_SERIAL/g' \ | ||
"config/console.h" | ||
|
||
/usr/bin/make "bin/undionly.kpxe" "bin-${ARCH}-efi/snponly.efi" ${IPXE_BUILD_OPTIONS[@]} | ||
|
||
mkdir -p "${IPXE_CUSTOM_FIRMWARE_DIR}" | ||
# These files will be copied by the rundnsmasq script to the shared volume. | ||
cp "/tmp/ipxe-source/src/bin/undionly.kpxe" \ | ||
"/tmp/ipxe-source/src/bin-${ARCH}-efi/snponly.efi" \ | ||
"${IPXE_CUSTOM_FIRMWARE_DIR}" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#!ipxe | ||
|
||
:chainload | ||
echo Initiating DHCP based interface configuration | ||
dhcp | ||
echo Start chainloading https://{{ env.IRONIC_IP }}:{{ env.IPXE_TLS_PORT }}/boot.ipxe | ||
chain https://{{ env.IRONIC_IP }}:{{ env.IPXE_TLS_PORT }}/boot.ipxe || goto boot_failed | ||
echo Chainloading succeeded! | ||
|
||
:boot_failed | ||
echo Chainloading failed! | ||
echo Press any key to reboot... | ||
prompt --timeout 60 | ||
reboot |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.