186 lines
6.4 KiB
YAML
186 lines
6.4 KiB
YAML
---
|
||
# --------------------------------------------------------------
|
||
# Ansible playbook: Harden a Fedora 44 server & install Fail2Ban
|
||
# --------------------------------------------------------------
|
||
# Requirements:
|
||
# - Ansible >= 2.14
|
||
# - A reachable Fedora 44 host with SSH access (password or key)
|
||
# - `sudo` rights for the control user (via become: true)
|
||
# --------------------------------------------------------------
|
||
|
||
- name: Harden Fedora 44 & install Fail2Ban
|
||
hosts: all
|
||
become: true # elevates to root for package/service ops
|
||
vars:
|
||
# ---- Tunables -------------------------------------------------
|
||
# Change these to match your environment
|
||
fail2ban_port: "22" # default SSH jail; can be "http","https",etc.
|
||
fail2ban_maxretry: 3 # how many attempts before ban
|
||
fail2ban_bantime: 3600 # seconds (1 h)
|
||
# -----------------------------------------------------------------
|
||
# Ensure we are on Fedora 44 (you can relax this if you wish)
|
||
fedora_release: "44"
|
||
tasks:
|
||
# --------------------------------------------------------------
|
||
# Verify OS version (informational, can be removed)
|
||
# --------------------------------------------------------------
|
||
- name: Gather os fact
|
||
ansible.builtin.debug:
|
||
var: ansible_distribution_version
|
||
|
||
- name: Ensure we are running Fedora {{ fedora_release }}
|
||
ansible.builtin.assert:
|
||
that:
|
||
- ansible_distribution == "Fedora"
|
||
- ansible_distribution_version == fedora_release
|
||
fail_msg: "This playbook targets Fedora {{ fedora_release }} only."
|
||
success_msg: "Running on the correct Fedora version."
|
||
|
||
# --------------------------------------------------------------
|
||
# Update / upgrade all packages
|
||
# --------------------------------------------------------------
|
||
- name: Update all packages to latest versions
|
||
ansible.builtin.dnf:
|
||
name: "*"
|
||
state: latest
|
||
update_cache: true
|
||
|
||
# --------------------------------------------------------------
|
||
# Install essential hardening packages
|
||
# --------------------------------------------------------------
|
||
- name: Install fail2ban, firewalld, and sudo
|
||
ansible.builtin.dnf:
|
||
name:
|
||
- fail2ban
|
||
- firewalld
|
||
- sudo
|
||
state: present
|
||
|
||
# --------------------------------------------------------------
|
||
# Start & enable firewalld (default-deny all, allow SSH)
|
||
# --------------------------------------------------------------
|
||
- name: Start and enable firewalld
|
||
ansible.builtin.systemd:
|
||
name: firewalld
|
||
state: started
|
||
enabled: true
|
||
|
||
- name: Allow SSH service through firewalld
|
||
ansible.builtin.command:
|
||
cmd: firewall-cmd --permanent --add-service=ssh
|
||
changed_when: false # idempotent check handled by firewall_cmd
|
||
|
||
- name: Reload firewalld to apply rules
|
||
ansible.builtin.command:
|
||
cmd: firewall-cmd --reload
|
||
changed_when: false
|
||
|
||
# --------------------------------------------------------------
|
||
# Harden SSH (disable root login, enforce key‑only auth)
|
||
# --------------------------------------------------------------
|
||
- name: Ensure SSH config directory exists
|
||
ansible.builtin.file:
|
||
path: /etc/ssh/sshd_config.d
|
||
state: directory
|
||
mode: "0755"
|
||
|
||
- name: Disable root login via SSH
|
||
ansible.builtin.lineinfile:
|
||
path: /etc/ssh/sshd_config.d/00-disable-root.conf
|
||
create: true
|
||
mode: "0644"
|
||
line: "PermitRootLogin no"
|
||
state: present
|
||
|
||
- name: Enforce password-auth disabled (key-only)
|
||
ansible.builtin.lineinfile:
|
||
path: /etc/ssh/sshd_config.d/00-key-only.conf
|
||
create: true
|
||
mode: "0644"
|
||
line: "PasswordAuthentication no"
|
||
state: present
|
||
|
||
- name: Require MFA (optional) — add if you use Duo, etc.
|
||
ansible.builtin.lineinfile:
|
||
path: /etc/ssh/sshd_config.d/00-mfa.conf
|
||
create: true
|
||
mode: "0644"
|
||
line: "AuthenticationMethods publickey,keyboard-interactive:pam"
|
||
state: present
|
||
|
||
- name: Restart sshd to apply changes
|
||
ansible.builtin.service:
|
||
name: sshd
|
||
state: restarted
|
||
|
||
# --------------------------------------------------------------
|
||
# Configure Fail2Ban
|
||
# --------------------------------------------------------------
|
||
- name: template fail2ban jail.local
|
||
ansible.builtin.template:
|
||
src: jail.local.j2
|
||
dest: /etc/fail2ban/jail.local
|
||
mode: "0644"
|
||
notify: Restart fail2ban
|
||
|
||
- name: Ensure fail2ban is started & enabled
|
||
ansible.builtin.service:
|
||
name: fail2ban
|
||
state: started
|
||
enabled: true
|
||
|
||
# --------------------------------------------------------------
|
||
# (Optional) Install & configure unattended‑security updates
|
||
# --------------------------------------------------------------
|
||
- name: Install dnf-automatic (security-only)
|
||
ansible.builtin.dnf:
|
||
name: dnf-automatic
|
||
state: present
|
||
|
||
- name: Enable security-only automatic updates
|
||
ansible.builtin.lineinfile:
|
||
path: /etc/dnf/automatic.conf
|
||
regexp: "^update_type"
|
||
line: "update_type = security"
|
||
state: present
|
||
|
||
- name: Enable and start dnf-automatic.timer
|
||
ansible.builtin.systemd:
|
||
name: "@dnf-automatic.timer"
|
||
state: started
|
||
enabled: true
|
||
|
||
# --------------------------------------------------------------
|
||
# Log rotation for security‑relevant logs
|
||
# --------------------------------------------------------------
|
||
- name: Ensure rsyslog is running
|
||
ansible.builtin.service:
|
||
name: rsyslog
|
||
state: started
|
||
enabled: true
|
||
|
||
- name: Add logrotate rule for fail2ban logs
|
||
ansible.builtin.lineinfile:
|
||
path: /etc/logrotate.d/fail2ban
|
||
create: true
|
||
mode: "0644"
|
||
content: |
|
||
/var/log/fail2ban/*.log {
|
||
daily
|
||
rotate 7
|
||
compress
|
||
missingok
|
||
notifempty
|
||
postrotate
|
||
/usr/bin/fail2ban-client reload >/dev/null 2>&1 || true
|
||
endscript
|
||
}
|
||
|
||
# --------------------------------------------------------------
|
||
# 9 Handlers
|
||
# --------------------------------------------------------------
|
||
handlers:
|
||
- name: Restart fail2ban
|
||
ansible.builtin.service:
|
||
name: fail2ban
|
||
state: restarted |