<!-- Copyright (c) 2026 defconxt. All rights reserved. -->
<!-- Licensed under AGPL-3.0 — see LICENSE file for details. -->

# Ansible CIS Hardening Reference

## Role Structure

`defaults/main.yml` (toggle flags), `tasks/` (idempotent controls), `handlers/` (restart triggers), `vars/` (OS-specific).

## Kernel Module Hardening (CIS 1.1.1.x)

```yaml
- name: "CIS 1.1.1.1 | Disable cramfs"
  ansible.builtin.lineinfile:
    dest: /etc/modprobe.d/cis.conf
    regexp: '^install cramfs'
    line: "install cramfs /bin/false"
    state: present
    create: true
    owner: root
    group: root
    mode: "0644"
- community.general.modprobe:
    name: cramfs
    state: absent
  when: ansible_facts['virtualization_type'] != "docker"
```

Blacklist pattern applies to: cramfs, freevxfs, hfs, hfsplus, jffs2, squashfs, udf, usb-storage (CIS 1.1.1.1–1.1.1.8).

## Sysctl Security Hardening

```yaml
- ansible.posix.sysctl:
    name: "{{ item.key }}"
    value: "{{ item.value }}"
    sysctl_set: true
    sysctl_file: /etc/sysctl.d/90-hardening.conf
    state: present
    reload: true
  with_dict:
    fs.protected_hardlinks: 1
    fs.protected_symlinks: 1
    fs.protected_fifos: 1
    fs.protected_regular: 2
    fs.suid_dumpable: 0
    kernel.kptr_restrict: 2
    kernel.kexec_load_disabled: 1
    kernel.randomize_va_space: 2
    kernel.yama.ptrace_scope: 1
    net.ipv4.conf.all.rp_filter: 1
    net.ipv4.conf.default.rp_filter: 1
    net.ipv4.icmp_echo_ignore_broadcasts: 1
    net.ipv4.tcp_syncookies: 1
    net.ipv4.tcp_timestamps: 0
    net.ipv4.ip_forward: 0
    net.ipv6.conf.all.forwarding: 0
```

## SSH Hardening Role

```yaml
- ansible.builtin.template:
    src: opensshd.conf.j2
    dest: /etc/ssh/sshd_config
    mode: "0600"
    owner: root
    group: root
    validate: "sshd -T -C user=root -C host=localhost -C addr=localhost -C lport=22 -f %s"
  notify: Restart sshd
```

Key sshd_config values: `PermitRootLogin no`, `MaxAuthTries 2`, `LoginGraceTime 30s`, `PasswordAuthentication no`, `X11Forwarding no`, `AllowAgentForwarding no`, `MaxSessions 2`, RSA key size 4096.

## UFW Firewall (CIS 4.x)

`community.general.ufw: rule=allow to_port=22 protocol=tcp log=true` then `state=enabled default=deny direction=incoming`.

## Logging/Audit (CIS 6.x)

Enable `systemd-journald.service`; set `Storage=persistent` in `/etc/systemd/journald.conf` via `lineinfile`. Enable auditd and configure rules for SUID executions, privilege escalation, and file access to `/etc/passwd`.

## User Account Hardening

`os_auth_pw_max_age: 60`, `os_auth_pw_min_age: 7`, `os_auth_retries: 5`, `os_auth_lockout_time: 600`, `os_remove_additional_root_users: true`, `os_security_suid_sgid_enforce: true`.

Remove insecure packages: `os_security_packages_list: [xinetd, inetd, ypserv, telnet-server, rsh-server, prelink]`.

## Anti-Patterns

- Raw `command:` instead of `ansible.posix.sysctl:` — breaks idempotency and `check_mode`.
- Skipping `validate:` on sshd_config template — a bad template locks you out.
