initial commit

This commit is contained in:
2026-09-13 13:12:07 -06:00
commit 3075996ad5
7 changed files with 280 additions and 0 deletions

5
.codegraph/.gitignore vendored Normal file
View 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

View 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
View 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.

2
README.md Normal file
View File

@@ -0,0 +1,2 @@
# stoat

186
harden_fedora44.yml Normal file
View 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
View 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
View 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
# --------------------------------------------------------------