Stage 4 · Provision
Secrets & Security
Hardening Playbooks
CIS benchmarks, SSH hardening, and compliance baselines.
CIS Benchmarks
The Center for Internet Security (CIS) publishes security benchmarks for major operating systems. These benchmarks define hundreds of configuration settings — password policies, file permissions, service configurations — that harden systems against common attacks.
---
- name: CIS-inspired hardening
hosts: all
become: yes
tasks:
- name: Set password policy
ansible.builtin.lineinfile:
path: /etc/login.defs
regexp: "^PASS_MAX_DAYS"
line: "PASS_MAX_DAYS 90"
- name: Set minimum password length
ansible.builtin.lineinfile:
path: /etc/login.defs
regexp: "^PASS_MIN_LEN"
line: "PASS_MIN_LEN 12"
- name: Disable unused filesystems
ansible.builtin.lineinfile:
path: /etc/modprobe.d/blacklist.conf
line: "install cramfs /bin/true"
create: yesCIS benchmarks provide specific, testable settings. Implement them as Ansible tasks for consistent, auditable hardening.
SSH Hardening
- name: Harden SSH configuration
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
loop:
- { regexp: "^#?PermitRootLogin", line: "PermitRootLogin no" }
- { regexp: "^#?PasswordAuthentication", line: "PasswordAuthentication no" }
- { regexp: "^#?X11Forwarding", line: "X11Forwarding no" }
- { regexp: "^#?MaxAuthTries", line: "MaxAuthTries 3" }
- { regexp: "^#?ClientAliveInterval", line: "ClientAliveInterval 300" }
- { regexp: "^#?ClientAliveCountMax", line: "ClientAliveCountMax 2" }
notify: Restart sshd
- name: Restrict SSH key exchange algorithms
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config
line: "KexAlgorithms curve25519-sha256@libssh.org"
notify: Restart sshdSSH hardening is one of the most impactful security measures. Disable password authentication, limit root access, and restrict algorithms.
Firewall Management
- name: Configure UFW firewall
community.general.ufw:
rule: "{{ item.rule }}"
port: "{{ item.port }}"
proto: "{{ item.proto }}"
state: enabled
loop:
- { rule: allow, port: "22", proto: tcp }
- { rule: allow, port: "80", proto: tcp }
- { rule: allow, port: "443", proto: tcp }
- { rule: deny, port: "23", proto: tcp }
- name: Set default deny policy
community.general.ufw:
direction: incoming
default: denyFirewall rules should be managed declaratively. Define allowed ports and deny everything else by default.
Compliance Checking
- name: Check compliance
hosts: all
tasks:
- name: Verify password policy
ansible.builtin.lineinfile:
path: /etc/login.defs
regexp: "^PASS_MAX_DAYS"
line: "PASS_MAX_DAYS 90"
check_mode: yes
register: result
failed_when: result.changed
- name: Verify SSH config
ansible.builtin.command: sshd -T
register: sshd_config
changed_when: false
- name: Fail if root login enabled
ansible.builtin.fail:
msg: "Root login is enabled — non-compliant"
when: "'permitrootlogin yes' in sshd_config.stdout | lower"Compliance tasks verify configuration without making changes. Use check_mode or read-only commands to audit state.
Building a Hardening Role
roles/
hardening/
defaults/main.yml
tasks/
main.yml
ssh.yml
firewall.yml
kernel.yml
handlers/main.yml
templates/
sysctl.conf.j2
molecule/
default/
molecule.yml
converge.ymlPackage hardening into a role for reuse across environments. Use molecule to test the role against different OS images.
Community roles like dev-sec.os-hardening and dev-sec.ssh-hardening implement CIS benchmarks. Install them from Galaxy and customize for your environment.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.