initial commit
This commit is contained in:
5
.codegraph/.gitignore
vendored
Normal file
5
.codegraph/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
# CodeGraph data files — local to each machine, not for committing.
|
||||
# Ignore everything in .codegraph/ except this file itself, so transient
|
||||
# files (the database, daemon.pid, sockets, logs) never show up in git.
|
||||
*
|
||||
!.gitignore
|
||||
10
.omo/run-continuation/ses_f63e23ebcffe7Q6sJKCl9W8sFt.json
Normal file
10
.omo/run-continuation/ses_f63e23ebcffe7Q6sJKCl9W8sFt.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"sessionID": "ses_f63e23ebcffe7Q6sJKCl9W8sFt",
|
||||
"updatedAt": "2026-09-13T19:05:07.347Z",
|
||||
"sources": {
|
||||
"background-task": {
|
||||
"state": "idle",
|
||||
"updatedAt": "2026-09-13T19:05:07.347Z"
|
||||
}
|
||||
}
|
||||
}
|
||||
18
LICENSE
Normal file
18
LICENSE
Normal file
@@ -0,0 +1,18 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 boxswapper
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
||||
associated documentation files (the "Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
|
||||
following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial
|
||||
portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
||||
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
|
||||
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
186
harden_fedora44.yml
Normal file
186
harden_fedora44.yml
Normal file
@@ -0,0 +1,186 @@
|
||||
---
|
||||
# --------------------------------------------------------------
|
||||
# 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
|
||||
15
inventory.ini
Normal file
15
inventory.ini
Normal file
@@ -0,0 +1,15 @@
|
||||
# --------------------------------------------------------------
|
||||
# Ansible inventory - servers to harden
|
||||
# Usage: ansible-playbook -i inventory.ini harden_fedora44.yml
|
||||
# --------------------------------------------------------------
|
||||
|
||||
[servers]
|
||||
stoat-demo ansible_host=stoat-demo ansible_user=YOUR_SSH_USER
|
||||
|
||||
[servers:vars]
|
||||
# Elevate privileges (the playbook already sets become: true,
|
||||
# but this allows per-group override if needed)
|
||||
ansible_become=yes
|
||||
ansible_become_method=sudo
|
||||
# Optional: path to your SSH private key
|
||||
# ansible_ssh_private_key_file=/home/you/.ssh/id_ed25519
|
||||
44
jail.local.j2
Normal file
44
jail.local.j2
Normal file
@@ -0,0 +1,44 @@
|
||||
# --------------------------------------------------------------
|
||||
# Fail2Ban jail.local - default settings for Fedora 44
|
||||
# Values like {{ fail2ban_port }} come from the playbook vars
|
||||
# --------------------------------------------------------------
|
||||
|
||||
[DEFAULT]
|
||||
# Ban IPs after maxretry failures for bantime seconds
|
||||
bantime = {{ fail2ban_bantime }}
|
||||
maxretry = {{ fail2ban_maxretry }}
|
||||
# Raise ban time incrementally for repeat offenders
|
||||
bantime.increment = true
|
||||
bantime.factor = 2
|
||||
bantime.maxtime = 24h
|
||||
|
||||
# --------------------------------------------------------------
|
||||
# SSH jail - protects against brute-force login attempts
|
||||
# --------------------------------------------------------------
|
||||
[sshd]
|
||||
enabled = true
|
||||
port = {{ fail2ban_port }}
|
||||
filter = sshd
|
||||
logpath = /var/log/secure
|
||||
backend = systemd
|
||||
maxretry = {{ fail2ban_maxretry }}
|
||||
bantime = {{ fail2ban_bantime }}
|
||||
|
||||
# --------------------------------------------------------------
|
||||
# HTTP auth jail - uncomment if you run a web server
|
||||
# --------------------------------------------------------------
|
||||
#[http-auth]
|
||||
#enabled = true
|
||||
#port = http,https
|
||||
#filter = http-auth
|
||||
#logpath = /var/log/nginx/access.log
|
||||
#maxretry = {{ fail2ban_maxretry }}
|
||||
#bantime = {{ fail2ban_bantime }}
|
||||
|
||||
# --------------------------------------------------------------
|
||||
# Add more jails below as needed, e.g.:
|
||||
# [vsftpd] - FTP brute force
|
||||
# [postfix] - mail smtp auth failures
|
||||
# [dovecot] - IMAP/POP3 brute force
|
||||
# Each jail needs: enabled = true, filter, logpath
|
||||
# --------------------------------------------------------------
|
||||
Reference in New Issue
Block a user