194 lines
7.4 KiB
YAML
194 lines
7.4 KiB
YAML
---
|
|
- name: Comprehensive Security Audit
|
|
hosts: all
|
|
become: true
|
|
gather_facts: true
|
|
|
|
tasks:
|
|
- name: Gather security information
|
|
block:
|
|
- name: Check SSH configuration
|
|
ansible.builtin.shell: |
|
|
echo "=== SSH Configuration ==="
|
|
sshd -T | grep -E '(permitrootlogin|passwordauthentication|pubkeyauthentication|permitemptypasswords|port)'
|
|
register: ssh_config
|
|
changed_when: false
|
|
|
|
- name: Check for users with empty passwords
|
|
ansible.builtin.shell: |
|
|
echo "=== Users with Empty Passwords ==="
|
|
awk -F: '($2 == "" || $2 == "!") {print $1}' /etc/shadow 2>/dev/null | head -20 || echo "Unable to check (requires root)"
|
|
register: empty_passwords
|
|
changed_when: false
|
|
failed_when: false
|
|
|
|
- name: Check sudo users
|
|
ansible.builtin.shell: |
|
|
echo "=== Sudo Users ==="
|
|
getent group sudo 2>/dev/null || getent group wheel 2>/dev/null || echo "No sudo group found"
|
|
register: sudo_users
|
|
changed_when: false
|
|
|
|
- name: Check firewall status
|
|
ansible.builtin.shell: |
|
|
echo "=== Firewall Status ==="
|
|
if command -v ufw >/dev/null 2>&1; then
|
|
ufw status verbose 2>/dev/null || echo "UFW not enabled"
|
|
elif command -v firewall-cmd >/dev/null 2>&1; then
|
|
firewall-cmd --list-all
|
|
else
|
|
echo "No firewall detected"
|
|
fi
|
|
register: firewall_status
|
|
changed_when: false
|
|
|
|
- name: Check open ports
|
|
ansible.builtin.shell: |
|
|
echo "=== Open Network Ports ==="
|
|
ss -tlnp | grep LISTEN | head -30
|
|
register: open_ports
|
|
changed_when: false
|
|
|
|
- name: Check failed login attempts
|
|
ansible.builtin.shell: |
|
|
echo "=== Recent Failed Login Attempts ==="
|
|
grep "Failed password" /var/log/auth.log 2>/dev/null | tail -10 || \
|
|
journalctl -u sshd --no-pager -n 20 | grep -i "failed\|authentication failure" || \
|
|
echo "No recent failed attempts or unable to check logs"
|
|
register: failed_logins
|
|
changed_when: false
|
|
failed_when: false
|
|
|
|
- name: Check for automatic updates
|
|
ansible.builtin.shell: |
|
|
echo "=== Automatic Updates Status ==="
|
|
if [ -f /etc/apt/apt.conf.d/20auto-upgrades ]; then
|
|
cat /etc/apt/apt.conf.d/20auto-upgrades
|
|
elif [ -f /etc/dnf/automatic.conf ]; then
|
|
grep -E "^apply_updates" /etc/dnf/automatic.conf
|
|
else
|
|
echo "Automatic updates not configured"
|
|
fi
|
|
register: auto_updates
|
|
changed_when: false
|
|
failed_when: false
|
|
|
|
- name: Check system updates available
|
|
ansible.builtin.shell: |
|
|
echo "=== Available Security Updates ==="
|
|
if command -v apt-get >/dev/null 2>&1; then
|
|
apt-get update -qq 2>/dev/null && apt-get -s upgrade | grep -i security || echo "No security updates or unable to check"
|
|
elif command -v yum >/dev/null 2>&1; then
|
|
yum check-update --security 2>/dev/null | tail -20 || echo "No security updates or unable to check"
|
|
fi
|
|
register: security_updates
|
|
changed_when: false
|
|
failed_when: false
|
|
|
|
- name: Check Docker security (if installed)
|
|
ansible.builtin.shell: |
|
|
echo "=== Docker Security ==="
|
|
if command -v docker >/dev/null 2>&1; then
|
|
echo "Docker version:"
|
|
docker --version
|
|
echo ""
|
|
echo "Running containers:"
|
|
docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}' | head -20
|
|
echo ""
|
|
echo "Docker daemon config:"
|
|
if [ -f /etc/docker/daemon.json ]; then
|
|
cat /etc/docker/daemon.json
|
|
else
|
|
echo "No daemon.json found (using defaults)"
|
|
fi
|
|
else
|
|
echo "Docker not installed"
|
|
fi
|
|
register: docker_security
|
|
changed_when: false
|
|
failed_when: false
|
|
|
|
- name: Check for world-writable files in critical directories
|
|
ansible.builtin.shell: |
|
|
echo "=== World-Writable Files (Sample) ==="
|
|
find /etc /usr/bin /usr/sbin -type f -perm -002 2>/dev/null | head -10 || echo "No world-writable files found or unable to check"
|
|
register: world_writable
|
|
changed_when: false
|
|
failed_when: false
|
|
|
|
- name: Check password policies
|
|
ansible.builtin.shell: |
|
|
echo "=== Password Policy ==="
|
|
if [ -f /etc/login.defs ]; then
|
|
grep -E "^PASS_MAX_DAYS|^PASS_MIN_DAYS|^PASS_MIN_LEN|^PASS_WARN_AGE" /etc/login.defs
|
|
else
|
|
echo "Password policy file not found"
|
|
fi
|
|
register: password_policy
|
|
changed_when: false
|
|
failed_when: false
|
|
|
|
always:
|
|
- name: Display security audit results
|
|
ansible.builtin.debug:
|
|
msg: |
|
|
|
|
╔════════════════════════════════════════════════════════════════╗
|
|
║ Security Audit Report: {{ inventory_hostname }}
|
|
╚════════════════════════════════════════════════════════════════╝
|
|
|
|
{{ ssh_config.stdout }}
|
|
|
|
{{ empty_passwords.stdout }}
|
|
|
|
{{ sudo_users.stdout }}
|
|
|
|
{{ firewall_status.stdout }}
|
|
|
|
{{ open_ports.stdout }}
|
|
|
|
{{ failed_logins.stdout }}
|
|
|
|
{{ auto_updates.stdout }}
|
|
|
|
{{ security_updates.stdout }}
|
|
|
|
{{ docker_security.stdout }}
|
|
|
|
{{ world_writable.stdout }}
|
|
|
|
{{ password_policy.stdout }}
|
|
|
|
- name: Generate Security Summary
|
|
hosts: localhost
|
|
gather_facts: false
|
|
|
|
tasks:
|
|
- name: Create security report summary
|
|
ansible.builtin.debug:
|
|
msg: |
|
|
|
|
╔════════════════════════════════════════════════════════════════╗
|
|
║ Security Audit Complete ║
|
|
╚════════════════════════════════════════════════════════════════╝
|
|
|
|
Review the output above for each server.
|
|
|
|
Key Security Checks Performed:
|
|
✓ SSH configuration and hardening
|
|
✓ User account security
|
|
✓ Firewall configuration
|
|
✓ Open network ports
|
|
✓ Failed login attempts
|
|
✓ Automatic updates
|
|
✓ Available security patches
|
|
✓ Docker security (if applicable)
|
|
✓ File permissions
|
|
✓ Password policies
|
|
|
|
Next Steps:
|
|
1. Review findings for each server
|
|
2. Address any critical issues found
|
|
3. Implement security recommendations
|
|
4. Run audit regularly to track improvements
|