diff --git a/app/views/unattended/partition_tables_templates/kickstart_default_encrypted.erb b/app/views/unattended/partition_tables_templates/kickstart_default_encrypted.erb new file mode 100644 index 00000000000..522d848125b --- /dev/null +++ b/app/views/unattended/partition_tables_templates/kickstart_default_encrypted.erb @@ -0,0 +1,18 @@ +<%# +kind: ptable +name: Kickstart default encrypted +model: Ptable +oses: +- AlmaLinux +- RedHat +- Rocky +-%> +<% if host_param('driverdisk_source') -%> +driverdisk --source=<%= host_param('driverdisk_source') %> +<% end -%> +<% if host_param('ignoredisk_options') -%> +ignoredisk <%= host_param('ignoredisk_options') %> +<% end -%> +zerombr +clearpart --all --initlabel +autopart --encrypted --passphrase="<%= host_param('disk_enc_passphrase', 'linux') %>" <%= host_param('autopart_options') %> diff --git a/app/views/unattended/partition_tables_templates/preseed_default_autoinstall_encrypted.erb b/app/views/unattended/partition_tables_templates/preseed_default_autoinstall_encrypted.erb new file mode 100644 index 00000000000..b75ccafbe71 --- /dev/null +++ b/app/views/unattended/partition_tables_templates/preseed_default_autoinstall_encrypted.erb @@ -0,0 +1,17 @@ +<%# +kind: ptable +name: Preseed default autoinstall encrypted +model: Ptable +description: | + Preseed Autoinstall default storage snippet configures drives automatically + with LVM and disk encryption. + Requires Ubuntu >= 22.04.3. + The snippet is automatically indented by 2 spaces. For reference: + https://ubuntu.com/server/docs/install/autoinstall-reference +oses: +- Ubuntu +%> +storage: + layout: + name: lvm + password: <%= host_param('disk_enc_passphrase', 'linux') %> diff --git a/app/views/unattended/provisioning_templates/provision/kickstart_default.erb b/app/views/unattended/provisioning_templates/provision/kickstart_default.erb index faee2687fc1..bddb63ea2fd 100644 --- a/app/views/unattended/provisioning_templates/provision/kickstart_default.erb +++ b/app/views/unattended/provisioning_templates/provision/kickstart_default.erb @@ -362,6 +362,7 @@ sed -e 's/DEFAULTKERNEL=kernel-uek/DEFAULTKERNEL=kernel/g' -i /etc/sysconfig/ker <%= snippet_if_exists(template_name + " custom post") %> <%= snippet 'insights' if host_param_true?('host_registration_insights') && os_major < 9 -%> +<%= snippet 'disk_enc_clevis_tang' if host_param('disk_enc_tang_servers') -%> touch /tmp/foreman_built diff --git a/app/views/unattended/provisioning_templates/snippet/disk_enc_clevis_tang.erb b/app/views/unattended/provisioning_templates/snippet/disk_enc_clevis_tang.erb new file mode 100644 index 00000000000..c881b7790c3 --- /dev/null +++ b/app/views/unattended/provisioning_templates/snippet/disk_enc_clevis_tang.erb @@ -0,0 +1,89 @@ +<%# +kind: snippet +name: disk_enc_clevis_tang +model: ProvisioningTemplate +snippet: true +description: | + Binds encrypted root directory ('/') utilizing Clevis to Tang server(s) for + decryption. The first parent device containing a LUKS container will be used. + The temporary passphrase will be removed afterwards. Currently, only Red Hat + family and Ubuntu operating systems are supported. +-%> +<% + passphrase = host_param('disk_enc_passphrase', 'linux') + tang_server_list = [] + packages_redhat = "clevis clevis-luks clevis-systemd clevis-dracut" + packages_ubuntu = "clevis clevis-luks clevis-systemd clevis-initramfs" + + unless host_param('disk_enc_tang_servers').blank? + if host_param('disk_enc_tang_servers').is_a?(String) + tang_server_list = [host_param('disk_enc_tang_servers')] + else + tang_server_list = host_param('disk_enc_tang_servers') + end + end +-%> + +<% if (@host.operatingsystem.family == 'Redhat' || @host.operatingsystem.name == 'Ubuntu') && unless tang_server_list.blank? -%> + +cat > /tmp/rootdir-luks-device.sh << "EOF" +#!/bin/sh +# +# Author Jan Löser +# Published under the GNU Public Licence 3 +# +# This scripts tries to find the 1st LUKS device for / (root directory). +# +set -o pipefail + +rootdev=$(df / --output=source | tail -n1) +targetdev=$(readlink -f $rootdev) +slavedev=$targetdev + +while : ; do + /sbin/cryptsetup luksDump $slavedev &>/dev/null && echo $slavedev && exit 0 + set -e + slave=$(find /sys/class/block/$(basename $slavedev)/slaves -type l | head -n1) + slavedev=$(find /dev -name "$(basename $slave)" | head -n1) + set +e +done + +exit 1 +EOF + +# needs bash here because Ubuntu's sh (dash) doesn't support `-o pipefail` option +luksdev=$(bash /tmp/rootdir-luks-device.sh) + +if [[ -n "$luksdev" ]]; then + echo "LUKS device found for '/': $luksdev" + +<% if @host.operatingsystem.family == 'Redhat' -%> + $PKG_MANAGER_INSTALL <%= packages_redhat %> +<% elsif @host.operatingsystem.name == 'Ubuntu' -%> + $PKG_MANAGER_INSTALL <%= packages_ubuntu %> +<% end -%> + +<% for tang_server in tang_server_list -%> + echo '<%= passphrase %>' | clevis luks bind -y -k - -d $luksdev tang '{"url": "<%= tang_server %>"}' + if [[ $? -ne 0 ]]; then + echo "---" + echo "There was an error during Clevis LUKS bind of '$luksdev' to Tang server '<%= tang_server %>'." + echo "System halted." + sleep infinity + fi +<% end -%> + echo '<%= passphrase %>' | cryptsetup luksRemoveKey $luksdev + systemctl enable clevis-luks-askpass.path + systemctl enable remote-cryptsetup.target + +<% if @host.operatingsystem.family == 'Redhat' -%> + dracut --verbose --force --hostonly-cmdline --regenerate-all +<% elsif @host.operatingsystem.name == 'Ubuntu' -%> + update-initramfs -u -k 'all' +<% end -%> + +else + echo "No LUKS device found!" +fi + +<% end -%> diff --git a/app/views/unattended/provisioning_templates/snippet/preseed_autoinstall_clevis_tang_wrapper.erb b/app/views/unattended/provisioning_templates/snippet/preseed_autoinstall_clevis_tang_wrapper.erb new file mode 100644 index 00000000000..a3ef18da895 --- /dev/null +++ b/app/views/unattended/provisioning_templates/snippet/preseed_autoinstall_clevis_tang_wrapper.erb @@ -0,0 +1,18 @@ +<%# +kind: snippet +name: preseed_autoinstall_clevis_tang_wrapper +model: ProvisioningTemplate +snippet: true +description: | + Wrapper snippet to set up Clevis/Tang disk encryption. + Requires Ubuntu >= 22.04.3. + The snippet is automatically indented by 2 spaces. For reference: + https://ubuntu.com/server/docs/install/autoinstall-reference +%> +- | + cat > /target/tmp/disk_enc_clevis_tang.sh <<"WRAPPER" + #!/bin/sh +<%= indent(2) { snippet 'disk_enc_clevis_tang' } %> + WRAPPER +- curtin in-target -- bash /tmp/disk_enc_clevis_tang.sh +- curtin in-target -- rm /tmp/disk_enc_clevis_tang.sh diff --git a/app/views/unattended/provisioning_templates/user_data/preseed_autoinstall_cloud_init.erb b/app/views/unattended/provisioning_templates/user_data/preseed_autoinstall_cloud_init.erb index 40a55d54dca..8e82c737fe3 100644 --- a/app/views/unattended/provisioning_templates/user_data/preseed_autoinstall_cloud_init.erb +++ b/app/views/unattended/provisioning_templates/user_data/preseed_autoinstall_cloud_init.erb @@ -24,6 +24,8 @@ username_to_create = host_param('username_to_create', 'root') realname_to_create = host_param('realname_to_create') || username_to_create password_to_create = host_param('password_to_create') || @host.root_pass enable_auto_update = (host_param_true?('package_upgrade') && !host_param('kt_activation_keys')) +os_major = @host.operatingsystem.major.to_i +os_minor = @host.operatingsystem.minor.to_i -%> #cloud-config autoinstall: @@ -67,9 +69,10 @@ autoinstall: allow-pw: true install-server: true updates: security -<%= indent(2) { @host.diskLayout } -%> +<%= indent(2) { @host.diskLayout } %> <%= indent(2) { snippet_if_exists(template_name + " custom root") } -%> late-commands: +<%= indent(2) { snippet 'preseed_autoinstall_clevis_tang_wrapper' if host_param('disk_enc_tang_servers') && os_major >= 22 && os_minor >= 3 } %> - wget -Y off <%= @static ? "'#{foreman_url('finish', static: 'true')}'" : foreman_url('finish') %> -O /target/tmp/finish.sh - curtin in-target -- chmod +x /tmp/finish.sh - curtin in-target -- /tmp/finish.sh diff --git a/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/user_data/Preseed_Autoinstall_cloud-init_user_data.ubuntu_autoinst4dhcp.snap.txt b/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/user_data/Preseed_Autoinstall_cloud-init_user_data.ubuntu_autoinst4dhcp.snap.txt index 0b1c9572c02..7425507a9be 100644 --- a/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/user_data/Preseed_Autoinstall_cloud-init_user_data.ubuntu_autoinst4dhcp.snap.txt +++ b/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/user_data/Preseed_Autoinstall_cloud-init_user_data.ubuntu_autoinst4dhcp.snap.txt @@ -31,7 +31,9 @@ autoinstall: storage: layout: name: lvm + late-commands: + - wget -Y off http://foreman.example.com/unattended/finish -O /target/tmp/finish.sh - curtin in-target -- chmod +x /tmp/finish.sh - curtin in-target -- /tmp/finish.sh