Files
Ansible-Bootstrap/roles/configuration/tasks/encryption.yml

345 lines
12 KiB
YAML

---
- name: Configure disk encryption
when: system_cfg.luks.enabled | bool
vars:
configuration_luks_passphrase: >-
{{ system_cfg.luks.passphrase | string }}
block:
- name: Set LUKS configuration facts
vars:
luks_tpm2_pcrs: >-
{{
(
system_cfg.luks.tpm2.pcrs
if system_cfg.luks.tpm2.pcrs is string
else (system_cfg.luks.tpm2.pcrs | map('string') | join('+'))
)
| string
| replace(',', '+')
| regex_replace('\\s+', '')
| regex_replace('^\\+|\\+$', '')
}}
ansible.builtin.set_fact:
configuration_luks_mapper_name: "{{ system_cfg.luks.mapper }}"
configuration_luks_uuid: "{{ partitioning_luks_uuid | default('') }}"
configuration_luks_device: "{{ partitioning_luks_device }}"
configuration_luks_options: "{{ system_cfg.luks.options }}"
configuration_luks_auto_method: >-
{{
(system_cfg.luks.auto | bool)
| ternary(
system_cfg.luks.method,
'manual'
)
}}
configuration_luks_tpm2_device: "{{ system_cfg.luks.tpm2.device }}"
configuration_luks_tpm2_pcrs: "{{ luks_tpm2_pcrs }}"
configuration_luks_keyfile_path: "/etc/cryptsetup-keys.d/{{ system_cfg.luks.mapper }}.key"
changed_when: false
- name: Validate LUKS UUID is available
ansible.builtin.assert:
that:
- configuration_luks_uuid | length > 0
fail_msg: LUKS UUID not available. Ensure partitioning ran before configuration.
- name: Validate LUKS passphrase for auto-decrypt
when: configuration_luks_auto_method in ['tpm2', 'keyfile']
ansible.builtin.assert:
that:
- configuration_luks_passphrase | length > 0
fail_msg: system.luks.passphrase must be set for LUKS auto-decrypt.
no_log: true
- name: Enroll TPM2 for LUKS
when: configuration_luks_auto_method == 'tpm2'
ansible.builtin.include_tasks: encryption/tpm2.yml
- name: Configure LUKS keyfile auto-decrypt
when: configuration_luks_auto_method == 'keyfile'
ansible.builtin.include_tasks: encryption/keyfile.yml
- name: Build LUKS parameters
vars:
luks_keyfile_in_use: "{{ configuration_luks_auto_method == 'keyfile' }}"
luks_option_list: >-
{{
(configuration_luks_options | trim).split(',')
if configuration_luks_options | trim | length > 0
else []
}}
luks_tpm2_option_list: >-
{{
(configuration_luks_auto_method == 'tpm2')
| ternary(
['tpm2-device=' + configuration_luks_tpm2_device]
+ (['tpm2-pcrs=' + configuration_luks_tpm2_pcrs]
if configuration_luks_tpm2_pcrs | length > 0 else []),
[]
)
}}
luks_crypttab_keyfile: "{{ configuration_luks_keyfile_path if luks_keyfile_in_use else 'none' }}"
luks_crypttab_options: >-
{{
(['luks'] + luks_option_list + luks_tpm2_option_list)
| join(',')
}}
luks_rd_options: "{{ (luks_option_list + luks_tpm2_option_list) | join(',') }}"
luks_kernel_args: >-
{{
(
['rd.luks.name=' + configuration_luks_uuid + '=' + configuration_luks_mapper_name]
+ (
['rd.luks.options=' + configuration_luks_uuid + '=' + luks_rd_options]
if luks_rd_options | length > 0 else []
)
+ (
['rd.luks.key=' + configuration_luks_uuid + '=' + configuration_luks_keyfile_path]
if luks_keyfile_in_use else []
)
) | join(' ')
}}
ansible.builtin.set_fact:
configuration_luks_keyfile_in_use: "{{ luks_keyfile_in_use }}"
configuration_luks_option_list: "{{ luks_option_list }}"
configuration_luks_tpm2_option_list: "{{ luks_tpm2_option_list }}"
configuration_luks_crypttab_keyfile: "{{ luks_crypttab_keyfile }}"
configuration_luks_crypttab_options: "{{ luks_crypttab_options }}"
configuration_luks_rd_options: "{{ luks_rd_options }}"
configuration_luks_kernel_args: "{{ luks_kernel_args }}"
- name: Remove LUKS keyfile if TPM2 auto-decrypt is active
when: configuration_luks_auto_method == 'tpm2'
ansible.builtin.file:
path: /mnt{{ configuration_luks_keyfile_path }}
state: absent
- name: Write crypttab entry
ansible.builtin.lineinfile:
path: /mnt/etc/crypttab
regexp: "^{{ configuration_luks_mapper_name }}\\s"
line: >-
{{ configuration_luks_mapper_name }} UUID={{ configuration_luks_uuid }}
{{ configuration_luks_crypttab_keyfile }} {{ configuration_luks_crypttab_options }}
create: true
mode: "0600"
- name: Ensure keyfile pattern for initramfs-tools
when:
- is_debian | bool
- configuration_luks_keyfile_in_use
ansible.builtin.lineinfile:
path: /mnt/etc/cryptsetup-initramfs/conf-hook
regexp: "^KEYFILE_PATTERN="
line: "KEYFILE_PATTERN=/etc/cryptsetup-keys.d/*.key"
create: true
mode: "0644"
- name: Configure mkinitcpio hooks for LUKS
when: os == 'archlinux'
ansible.builtin.lineinfile:
path: /mnt/etc/mkinitcpio.conf
regexp: "^HOOKS="
line: >-
HOOKS=(base systemd autodetect microcode modconf kms keyboard sd-vconsole
block sd-encrypt{{ ' lvm2' if system_cfg.filesystem != 'btrfs' else '' }} filesystems fsck)
- name: Read mkinitcpio configuration
when: os == 'archlinux'
ansible.builtin.slurp:
src: /mnt/etc/mkinitcpio.conf
register: configuration_mkinitcpio_slurp
- name: Build mkinitcpio FILES list
when: os == 'archlinux'
vars:
mkinitcpio_files_list: >-
{{
(
configuration_mkinitcpio_slurp.content | b64decode
| regex_findall('^FILES=\\(([^)]*)\\)', multiline=True)
| default([])
| first
| default('')
).split()
}}
mkinitcpio_files_list_new: >-
{{
(
(mkinitcpio_files_list + [configuration_luks_keyfile_path])
if configuration_luks_keyfile_in_use
else (
mkinitcpio_files_list
| reject('equalto', configuration_luks_keyfile_path)
| list
)
)
| unique
}}
ansible.builtin.set_fact:
configuration_mkinitcpio_files_list_new: "{{ mkinitcpio_files_list_new }}"
- name: Configure mkinitcpio FILES list
when: os == 'archlinux'
ansible.builtin.lineinfile:
path: /mnt/etc/mkinitcpio.conf
regexp: "^FILES="
line: >-
FILES=({{
configuration_mkinitcpio_files_list_new | join(' ')
}})
- name: Ensure dracut config directory exists
when: is_rhel | bool
ansible.builtin.file:
path: /mnt/etc/dracut.conf.d
state: directory
mode: "0755"
- name: Configure dracut for LUKS
when: is_rhel | bool
ansible.builtin.copy:
dest: /mnt/etc/dracut.conf.d/crypt.conf
content: |
add_dracutmodules+=" crypt "
{% if configuration_luks_keyfile_in_use %}
install_items+=" {{ configuration_luks_keyfile_path }} "
{% endif %}
mode: "0644"
- name: Read kernel cmdline defaults
when: is_rhel | bool
ansible.builtin.slurp:
src: /mnt/etc/kernel/cmdline
register: configuration_kernel_cmdline_slurp
- name: Build kernel cmdline with LUKS args
when: is_rhel | bool
vars:
kernel_cmdline_current: >-
{{ configuration_kernel_cmdline_slurp.content | b64decode | trim }}
kernel_cmdline_list: >-
{{
kernel_cmdline_current.split()
if kernel_cmdline_current | length > 0 else []
}}
kernel_cmdline_filtered: >-
{{
kernel_cmdline_list
| reject('match', '^rd\\.luks\\.(name|options|key)=' ~ configuration_luks_uuid ~ '=')
| list
}}
kernel_cmdline_new: >-
{{
(kernel_cmdline_filtered + configuration_luks_kernel_args.split())
| unique
| join(' ')
}}
ansible.builtin.set_fact:
configuration_kernel_cmdline_new: "{{ kernel_cmdline_new }}"
changed_when: false
- name: Write kernel cmdline with LUKS args
when: is_rhel | bool
ansible.builtin.copy:
dest: /mnt/etc/kernel/cmdline
mode: "0644"
content: "{{ configuration_kernel_cmdline_new }}\n"
- name: Find BLS entries
when: is_rhel | bool
ansible.builtin.find:
paths: /mnt/boot/loader/entries
patterns: "*.conf"
register: configuration_kernel_bls_entries
changed_when: false
- name: Update BLS options with LUKS args
when:
- is_rhel | bool
- configuration_kernel_bls_entries.files | length > 0
ansible.builtin.lineinfile:
path: "{{ item.path }}"
regexp: "^options "
line: "options {{ configuration_kernel_cmdline_new }}"
loop: "{{ configuration_kernel_bls_entries.files }}"
loop_control:
label: "{{ item.path }}"
- name: Read grub defaults
when: not is_rhel | bool
ansible.builtin.slurp:
src: /mnt/etc/default/grub
register: configuration_grub_slurp
- name: Build grub command lines with LUKS args
when: not is_rhel | bool
vars:
grub_content: "{{ configuration_grub_slurp.content | b64decode }}"
grub_cmdline_linux: >-
{{
grub_content
| regex_findall('^GRUB_CMDLINE_LINUX=\"(.*)\"', multiline=True)
| default([])
| first
| default('')
}}
grub_cmdline_default: >-
{{
grub_content
| regex_findall('^GRUB_CMDLINE_LINUX_DEFAULT=\"(.*)\"', multiline=True)
| default([])
| first
| default('')
}}
grub_cmdline_linux_list: >-
{{
grub_cmdline_linux.split()
if grub_cmdline_linux | length > 0 else []
}}
grub_cmdline_default_list: >-
{{
grub_cmdline_default.split()
if grub_cmdline_default | length > 0 else []
}}
luks_kernel_args_list: "{{ configuration_luks_kernel_args.split() }}"
grub_cmdline_linux_new: >-
{{
(
(
grub_cmdline_linux_list
| reject('match', '^rd\\.luks\\.(name|options|key)=' ~ configuration_luks_uuid ~ '=')
| list
)
+ luks_kernel_args_list
)
| unique
| join(' ')
}}
grub_cmdline_default_new: >-
{{
(
(
grub_cmdline_default_list
| reject('match', '^rd\\.luks\\.(name|options|key)=' ~ configuration_luks_uuid ~ '=')
| list
)
+ luks_kernel_args_list
)
| unique
| join(' ')
}}
ansible.builtin.set_fact:
configuration_grub_content: "{{ grub_content }}"
configuration_grub_cmdline_linux: "{{ grub_cmdline_linux }}"
configuration_grub_cmdline_default: "{{ grub_cmdline_default }}"
configuration_grub_cmdline_linux_new: "{{ grub_cmdline_linux_new }}"
configuration_grub_cmdline_default_new: "{{ grub_cmdline_default_new }}"
- name: Update GRUB_CMDLINE_LINUX_DEFAULT for LUKS
when: not is_rhel | bool
ansible.builtin.lineinfile:
path: /mnt/etc/default/grub
regexp: "^GRUB_CMDLINE_LINUX_DEFAULT="
line: 'GRUB_CMDLINE_LINUX_DEFAULT="{{ configuration_grub_cmdline_default_new }}"'