Linux Hardening Using Ansible

Table of Contents

Lets autotmate what was discussed in previous posts.

Feature

Any of this list can be enabled or disabled and is group as roles. User Management

  • User and Group Creation
  • Add user to group
  • Add user public key
  • Option to add to sudo/wheel group
  • Set user password aging

Access Control

  • Disable root access through SSH
  • Disable password authentication
  • Set maximum simultaneous login
  • Add SSH Login Banner
  • Set password complexity
  • Enable firewall and add SSH

Package Management

  • Update repo and upgrade current package
  • Enable automatic install/upgrade security package
  • Enable fail2ban
  • Enable logrotate
  • Enable NTP/Chrony
  • Disable unnecessary package

System Hardening

  • Removed development pacakge
  • Make security dir immutable
  • Enable system audit
  • Enable Advanced Intrusion Detection Environment
  • Kernel hardening sysctl
  • Ensure sudo use password and uses log

SSH Login Alert (Bonus)

  • Send alert to telegram bot when user login

Environment

I’ve dockerized ansible - tailored to the specific task. Check Dockerfile if you want to run it locally.

First clone the repo.

1git clone https://github.com/mcbtaguiad/libvirt-cloudinit-ansible.git

Build the package or just pull the image from gihub registry.

1cd linux-hardening-playbook
2docker compose build 
3docker compose up -d
4
5# or
6docker compose up -d

Configuration

Inventory

This will use sudo so set ansible_user to root or a user with root access.

inventory/hosts.ini

1[all]
2server01 ansible_host=192.168.254.101 ansible_user=mcbtaguiad
3server02 ansible_host=192.168.254.102 ansible_user=mcbtaguiad
4
5[debian-server]
6server01 ansible_host=192.168.254.101 ansible_user=mcbtaguiad
7
8[redhat-server]
9server02 ansible_host=192.168.254.102 ansible_user=mcbtaguiad

Playbook

Run individual role or just run the main playbook.

main.yaml

 1---
 2- name: main playbook
 3  hosts: all
 4  become: true          # use sudo for all tasks
 5  become_method: sudo
 6  # ansible_become_pass: "YOUR_SUDO_PASSWORD"
 7  roles:
 8    - role: user_management
 9      vars:
10        password_maxdays: 90
11        password_warndays: 7
12        users:
13        - name: mark
14          sudo: true
15          key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDtf3e9lQR1uAypz4nrq2nDj0DvZZGONku5wO+M87wUVTistrY8REsWO2W1N/v4p2eX30Bnwk7D486jmHGpXFrpHM0EMf7wtbNj5Gt1bDHo76WSci/IEHpMrbdD5vN8wCW2ZMwJG4JC8lfFpUbdmUDWLL21Quq4q9XDx7/ugs1tCZoNybgww4eCcAi7/GAmXcS/u9huUkyiX4tbaKXQx1co7rTHd7f2u5APTVMzX0C1V9Ezc6l8I+LmjZ9rvQav5N1NgFh9B60qk9QJAb8AK9+aYy7bnBCBJ/BwIkWKYmLoVBi8j8v8UVhVdQMvQxLax41YcD8pbgU5s1O2nxM1+TqeGxrGHG6f7jqxhGWe21I7i8HPvOHNJcW4oycxFC5PNKnXNybEawE23oIDQfIG3+EudQKfAkJ3YhmrB2l+InIo0Wi9BHBIUNPzTldMS53q2teNdZR9UDqASdBdMgp4Uzfs1+LGdE5ExecSQzt4kZ8+o9oo9hmee4AYNOTWefXdip0= mtaguiad@tags-p51"
16          groups:
17            - admins
18            - developers
19        - name: christian
20          sudo: false
21          key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDtf3e9lQR1uAypz4nrq2nDj0DvZZGONku5wO+M87wUVTistrY8REsWO2W1N/v4p2eX30Bnwk7D486jmHGpXFrpHM0EMf7wtbNj5Gt1bDHo76WSci/IEHpMrbdD5vN8wCW2ZMwJG4JC8lfFpUbdmUDWLL21Quq4q9XDx7/ugs1tCZoNybgww4eCcAi7/GAmXcS/u9huUkyiX4tbaKXQx1co7rTHd7f2u5APTVMzX0C1V9Ezc6l8I+LmjZ9rvQav5N1NgFh9B60qk9QJAb8AK9+aYy7bnBCBJ/BwIkWKYmLoVBi8j8v8UVhVdQMvQxLax41YcD8pbgU5s1O2nxM1+TqeGxrGHG6f7jqxhGWe21I7i8HPvOHNJcW4oycxFC5PNKnXNybEawE23oIDQfIG3+EudQKfAkJ3YhmrB2l+InIo0Wi9BHBIUNPzTldMS53q2teNdZR9UDqASdBdMgp4Uzfs1+LGdE5ExecSQzt4kZ8+o9oo9hmee4AYNOTWefXdip0= mtaguiad@tags-p51"
22          groups:
23            - developers
24
25    - role: access_control
26      vars:
27        max_logins: 2
28        password_minlen: 12
29
30     - role: package
31       vars:
32         unnecessary_services:
33          - cups
34          - rpcbind
35          - nfs-server
36          - vsftpd 
37
38     - role: system_hardening
39       vars:
40         devel_packages_debian:
41          - gcc
42          - g++
43          - make
44          - build-essential
45          - kernel-devel
46          - linux-headers-$(uname -r)
47        devel_packages_redhat:
48          - gcc
49          - gcc-c++
50          - make
51          - kernel-devel
52          - redhat-lsb-core
53          - perl
54        secure_dirs:
55          - /etc/ssh
56          - /etc/sudoers.d
57        kernel_hardening:
58          net.ipv4.ip_forward: 0
59          net.ipv4.conf.all.accept_redirects: 0
60          net.ipv4.conf.all.send_redirects: 0
61          net.ipv4.conf.all.accept_source_route: 0
62          net.ipv4.tcp_syncookies: 1
63          net.ipv4.conf.all.rp_filter: 1
64          kernel.randomize_va_space: 2
65
66    - role: ssh_login_alert
67      vars:
68        telegram_bot_token: "xxxxxxxxxxxxxxx"
69        telegram_chat_id: "xxxxxxxxx"

Disable and set what you need to be configured in your host/server.

Exec to docker container.

1docker exec -it ansible-linux-hardening  bash

Run playbook.

1ansible-playbook playbook/main.yml -i inventory/hosts.ini