update
This commit is contained in:
parent
b493cf7459
commit
2c6d0394a1
46 changed files with 844 additions and 42 deletions
|
|
@ -7,11 +7,17 @@
|
||||||
# - 172.20.21.193
|
# - 172.20.21.193
|
||||||
become: true
|
become: true
|
||||||
vars:
|
vars:
|
||||||
ansible_ssh_user: root
|
#ansible_ssh_user: root
|
||||||
ansible_ssh_password: nmklop90
|
#ansible_ssh_password: nmklop90
|
||||||
reboot_system: false
|
reboot_system: false
|
||||||
hostname: rocky9-template.local.mrwho.ru
|
hostname: rocky9-template.local.mrwho.ru
|
||||||
roles:
|
roles:
|
||||||
- users
|
- users
|
||||||
- rocky9
|
- rocky9
|
||||||
- root-cert
|
- root-cert
|
||||||
|
- linux_login_banner_rhel9
|
||||||
|
- linux_core_dumps_rhel9
|
||||||
|
- linux_ctrl_alt_del_rhel9
|
||||||
|
- linux_dnf_automatic_rhel9
|
||||||
|
# - linux_ssh_hardening_rhel9
|
||||||
|
- linux_wireless_rhel9
|
||||||
|
|
|
||||||
17
roles/linux_core_dumps_rhel9/README.md
Normal file
17
roles/linux_core_dumps_rhel9/README.md
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
# linux_core_dumps_rhel9
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
Restricts core dump creation via PAM limits and sysctl settings to prevent sensitive memory contents from being written to disk.
|
||||||
|
|
||||||
|
## Targeted OS
|
||||||
|
RHEL 9 / AlmaLinux 9 / Rocky Linux 9
|
||||||
|
|
||||||
|
## CIS Alignment
|
||||||
|
CIS Section 1.5.1 — Ensure core dumps are restricted
|
||||||
|
|
||||||
|
## Key Variables
|
||||||
|
```yaml
|
||||||
|
linux_core_dumps_rhel9_disabled: false # set to true to skip this role
|
||||||
|
```
|
||||||
|
|
||||||
|
See `defaults/main.yml` for all tunable parameters.
|
||||||
16
roles/linux_core_dumps_rhel9/defaults/main.yml
Normal file
16
roles/linux_core_dumps_rhel9/defaults/main.yml
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
# Enable core dump hardening (CIS 1.5.4)
|
||||||
|
linux_core_dumps_enabled: true
|
||||||
|
|
||||||
|
# Disable core dumps globally (recommended for servers)
|
||||||
|
linux_core_dumps_limit: "0"
|
||||||
|
|
||||||
|
# Disable setuid core dumps (CIS 1.5.4)
|
||||||
|
linux_core_suid_dumpable: "0"
|
||||||
|
|
||||||
|
# Restrict core pattern (no executable core files in cwd)
|
||||||
|
linux_core_pattern: "/dev/null"
|
||||||
|
|
||||||
|
# Role disable var
|
||||||
|
linux_core_dumps_disabled: false
|
||||||
6
roles/linux_core_dumps_rhel9/handlers/main.yml
Normal file
6
roles/linux_core_dumps_rhel9/handlers/main.yml
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
# No handlers needed – sysctl module applies changes live
|
||||||
|
# If you want a reload handler later, you can add it here
|
||||||
|
|
||||||
|
...
|
||||||
5
roles/linux_core_dumps_rhel9/tasks/main.yml
Normal file
5
roles/linux_core_dumps_rhel9/tasks/main.yml
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
- name: "Apply core dump hardening (RHEL 9 family)"
|
||||||
|
when: "linux_core_dumps_disabled is not defined or not linux_core_dumps_disabled | bool"
|
||||||
|
ansible.builtin.import_tasks: "tasks.yml"
|
||||||
|
tags: "linux_core_dumps_rhel9"
|
||||||
52
roles/linux_core_dumps_rhel9/tasks/tasks.yml
Normal file
52
roles/linux_core_dumps_rhel9/tasks/tasks.yml
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
---
|
||||||
|
- name: "Set core dump limit to 0 in limits.conf"
|
||||||
|
ansible.builtin.lineinfile:
|
||||||
|
path: "/etc/security/limits.conf"
|
||||||
|
regexp: "^\\*\\s+hard\\s+core\\s+"
|
||||||
|
line: "* hard core {{ linux_core_dumps_limit }}"
|
||||||
|
create: true
|
||||||
|
mode: "0644"
|
||||||
|
register: "limits_conf_result"
|
||||||
|
|
||||||
|
- name: "Set core dump limit to 0 for root in limits.conf"
|
||||||
|
ansible.builtin.lineinfile:
|
||||||
|
path: "/etc/security/limits.conf"
|
||||||
|
regexp: "^root\\s+hard\\s+core\\s+"
|
||||||
|
line: "root hard core {{ linux_core_dumps_limit }}"
|
||||||
|
create: true
|
||||||
|
mode: "0644"
|
||||||
|
register: "root_limits_result"
|
||||||
|
|
||||||
|
- name: "Disable setuid core dumps (fs.suid_dumpable)"
|
||||||
|
ansible.posix.sysctl:
|
||||||
|
name: "fs.suid_dumpable"
|
||||||
|
value: "{{ linux_core_suid_dumpable }}"
|
||||||
|
state: "present"
|
||||||
|
sysctl_set: true
|
||||||
|
sysctl_file: "/etc/sysctl.d/99-cis-core-dumps.conf"
|
||||||
|
reload: true
|
||||||
|
register: "suid_dumpable_result"
|
||||||
|
|
||||||
|
- name: "Set core pattern to /dev/null (prevent core files in cwd)"
|
||||||
|
ansible.posix.sysctl:
|
||||||
|
name: "kernel.core_pattern"
|
||||||
|
value: "{{ linux_core_pattern }}"
|
||||||
|
state: "present"
|
||||||
|
sysctl_set: true
|
||||||
|
sysctl_file: "/etc/sysctl.d/99-cis-core-dumps.conf"
|
||||||
|
reload: true
|
||||||
|
register: "core_pattern_result"
|
||||||
|
|
||||||
|
- name: "Apply sysctl changes immediately if needed"
|
||||||
|
when: "suid_dumpable_result.changed or core_pattern_result.changed"
|
||||||
|
ansible.builtin.command: "sysctl --system"
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: "Debug core dump hardening status (verbosity >=1)"
|
||||||
|
when: "ansible_verbosity >= 1"
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg:
|
||||||
|
- "Core limit applied: {{ limits_conf_result.changed | default(false) }}"
|
||||||
|
- "Root core limit applied: {{ root_limits_result.changed | default(false) }}"
|
||||||
|
- "fs.suid_dumpable: {{ linux_core_suid_dumpable }}"
|
||||||
|
- "kernel.core_pattern: {{ linux_core_pattern }}"
|
||||||
17
roles/linux_ctrl_alt_del_rhel9/README.md
Normal file
17
roles/linux_ctrl_alt_del_rhel9/README.md
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
# linux_ctrl_alt_del_rhel9
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
Disables the Ctrl+Alt+Del keyboard shortcut to prevent accidental or malicious system reboots from the console.
|
||||||
|
|
||||||
|
## Targeted OS
|
||||||
|
RHEL 9 / AlmaLinux 9 / Rocky Linux 9
|
||||||
|
|
||||||
|
## CIS Alignment
|
||||||
|
CIS Section 1.6.1 — Ensure system-wide crypto policy is not legacy
|
||||||
|
|
||||||
|
## Key Variables
|
||||||
|
```yaml
|
||||||
|
linux_ctrl_alt_del_rhel9_disabled: false # set to true to skip this role
|
||||||
|
```
|
||||||
|
|
||||||
|
See `defaults/main.yml` for all tunable parameters.
|
||||||
5
roles/linux_ctrl_alt_del_rhel9/defaults/main.yml
Normal file
5
roles/linux_ctrl_alt_del_rhel9/defaults/main.yml
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
linux_ctrl_alt_del_enabled: true
|
||||||
|
|
||||||
|
linux_ctrl_alt_del_disabled: false
|
||||||
4
roles/linux_ctrl_alt_del_rhel9/handlers/main.yml
Normal file
4
roles/linux_ctrl_alt_del_rhel9/handlers/main.yml
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
- name: "Reload systemd after Ctrl+Alt+Del changes"
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
daemon_reload: true
|
||||||
5
roles/linux_ctrl_alt_del_rhel9/tasks/main.yml
Normal file
5
roles/linux_ctrl_alt_del_rhel9/tasks/main.yml
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
- name: "Apply Ctrl+Alt+Del disable hardening (RHEL 9 family)"
|
||||||
|
when: "linux_ctrl_alt_del_disabled is not defined or not linux_ctrl_alt_del_disabled | bool"
|
||||||
|
ansible.builtin.import_tasks: "tasks.yml"
|
||||||
|
tags: "linux_ctrl_alt_del_rhel9"
|
||||||
52
roles/linux_ctrl_alt_del_rhel9/tasks/tasks.yml
Normal file
52
roles/linux_ctrl_alt_del_rhel9/tasks/tasks.yml
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
---
|
||||||
|
- name: Remove existing ctrl-alt-del.target symlink
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: /etc/systemd/system/ctrl-alt-del.target
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: "Mask Ctrl+Alt+Del target to prevent reboot"
|
||||||
|
when: "linux_ctrl_alt_del_enabled | bool"
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "ctrl-alt-del.target"
|
||||||
|
masked: true
|
||||||
|
state: "stopped"
|
||||||
|
register: "cad_mask_result"
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
# FIX: create the .target.d/ drop-in directory before writing into it.
|
||||||
|
# ansible.builtin.copy does NOT create missing parent directories.
|
||||||
|
- name: "Ensure ctrl-alt-del.target.d drop-in directory exists"
|
||||||
|
when: "linux_ctrl_alt_del_enabled | bool"
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "/etc/systemd/system/ctrl-alt-del.target.d"
|
||||||
|
state: "directory"
|
||||||
|
mode: "0755"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
|
||||||
|
- name: "Deploy ctrl-alt-del override to reinforce mask"
|
||||||
|
when: "linux_ctrl_alt_del_enabled | bool"
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: "[Unit]\nDescription=Ctrl-Alt-Del disabled by CyberAar hardening\n"
|
||||||
|
dest: "/etc/systemd/system/ctrl-alt-del.target.d/override.conf"
|
||||||
|
mode: "0644"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
register: "cad_override_result"
|
||||||
|
|
||||||
|
- name: "Reload systemd daemon after mask/override"
|
||||||
|
when: "cad_mask_result.changed or cad_override_result.changed"
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
daemon_reload: true
|
||||||
|
|
||||||
|
- name: "Verify Ctrl+Alt+Del mask status (verbosity >=1)" # noqa: command-instead-of-module
|
||||||
|
when: "ansible_verbosity >= 1"
|
||||||
|
ansible.builtin.command: "systemctl is-enabled ctrl-alt-del.target"
|
||||||
|
changed_when: false
|
||||||
|
register: "cad_status"
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: "Show Ctrl+Alt+Del mask status"
|
||||||
|
when: "ansible_verbosity >= 1"
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "ctrl-alt-del.target status: {{ cad_status.stdout | default('unknown') }}"
|
||||||
17
roles/linux_dnf_automatic_rhel9/README.md
Normal file
17
roles/linux_dnf_automatic_rhel9/README.md
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
# linux_dnf_automatic_rhel9
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
Installs and configures dnf-automatic to automatically apply security updates on a scheduled basis, ensuring critical patches are applied without manual intervention.
|
||||||
|
|
||||||
|
## Targeted OS
|
||||||
|
RHEL 9 / AlmaLinux 9 / Rocky Linux 9
|
||||||
|
|
||||||
|
## CIS Alignment
|
||||||
|
CIS Section 1.9 — Ensure updates, patches, and additional security software are installed
|
||||||
|
|
||||||
|
## Key Variables
|
||||||
|
```yaml
|
||||||
|
linux_dnf_automatic_rhel9_disabled: false # set to true to skip this role
|
||||||
|
```
|
||||||
|
|
||||||
|
See `defaults/main.yml` for all tunable parameters.
|
||||||
21
roles/linux_dnf_automatic_rhel9/defaults/main.yml
Normal file
21
roles/linux_dnf_automatic_rhel9/defaults/main.yml
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
# Enable automatic security updates (CIS 1.7.1)
|
||||||
|
linux_dnf_automatic_enabled: true
|
||||||
|
|
||||||
|
# Apply only security updates (recommended for servers)
|
||||||
|
linux_dnf_automatic_apply_updates: "security"
|
||||||
|
|
||||||
|
# Email notifications (optional – requires mail setup)
|
||||||
|
linux_dnf_automatic_email_notify: true
|
||||||
|
linux_dnf_automatic_email_to: "root@localhost"
|
||||||
|
linux_dnf_automatic_email_from: "dnf-automatic@{{ ansible_fqdn }}"
|
||||||
|
|
||||||
|
# When to apply updates (daily is CIS default)
|
||||||
|
linux_dnf_automatic_schedule: "daily"
|
||||||
|
|
||||||
|
# Random delay (minutes) to avoid thundering herd
|
||||||
|
linux_dnf_automatic_random_sleep: 300
|
||||||
|
|
||||||
|
# Role disable var
|
||||||
|
linux_dnf_automatic_disabled: false
|
||||||
6
roles/linux_dnf_automatic_rhel9/handlers/main.yml
Normal file
6
roles/linux_dnf_automatic_rhel9/handlers/main.yml
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
- name: "Restart dnf-automatic timer"
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "dnf-automatic.timer"
|
||||||
|
state: "restarted"
|
||||||
|
daemon_reload: true
|
||||||
5
roles/linux_dnf_automatic_rhel9/tasks/main.yml
Normal file
5
roles/linux_dnf_automatic_rhel9/tasks/main.yml
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
- name: "Apply dnf-automatic security updates (RHEL 9 family)"
|
||||||
|
when: "linux_dnf_automatic_disabled is not defined or not linux_dnf_automatic_disabled | bool"
|
||||||
|
ansible.builtin.import_tasks: "tasks.yml"
|
||||||
|
tags: "linux_dnf_automatic_rhel9"
|
||||||
34
roles/linux_dnf_automatic_rhel9/tasks/tasks.yml
Normal file
34
roles/linux_dnf_automatic_rhel9/tasks/tasks.yml
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
---
|
||||||
|
- name: "Install dnf-automatic package"
|
||||||
|
ansible.builtin.package:
|
||||||
|
name: "dnf-automatic"
|
||||||
|
state: "present"
|
||||||
|
|
||||||
|
- name: "Deploy dnf-automatic configuration"
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "automatic.conf.j2"
|
||||||
|
dest: "/etc/dnf/automatic.conf"
|
||||||
|
mode: "0644"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
backup: true
|
||||||
|
register: "dnf_auto_config_result"
|
||||||
|
notify: "Restart dnf-automatic timer"
|
||||||
|
|
||||||
|
- name: "Enable and start dnf-automatic timer (daily)"
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "dnf-automatic.timer"
|
||||||
|
state: "started"
|
||||||
|
enabled: true
|
||||||
|
masked: false
|
||||||
|
|
||||||
|
- name: "Debug dnf-automatic status (verbosity >=1)"
|
||||||
|
when: "ansible_verbosity >= 1"
|
||||||
|
ansible.builtin.command: "systemctl status dnf-automatic.timer"
|
||||||
|
changed_when: false
|
||||||
|
register: "dnf_timer_status"
|
||||||
|
|
||||||
|
- name: "Show dnf-automatic timer status"
|
||||||
|
when: "ansible_verbosity >= 1"
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "{{ dnf_timer_status.stdout_lines | default([]) }}"
|
||||||
21
roles/linux_dnf_automatic_rhel9/templates/automatic.conf.j2
Normal file
21
roles/linux_dnf_automatic_rhel9/templates/automatic.conf.j2
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
# Managed by Ansible role linux_dnf_automatic_rhel9
|
||||||
|
|
||||||
|
[commands]
|
||||||
|
# Only apply security updates (CIS safe choice)
|
||||||
|
upgrade_type = {{ linux_dnf_automatic_apply_updates }}
|
||||||
|
|
||||||
|
# Random delay before starting (minutes)
|
||||||
|
random_sleep = {{ linux_dnf_automatic_random_sleep }}
|
||||||
|
|
||||||
|
[emit_via]
|
||||||
|
# Emit via email (requires postfix or mail setup)
|
||||||
|
emit_via = {{ 'email' if linux_dnf_automatic_email_notify | bool else 'stdio' }}
|
||||||
|
|
||||||
|
# Email settings
|
||||||
|
email_from = {{ linux_dnf_automatic_email_from }}
|
||||||
|
email_to = {{ linux_dnf_automatic_email_to }}
|
||||||
|
email_host = localhost
|
||||||
|
|
||||||
|
[base]
|
||||||
|
# Debug level (0-10, higher = more verbose)
|
||||||
|
debuglevel = 1
|
||||||
17
roles/linux_journald_rhel9/README.md
Normal file
17
roles/linux_journald_rhel9/README.md
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
# linux_journald_rhel9
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
Configures systemd-journald with persistent log storage, compression, and rate limiting to ensure reliable and efficient system log retention.
|
||||||
|
|
||||||
|
## Targeted OS
|
||||||
|
RHEL 9 / AlmaLinux 9 / Rocky Linux 9
|
||||||
|
|
||||||
|
## CIS Alignment
|
||||||
|
CIS Section 4.2.1.x — Configure journald
|
||||||
|
|
||||||
|
## Key Variables
|
||||||
|
```yaml
|
||||||
|
linux_journald_rhel9_disabled: false # set to true to skip this role
|
||||||
|
```
|
||||||
|
|
||||||
|
See `defaults/main.yml` for all tunable parameters.
|
||||||
32
roles/linux_journald_rhel9/defaults/main.yml
Normal file
32
roles/linux_journald_rhel9/defaults/main.yml
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
# Write logs to /var/log/journal (persistent across reboots) — CIS 4.2.1.1.1
|
||||||
|
linux_journald_storage: "persistent"
|
||||||
|
|
||||||
|
# Compress large journal files — CIS 4.2.1.1.2
|
||||||
|
linux_journald_compress: "yes"
|
||||||
|
|
||||||
|
# Forward entries to syslog socket (integrates with rsyslog)
|
||||||
|
linux_journald_forward_to_syslog: "yes"
|
||||||
|
|
||||||
|
# Rate limiting — prevent log flooding
|
||||||
|
linux_journald_rate_limit_interval: "30s"
|
||||||
|
linux_journald_rate_limit_burst: 10000
|
||||||
|
|
||||||
|
# Maximum total disk usage by journald
|
||||||
|
linux_journald_system_max_use: "1G"
|
||||||
|
|
||||||
|
# Minimum free disk space journald will leave available
|
||||||
|
linux_journald_system_keep_free: "256M"
|
||||||
|
|
||||||
|
# Maximum size of a single journal file
|
||||||
|
linux_journald_system_max_file_size: "100M"
|
||||||
|
|
||||||
|
# Rotate individual files after this period
|
||||||
|
linux_journald_max_file_sec: "1month"
|
||||||
|
|
||||||
|
# Delete old journal files beyond this total retention period
|
||||||
|
linux_journald_max_retention_sec: "2year"
|
||||||
|
|
||||||
|
# Role disable var
|
||||||
|
linux_journald_disabled: false
|
||||||
7
roles/linux_journald_rhel9/handlers/main.yml
Normal file
7
roles/linux_journald_rhel9/handlers/main.yml
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
- name: "Restart journald"
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "systemd-journald"
|
||||||
|
state: "restarted"
|
||||||
|
daemon_reload: true
|
||||||
|
failed_when: false
|
||||||
5
roles/linux_journald_rhel9/tasks/main.yml
Normal file
5
roles/linux_journald_rhel9/tasks/main.yml
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
- name: "Apply journald hardening (RHEL 9 family)"
|
||||||
|
when: "linux_journald_disabled is not defined or not linux_journald_disabled | bool"
|
||||||
|
ansible.builtin.import_tasks: "tasks.yml"
|
||||||
|
tags: "linux_journald_rhel9"
|
||||||
39
roles/linux_journald_rhel9/tasks/tasks.yml
Normal file
39
roles/linux_journald_rhel9/tasks/tasks.yml
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
---
|
||||||
|
- name: "Ensure /etc/systemd/journald.conf.d directory exists (CIS 4.2.1.x)"
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "/etc/systemd/journald.conf.d"
|
||||||
|
state: directory
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0755"
|
||||||
|
|
||||||
|
- name: "Deploy journald hardening configuration (CIS 4.2.1.x)"
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "99-cis-journald.conf.j2"
|
||||||
|
dest: "/etc/systemd/journald.conf.d/99-cis-journald.conf"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
notify: "Restart journald"
|
||||||
|
register: "journald_config_result"
|
||||||
|
|
||||||
|
- name: "Ensure /var/log/journal directory exists for persistent storage (CIS 4.2.1.1.1)"
|
||||||
|
when: "linux_journald_storage == 'persistent'"
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "/var/log/journal"
|
||||||
|
state: directory
|
||||||
|
owner: "root"
|
||||||
|
group: "systemd-journal"
|
||||||
|
mode: "2755"
|
||||||
|
register: "journal_dir_result"
|
||||||
|
|
||||||
|
- name: "Debug journald configuration status (verbosity >= 1)"
|
||||||
|
when: "ansible_verbosity >= 1"
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg:
|
||||||
|
- "Storage: {{ linux_journald_storage }}"
|
||||||
|
- "Compress: {{ linux_journald_compress }}"
|
||||||
|
- "ForwardToSyslog: {{ linux_journald_forward_to_syslog }}"
|
||||||
|
- "RateLimitBurst: {{ linux_journald_rate_limit_burst }}"
|
||||||
|
- "SystemMaxUse: {{ linux_journald_system_max_use }}"
|
||||||
|
- "Config changed: {{ journald_config_result.changed | default(false) }}"
|
||||||
14
roles/linux_journald_rhel9/templates/99-cis-journald.conf.j2
Normal file
14
roles/linux_journald_rhel9/templates/99-cis-journald.conf.j2
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
# CyberAar — systemd-journald hardening (CIS 4.2.1.x)
|
||||||
|
# Managed by Ansible — do not edit manually
|
||||||
|
|
||||||
|
[Journal]
|
||||||
|
Storage={{ linux_journald_storage }}
|
||||||
|
Compress={{ linux_journald_compress }}
|
||||||
|
ForwardToSyslog={{ linux_journald_forward_to_syslog }}
|
||||||
|
RateLimitInterval={{ linux_journald_rate_limit_interval }}
|
||||||
|
RateLimitBurst={{ linux_journald_rate_limit_burst }}
|
||||||
|
SystemMaxUse={{ linux_journald_system_max_use }}
|
||||||
|
SystemKeepFree={{ linux_journald_system_keep_free }}
|
||||||
|
SystemMaxFileSize={{ linux_journald_system_max_file_size }}
|
||||||
|
MaxFileSec={{ linux_journald_max_file_sec }}
|
||||||
|
MaxRetentionSec={{ linux_journald_max_retention_sec }}
|
||||||
17
roles/linux_login_banner_rhel9/README.md
Normal file
17
roles/linux_login_banner_rhel9/README.md
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
# linux_login_banner_rhel9
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
Configures legal warning banners for SSH and local console login prompts to satisfy regulatory requirements and deter unauthorized access.
|
||||||
|
|
||||||
|
## Targeted OS
|
||||||
|
RHEL 9 / AlmaLinux 9 / Rocky Linux 9
|
||||||
|
|
||||||
|
## CIS Alignment
|
||||||
|
CIS Section 1.7 — Warning Banners
|
||||||
|
|
||||||
|
## Key Variables
|
||||||
|
```yaml
|
||||||
|
linux_login_banner_rhel9_disabled: false # set to true to skip this role
|
||||||
|
```
|
||||||
|
|
||||||
|
See `defaults/main.yml` for all tunable parameters.
|
||||||
16
roles/linux_login_banner_rhel9/defaults/main.yml
Normal file
16
roles/linux_login_banner_rhel9/defaults/main.yml
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
# Enable login banners (CIS 5.6)
|
||||||
|
linux_login_banner_enabled: true
|
||||||
|
|
||||||
|
# Pre-login banner (/etc/issue.net) – shown before SSH login
|
||||||
|
linux_login_banner_prelogin: true
|
||||||
|
|
||||||
|
# Post-login banner (/etc/motd) – shown after successful login
|
||||||
|
linux_login_banner_postlogin: true
|
||||||
|
|
||||||
|
# Additional static issue file (/etc/issue) – shown on console/TTY
|
||||||
|
linux_login_banner_issue: true
|
||||||
|
|
||||||
|
# Role disable var
|
||||||
|
linux_login_banner_disabled: false
|
||||||
9
roles/linux_login_banner_rhel9/handlers/main.yml
Normal file
9
roles/linux_login_banner_rhel9/handlers/main.yml
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
# No handlers needed – banner changes are immediate (shown on next login)
|
||||||
|
# If you want to force a message on current sessions, you could add:
|
||||||
|
# - name: "Notify banner updated"
|
||||||
|
# ansible.builtin.debug:
|
||||||
|
# msg: "Login banners updated – visible on next login/console session"
|
||||||
|
|
||||||
|
...
|
||||||
5
roles/linux_login_banner_rhel9/tasks/main.yml
Normal file
5
roles/linux_login_banner_rhel9/tasks/main.yml
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
- name: "Apply login banners hardening (RHEL 9 family)"
|
||||||
|
when: "linux_login_banner_disabled is not defined or not linux_login_banner_disabled | bool"
|
||||||
|
ansible.builtin.import_tasks: "tasks.yml"
|
||||||
|
tags: "linux_login_banner_rhel9"
|
||||||
44
roles/linux_login_banner_rhel9/tasks/tasks.yml
Normal file
44
roles/linux_login_banner_rhel9/tasks/tasks.yml
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
---
|
||||||
|
- name: "Deploy CyberAar pre-login banner (/etc/issue.net)"
|
||||||
|
when: "linux_login_banner_prelogin | bool"
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "issue.net.j2"
|
||||||
|
dest: "/etc/issue.net"
|
||||||
|
mode: "0644"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
backup: true
|
||||||
|
register: "prelogin_banner_result"
|
||||||
|
changed_when: "prelogin_banner_result.changed"
|
||||||
|
|
||||||
|
- name: "Deploy CyberAar post-login banner (/etc/motd)"
|
||||||
|
when: "linux_login_banner_postlogin | bool"
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "motd.j2"
|
||||||
|
dest: "/etc/motd"
|
||||||
|
mode: "0644"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
backup: true
|
||||||
|
register: "motd_result"
|
||||||
|
changed_when: "motd_result.changed"
|
||||||
|
|
||||||
|
- name: "Deploy CyberAar console login banner (/etc/issue)"
|
||||||
|
when: "linux_login_banner_issue | bool"
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "issue.j2"
|
||||||
|
dest: "/etc/issue"
|
||||||
|
mode: "0644"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
backup: true
|
||||||
|
register: "issue_banner_result"
|
||||||
|
changed_when: "issue_banner_result.changed"
|
||||||
|
|
||||||
|
- name: "Debug login banner status (verbosity >=1)"
|
||||||
|
when: "ansible_verbosity >= 1"
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg:
|
||||||
|
- "Pre-login banner (/etc/issue.net) updated: {{ prelogin_banner_result.changed | default(false) }}"
|
||||||
|
- "Post-login banner (/etc/motd) updated: {{ motd_result.changed | default(false) }}"
|
||||||
|
- "Console banner (/etc/issue) updated: {{ issue_banner_result.changed | default(false) }}"
|
||||||
29
roles/linux_login_banner_rhel9/templates/issue.j2
Normal file
29
roles/linux_login_banner_rhel9/templates/issue.j2
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
⣠⣤⣤⣄⣀
|
||||||
|
⣴⣿⠟⠛⠛⠛⠿⣿⣿⣿⣿⣶⣤⡀
|
||||||
|
⣠⣴⣿⡟⠁⢀⣤⣀ ⠉⠻⣿⣦
|
||||||
|
⣾⡿⠿⠛⠁⣰⣿⣿⣿⡆ ⣴⣶⣶⠄ ⢻⣿⡄
|
||||||
|
⣾⡿⠁ ⠻⣿⣿⣿⠃ ⣼⣿⣿⣿ ⢿⣷⣄
|
||||||
|
⣾⣿⠁ ⣤⣶⡄ ⠈⠉⠁ ⠈⠛⠊⠁ ⠙⢿⣷
|
||||||
|
⣿⡇ ⢸⣿⣿⡿⡆ ⣴⣶⣶⣴⣶⣄ ⢠⣶⣿⣦ ⣿⡇
|
||||||
|
⣿⡇ ⠛⠙⠉ ⣰⣿⣿⣿⣿⣿⣿⣿⣇ ⣿⣿⣿⣿ ⣿⡇
|
||||||
|
⣿⣇ ⢀⣾⣿⣿⣿⣿⣿⣿⣷⣿⣷⡀ ⠉⠉ ⣸⣿⠇
|
||||||
|
⣿⣿ ⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ ⣻⡟⠘
|
||||||
|
⢹⣿ ⠉⠛⠉⠁⠉⠁⠙⠻⠿⠟ ⣾⣿⠁
|
||||||
|
⣿⡆ ⣿⡏
|
||||||
|
⣿⣿ ⢸⣿⡇
|
||||||
|
⣻⣿ ⢸⣿⡇
|
||||||
|
⢸⣿⡄ ⢸⣿⡇
|
||||||
|
|
||||||
|
..|'''.| | |''||''|
|
||||||
|
.|' ' ||| ||
|
||||||
|
|| | || ||
|
||||||
|
'|. . .''''|. ||
|
||||||
|
''|....' .|. .||. .||.
|
||||||
|
|
||||||
|
|
||||||
|
'||''|. ..|''|| '|| '||' '|' '||''''| '||''|.
|
||||||
|
|| || .|' || '|. '|. .' || . || ||
|
||||||
|
||...|' || || || || | ||''| ||''|'
|
||||||
|
|| '|. || ||| ||| || || |.
|
||||||
|
.||. ''|...|' | | .||.....| .||. '|'
|
||||||
|
|
||||||
29
roles/linux_login_banner_rhel9/templates/issue.net.j2
Normal file
29
roles/linux_login_banner_rhel9/templates/issue.net.j2
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
⣠⣤⣤⣄⣀
|
||||||
|
⣴⣿⠟⠛⠛⠛⠿⣿⣿⣿⣿⣶⣤⡀
|
||||||
|
⣠⣴⣿⡟⠁⢀⣤⣀ ⠉⠻⣿⣦
|
||||||
|
⣾⡿⠿⠛⠁⣰⣿⣿⣿⡆ ⣴⣶⣶⠄ ⢻⣿⡄
|
||||||
|
⣾⡿⠁ ⠻⣿⣿⣿⠃ ⣼⣿⣿⣿ ⢿⣷⣄
|
||||||
|
⣾⣿⠁ ⣤⣶⡄ ⠈⠉⠁ ⠈⠛⠊⠁ ⠙⢿⣷
|
||||||
|
⣿⡇ ⢸⣿⣿⡿⡆ ⣴⣶⣶⣴⣶⣄ ⢠⣶⣿⣦ ⣿⡇
|
||||||
|
⣿⡇ ⠛⠙⠉ ⣰⣿⣿⣿⣿⣿⣿⣿⣇ ⣿⣿⣿⣿ ⣿⡇
|
||||||
|
⣿⣇ ⢀⣾⣿⣿⣿⣿⣿⣿⣷⣿⣷⡀ ⠉⠉ ⣸⣿⠇
|
||||||
|
⣿⣿ ⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ ⣻⡟⠘
|
||||||
|
⢹⣿ ⠉⠛⠉⠁⠉⠁⠙⠻⠿⠟ ⣾⣿⠁
|
||||||
|
⣿⡆ ⣿⡏
|
||||||
|
⣿⣿ ⢸⣿⡇
|
||||||
|
⣻⣿ ⢸⣿⡇
|
||||||
|
⢸⣿⡄ ⢸⣿⡇
|
||||||
|
|
||||||
|
..|'''.| | |''||''|
|
||||||
|
.|' ' ||| ||
|
||||||
|
|| | || ||
|
||||||
|
'|. . .''''|. ||
|
||||||
|
''|....' .|. .||. .||.
|
||||||
|
|
||||||
|
|
||||||
|
'||''|. ..|''|| '|| '||' '|' '||''''| '||''|.
|
||||||
|
|| || .|' || '|. '|. .' || . || ||
|
||||||
|
||...|' || || || || | ||''| ||''|'
|
||||||
|
|| '|. || ||| ||| || || |.
|
||||||
|
.||. ''|...|' | | .||.....| .||. '|'
|
||||||
|
|
||||||
17
roles/linux_login_banner_rhel9/templates/motd.j2
Normal file
17
roles/linux_login_banner_rhel9/templates/motd.j2
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
__ __
|
||||||
|
/\ \ /\ \
|
||||||
|
\ `\`\\/'/ ___ __ __
|
||||||
|
`\ `\ /' / __`\/\ \/\ \ /\_/\
|
||||||
|
`\ \ \/\ \L\ \ \ \_\ \ ( o.o )
|
||||||
|
\ \_\ \____/\ \____/ > ^ <
|
||||||
|
\/_/\/___/ \/___/
|
||||||
|
|
||||||
|
___ __
|
||||||
|
/\_ \ /\ \ __
|
||||||
|
\//\ \ ___ __ __ __ \_\ \ /\_\ ___
|
||||||
|
\ \ \ / __`\ /'_ `\ /'_ `\ /'__`\ /'_` \ \/\ \ /' _ `\
|
||||||
|
\_\ \_/\ \L\ \/\ \L\ \/\ \L\ \/\ __//\ \L\ \ \ \ \/\ \/\ \
|
||||||
|
/\____\ \____/\ \____ \ \____ \ \____\ \___,_\ \ \_\ \_\ \_\
|
||||||
|
\/____/\/___/ \/___L\ \/___L\ \/____/\/__,_ / \/_/\/_/\/_/
|
||||||
|
/\____/ /\____/
|
||||||
|
\_/__/ \_/__/
|
||||||
17
roles/linux_ssh_hardening_rhel9/README.md
Normal file
17
roles/linux_ssh_hardening_rhel9/README.md
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
# linux_ssh_hardening_rhel9
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
Applies deep SSH server hardening by enforcing strong ciphers, MACs, key exchange algorithms, authentication restrictions, and login banners to minimize SSH attack exposure.
|
||||||
|
|
||||||
|
## Targeted OS
|
||||||
|
RHEL 9 / AlmaLinux 9 / Rocky Linux 9
|
||||||
|
|
||||||
|
## CIS Alignment
|
||||||
|
CIS Section 5.1 — Configure SSH Server
|
||||||
|
|
||||||
|
## Key Variables
|
||||||
|
```yaml
|
||||||
|
linux_ssh_hardening_rhel9_disabled: false # set to true to skip this role
|
||||||
|
```
|
||||||
|
|
||||||
|
See `defaults/main.yml` for all tunable parameters.
|
||||||
45
roles/linux_ssh_hardening_rhel9/defaults/main.yml
Normal file
45
roles/linux_ssh_hardening_rhel9/defaults/main.yml
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
# Enable SSH server hardening (default true)
|
||||||
|
linux_ssh_hardening_enabled: true
|
||||||
|
|
||||||
|
# Disable root login over SSH (CIS 5.1.3.1)
|
||||||
|
linux_ssh_permit_root_login: "no"
|
||||||
|
|
||||||
|
# Disable password authentication (force keys – CIS 5.1.3.2)
|
||||||
|
linux_ssh_password_auth: "no"
|
||||||
|
|
||||||
|
# Disable empty passwords (CIS 5.1.8)
|
||||||
|
linux_ssh_permit_empty_passwords: "no"
|
||||||
|
|
||||||
|
# Disable X11 forwarding (CIS 5.1.10)
|
||||||
|
linux_ssh_x11_forwarding: "no"
|
||||||
|
|
||||||
|
# Disable TCP forwarding (CIS 5.1.11)
|
||||||
|
linux_ssh_allow_tcp_forwarding: "no"
|
||||||
|
|
||||||
|
# Strong ciphers/MACs/Kex (align with crypto policies – CIS 5.1.13–5.1.15)
|
||||||
|
linux_ssh_ciphers: "chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr"
|
||||||
|
linux_ssh_macs: "hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256"
|
||||||
|
linux_ssh_kexalgorithms: "curve25519-sha256,diffie-hellman-group-exchange-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512"
|
||||||
|
|
||||||
|
# Banner / legal notice (CIS 5.1.7)
|
||||||
|
linux_ssh_banner: "/etc/issue.net"
|
||||||
|
|
||||||
|
# Max auth tries (anti-brute-force – CIS 5.1.5)
|
||||||
|
linux_ssh_max_auth_tries: 4
|
||||||
|
linux_ssh_max_sessions: 8
|
||||||
|
linux_ssh_max_startups: "10:30:60"
|
||||||
|
linux_ssh_login_grace_time: "60"
|
||||||
|
|
||||||
|
# Keepalive — CountMax 3 means 3 missed probes before drop (15 min total)
|
||||||
|
# Do NOT set CountMax to 0 — that drops the session on the first missed probe,
|
||||||
|
# which kills Ansible connections during long package installs or AIDE init.
|
||||||
|
linux_ssh_client_alive_interval: 300
|
||||||
|
linux_ssh_client_alive_count_max: 3
|
||||||
|
|
||||||
|
# Disable unused subsystems (e.g. sftp if not needed)
|
||||||
|
linux_ssh_subsystem: "sftp internal-sftp"
|
||||||
|
|
||||||
|
# Role disable var
|
||||||
|
linux_ssh_hardening_disabled: false
|
||||||
5
roles/linux_ssh_hardening_rhel9/handlers/main.yml
Normal file
5
roles/linux_ssh_hardening_rhel9/handlers/main.yml
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
- name: "Restart sshd"
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: "sshd"
|
||||||
|
state: "restarted"
|
||||||
5
roles/linux_ssh_hardening_rhel9/tasks/main.yml
Normal file
5
roles/linux_ssh_hardening_rhel9/tasks/main.yml
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
- name: "Apply SSH server hardening (RHEL 9 family)"
|
||||||
|
when: "linux_ssh_hardening_disabled is not defined or not linux_ssh_hardening_disabled | bool"
|
||||||
|
ansible.builtin.import_tasks: "tasks.yml"
|
||||||
|
tags: "linux_ssh_hardening_rhel9"
|
||||||
48
roles/linux_ssh_hardening_rhel9/tasks/tasks.yml
Normal file
48
roles/linux_ssh_hardening_rhel9/tasks/tasks.yml
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
---
|
||||||
|
- name: "Ensure openssh-server is installed"
|
||||||
|
ansible.builtin.package:
|
||||||
|
name: "openssh-server"
|
||||||
|
state: "present"
|
||||||
|
|
||||||
|
- name: "Deploy hardened sshd_config"
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "sshd_config.j2"
|
||||||
|
dest: "/etc/ssh/sshd_config"
|
||||||
|
mode: "0600"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
backup: true
|
||||||
|
validate: "/usr/sbin/sshd -T -f %s"
|
||||||
|
register: "sshd_config_result"
|
||||||
|
notify: "Restart sshd"
|
||||||
|
|
||||||
|
- name: "Deploy CyberAar-branded SSH pre-login banner (/etc/issue.net)"
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "issue.net.j2"
|
||||||
|
dest: "/etc/issue.net"
|
||||||
|
mode: "0644"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
backup: true
|
||||||
|
when: "linux_ssh_banner != ''"
|
||||||
|
register: "banner_result"
|
||||||
|
changed_when: "banner_result.changed"
|
||||||
|
|
||||||
|
- name: "Enable and start sshd service"
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: "sshd"
|
||||||
|
state: "started"
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
- name: "Verify SSH configuration is valid"
|
||||||
|
ansible.builtin.command: "sshd -t"
|
||||||
|
changed_when: false
|
||||||
|
register: "sshd_test"
|
||||||
|
failed_when: "sshd_test.rc != 0"
|
||||||
|
|
||||||
|
- name: "Debug SSH hardening status (verbosity >=1)"
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg:
|
||||||
|
- "sshd_config updated: {{ sshd_config_result.changed | default(false) }}"
|
||||||
|
- "SSHD test: {{ sshd_test.rc | default('unknown') }}"
|
||||||
|
# when: "ansible_verbosity >= 1"
|
||||||
13
roles/linux_ssh_hardening_rhel9/templates/issue.net.j2
Normal file
13
roles/linux_ssh_hardening_rhel9/templates/issue.net.j2
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
********************************************************************************
|
||||||
|
* MRWHO – DIGITAL SECURITY *
|
||||||
|
* *
|
||||||
|
* This system is the exclusive property of mrwho *
|
||||||
|
* Unauthorized access is strictly prohibited and will be prosecuted. *
|
||||||
|
* *
|
||||||
|
* This system is for the use of authorized users only. *
|
||||||
|
* Individuals using this computer system without authority, or in excess of *
|
||||||
|
* their authority, are subject to having all of their activities on this *
|
||||||
|
* system monitored and recorded by system personnel. *
|
||||||
|
* *
|
||||||
|
* Welcome to {{ ansible_hostname }} *
|
||||||
|
********************************************************************************
|
||||||
27
roles/linux_ssh_hardening_rhel9/templates/sshd_config.j2
Normal file
27
roles/linux_ssh_hardening_rhel9/templates/sshd_config.j2
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
# Managed by Ansible role linux_ssh_hardening_rhel9
|
||||||
|
# CIS-aligned SSH server hardening
|
||||||
|
|
||||||
|
PermitRootLogin {{ linux_ssh_permit_root_login }}
|
||||||
|
PasswordAuthentication {{ linux_ssh_password_auth }}
|
||||||
|
PermitEmptyPasswords {{ linux_ssh_permit_empty_passwords }}
|
||||||
|
X11Forwarding {{ linux_ssh_x11_forwarding }}
|
||||||
|
AllowTcpForwarding {{ linux_ssh_allow_tcp_forwarding }}
|
||||||
|
|
||||||
|
Ciphers {{ linux_ssh_ciphers }}
|
||||||
|
MACs {{ linux_ssh_macs }}
|
||||||
|
KexAlgorithms {{ linux_ssh_kexalgorithms }}
|
||||||
|
|
||||||
|
MaxAuthTries {{ linux_ssh_max_auth_tries }}
|
||||||
|
MaxSessions {{ linux_ssh_max_sessions }}
|
||||||
|
MaxStartups {{ linux_ssh_max_startups }}
|
||||||
|
|
||||||
|
Banner {{ linux_ssh_banner }}
|
||||||
|
|
||||||
|
Subsystem sftp {{ linux_ssh_subsystem }}
|
||||||
|
|
||||||
|
# Additional security
|
||||||
|
LoginGraceTime {{ linux_ssh_login_grace_time }}
|
||||||
|
ClientAliveInterval {{ linux_ssh_client_alive_interval }}
|
||||||
|
ClientAliveCountMax {{ linux_ssh_client_alive_count_max }}
|
||||||
|
IgnoreRhosts yes
|
||||||
|
PermitUserEnvironment no
|
||||||
17
roles/linux_wireless_rhel9/README.md
Normal file
17
roles/linux_wireless_rhel9/README.md
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
# linux_wireless_rhel9
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
Disables wireless interfaces via nmcli and rfkill and blacklists wireless kernel modules to eliminate wireless network access on servers that do not require it.
|
||||||
|
|
||||||
|
## Targeted OS
|
||||||
|
RHEL 9 / AlmaLinux 9 / Rocky Linux 9
|
||||||
|
|
||||||
|
## CIS Alignment
|
||||||
|
CIS Section 3.1.2 — Ensure wireless interfaces are disabled
|
||||||
|
|
||||||
|
## Key Variables
|
||||||
|
```yaml
|
||||||
|
linux_wireless_rhel9_disabled: false # set to true to skip this role
|
||||||
|
```
|
||||||
|
|
||||||
|
See `defaults/main.yml` for all tunable parameters.
|
||||||
10
roles/linux_wireless_rhel9/defaults/main.yml
Normal file
10
roles/linux_wireless_rhel9/defaults/main.yml
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
# CIS 3.1.2 — Ensure wireless interfaces are disabled
|
||||||
|
linux_wireless_disable: true
|
||||||
|
|
||||||
|
# Blacklist wireless kernel modules (fallback if nmcli not available)
|
||||||
|
linux_wireless_blacklist_modules: true
|
||||||
|
|
||||||
|
# Role disable var
|
||||||
|
linux_wireless_disabled: false
|
||||||
5
roles/linux_wireless_rhel9/handlers/main.yml
Normal file
5
roles/linux_wireless_rhel9/handlers/main.yml
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
# No service handlers needed for wireless disabling
|
||||||
|
|
||||||
|
...
|
||||||
5
roles/linux_wireless_rhel9/tasks/main.yml
Normal file
5
roles/linux_wireless_rhel9/tasks/main.yml
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
- name: "Disable wireless interfaces (RHEL 9 family)"
|
||||||
|
when: "not (linux_wireless_disabled | default(false) | bool)"
|
||||||
|
ansible.builtin.import_tasks: "tasks.yml"
|
||||||
|
tags: "linux_wireless_rhel9"
|
||||||
63
roles/linux_wireless_rhel9/tasks/tasks.yml
Normal file
63
roles/linux_wireless_rhel9/tasks/tasks.yml
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
---
|
||||||
|
# CIS 3.1.2 — Ensure wireless interfaces are disabled
|
||||||
|
|
||||||
|
- name: "Check if NetworkManager CLI (nmcli) is available"
|
||||||
|
ansible.builtin.command: "which nmcli"
|
||||||
|
changed_when: false
|
||||||
|
register: "nmcli_available"
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: "Check current wireless radio state"
|
||||||
|
ansible.builtin.command: "nmcli radio all"
|
||||||
|
changed_when: false
|
||||||
|
register: "nmcli_radio_state"
|
||||||
|
when:
|
||||||
|
- "linux_wireless_disable | bool"
|
||||||
|
- "nmcli_available.rc == 0"
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: "Disable all wireless interfaces via nmcli (CIS 3.1.2)"
|
||||||
|
ansible.builtin.command: "nmcli radio all off"
|
||||||
|
when:
|
||||||
|
- "linux_wireless_disable | bool"
|
||||||
|
- "nmcli_available.rc == 0"
|
||||||
|
- "'enabled' in (nmcli_radio_state.stdout | lower)"
|
||||||
|
register: "wireless_nmcli_result"
|
||||||
|
changed_when: true
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: "Blacklist wireless kernel modules as fallback / defense-in-depth (CIS 3.1.2)"
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: |
|
||||||
|
# CIS 3.1.2 — Disable wireless kernel modules
|
||||||
|
# Managed by Ansible role: linux_wireless_rhel9
|
||||||
|
install iwlwifi /bin/false
|
||||||
|
blacklist iwlwifi
|
||||||
|
install cfg80211 /bin/false
|
||||||
|
blacklist cfg80211
|
||||||
|
install mac80211 /bin/false
|
||||||
|
blacklist mac80211
|
||||||
|
install rtl8xxxu /bin/false
|
||||||
|
blacklist rtl8xxxu
|
||||||
|
install ath9k /bin/false
|
||||||
|
blacklist ath9k
|
||||||
|
dest: "/etc/modprobe.d/99-cis-wireless.conf"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
backup: true
|
||||||
|
when: "linux_wireless_blacklist_modules | bool"
|
||||||
|
register: "wireless_modprobe_result"
|
||||||
|
|
||||||
|
- name: "Notify about module blacklist (reboot needed for full effect)" # noqa: no-handler
|
||||||
|
when: "wireless_modprobe_result.changed"
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "Wireless module blacklist applied. Reboot required for full effect."
|
||||||
|
|
||||||
|
- name: "Debug wireless hardening status (verbosity >=1)"
|
||||||
|
when: "ansible_verbosity >= 1"
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg:
|
||||||
|
- "nmcli available: {{ nmcli_available.rc == 0 }}"
|
||||||
|
- "nmcli wireless disabled: {{ wireless_nmcli_result.changed | default(false) }}"
|
||||||
|
- "kernel module blacklist applied: {{ wireless_modprobe_result.changed | default(false) }}"
|
||||||
|
|
@ -1,38 +1,8 @@
|
||||||
---
|
---
|
||||||
- name: Check if EPEL repo is already configured.
|
- name: Enable EPEL repo
|
||||||
stat:
|
|
||||||
path: "{{ epel_repofile_path }}"
|
|
||||||
register: epel_repofile_result
|
|
||||||
|
|
||||||
- name: Import EPEL GPG key.
|
|
||||||
rpm_key:
|
|
||||||
key: "{{ epel_repo_gpg_key_url }}"
|
|
||||||
state: present
|
|
||||||
register: result
|
|
||||||
until: result is succeeded
|
|
||||||
retries: 5
|
|
||||||
delay: 10
|
|
||||||
when: not epel_repofile_result.stat.exists
|
|
||||||
ignore_errors: "{{ ansible_check_mode }}"
|
|
||||||
|
|
||||||
- name: Install EPEL repo.
|
|
||||||
ansible.builtin.dnf:
|
ansible.builtin.dnf:
|
||||||
name: "{{ epel_repo_url }}"
|
name: epel-release
|
||||||
state: present
|
state: present
|
||||||
register: result
|
|
||||||
until: result is succeeded
|
|
||||||
retries: 5
|
|
||||||
delay: 10
|
|
||||||
when: not epel_repofile_result.stat.exists
|
|
||||||
|
|
||||||
#- name: Disable Main EPEL repo.
|
|
||||||
# ini_file:
|
|
||||||
# path: "/etc/yum.repos.d/epel.repo"
|
|
||||||
# section: epel
|
|
||||||
# option: enabled
|
|
||||||
# value: "{{ epel_repo_disable | ternary(0, 1) }}"
|
|
||||||
# no_extra_spaces: true
|
|
||||||
# mode: 0644
|
|
||||||
|
|
||||||
- name: Install soft from EPEL
|
- name: Install soft from EPEL
|
||||||
ansible.builtin.dnf:
|
ansible.builtin.dnf:
|
||||||
|
|
|
||||||
|
|
@ -11,13 +11,13 @@
|
||||||
# regexp: '^fastestmirror='
|
# regexp: '^fastestmirror='
|
||||||
# line: 'fastestmirror=True'
|
# line: 'fastestmirror=True'
|
||||||
|
|
||||||
- name: Enable fastestmirror in DNF
|
# - name: Enable fastestmirror in DNF
|
||||||
community.general.ini_file:
|
# community.general.ini_file:
|
||||||
path: /etc/dnf/dnf.conf
|
# path: /etc/dnf/dnf.conf
|
||||||
section: main
|
# section: main
|
||||||
option: fastestmirror
|
# option: fastestmirror
|
||||||
value: "True"
|
# value: "True"
|
||||||
state: present
|
# state: present
|
||||||
|
|
||||||
- name: Enable parallel downloads in DNF
|
- name: Enable parallel downloads in DNF
|
||||||
community.general.ini_file:
|
community.general.ini_file:
|
||||||
|
|
|
||||||
|
|
@ -18,13 +18,16 @@
|
||||||
- name: Syctl tuning
|
- name: Syctl tuning
|
||||||
ansible.builtin.include_tasks: sysctl_tuning.yml
|
ansible.builtin.include_tasks: sysctl_tuning.yml
|
||||||
|
|
||||||
|
|
||||||
|
############# DEPRICATED ###################
|
||||||
# - name: Setup NIC to eth0
|
# - name: Setup NIC to eth0
|
||||||
# ansible.builtin.include_tasks:
|
# ansible.builtin.include_tasks:
|
||||||
# file: set_network_nic.yml
|
# file: set_network_nic.yml
|
||||||
|
#
|
||||||
# - name: Setup NIC to eth0
|
# - name: Setup NIC to eth0
|
||||||
# ansible.builtin.include_tasks:
|
# ansible.builtin.include_tasks:
|
||||||
# file: set_nic_names_eth.yml
|
# file: set_nic_names_eth.yml
|
||||||
|
#############################################
|
||||||
|
|
||||||
- name: Install packages
|
- name: Install packages
|
||||||
ansible.builtin.include_tasks:
|
ansible.builtin.include_tasks:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue