-
Notifications
You must be signed in to change notification settings - Fork 9
/
harden.yml
157 lines (154 loc) · 5.57 KB
/
harden.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
---
- name: Harden
hosts: localhost
vars_files:
- vars.yml
tasks:
# Bunch of checks first, so the playbook doesn't fail in the middle.
- name: Check OS version
ansible.builtin.assert:
that: >
(ansible_distribution == "Slackware" and ansible_distribution_major_version | int >= 15) or
(ansible_distribution == "Debian" and ansible_distribution_major_version | int >= 12) or
(ansible_distribution == "CentOS" and ansible_distribution_major_version == "7") or
ansible_distribution == "Kali"
msg: "Unsupported operating system"
tags: check
- name: Sudo checks
tags:
- check
- sudo
block:
- name: 'Check that some user(s) exist in "sudo" group'
ansible.builtin.getent:
database: group
key: sudo
failed_when: getent_group.sudo[2] == ""
when: ansible_distribution == "Debian" or ansible_distribution == "Kali"
tags: debian
- name: 'Check that some user(s) exist in "wheel" group'
ansible.builtin.getent:
database: group
key: wheel
failed_when: getent_group.wheel[2] == "" or getent_group.wheel[2] == "root"
when: ansible_distribution == "Slackware"
tags: slackware
# PAM's access.conf and sshd_config will actually start blocking access, so
# check that we are not locking ourselves out of the system being hardened.
- name: 'Check that some user(s) exist in "{{ allowed_group }}" group'
ansible.builtin.getent:
database: group
key: "{{ allowed_group }}"
failed_when: getent_group.{{ allowed_group }}[2] == ""
tags:
- check
- pam
- ssh
- authorization
- name: Check that AIDE is installed (Slackware)
tags:
- slackware
- check
- aide
when: ansible_distribution == "Slackware"
ansible.builtin.stat:
path: /usr/bin/aide
register: result
failed_when: not result.stat.exists
- name: Check that rkhunter is installed (Slackware)
tags:
- slackware
- check
- rkhunter
when: ansible_distribution == "Slackware"
ansible.builtin.stat:
path: /usr/bin/rkhunter
register: result
failed_when: not result.stat.exists
- name: Check that audit is installed (Slackware)
tags:
- slackware
- check
- audit
when: ansible_distribution == "Slackware"
ansible.builtin.stat:
path: /sbin/auditd
register: result
failed_when: not result.stat.exists
# Once we change existing users max password age and set the inactive age,
# the user isn't able to authenticate anymore if the password is too old.
- name: Check that Ansible user's password is not too old
become: true
tags:
- accounts
- passwords
- authorization
- check
block:
- name: getent shadow for Ansible user
ansible.builtin.getent:
database: shadow
key: '{{ ansible_user_id }}'
split: ':'
no_log: true
# If password age is today-pass_max_days, you're still able to login with "Your password will expire today."
# So > comparison should be sufficient, but we'll put in the one day safe margin (>=) just in case.
- name: Check that Ansible user's password is not too old
ansible.builtin.assert:
that: ansible_facts.getent_shadow[ansible_user_id][1] | int >= ((ansible_date_time.epoch_int | int / 86400) | int) - pass_max_days
msg: "Ansible user's password too old"
# End of checks. Start hardening.
- name: sudoers
ansible.builtin.import_tasks: tasks/sudoers.yml
tags: sudo
- name: Lynis
ansible.builtin.import_tasks: tasks/lynis.yml
- name: Filesystem related
ansible.builtin.import_tasks: tasks/filesystem.yml
- name: CA certificates
ansible.builtin.import_tasks: tasks/ca-certs.yml
- name: AIDE
ansible.builtin.import_tasks: tasks/aide.yml
- name: Debian packages
ansible.builtin.import_tasks: tasks/debian_packages.yml
- name: Audit
ansible.builtin.import_tasks: tasks/audit.yml
tags: audit
- name: login_defs
ansible.builtin.import_tasks: tasks/login_defs.yml
- name: PAM
ansible.builtin.import_tasks: tasks/pam.yml
- name: Services
ansible.builtin.import_tasks: tasks/services.yml
- name: Kernel
ansible.builtin.import_tasks: tasks/kernel.yml
- name: Accounting services
ansible.builtin.import_tasks: tasks/services-accounting.yml
- name: AppArmor
ansible.builtin.import_tasks: tasks/apparmor.yml
tags:
- apparmor
- debian
- name: Logging
ansible.builtin.import_tasks: tasks/logging.yml
- name: Miscellaneous
ansible.builtin.import_tasks: tasks/misc.yml
- name: Banners
ansible.builtin.import_tasks: tasks/banners.yml
- name: Network
ansible.builtin.import_tasks: tasks/network.yml
- name: Entropy
ansible.builtin.import_tasks: tasks/entropy.yml
- name: rkhunter
ansible.builtin.import_tasks: tasks/rkhunter.yml
- name: ClamAV
ansible.builtin.import_tasks: tasks/clamav.yml
- name: Display managers
ansible.builtin.import_tasks: tasks/display_managers.yml
- name: Apache httpd
ansible.builtin.import_tasks: tasks/apache.yml
- name: Slackware cgroups
ansible.builtin.import_tasks: tasks/cgroup.yml
handlers:
- name: Handlers
ansible.builtin.import_tasks: tasks/handlers.yml