453 lines
17 KiB
YAML
453 lines
17 KiB
YAML
---
|
|
- name: Ensure system input is a dictionary
|
|
ansible.builtin.set_fact:
|
|
system: "{{ system | default({}) }}"
|
|
changed_when: false
|
|
|
|
- name: Validate system input type
|
|
ansible.builtin.assert:
|
|
that:
|
|
- system is mapping
|
|
fail_msg: "system must be a dictionary"
|
|
quiet: true
|
|
|
|
- name: Normalize base system fields
|
|
vars:
|
|
system_type_effective: >-
|
|
{{
|
|
system.type
|
|
if system.type is defined and (system.type | string | length) > 0
|
|
else system_defaults.type
|
|
}}
|
|
system_name_effective: >-
|
|
{{
|
|
system.name
|
|
if system.name is defined and (system.name | string | length) > 0
|
|
else inventory_hostname
|
|
}}
|
|
system_os_effective: >-
|
|
{{
|
|
system.os
|
|
if system.os is defined and (system.os | string | length) > 0
|
|
else ''
|
|
}}
|
|
system_os_version_effective: >-
|
|
{{
|
|
system.os_version
|
|
if system.os_version is defined and (system.os_version | string | length) > 0
|
|
else ''
|
|
}}
|
|
system_id_effective: >-
|
|
{{
|
|
system.id
|
|
if system.id is defined and (system.id | string | length) > 0
|
|
else ''
|
|
}}
|
|
system_cpus_effective: >-
|
|
{{
|
|
system.cpus
|
|
if system.cpus is defined and (system.cpus | int) > 0
|
|
else 0
|
|
}}
|
|
system_memory_effective: >-
|
|
{{
|
|
system.memory
|
|
if system.memory is defined and (system.memory | int) > 0
|
|
else 0
|
|
}}
|
|
system_balloon_effective: >-
|
|
{{
|
|
system.balloon
|
|
if system.balloon is defined and (system.balloon | int) > 0
|
|
else 0
|
|
}}
|
|
system_network_effective: >-
|
|
{{
|
|
system.network
|
|
if system.network is defined and (system.network | string | length) > 0
|
|
else ''
|
|
}}
|
|
system_vlan_effective: >-
|
|
{{
|
|
system.vlan
|
|
if system.vlan is defined and (system.vlan | string | length) > 0
|
|
else ''
|
|
}}
|
|
system_ip_effective: >-
|
|
{{
|
|
system.ip
|
|
if system.ip is defined and (system.ip | string | length) > 0
|
|
else ''
|
|
}}
|
|
system_prefix_effective: >-
|
|
{{
|
|
system.prefix
|
|
if system.prefix is defined and (system.prefix | int) > 0
|
|
else ''
|
|
}}
|
|
system_gateway_effective: >-
|
|
{{
|
|
system.gateway
|
|
if system.gateway is defined and (system.gateway | string | length) > 0
|
|
else ''
|
|
}}
|
|
system_dns_effective: >-
|
|
{{
|
|
(system_defaults.dns | default({'servers': [], 'search': []}))
|
|
| combine((system.dns if system.dns is defined else {}), recursive=True)
|
|
}}
|
|
system_dns_resolvers_value: "{{ system_dns_effective.servers if system_dns_effective.servers is defined else [] }}"
|
|
system_dns_resolvers_list_raw: >-
|
|
{{
|
|
system_dns_resolvers_value
|
|
if system_dns_resolvers_value is iterable and system_dns_resolvers_value is not string
|
|
else (system_dns_resolvers_value | string).split(',')
|
|
}}
|
|
system_dns_resolvers_effective: >-
|
|
{{
|
|
system_dns_resolvers_list_raw
|
|
| map('trim')
|
|
| reject('equalto', '')
|
|
| list
|
|
}}
|
|
system_dns_domains_value: "{{ system_dns_effective.search if system_dns_effective.search is defined else [] }}"
|
|
system_dns_domains_list_raw: >-
|
|
{{
|
|
system_dns_domains_value
|
|
if system_dns_domains_value is iterable and system_dns_domains_value is not string
|
|
else (system_dns_domains_value | string).split(',')
|
|
}}
|
|
system_dns_domains_effective: >-
|
|
{{
|
|
system_dns_domains_list_raw
|
|
| map('trim')
|
|
| reject('equalto', '')
|
|
| list
|
|
}}
|
|
system_path_effective: >-
|
|
{{
|
|
system.path
|
|
if system.path is defined and (system.path | string | length) > 0
|
|
else ''
|
|
}}
|
|
system_user_effective: >-
|
|
{{
|
|
(system_defaults.user | default({}))
|
|
| combine(
|
|
(system.user if (system.user is defined and system.user is mapping) else {}),
|
|
recursive=True
|
|
)
|
|
}}
|
|
system_root_effective: >-
|
|
{{
|
|
(system_defaults.root | default({}))
|
|
| combine(
|
|
(system.root if (system.root is defined and system.root is mapping) else {}),
|
|
recursive=True
|
|
)
|
|
}}
|
|
system_luks_effective: >-
|
|
{{
|
|
(system_defaults.luks | default({}))
|
|
| combine(
|
|
(system.luks if (system.luks is defined and system.luks is mapping) else {}),
|
|
recursive=True
|
|
)
|
|
}}
|
|
system_features_effective: >-
|
|
{{
|
|
(system_defaults.features | default({}))
|
|
| combine(
|
|
(system.features if (system.features is defined and system.features is mapping) else {}),
|
|
recursive=True
|
|
)
|
|
}}
|
|
system_user_name_effective: "{{ (system_user_effective.name | default('') | string) }}"
|
|
system_user_password_effective: "{{ (system_user_effective.password | default('') | string) }}"
|
|
system_user_public_key_effective: "{{ (system_user_effective.public_key | default('') | string) }}"
|
|
system_root_password_effective: "{{ (system_root_effective.password | default('') | string) }}"
|
|
system_luks_passphrase_effective: "{{ (system_luks_effective.passphrase | default('') | string) }}"
|
|
system_luks_mapper_name_effective: "{{ (system_luks_effective.mapper_name | default('SYSTEM_DECRYPTED') | string) }}"
|
|
system_luks_auto_decrypt_method_effective: "{{ (system_luks_effective.auto_decrypt_method | default('tpm2') | string | lower) }}"
|
|
system_luks_tpm2_device_effective: "{{ (system_luks_effective.tpm2_device | default('auto') | string) }}"
|
|
system_luks_tpm2_pcrs_effective: "{{ (system_luks_effective.tpm2_pcrs | default('') | string) }}"
|
|
system_luks_options_effective: "{{ (system_luks_effective.options | default('discard,tries=3') | string) }}"
|
|
system_luks_type_effective: "{{ (system_luks_effective.type | default('luks2') | string) }}"
|
|
system_luks_cipher_effective: "{{ (system_luks_effective.cipher | default('aes-xts-plain64') | string) }}"
|
|
system_luks_hash_effective: "{{ (system_luks_effective.hash | default('sha512') | string) }}"
|
|
system_luks_iter_time_effective: "{{ (system_luks_effective.iter_time | default(4000) | int) }}"
|
|
system_luks_key_size_effective: "{{ (system_luks_effective.key_size | default(512) | int) }}"
|
|
system_luks_pbkdf_effective: "{{ (system_luks_effective.pbkdf | default('argon2id') | string) }}"
|
|
system_luks_keyfile_size_effective: "{{ (system_luks_effective.keyfile_size | default(64) | int) }}"
|
|
system_luks_enabled_effective: "{{ system_luks_effective.enabled | default(false) | bool }}"
|
|
system_luks_auto_decrypt_effective: "{{ system_luks_effective.auto_decrypt | default(true) | bool }}"
|
|
system_luks_use_urandom_effective: "{{ system_luks_effective.use_urandom | default(true) | bool }}"
|
|
system_luks_verify_passphrase_effective: "{{ system_luks_effective.verify_passphrase | default(true) | bool }}"
|
|
system_features_cis_enabled_effective: "{{ system_features_effective.cis.enabled | default(false) | bool }}"
|
|
system_features_selinux_enabled_effective: "{{ system_features_effective.selinux.enabled | default(true) | bool }}"
|
|
system_features_firewall_enabled_effective: "{{ system_features_effective.firewall.enabled | default(true) | bool }}"
|
|
system_features_firewall_backend_effective: "{{ (system_features_effective.firewall.backend | default('firewalld') | string | lower) }}"
|
|
system_features_firewall_toolkit_effective: "{{ (system_features_effective.firewall.toolkit | default('nftables') | string | lower) }}"
|
|
system_features_ssh_enabled_effective: "{{ system_features_effective.ssh.enabled | default(true) | bool }}"
|
|
system_features_zstd_enabled_effective: "{{ system_features_effective.zstd.enabled | default(true) | bool }}"
|
|
system_features_swap_enabled_effective: "{{ system_features_effective.swap.enabled | default(true) | bool }}"
|
|
system_features_banner_motd_effective: "{{ system_features_effective.banner.motd | default(true) | bool }}"
|
|
system_features_banner_sudo_effective: "{{ system_features_effective.banner.sudo | default(true) | bool }}"
|
|
system_features_chroot_tool_effective: "{{ (system_features_effective.chroot.tool | default('arch-chroot') | string) }}"
|
|
system_packages_value: "{{ system.packages if system.packages is defined else [] }}"
|
|
system_packages_list_raw: >-
|
|
{{
|
|
system_packages_value
|
|
if system_packages_value is iterable and system_packages_value is not string
|
|
else (system_packages_value | string).split(',')
|
|
}}
|
|
system_packages_effective: >-
|
|
{{
|
|
system_packages_list_raw
|
|
| map('trim')
|
|
| reject('equalto', '')
|
|
| list
|
|
}}
|
|
ansible.builtin.set_fact:
|
|
hostname: "{{ system_name_effective }}"
|
|
os: "{{ system_os_effective | lower }}"
|
|
os_version: "{{ system_os_version_effective | string }}"
|
|
system_cfg: >-
|
|
{{
|
|
system_defaults
|
|
| combine(system, recursive=True)
|
|
| combine(
|
|
{
|
|
'type': system_type_effective | lower,
|
|
'name': system_name_effective,
|
|
'os': system_os_effective | lower,
|
|
'os_version': system_os_version_effective | string,
|
|
'id': system_id_effective,
|
|
'cpus': system_cpus_effective,
|
|
'memory': system_memory_effective,
|
|
'balloon': system_balloon_effective,
|
|
'network': system_network_effective,
|
|
'vlan': system_vlan_effective,
|
|
'ip': system_ip_effective,
|
|
'prefix': system_prefix_effective,
|
|
'gateway': system_gateway_effective,
|
|
'dns': {
|
|
'servers': system_dns_resolvers_effective,
|
|
'search': system_dns_domains_effective
|
|
},
|
|
'path': system_path_effective,
|
|
'packages': system_packages_effective,
|
|
'user': {
|
|
'name': system_user_name_effective,
|
|
'password': system_user_password_effective,
|
|
'public_key': system_user_public_key_effective
|
|
},
|
|
'root': {
|
|
'password': system_root_password_effective
|
|
},
|
|
'luks': {
|
|
'enabled': system_luks_enabled_effective,
|
|
'passphrase': system_luks_passphrase_effective,
|
|
'mapper_name': system_luks_mapper_name_effective,
|
|
'auto_decrypt': system_luks_auto_decrypt_effective,
|
|
'auto_decrypt_method': system_luks_auto_decrypt_method_effective,
|
|
'tpm2_device': system_luks_tpm2_device_effective,
|
|
'tpm2_pcrs': system_luks_tpm2_pcrs_effective,
|
|
'keyfile_size': system_luks_keyfile_size_effective,
|
|
'options': system_luks_options_effective,
|
|
'type': system_luks_type_effective,
|
|
'cipher': system_luks_cipher_effective,
|
|
'hash': system_luks_hash_effective,
|
|
'iter_time': system_luks_iter_time_effective,
|
|
'key_size': system_luks_key_size_effective,
|
|
'pbkdf': system_luks_pbkdf_effective,
|
|
'use_urandom': system_luks_use_urandom_effective,
|
|
'verify_passphrase': system_luks_verify_passphrase_effective
|
|
},
|
|
'features': {
|
|
'cis': {
|
|
'enabled': system_features_cis_enabled_effective
|
|
},
|
|
'selinux': {
|
|
'enabled': system_features_selinux_enabled_effective
|
|
},
|
|
'firewall': {
|
|
'enabled': system_features_firewall_enabled_effective,
|
|
'backend': system_features_firewall_backend_effective,
|
|
'toolkit': system_features_firewall_toolkit_effective
|
|
},
|
|
'ssh': {
|
|
'enabled': system_features_ssh_enabled_effective
|
|
},
|
|
'zstd': {
|
|
'enabled': system_features_zstd_enabled_effective
|
|
},
|
|
'swap': {
|
|
'enabled': system_features_swap_enabled_effective
|
|
},
|
|
'banner': {
|
|
'motd': system_features_banner_motd_effective,
|
|
'sudo': system_features_banner_sudo_effective
|
|
},
|
|
'chroot': {
|
|
'tool': system_features_chroot_tool_effective
|
|
}
|
|
}
|
|
},
|
|
recursive=True
|
|
)
|
|
}}
|
|
changed_when: false
|
|
|
|
- name: Normalize system disks input
|
|
vars:
|
|
system_disk_defaults:
|
|
size: 0
|
|
device: ""
|
|
mount:
|
|
path: ""
|
|
fstype: ""
|
|
label: ""
|
|
opts: "defaults"
|
|
system_disks_raw: >-
|
|
{{
|
|
system_cfg.disks
|
|
if system_cfg.disks is defined
|
|
else []
|
|
}}
|
|
system_disks_effective: >-
|
|
{{
|
|
system_disks_raw
|
|
}}
|
|
system_disk_device_prefix: >-
|
|
{{
|
|
'/dev/vd'
|
|
if (system_cfg.type | lower) == 'virtual' and (hypervisor_type | default('')) == 'libvirt'
|
|
else (
|
|
'/dev/xvd'
|
|
if (system_cfg.type | lower) == 'virtual' and (hypervisor_type | default('')) == 'xen'
|
|
else (
|
|
'/dev/sd'
|
|
if (system_cfg.type | lower) == 'virtual'
|
|
and (hypervisor_type | default('')) in ['proxmox', 'vmware']
|
|
else ''
|
|
)
|
|
)
|
|
}}
|
|
system_disk_letter_map: "abcdefghijklmnopqrstuvwxyz"
|
|
block:
|
|
- name: Validate system disks type
|
|
ansible.builtin.assert:
|
|
that:
|
|
- system_disks_effective is sequence
|
|
fail_msg: "system.disks must be a list"
|
|
quiet: true
|
|
|
|
- name: Validate system disk items
|
|
ansible.builtin.assert:
|
|
that:
|
|
- item is mapping
|
|
fail_msg: "Each system disk entry must be a dictionary"
|
|
quiet: true
|
|
loop: "{{ system_disks_effective }}"
|
|
loop_control:
|
|
label: "{{ item | to_json }}"
|
|
|
|
- name: Validate system disk mount schema
|
|
ansible.builtin.assert:
|
|
that:
|
|
- item.mount is not defined or item.mount is mapping
|
|
fail_msg: "system.disks[].mount must be a dictionary (e.g. mount: {path: /data})."
|
|
quiet: true
|
|
loop: "{{ system_disks_effective }}"
|
|
loop_control:
|
|
label: "{{ item | to_json }}"
|
|
|
|
- name: Validate system disk count
|
|
ansible.builtin.assert:
|
|
that:
|
|
- (system_disks_effective | length) <= 26
|
|
fail_msg: "system.disks supports at most 26 entries."
|
|
quiet: true
|
|
|
|
- name: Initialize normalized disk list
|
|
ansible.builtin.set_fact:
|
|
system_disks_cfg: []
|
|
changed_when: false
|
|
|
|
- name: Build normalized system disk configuration
|
|
ansible.builtin.set_fact:
|
|
system_disks_cfg: "{{ system_disks_cfg | default([]) + [system_disk_cfg] }}"
|
|
vars:
|
|
disk_idx: "{{ ansible_loop.index0 }}"
|
|
disk_letter: "{{ system_disk_letter_map[disk_idx] }}"
|
|
disk_device_default: >-
|
|
{{
|
|
(system_disk_device_prefix ~ disk_letter)
|
|
if (system_cfg.type | lower) == 'virtual'
|
|
else ''
|
|
}}
|
|
system_disk_cfg_base: "{{ system_disk_defaults | combine(item, recursive=True) }}"
|
|
system_disk_mount_path: "{{ (system_disk_cfg_base.mount.path | default('') | string) | trim }}"
|
|
system_disk_cfg_tmp: >-
|
|
{{
|
|
system_disk_cfg_base
|
|
| combine(
|
|
{
|
|
'device': (
|
|
system_disk_cfg_base.device
|
|
if system_disk_cfg_base.device | string | length > 0
|
|
else disk_device_default
|
|
),
|
|
'mount': (
|
|
system_disk_cfg_base.mount
|
|
| combine(
|
|
{
|
|
'path': system_disk_mount_path,
|
|
'fstype': (
|
|
system_disk_cfg_base.mount.fstype
|
|
if (system_disk_cfg_base.mount.fstype | default('') | string | length) > 0
|
|
else ('ext4' if system_disk_mount_path | length > 0 else '')
|
|
)
|
|
},
|
|
recursive=True
|
|
)
|
|
)
|
|
},
|
|
recursive=True
|
|
)
|
|
}}
|
|
system_disk_partition_device: >-
|
|
{{
|
|
system_disk_cfg_tmp.device
|
|
~ ('p1' if (system_disk_cfg_tmp.device | regex_search('\\d$')) else '1')
|
|
}}
|
|
system_disk_cfg: >-
|
|
{{
|
|
system_disk_cfg_tmp
|
|
| combine(
|
|
{
|
|
'partition': system_disk_partition_device
|
|
},
|
|
recursive=True
|
|
)
|
|
}}
|
|
loop: "{{ system_disks_effective }}"
|
|
loop_control:
|
|
loop_var: item
|
|
extended: true
|
|
label: "{{ item | to_json }}"
|
|
|
|
- name: Update system configuration with normalized disks
|
|
ansible.builtin.set_fact:
|
|
system_cfg: "{{ system_cfg | combine({'disks': system_disks_cfg | default([])}, recursive=True) }}"
|
|
changed_when: false
|
|
|
|
- name: Set install_drive from system disk definition
|
|
when:
|
|
- system_disks_cfg | length > 0
|
|
- system_disks_cfg[0].device | string | length > 0
|
|
ansible.builtin.set_fact:
|
|
install_drive: "{{ system_disks_cfg[0].device }}"
|
|
changed_when: false
|