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