LUKS enrollment and RHEL cmdline/BLS

This commit is contained in:
2025-12-26 22:09:08 +01:00
parent efad1b9a67
commit 72ec492a33
4 changed files with 674 additions and 0 deletions

View File

@@ -0,0 +1,110 @@
---
- name: Configure LUKS keyfile auto-decrypt
block:
- name: Ensure cryptsetup key directory exists
ansible.builtin.file:
path: /mnt/etc/cryptsetup-keys.d
state: directory
owner: root
group: root
mode: "0700"
- name: Ensure LUKS keyfile exists
ansible.builtin.copy:
dest: /mnt{{ configuration_luks_keyfile_path }}
content: >-
{{
lookup(
'community.general.random_string',
length=(partitioning_luks_keyfile_size | default(luks_keyfile_size | default(64)) | int),
override_all='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
)
}}
owner: root
group: root
mode: "0600"
force: false
register: configuration_luks_keyfile_copy
no_log: true
- name: Ensure keyfile permissions
ansible.builtin.file:
path: /mnt{{ configuration_luks_keyfile_path }}
owner: root
group: root
mode: "0600"
- name: Check whether keyfile already unlocks the LUKS device
ansible.builtin.command:
argv:
- cryptsetup
- luksOpen
- --test-passphrase
- --key-file
- "/mnt{{ configuration_luks_keyfile_path }}"
- "{{ configuration_luks_device }}"
register: configuration_luks_keyfile_unlock_test
changed_when: false
failed_when: false
no_log: true
- name: Add keyfile to LUKS header
when: configuration_luks_keyfile_unlock_test.rc != 0
community.crypto.luks_device:
device: "{{ configuration_luks_device }}"
passphrase: "{{ configuration_luks_passphrase_effective }}"
new_keyfile: "/mnt{{ configuration_luks_keyfile_path }}"
register: configuration_luks_addkey_result
failed_when: false
no_log: true
- name: Regenerate keyfile and retry adding to LUKS header
when:
- configuration_luks_keyfile_unlock_test.rc != 0
- configuration_luks_keyfile_copy.changed | default(false) | bool
- configuration_luks_addkey_result is failed
block:
- name: Regenerate LUKS keyfile
ansible.builtin.copy:
dest: /mnt{{ configuration_luks_keyfile_path }}
content: >-
{{
lookup(
'community.general.random_string',
length=(partitioning_luks_keyfile_size | default(luks_keyfile_size | default(64)) | int),
override_all='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
)
}}
owner: root
group: root
mode: "0600"
force: true
no_log: true
- name: Retry adding keyfile to LUKS header
community.crypto.luks_device:
device: "{{ configuration_luks_device }}"
passphrase: "{{ configuration_luks_passphrase_effective }}"
new_keyfile: "/mnt{{ configuration_luks_keyfile_path }}"
register: configuration_luks_addkey_retry
failed_when: false
no_log: true
- name: Re-check whether keyfile unlocks the LUKS device
ansible.builtin.command:
argv:
- cryptsetup
- luksOpen
- --test-passphrase
- --key-file
- "/mnt{{ configuration_luks_keyfile_path }}"
- "{{ configuration_luks_device }}"
register: configuration_luks_keyfile_unlock_test_after
changed_when: false
failed_when: false
no_log: true
- name: Fallback to manual LUKS unlock if keyfile enrollment failed
when: (configuration_luks_keyfile_unlock_test_after.rc | default(1)) != 0
ansible.builtin.set_fact:
configuration_luks_auto_method: manual

View File

@@ -0,0 +1,90 @@
---
- name: Enroll TPM2 for LUKS
block:
- name: Create temporary passphrase file for TPM2 enrollment
ansible.builtin.tempfile:
path: /mnt/tmp
prefix: luks-passphrase-
state: file
register: configuration_luks_tpm2_passphrase_tempfile
- name: Write passphrase into temporary file for TPM2 enrollment
ansible.builtin.copy:
dest: "{{ configuration_luks_tpm2_passphrase_tempfile.path }}"
content: "{{ configuration_luks_passphrase_effective }}"
owner: root
group: root
mode: "0600"
no_log: true
- name: Enroll TPM2 token
vars:
configuration_luks_enroll_args: >-
{{
[
'/usr/bin/systemd-cryptenroll',
'--tpm2-device=' + configuration_luks_tpm2_device,
'--tpm2-with-pin=false',
'--wipe-slot=tpm2',
'--unlock-key-file=' + (
configuration_luks_tpm2_passphrase_tempfile.path
| regex_replace('^/mnt', '')
)
]
+ (['--tpm2-pcrs=' + configuration_luks_tpm2_pcrs_effective]
if configuration_luks_tpm2_pcrs_effective | length > 0 else [])
+ [configuration_luks_device]
}}
configuration_luks_enroll_chroot_args: "{{ ['arch-chroot', '/mnt'] + configuration_luks_enroll_args }}"
ansible.builtin.command:
argv: "{{ configuration_luks_enroll_chroot_args }}"
register: configuration_luks_tpm2_enroll_chroot
changed_when: configuration_luks_tpm2_enroll_chroot.rc == 0
failed_when: false
- name: Retry TPM2 enrollment in installer environment
when:
- (configuration_luks_tpm2_enroll_chroot.rc | default(1)) != 0
vars:
configuration_luks_enroll_args: >-
{{
[
'/usr/bin/systemd-cryptenroll',
'--tpm2-device=' + configuration_luks_tpm2_device,
'--tpm2-with-pin=false',
'--wipe-slot=tpm2',
'--unlock-key-file=' + configuration_luks_tpm2_passphrase_tempfile.path
]
+ (['--tpm2-pcrs=' + configuration_luks_tpm2_pcrs_effective]
if configuration_luks_tpm2_pcrs_effective | length > 0 else [])
+ [configuration_luks_device]
}}
ansible.builtin.command:
argv: "{{ configuration_luks_enroll_args }}"
register: configuration_luks_tpm2_enroll_host
changed_when: configuration_luks_tpm2_enroll_host.rc == 0
failed_when: false
- name: Validate TPM2 enrollment succeeded
ansible.builtin.assert:
that:
- >-
(configuration_luks_tpm2_enroll_chroot.rc | default(1)) == 0
or (configuration_luks_tpm2_enroll_host.rc | default(1)) == 0
fail_msg: >-
TPM2 enrollment failed.
chroot rc={{ configuration_luks_tpm2_enroll_chroot.rc | default('n/a') }},
host rc={{ configuration_luks_tpm2_enroll_host.rc | default('n/a') }},
chroot stderr={{ configuration_luks_tpm2_enroll_chroot.stderr | default('') }},
host stderr={{ configuration_luks_tpm2_enroll_host.stderr | default('') }}
rescue:
- name: Fallback to keyfile auto-decrypt
ansible.builtin.set_fact:
configuration_luks_auto_method: keyfile
always:
- name: Remove TPM2 enrollment passphrase file
when: configuration_luks_tpm2_passphrase_tempfile.path is defined
ansible.builtin.file:
path: "{{ configuration_luks_tpm2_passphrase_tempfile.path }}"
state: absent
changed_when: false