Skip to content

Commit

Permalink
v7.0.0 (#19)
Browse files Browse the repository at this point in the history
* rename role harden-linux to harden_linux to follow Ansible Galaxy requirements

* README.md: add information about Molecule test

* rename molecule/kvm to molecule/default

* remove support for Ubuntu 18.04 (reached EOL)

* defaults/main.yml: fix link

* molecule/default/molecule.yml: rename host test-harden-linux-ubuntu1804-openntpd to test-harden-linux-ubuntu2204-openntpd

* molecule/default/molecule.yml: adjust verifier

* molecule/default/molecule.yml: rename test-harden-linux-ubuntu1804-openntpd to test-harden-linux-ubuntu2204-openntpd

* molecule/default/molecule.yml: rename scenario kvm to default

* molecule/default/molecule.yml: move memory and cpus properties to hosts

* molecule/default/molecule.yml: use generic/ubuntu2204 VM image instead of alvistack/ubuntu-22.04

* molecule/default/molecule.yml: remove role_name_check (no longer needed)

* tasks/ufw.yml: use community.general.ufw module instead of ansible.builtin.ufw (recommended by ansible-lint)

* tasks/sshguard.yml: formatting

* tasks/sshguard-archlinux.yml: fix mode value

* tasks/setup-ubuntu.yml: fix mode value

* remove tasks/sshguard-ubuntu-18.yml

* .ansible-lint: remove role-name / add name[template]

* tasks/setup-archlinux.yml: use community.general.pacman module instead of ansible.builtin.pacman (as recommended by ansible-lint)

* tasks/ntp_systemd-timesyncd.yml: improve the task key order

* tasks/main.yml: use ansible.posix.sysctl module instead of ansible.builtin.sysctl (as recommended by ansible-lint)

* handlers/main.yml: use community.general.ufw module instead of ansible.builtin.ufw (as recommended by ansible-lint)

* tasks/deployuser.yml: use ansible.posix.authorized_key module instead of ansible.builtin.authorized_key (as recommended by ansible-lint)

* update README

* remove vars/ubuntu-18.yml

* molecule/default/molecule.yml: put hosts into groups / move harden_linux_root_password for all hosts to only specific hosts

* Molecule: add verify step

* update CHANGELOG

* update CHANGELOG
  • Loading branch information
githubixx authored Sep 9, 2023
1 parent 4f29e48 commit 76ceedc
Show file tree
Hide file tree
Showing 22 changed files with 195 additions and 68 deletions.
2 changes: 1 addition & 1 deletion .ansible-lint
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
---
skip_list:
- 'role-name'
- 'name[template]'
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
Changelog
---------

**v7.0.0**

- **BREAKING**: `meta/main.yml`: change `role_name` from `harden-linux` to `harden_linux`. This is a requirement since quite some time for Ansible Galaxy. But the requirement was introduced after this role already existed for quite some time. So please update the name of the role in your playbook accordingly!
- **BREAKING**: remove support for Ubuntu 18.04 (reached EOL)
- Molecule: add `verify` step
- Fix various `ansible-lint` issues
- `.ansible-lint`: remove `role-name` / add `name[template]`
- `molecule/default/molecule.yml`: use `generic/ubuntu2204` VM image instead of `alvistack/ubuntu-22.04`
- `molecule/default/molecule.yml`: move `memory` and `cpus` properties to hosts
- `molecule/default/molecule.yml`: rename scenario `kvm` to `default`
- `molecule/default/molecule.yml`: rename `test-harden-linux-ubuntu1804-openntpd` to `test-harden-linux-ubuntu2204-openntpd`
- `molecule/default/molecule.yml`: adjust `verifier`
- `defaults/main.yml`: fix link
- `README.md`: add information about Molecule test

**v6.2.0**

- fix various `ansible-lint` issues
Expand Down
36 changes: 30 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ ansible-role-harden-linux

This Ansible role was mainly created for my blog series [Kubernetes the not so hard way with Ansible - Harden the instances](https://www.tauceti.blog/posts/kubernetes-the-not-so-hard-way-with-ansible-harden-the-instances/). But it can be used also standalone of course to harden Linux. It has the following features:

- Change root password
- Optional: Change root password
- Add a regular/deploy user used for administration (e.g. for Ansible or login via SSH)
- Adjust APT update intervals
- Setup UFW firewall and allow only SSH access by default (add more rules/allowed networks if you like)
Expand All @@ -28,6 +28,7 @@ Role Variables
The following variables don't have defaults. You need to specify them either in a file in `group_vars` or `host_vars` directory. E.g. if this settings should be used only for one specific host create a file for that host called like the FQDN of that host (e.g `host_vars/your-server.example.tld`) and put the variables with the correct values there. If you want to apply this variables to a host group create a file `group_vars/your-group.yml` e.g. Replace `your-group` with the host group name which you created in the Ansible `hosts` file (do not confuse with /etc/hosts...). `harden_linux_deploy_user_public_keys` loads all the public SSH key files specified in the list from your local hard disk. So at least you need to specify:

```yaml
# This is optional. If not specified "root" account password won't be changed.
harden_linux_root_password: your_encrypted_password_here

harden_linux_deploy_user: deploy
Expand All @@ -37,13 +38,13 @@ harden_linux_deploy_user_public_keys:
- /home/your_user/.ssh/id_rsa.pub
```
With `harden_linux_root_password` and `harden_linux_deploy_user_password` we specify the password for the `root` user and the `deploy` user. Ansible won't encrypt the password for you. How to create an encrypted password is described in the [Ansible FAQs](http://docs.ansible.com/ansible/latest/reference_appendices/faq.html#how-do-i-generate-encrypted-passwords-for-the-user-module). But as Ansible is installed anyways the most easiest way is probably the following command:
With `harden_linux_root_password` (optional as mentioned above) and `harden_linux_deploy_user_password` we specify the password for the `root` user and the `deploy` user. Ansible won't encrypt the password for you. How to create an encrypted password is described in the [Ansible FAQs](http://docs.ansible.com/ansible/latest/reference_appendices/faq.html#how-do-i-generate-encrypted-passwords-for-the-user-module). But as Ansible is installed anyways the most easiest way is probably the following command:

```bash
ansible localhost -m debug -a "msg={{ 'mypassword' | password_hash('sha512', 'mysecretsalt') }}"
```

`harden_linux_deploy_user` specifies the user we want to use to login at the remote host. As already mentioned the `harden-linux` role will disable root user login via SSH for a good reason. So a different user is needed. This user will get "sudo" permission which is need for Ansible (and/or yourself of course) to do it's work.
`harden_linux_deploy_user` specifies the user we want to use to login at the remote host. As already mentioned the `harden_linux` role will disable root user login via SSH for a good reason. So a different user is needed. This user will get "sudo" permission which is need for Ansible (and/or yourself of course) to do it's work.

`harden_linux_deploy_user_public_keys` specifies a list of public SSH key files you want to add to `$HOME/.ssh/authorized_keys` of the deploy user on the remote host. If you specify `/home/deploy/.ssh/id_rsa.pub` e.g. as a value here the content of that **local** file will be added to `$HOME/.ssh/authorized_keys` of the deploy user on the remote host.

Expand Down Expand Up @@ -130,7 +131,7 @@ harden_linux_ufw_allow_networks:
- "10.200.0.0/16"
```

Next harden-linux role also changes some system variables (sysctl.conf / proc filesystem). This settings are recommendations from Google which they use for their Google Compute Cloud OS images (see [Google Cloud - Requirements to build custom images](https://cloud.google.com/compute/docs/images/building-custom-os) and [Configure your imported image for Compute Engine](https://cloud.google.com/compute/docs/images/configuring-imported-images)). These are the default settings (if you are happy with this settings you don't have to do anything but I recommend to verify if they work for your setup):
Next `harden_linux` role also changes some system variables (sysctl.conf / proc filesystem). This settings are recommendations from Google which they use for their Google Compute Cloud OS images (see [Google Cloud - Requirements to build custom images](https://cloud.google.com/compute/docs/images/building-custom-os) and [Configure your imported image for Compute Engine](https://cloud.google.com/compute/docs/images/configuring-imported-images)). These are the default settings (if you are happy with this settings you don't have to do anything but I recommend to verify if they work for your setup):

```yaml
harden_linux_sysctl_settings:
Expand Down Expand Up @@ -271,12 +272,35 @@ harden_linux_archlinux_update_cache: true
Example Playbook
----------------

If you installed the role via `ansible-galaxy install githubixx.harden-linux` then include the role into your playbook like in this example:
If you installed the role via `ansible-galaxy install githubixx.harden_linux` then include the role into your playbook like in this example:

```yaml
- hosts: webservers
roles:
- githubixx.harden-linux
- githubixx.harden_linux
```

Testing
-------

This role has a small test setup that is created using [Molecule](https://github.com/ansible-community/molecule), libvirt (vagrant-libvirt) and QEMU/KVM. Please see my blog post [Testing Ansible roles with Molecule, libvirt (vagrant-libvirt) and QEMU/KVM](https://www.tauceti.blog/posts/testing-ansible-roles-with-molecule-libvirt-vagrant-qemu-kvm/) how to setup. The test configuration is [here](https://github.com/githubixx/ansible-role-runc/tree/master/molecule/default).

Afterwards molecule can be executed:

```bash
molecule converge
```

This will setup a few virtual machines (VM) with different supported Linux operating systems and setup `harden_linux` role accordingly. A small verification step is also included:

```bash
molecule verify
```

To clean up run

```bash
molecule destroy
```

License
Expand Down
2 changes: 1 addition & 1 deletion defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ harden_linux_files_to_delete:
#
# For more information about this settings have a look at:
# https://cloud.google.com/compute/docs/images/building-custom-os
# https://cloud.google.com/compute/docs/images/configuring-imported-images
# https://cloud.google.com/compute/docs/import/configuring-imported-images
# With ufw package installed: /etc/ufw/sysctl.conf
#
# The following settings are not available for all kernels so they you need
Expand Down
2 changes: 1 addition & 1 deletion handlers/main.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
- name: Reload ufw
ansible.builtin.ufw:
community.general.ufw:
state: reloaded

- name: Restart ssh
Expand Down
3 changes: 1 addition & 2 deletions meta/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@ galaxy_info:
description: Ansible role for hardening Linux
license: GPLv3
min_ansible_version: "2.9"
role_name: harden-linux
role_name: harden_linux
namespace: githubixx
platforms:
- name: ArchLinux
- name: Ubuntu
versions:
- "bionic"
- "focal"
- "jammy"
galaxy_tags:
Expand Down
4 changes: 2 additions & 2 deletions molecule/kvm/converge.yml → molecule/default/converge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
become: true
gather_facts: true
tasks:
- name: Include harden-linux role
- name: Include harden_linux role
include_role:
name: githubixx.harden-linux
name: githubixx.harden_linux
50 changes: 30 additions & 20 deletions molecule/kvm/molecule.yml → molecule/default/molecule.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,49 +7,64 @@ driver:
provider:
name: libvirt
type: libvirt
options:
memory: 192
cpus: 2

platforms:
- name: test-harden-linux-ubuntu2004-timesyncd
box: generic/ubuntu2004
memory: 2048
cpus: 2
groups:
- timesyncd
interfaces:
- auto_config: true
network_name: private_network
type: static
ip: 192.168.10.10
- name: test-harden-linux-ubuntu2004-ntp
box: generic/ubuntu2004
memory: 2048
cpus: 2
groups:
- ntp
interfaces:
- auto_config: true
network_name: private_network
type: static
ip: 192.168.10.20
- name: test-harden-linux-ubuntu1804-openntpd
box: generic/ubuntu1804
- name: test-harden-linux-ubuntu2204-openntpd
box: generic/ubuntu2204
memory: 2048
cpus: 2
groups:
- openntpd
interfaces:
- auto_config: true
network_name: private_network
type: static
ip: 192.168.10.30
- name: test-harden-linux-arch-timesyncd
box: archlinux/archlinux
memory: 2048
cpus: 2
groups:
- timesyncd
interfaces:
- auto_config: true
network_name: private_network
type: static
ip: 192.168.10.40
- name: test-harden-linux-ubuntu2204-timesyncd
box: alvistack/ubuntu-22.04
box: generic/ubuntu2204
memory: 2048
cpus: 2
groups:
- timesyncd
interfaces:
- auto_config: true
network_name: private_network
type: static
ip: 192.168.10.50

role_name_check: 1

provisioner:
name: ansible
connection_options:
Expand All @@ -61,7 +76,6 @@ provisioner:
inventory:
group_vars:
all:
harden_linux_root_password: "{{ lookup('file', 'myuserpassword_hash') }}" # mypassword
harden_linux_deploy_user: deployer
harden_linux_deploy_user_password: "{{ lookup('file', 'myuserpassword_hash') }}" # mypassword
harden_linux_deploy_user_home: /home/deployer
Expand Down Expand Up @@ -103,43 +117,39 @@ provisioner:
harden_linux_optional_packages:
- mlocate
test-harden-linux-ubuntu2004-ntp:
harden_linux_root_password: "{{ lookup('file', 'myuserpassword_hash') }}" # mypassword
harden_linux_ntp: "ntp"
harden_linux_ntp_settings:
"^pool 0": "pool 0.ubuntu.pool.ntp.org iburst"
"^pool 1": "pool 1.ubuntu.pool.ntp.org iburst"
"^pool 2": "pool 2.ubuntu.pool.ntp.org iburst"
"^pool 3": "pool 3.ubuntu.pool.ntp.org iburst"
test-harden-linux-ubuntu1804-openntpd:
test-harden-linux-ubuntu2204-openntpd:
harden_linux_ntp: "openntpd"
harden_linux_ntp_settings:
"^servers 0": "servers 0.debian.pool.ntp.org"
"^servers 1": "servers 1.debian.pool.ntp.org"
"^servers 2": "servers 2.debian.pool.ntp.org"
"^servers 3": "servers 3.debian.pool.ntp.org"
test-harden-linux-arch-timesyncd:
harden_linux_root_password: "{{ lookup('file', 'myuserpassword_hash') }}" # mypassword
harden_linux_ntp: "systemd-timesyncd"
harden_linux_optional_packages:
- mlocate
test-harden-linux-ubuntu2204-timesyncd:
harden_linux_root_password: "{{ lookup('file', 'myuserpassword_hash') }}" # mypassword
harden_linux_ntp: "systemd-timesyncd"
harden_linux_ntp_settings:
"^#NTP=": "NTP=ntp.ubuntu.com"
harden_linux_optional_packages:
- mlocate

scenario:
name: kvm
name: default
test_sequence:
- prepare
- converge

verifier:
name: testinfra
directory: tests
options:
# Add a -v so you see the individual test names,
# particularly useful with parameterized tests
v: true
sudo: true
lint:
name: flake8
name: ansible
enabled: true
File renamed without changes.
File renamed without changes.
12 changes: 12 additions & 0 deletions molecule/default/tasks/sshd_config_settings.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
- name: Ensure sshd_config setting
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config
regexp: '{{ harden_linux__sshd_config_setting }}'
line: "PasswordAuthentication yes"
register: harden_linux__sshd_config_setting_status

- name: Ensure sshd_config setting and value is present
ansible.builtin.assert:
that:
- harden_linux__sshd_config_setting_status is not changed
86 changes: 86 additions & 0 deletions molecule/default/verify.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
---
- name: Verify sshguard
hosts: all
tasks:
- name: Get sshguard status
ansible.builtin.systemd:
service: sshguard
state: started
register: sshguard__status

- name: Ensure sshguard is started
ansible.builtin.assert:
that:
- sshguard__status.state == "started"

- name: Verify systemd-timesyncd
hosts: timesyncd
tasks:
- name: Get systemd-timesyncd status
ansible.builtin.systemd:
service: systemd-timesyncd
state: started
register: timesyncd__status

- name: Ensure systemd-timesyncd is started
ansible.builtin.assert:
that:
- timesyncd__status.state == "started"

- name: Verify openntpd
hosts: openntpd
tasks:
- name: Get openntpd status
ansible.builtin.systemd:
service: openntpd
state: started
register: openntpd__status

- name: Ensure openntpd is started
ansible.builtin.assert:
that:
- openntpd__status.state == "started"

- name: Verify UFW
hosts: all
tasks:
- name: Execute ufw status to capture output
ansible.builtin.command:
cmd: /usr/sbin/ufw status
register: harden_linux__ufw_status
changed_when: false

- name: Ensure ufw status output contains correct output
ansible.builtin.assert:
that:
- "'{{ harden_linux__ufw_status_output }}' in harden_linux__ufw_status.stdout"
loop:
- "22/tcp ALLOW Anywhere"
- "80/tcp ALLOW Anywhere"
- "443/tcp ALLOW Anywhere"
- "Anywhere ALLOW 10.0.0.0/8"
- "Anywhere ALLOW 172.16.0.0/12"
- "Anywhere ALLOW 192.168.0.0/16"
- "22/tcp (v6) ALLOW Anywhere (v6)"
- "80/tcp (v6) ALLOW Anywhere (v6)"
- "443/tcp (v6) ALLOW Anywhere (v6)"
loop_control:
loop_var: harden_linux__ufw_status_output

- name: Verify sshd_config settings
hosts: all
vars:
harden_linux__sshd_settings:
password_authentication:
regex: '^PasswordAuthentication'
value: 'PasswordAuthentication yes'
x11forwarding:
regex: '^X11Forwarding'
value: 'X11Forwarding no'
tasks:
- name: Check sshd_config settings
ansible.builtin.include_tasks:
file: tasks/sshd_config_settings.yml
loop: "{{ harden_linux__sshd_settings | dict2items }}"
loop_control:
loop_var: harden_linux__sshd_config_setting
2 changes: 1 addition & 1 deletion tasks/deployuser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
- user

- name: Add authorized keys for deploy user
ansible.builtin.authorized_key:
ansible.posix.authorized_key:
user: "{{ harden_linux_deploy_user }}"
key: "{{ lookup('file', item) }}"
loop: "{{ harden_linux_deploy_user_public_keys }}"
Expand Down
2 changes: 1 addition & 1 deletion tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@
- sysctl

- name: Sysctl settings
ansible.builtin.sysctl:
ansible.posix.sysctl:
name: "{{ item }}"
value: "{{ harden_linux_sysctl_settings[item] }}"
sysctl_set: true
Expand Down
Loading

0 comments on commit 76ceedc

Please sign in to comment.