fix: encryption, partitioning, cis and virtualization hardening
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
# User-facing API: override via top-level `cis` dict in inventory.
|
# User-facing API: override via top-level `cis` dict in inventory.
|
||||||
# Merged with these defaults in _normalize.yml → cis_cfg.
|
# Merged with these defaults in _normalize.yml -> cis_cfg.
|
||||||
cis_defaults:
|
cis_defaults:
|
||||||
modules_blacklist:
|
modules_blacklist:
|
||||||
- freevxfs
|
- freevxfs
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
- name: Disable Kernel Modules
|
- name: Disable Kernel Modules
|
||||||
vars:
|
vars:
|
||||||
# Ubuntu uses squashfs for snap packages — blacklisting it breaks snap entirely
|
# Ubuntu uses squashfs for snap packages - blacklisting it breaks snap entirely
|
||||||
cis_modules_squashfs: "{{ [] if os in ['ubuntu', 'ubuntu-lts'] else ['squashfs'] }}"
|
cis_modules_squashfs: "{{ [] if os in ['ubuntu', 'ubuntu-lts'] else ['squashfs'] }}"
|
||||||
cis_modules_all: "{{ cis_cfg.modules_blacklist + cis_modules_squashfs }}"
|
cis_modules_all: "{{ cis_cfg.modules_blacklist + cis_modules_squashfs }}"
|
||||||
ansible.builtin.copy:
|
ansible.builtin.copy:
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
---
|
---
|
||||||
# Network configuration dispatch — maps OS name to the task file
|
# Network configuration dispatch - maps OS name to the task file
|
||||||
# that writes network config. Default (NetworkManager) applies to
|
# that writes network config. Default (NetworkManager) applies to
|
||||||
# all OSes not explicitly listed.
|
# all OSes not explicitly listed.
|
||||||
configuration_network_task_map:
|
configuration_network_task_map: {}
|
||||||
alpine: network_alpine.yml
|
|
||||||
void: network_void.yml
|
|
||||||
|
|||||||
@@ -16,9 +16,9 @@
|
|||||||
RedHat: >-
|
RedHat: >-
|
||||||
{{ chroot_command }} dnf install -y
|
{{ chroot_command }} dnf install -y
|
||||||
clevis clevis-luks clevis-systemd tpm2-tools
|
clevis clevis-luks clevis-systemd tpm2-tools
|
||||||
Suse: >-
|
Archlinux: >-
|
||||||
{{ chroot_command }} zypper install -y
|
{{ chroot_command }} pacman -S --noconfirm --needed
|
||||||
clevis clevis-systemd tpm2.0-tools
|
clevis tpm2-tools
|
||||||
ansible.builtin.command: "{{ _clevis_install_cmd[os_family] }}"
|
ansible.builtin.command: "{{ _clevis_install_cmd[os_family] }}"
|
||||||
register: _clevis_install_result
|
register: _clevis_install_result
|
||||||
changed_when: _clevis_install_result.rc == 0
|
changed_when: _clevis_install_result.rc == 0
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
# Sets _initramfs_generator and _tpm2_method facts.
|
# Sets _initramfs_generator and _tpm2_method facts.
|
||||||
#
|
#
|
||||||
# Generator detection: derived from the platform's initramfs_cmd
|
# Generator detection: derived from the platform's initramfs_cmd
|
||||||
# (dracut → dracut, mkinitcpio → mkinitcpio, else → initramfs-tools)
|
# (dracut -> dracut, mkinitcpio -> mkinitcpio, else -> initramfs-tools)
|
||||||
# TPM2 method: systemd-cryptenroll when generator supports tpm2-device,
|
# TPM2 method: systemd-cryptenroll when generator supports tpm2-device,
|
||||||
# clevis fallback otherwise. Non-native dracut installed automatically.
|
# clevis fallback otherwise. Non-native dracut installed automatically.
|
||||||
|
|
||||||
|
|||||||
@@ -107,7 +107,7 @@
|
|||||||
when: (configuration_luks_keyfile_unlock_test_after.rc | default(1)) != 0
|
when: (configuration_luks_keyfile_unlock_test_after.rc | default(1)) != 0
|
||||||
ansible.builtin.debug:
|
ansible.builtin.debug:
|
||||||
msg: >-
|
msg: >-
|
||||||
LUKS keyfile enrollment failed — falling back to manual unlock at boot.
|
LUKS keyfile enrollment failed - falling back to manual unlock at boot.
|
||||||
The system will prompt for the LUKS passphrase during startup.
|
The system will prompt for the LUKS passphrase during startup.
|
||||||
|
|
||||||
- name: Fallback to manual LUKS unlock if keyfile enrollment failed
|
- name: Fallback to manual LUKS unlock if keyfile enrollment failed
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
# TPM2 enrollment via systemd-cryptenroll.
|
# TPM2 enrollment via systemd-cryptenroll.
|
||||||
# Works with dracut and mkinitcpio (sd-encrypt). The user-set passphrase
|
# Works with dracut and mkinitcpio (sd-encrypt). The user-set passphrase
|
||||||
# remains as a backup unlock method — no auto-generated keyfiles.
|
# remains as a backup unlock method - no auto-generated keyfiles.
|
||||||
- name: Enroll TPM2 for LUKS
|
- name: Enroll TPM2 for LUKS
|
||||||
block:
|
block:
|
||||||
- name: Create temporary passphrase file for TPM2 enrollment
|
- name: Create temporary passphrase file for TPM2 enrollment
|
||||||
|
|||||||
@@ -30,7 +30,6 @@
|
|||||||
- name: Create zram config
|
- name: Create zram config
|
||||||
when:
|
when:
|
||||||
- (os != "debian" or (os_version | string) != "11") and os != "rhel"
|
- (os != "debian" or (os_version | string) != "11") and os != "rhel"
|
||||||
- os not in ["alpine", "void"]
|
|
||||||
- system_cfg.features.swap.enabled | bool
|
- system_cfg.features.swap.enabled | bool
|
||||||
ansible.builtin.copy:
|
ansible.builtin.copy:
|
||||||
dest: /mnt/etc/systemd/zram-generator.conf
|
dest: /mnt/etc/systemd/zram-generator.conf
|
||||||
|
|||||||
@@ -15,7 +15,8 @@
|
|||||||
validate: /usr/sbin/visudo --check --file=%s
|
validate: /usr/sbin/visudo --check --file=%s
|
||||||
|
|
||||||
- name: Deploy per-user sudoers rules
|
- name: Deploy per-user sudoers rules
|
||||||
when: item.value.sudo is defined and (item.value.sudo | string | length > 0)
|
# Jinja truthiness: bool true / a rule string => deploy; false / '' / unset => skip.
|
||||||
|
when: item.value.sudo | default(false)
|
||||||
vars:
|
vars:
|
||||||
configuration_sudoers_rule: >-
|
configuration_sudoers_rule: >-
|
||||||
{{ item.value.sudo if item.value.sudo is string else 'ALL=(ALL) NOPASSWD: ALL' }}
|
{{ item.value.sudo if item.value.sudo is string else 'ALL=(ALL) NOPASSWD: ALL' }}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
partitioning_btrfs_compress_opt: "{{ 'compress=zstd:15' if system_cfg.features.zstd.enabled | bool else '' }}"
|
partitioning_btrfs_compress_opt: "{{ 'compress=zstd:15' if system_cfg.features.zstd.enabled | bool else '' }}"
|
||||||
# Partition separator: 'p' for NVMe/mmcblk (device path ends in digit), empty for SCSI/virtio.
|
# Partition separator: 'p' for NVMe/mmcblk (device path ends in digit), empty for SCSI/virtio.
|
||||||
# Examples: /dev/sda → /dev/sda1, /dev/nvme0n1 → /dev/nvme0n1p1
|
# Examples: /dev/sda -> /dev/sda1, /dev/nvme0n1 -> /dev/nvme0n1p1
|
||||||
partitioning_part_sep: "{{ 'p' if (install_drive | default('') | regex_search('\\d$')) else '' }}"
|
partitioning_part_sep: "{{ 'p' if (install_drive | default('') | regex_search('\\d$')) else '' }}"
|
||||||
partitioning_boot_partition_suffix: 1
|
partitioning_boot_partition_suffix: 1
|
||||||
partitioning_main_partition_suffix: 2
|
partitioning_main_partition_suffix: 2
|
||||||
|
|||||||
@@ -4,14 +4,14 @@
|
|||||||
# Sizes are computed from disk_size_gb, memory_mb, and feature flags.
|
# Sizes are computed from disk_size_gb, memory_mb, and feature flags.
|
||||||
#
|
#
|
||||||
# Swap sizing:
|
# Swap sizing:
|
||||||
# - RAM >= 16 GB → swap = RAM/2 (in GB)
|
# - RAM >= 16 GB -> swap = RAM/2 (in GB)
|
||||||
# - RAM < 16 GB → swap = max(RAM_GB, 2)
|
# - RAM < 16 GB -> swap = max(RAM_GB, 2)
|
||||||
# - Capped to: min(target, 4 + max(disk - overhead, 0))
|
# - Capped to: min(target, 4 + max(disk - overhead, 0))
|
||||||
# - Further capped to: max available after subtracting reserved + CIS + extent reserve + 4 GB buffer
|
# - Further capped to: max available after subtracting reserved + CIS + extent reserve + 4 GB buffer
|
||||||
#
|
#
|
||||||
# Root sizing:
|
# Root sizing:
|
||||||
# - Full-disk mode (default): disk - reserved - swap - extent_reserve - (CIS volumes if enabled)
|
# - Full-disk mode (default): disk - reserved - swap - extent_reserve - (CIS volumes if enabled)
|
||||||
# - Partial mode: tiered — <4 GB available → 4 GB, 4-12 GB → all available, >12 GB → 40% of disk
|
# - Partial mode: tiered - <4 GB available -> 4 GB, 4-12 GB -> all available, >12 GB -> 40% of disk
|
||||||
#
|
#
|
||||||
# CIS volumes (only when CIS enabled):
|
# CIS volumes (only when CIS enabled):
|
||||||
# - /home: max(min(home_raw, home_max), home_min) where home_raw = (disk - overhead) * 10%
|
# - /home: max(min(home_raw, home_max), home_min) where home_raw = (disk - overhead) * 10%
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
---
|
---
|
||||||
# Cloud-init support matrix:
|
# Cloud-init support matrix:
|
||||||
# libvirt — cloud-init ISO attached as CDROM (user-data + network-config)
|
# libvirt - cloud-init ISO attached as CDROM (user-data + network-config)
|
||||||
# proxmox — cloud-init via Proxmox API (cicustom, ciuser, cipassword, etc.)
|
# proxmox - cloud-init via Proxmox API (cicustom, ciuser, cipassword, etc.)
|
||||||
# vmware — no cloud-init; configuration is applied post-install via chroot
|
# vmware - no cloud-init; configuration is applied post-install via chroot
|
||||||
# xen — no cloud-init; configuration is applied post-install via chroot
|
# xen - no cloud-init; configuration is applied post-install via chroot
|
||||||
virtualization_libvirt_image_dir: >-
|
virtualization_libvirt_image_dir: >-
|
||||||
{{
|
{{
|
||||||
system_cfg.path
|
system_cfg.path
|
||||||
@@ -17,8 +17,18 @@ virtualization_libvirt_cloudinit_path: >-
|
|||||||
virtualization_xen_disk_path: /var/lib/xen/images
|
virtualization_xen_disk_path: /var/lib/xen/images
|
||||||
|
|
||||||
virtualization_libvirt_machine_type: q35
|
virtualization_libvirt_machine_type: q35
|
||||||
virtualization_libvirt_ovmf_code: /usr/share/edk2/x64/OVMF_CODE.secboot.4m.fd
|
# Secboot OVMF firmware candidates, ordered Arch, Debian/Ubuntu, Fedora/RHEL.
|
||||||
virtualization_libvirt_ovmf_vars: /usr/share/edk2/x64/OVMF_VARS.4m.fd
|
# libvirt.yml resolves these to the first file present on the controller.
|
||||||
|
virtualization_libvirt_ovmf_code_candidates:
|
||||||
|
- /usr/share/edk2/x64/OVMF_CODE.secboot.4m.fd
|
||||||
|
- /usr/share/OVMF/OVMF_CODE_4M.secboot.fd
|
||||||
|
- /usr/share/edk2/ovmf/OVMF_CODE.secboot.fd
|
||||||
|
- /usr/share/OVMF/OVMF_CODE.secboot.fd
|
||||||
|
virtualization_libvirt_ovmf_vars_candidates:
|
||||||
|
- /usr/share/edk2/x64/OVMF_VARS.4m.fd
|
||||||
|
- /usr/share/OVMF/OVMF_VARS_4M.fd
|
||||||
|
- /usr/share/edk2/ovmf/OVMF_VARS.fd
|
||||||
|
- /usr/share/OVMF/OVMF_VARS.fd
|
||||||
|
|
||||||
virtualization_tpm2_enabled: >-
|
virtualization_tpm2_enabled: >-
|
||||||
{{
|
{{
|
||||||
|
|||||||
@@ -70,6 +70,19 @@
|
|||||||
- /tmp/cloud-user-data-{{ hostname }}.yml
|
- /tmp/cloud-user-data-{{ hostname }}.yml
|
||||||
- /tmp/cloud-network-config-{{ hostname }}.yml
|
- /tmp/cloud-network-config-{{ hostname }}.yml
|
||||||
|
|
||||||
|
# Resolve OVMF firmware to the first candidate present on the controller
|
||||||
|
# unless the user pinned an explicit path. first_found needs the localhost
|
||||||
|
# delegation since the candidates live on the libvirt host, not the target.
|
||||||
|
- name: Resolve OVMF firmware paths
|
||||||
|
delegate_to: localhost
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
virtualization_libvirt_ovmf_code: >-
|
||||||
|
{{ virtualization_libvirt_ovmf_code if virtualization_libvirt_ovmf_code | default('', true) | length > 0
|
||||||
|
else lookup('ansible.builtin.first_found', virtualization_libvirt_ovmf_code_candidates) }}
|
||||||
|
virtualization_libvirt_ovmf_vars: >-
|
||||||
|
{{ virtualization_libvirt_ovmf_vars if virtualization_libvirt_ovmf_vars | default('', true) | length > 0
|
||||||
|
else lookup('ansible.builtin.first_found', virtualization_libvirt_ovmf_vars_candidates) }}
|
||||||
|
|
||||||
# uri defaults to qemu:///system (local libvirtd)
|
# uri defaults to qemu:///system (local libvirtd)
|
||||||
- name: Create VM using libvirt
|
- name: Create VM using libvirt
|
||||||
delegate_to: localhost
|
delegate_to: localhost
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
esxi_hostname: "{{ hypervisor_cfg.node if (hypervisor_cfg.node | default('') | length > 0) else omit }}"
|
esxi_hostname: "{{ hypervisor_cfg.node if (hypervisor_cfg.node | default('') | length > 0) else omit }}"
|
||||||
folder: "{{ system_cfg.path if system_cfg.path | string | length > 0 else omit }}"
|
folder: "{{ system_cfg.path if system_cfg.path | string | length > 0 else omit }}"
|
||||||
name: "{{ hostname }}"
|
name: "{{ hostname }}"
|
||||||
# Generic guest ID — VMware auto-detects OS post-install
|
# Generic guest ID - VMware auto-detects OS post-install
|
||||||
guest_id: otherLinux64Guest
|
guest_id: otherLinux64Guest
|
||||||
annotation: |
|
annotation: |
|
||||||
{{ note if note is defined else '' }}
|
{{ note if note is defined else '' }}
|
||||||
|
|||||||
Reference in New Issue
Block a user