- Terraform + Ansible + K3s + Vault + Consul + Observability - Decentralized network architecture (own datacenters) - Complete Ansible playbooks: - bootstrap.yml: OS setup, packages, SSH - hardening.yml: Security (UFW, fail2ban, auditd, Trivy) - k3s-install.yml: Lightweight Kubernetes cluster - Production inventory with NODE1, NODE3 - Group variables for all nodes - Security check cron script - Multi-DC ready with Consul support
289 lines
9.8 KiB
YAML
289 lines
9.8 KiB
YAML
# DAARION Network - Security Hardening Playbook
|
|
# Comprehensive security setup for all nodes
|
|
---
|
|
- name: Security Hardening
|
|
hosts: all
|
|
become: yes
|
|
|
|
vars:
|
|
allowed_ssh_port: "{{ ansible_port | default(22) }}"
|
|
|
|
tasks:
|
|
# =========================================================================
|
|
# SECURITY PACKAGES
|
|
# =========================================================================
|
|
- name: Install security packages
|
|
apt:
|
|
name: "{{ security_packages }}"
|
|
state: present
|
|
when: ansible_os_family == "Debian"
|
|
|
|
- name: Install Trivy (vulnerability scanner)
|
|
shell: |
|
|
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
|
|
args:
|
|
creates: /usr/local/bin/trivy
|
|
|
|
# =========================================================================
|
|
# UFW FIREWALL
|
|
# =========================================================================
|
|
- name: UFW - Reset to defaults
|
|
ufw:
|
|
state: reset
|
|
|
|
- name: UFW - Default deny incoming
|
|
ufw:
|
|
direction: incoming
|
|
policy: deny
|
|
|
|
- name: UFW - Default deny outgoing
|
|
ufw:
|
|
direction: outgoing
|
|
policy: deny
|
|
|
|
- name: UFW - Allow SSH
|
|
ufw:
|
|
rule: allow
|
|
port: "{{ allowed_ssh_port }}"
|
|
proto: tcp
|
|
|
|
- name: UFW - Allow necessary TCP ports
|
|
ufw:
|
|
rule: allow
|
|
port: "{{ item }}"
|
|
proto: tcp
|
|
loop: "{{ firewall_allowed_tcp_ports }}"
|
|
when: firewall_allowed_tcp_ports is defined
|
|
|
|
- name: UFW - Allow necessary outgoing
|
|
ufw:
|
|
rule: allow
|
|
direction: out
|
|
port: "{{ item.port }}"
|
|
proto: "{{ item.proto }}"
|
|
loop: "{{ firewall_allowed_outgoing }}"
|
|
|
|
- name: UFW - Block internal networks
|
|
ufw:
|
|
rule: deny
|
|
direction: out
|
|
to_ip: "{{ item }}"
|
|
loop: "{{ firewall_blocked_networks }}"
|
|
when: firewall_blocked_networks is defined
|
|
|
|
- name: UFW - Enable
|
|
ufw:
|
|
state: enabled
|
|
|
|
# =========================================================================
|
|
# FAIL2BAN
|
|
# =========================================================================
|
|
- name: Configure fail2ban
|
|
copy:
|
|
dest: /etc/fail2ban/jail.local
|
|
content: |
|
|
[DEFAULT]
|
|
bantime = 3600
|
|
findtime = 600
|
|
maxretry = 3
|
|
|
|
[sshd]
|
|
enabled = true
|
|
port = {{ allowed_ssh_port }}
|
|
filter = sshd
|
|
logpath = /var/log/auth.log
|
|
maxretry = 3
|
|
bantime = 86400
|
|
notify: restart fail2ban
|
|
|
|
- name: Enable fail2ban
|
|
service:
|
|
name: fail2ban
|
|
enabled: yes
|
|
state: started
|
|
|
|
# =========================================================================
|
|
# AUDITD
|
|
# =========================================================================
|
|
- name: Configure auditd rules
|
|
copy:
|
|
dest: /etc/audit/rules.d/daarion.rules
|
|
content: |
|
|
# Monitor file changes in critical directories
|
|
-w /etc/passwd -p wa -k passwd_changes
|
|
-w /etc/shadow -p wa -k shadow_changes
|
|
-w /etc/ssh/sshd_config -p wa -k sshd_config
|
|
|
|
# Monitor Docker
|
|
-w /var/lib/docker -p wa -k docker
|
|
-w /etc/docker -p wa -k docker_config
|
|
|
|
# Monitor cron
|
|
-w /etc/crontab -p wa -k cron
|
|
-w /etc/cron.d -p wa -k cron
|
|
|
|
# Monitor tmp (malware indicator)
|
|
-w /tmp -p x -k tmp_exec
|
|
-w /var/tmp -p x -k var_tmp_exec
|
|
notify: restart auditd
|
|
|
|
- name: Enable auditd
|
|
service:
|
|
name: auditd
|
|
enabled: yes
|
|
state: started
|
|
|
|
# =========================================================================
|
|
# KERNEL HARDENING
|
|
# =========================================================================
|
|
- name: Kernel security parameters
|
|
sysctl:
|
|
name: "{{ item.name }}"
|
|
value: "{{ item.value }}"
|
|
state: present
|
|
reload: yes
|
|
loop:
|
|
- { name: 'net.ipv4.conf.all.accept_redirects', value: '0' }
|
|
- { name: 'net.ipv4.conf.default.accept_redirects', value: '0' }
|
|
- { name: 'net.ipv4.conf.all.send_redirects', value: '0' }
|
|
- { name: 'net.ipv4.conf.default.send_redirects', value: '0' }
|
|
- { name: 'net.ipv4.tcp_syncookies', value: '1' }
|
|
- { name: 'net.ipv4.icmp_echo_ignore_broadcasts', value: '1' }
|
|
- { name: 'kernel.randomize_va_space', value: '2' }
|
|
- { name: 'kernel.kptr_restrict', value: '2' }
|
|
- { name: 'kernel.dmesg_restrict', value: '1' }
|
|
|
|
# =========================================================================
|
|
# SECURITY CHECK SCRIPT
|
|
# =========================================================================
|
|
- name: Deploy security check script
|
|
copy:
|
|
dest: "{{ scripts_dir }}/security-check.sh"
|
|
mode: '0755'
|
|
content: |
|
|
#!/bin/bash
|
|
# DAARION Security Check Script
|
|
# Runs hourly via cron
|
|
|
|
LOG="{{ logs_dir }}/security-$(date +%Y%m%d).log"
|
|
ALERT_FILE="/tmp/security_alert"
|
|
|
|
log() {
|
|
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG"
|
|
}
|
|
|
|
log "=== Security Check Started ==="
|
|
|
|
# Check for suspicious processes
|
|
SUSPICIOUS=$(ps aux | grep -E "(xmrig|kdevtmp|kinsing|perfctl|httpd.*tmp|mysql.*tmp)" | grep -v grep)
|
|
if [ -n "$SUSPICIOUS" ]; then
|
|
log "CRITICAL: Suspicious process detected!"
|
|
log "$SUSPICIOUS"
|
|
pkill -9 -f "xmrig|kdevtmp|kinsing|perfctl"
|
|
touch "$ALERT_FILE"
|
|
fi
|
|
|
|
# Check for executables in /tmp
|
|
TMP_EXEC=$(find /tmp /var/tmp /dev/shm -type f -executable 2>/dev/null)
|
|
if [ -n "$TMP_EXEC" ]; then
|
|
log "WARNING: Executable files in tmp directories!"
|
|
log "$TMP_EXEC"
|
|
rm -f $TMP_EXEC 2>/dev/null
|
|
fi
|
|
|
|
# Check CPU usage (potential mining)
|
|
LOAD=$(cat /proc/loadavg | cut -d' ' -f1)
|
|
CPU_COUNT=$(nproc)
|
|
THRESHOLD=$(echo "$CPU_COUNT * 2" | bc)
|
|
if (( $(echo "$LOAD > $THRESHOLD" | bc -l) )); then
|
|
log "WARNING: High CPU load: $LOAD (threshold: $THRESHOLD)"
|
|
fi
|
|
|
|
# Check for unauthorized SSH keys
|
|
for user_home in /root /home/*; do
|
|
if [ -f "$user_home/.ssh/authorized_keys" ]; then
|
|
KEY_COUNT=$(wc -l < "$user_home/.ssh/authorized_keys")
|
|
log "INFO: $user_home has $KEY_COUNT SSH keys"
|
|
fi
|
|
done
|
|
|
|
# Check failed SSH attempts
|
|
FAILED_SSH=$(grep "Failed password" /var/log/auth.log 2>/dev/null | wc -l)
|
|
log "INFO: Failed SSH attempts today: $FAILED_SSH"
|
|
|
|
# Check Docker containers
|
|
if command -v docker &> /dev/null; then
|
|
CONTAINER_COUNT=$(docker ps -q | wc -l)
|
|
log "INFO: Running Docker containers: $CONTAINER_COUNT"
|
|
|
|
# Check for containers running as root
|
|
docker ps -q | while read cid; do
|
|
USER=$(docker inspect --format '{{.Config.User}}' $cid)
|
|
NAME=$(docker inspect --format '{{.Name}}' $cid)
|
|
if [ -z "$USER" ] || [ "$USER" = "root" ] || [ "$USER" = "0" ]; then
|
|
log "WARNING: Container $NAME running as root"
|
|
fi
|
|
done
|
|
fi
|
|
|
|
log "=== Security Check Completed ==="
|
|
|
|
- name: Setup security cron
|
|
cron:
|
|
name: "Hourly security check"
|
|
minute: "0"
|
|
job: "{{ scripts_dir }}/security-check.sh"
|
|
|
|
- name: Setup daily rkhunter scan
|
|
cron:
|
|
name: "Daily rkhunter scan"
|
|
hour: "3"
|
|
minute: "0"
|
|
job: "rkhunter --update && rkhunter --check --skip-keypress > {{ logs_dir }}/rkhunter.log 2>&1"
|
|
|
|
# =========================================================================
|
|
# AUTO UPDATES
|
|
# =========================================================================
|
|
- name: Configure unattended-upgrades
|
|
copy:
|
|
dest: /etc/apt/apt.conf.d/50unattended-upgrades
|
|
content: |
|
|
Unattended-Upgrade::Allowed-Origins {
|
|
"${distro_id}:${distro_codename}";
|
|
"${distro_id}:${distro_codename}-security";
|
|
"${distro_id}ESMApps:${distro_codename}-apps-security";
|
|
"${distro_id}ESM:${distro_codename}-infra-security";
|
|
};
|
|
Unattended-Upgrade::AutoFixInterruptedDpkg "true";
|
|
Unattended-Upgrade::Remove-Unused-Dependencies "true";
|
|
Unattended-Upgrade::Automatic-Reboot "false";
|
|
when: ansible_os_family == "Debian"
|
|
|
|
# =========================================================================
|
|
# VERIFICATION
|
|
# =========================================================================
|
|
- name: Verify security setup
|
|
shell: |
|
|
echo "=== Security Status ==="
|
|
echo "UFW: $(ufw status | head -1)"
|
|
echo "Fail2ban: $(systemctl is-active fail2ban)"
|
|
echo "Auditd: $(systemctl is-active auditd)"
|
|
echo "Trivy: $(trivy --version 2>/dev/null | head -1 || echo 'not installed')"
|
|
register: security_status
|
|
changed_when: false
|
|
|
|
- name: Show security status
|
|
debug:
|
|
var: security_status.stdout_lines
|
|
|
|
handlers:
|
|
- name: restart fail2ban
|
|
service:
|
|
name: fail2ban
|
|
state: restarted
|
|
|
|
- name: restart auditd
|
|
service:
|
|
name: auditd
|
|
state: restarted
|