-
Notifications
You must be signed in to change notification settings - Fork 0
/
playbook.yaml
244 lines (208 loc) · 8.43 KB
/
playbook.yaml
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
---
- name: "Play to create hetzner cloud servers"
hosts: localhost
connection: local
gather_facts: false
module_defaults:
group/hetzner.hcloud.all:
api_token: "{{ hcloud_api_token }}"
tasks:
- name: "Ensure local ssh key exists"
ansible.builtin.include_tasks:
file: "tasks/local/ensure-keys-exists.yaml"
# The interaction with hetzner cloud needs to be done always,
# because it sets the ip address for the cloud server.
- name: "Interact with hetzner cloud"
ansible.builtin.include_tasks:
file: "tasks/local/hetzner-cloud.yaml"
apply:
tags: [always]
tags: [always]
- name: "Play to configure servers"
hosts: all
strategy: free
handlers:
- name: "Restart sshd"
ansible.builtin.systemd:
name: sshd
state: restarted
become: true
- name: "Restart auditd"
when: "ansible_distribution not in ['AlmaLinux']" # TODO doesn't work
ansible.builtin.systemd:
name: auditd
state: restarted
become: true
tasks:
- name: "Create low privileged user account"
ansible.builtin.include_tasks:
file: "tasks/linux/create-worker-user.yaml"
- name: "Remove labels from cloud server"
when:
- "new_server"
hetzner.hcloud.server:
api_token: "{{ hcloud_api_token }}"
name: "{{ inventory_hostname }}"
labels: {}
state: present
delegate_to: localhost
- name: "Setup sshd"
tags: [hardening]
block:
- name: "Setup sshd"
ansible.builtin.include_tasks:
file: "tasks/linux/setup-sshd.yaml"
apply:
tags: [hardening]
- name: "Add tcp/22 to allowed ports of hetzner firewall"
ansible.builtin.set_fact:
hetzner_firewall_rules: "{{ hetzner_firewall_rules | default([]) + [{'direction': 'in', 'protocol': 'tcp', 'source_ips': ['0.0.0.0/0', '::/0'], 'port': 22}] }}"
tags: [hardening, firewall]
- name: "Update repositories cache on systems using apt"
when:
- "ansible_pkg_mgr == 'apt'"
ansible.builtin.apt:
update_cache: true
changed_when: false
become: true
- name: "Ensure extra packages for enterprise linux are installed"
when:
- "ansible_distribution in ['CentOS', 'AlmaLinux', 'Rocky']"
ansible.builtin.package:
name: epel-release
state: present
become: true
- name: "Setup fail2ban"
tags: [hardening]
ansible.builtin.include_tasks:
file: "tasks/linux/setup-fail2ban.yaml"
apply:
tags: [hardening]
- name: "Setup automatic updates of installed packages"
tags: [hardening]
ansible.builtin.include_tasks:
file: "tasks/linux/setup-auto-update.yaml"
apply:
tags: [hardening]
- name: "Setup clamav"
tags: [hardening]
ansible.builtin.include_tasks:
file: "tasks/linux/setup-clamav.yaml"
apply:
tags: [hardening]
- name: "Setup rkhunter"
tags: [hardening]
ansible.builtin.include_tasks:
file: "tasks/linux/setup-rkhunter.yaml"
apply:
tags: [hardening]
- name: "Configure iptables"
ansible.builtin.include_tasks:
file: "tasks/linux/setup-iptables.yaml"
apply:
tags: [hardening, firewall]
tags: [hardening, firewall]
- name: "Setup auditd"
when: ansible_distribution in ['CentOS', 'AlmaLinux', 'Rocky'] # TODO until bugs fixed
tags: [hardening]
ansible.builtin.include_tasks:
file: "tasks/linux/setup-auditd.yaml"
apply:
tags: [hardening]
# TODO setup aide
# TODO setup IDS (Suricata / snort)
# TODO setup LSM (e.g. selinux, apparmor)
# TODO setup agent: wazuh agent / filebeat / splunk universal forwarder
# TODO think about backup
- name: "Create users"
tags: [users]
ansible.builtin.include_tasks:
file: "tasks/linux/create-users.yaml"
apply:
tags: [users]
- name: "Audit the system using openscap"
tags: [audit]
when: "ansible_distribution not in ['Ubuntu', 'Debian']" # TODO ssg files does not exist -> find solution
ansible.builtin.include_tasks:
file: "tasks/linux/audit-openscap.yaml"
apply:
tags: [audit]
- name: "Audit the system using lynis"
tags: [audit]
ansible.builtin.include_tasks:
file: "tasks/linux/audit-lynis.yaml"
apply:
tags: [audit]
- name: "Setup postgresql"
when:
- "install_postgresql"
tags: [postgresql]
block:
# Note: The passwords of postgresql users are not being stored with the
# other (e.g. database) settings in the host_vars/<hostname>/vars.yaml
# for security reasons. Instead the are stored in the vault of the host
# (host_vars/<hostname>/vault) and will be merged by the following task.
- name: "Merge PostgreSQL users variables with passwords from vault"
ansible.builtin.set_fact:
postgresql_users: "{{ postgresql_users | default([]) + [item_u | combine(item_e)] }}"
loop: "{{ postgresql_users_u | default([]) }}"
loop_control:
loop_var: item_u
vars:
item_e: "{{ postgresql_users_e | selectattr('name', '==', item_u.name) | first }}"
- name: "Install postgresql using ansible-role"
ansible.builtin.include_role:
name: "geerlingguy.postgresql"
apply:
become: true
tags: [postgresql]
- name: "Setup redis"
when:
- "install_redis"
tags: [redis]
ansible.builtin.include_role:
name: "geerlingguy.redis"
apply:
become: true
tags: [redis]
# TODO setup nginx with ModSecurity if install_nginx is true:
# - debian: libnginx-mod-http-modsecurity modsecurity-crs
# - ubuntu: modsecurity-crs libmodsecurity3
# - rhel: libmodsecurity nginx-mod-modsecurity
post_tasks:
- name: "Configure hetzner firewall"
tags: [hardening, firewall]
block:
- name: "Add icmp to allowed protocols for incomming connections of hetzner firewall"
ansible.builtin.set_fact:
hetzner_firewall_rules: "{{ hetzner_firewall_rules | default([]) + [{'direction': 'in', 'source_ips': ['0.0.0.0/0', '::/0'], 'protocol': 'icmp'}] }}"
- name: "Add icmp to allowed protocols for incomming connections of hetzner firewall"
ansible.builtin.set_fact:
hetzner_firewall_rules: "{{ hetzner_firewall_rules | default([]) + [{'direction': 'out', 'destination_ips': ['0.0.0.0/0', '::/0'], 'protocol': 'icmp'}] }}"
- name: "Add dns to allowed protocols for outgoing connections of hetzner firewall"
ansible.builtin.set_fact:
hetzner_firewall_rules: "{{ hetzner_firewall_rules | default([]) + [{'direction': 'out', 'destination_ips': ['0.0.0.0/0', '::/0'], 'protocol': 'udp', 'port': '53'}] }}"
- name: "Allow ntp for outgoing connections on hetzner firewall"
ansible.builtin.set_fact:
hetzner_firewall_rules: "{{ hetzner_firewall_rules | default([]) + [{'direction': 'out', 'destination_ips': ['0.0.0.0/0', '::/0'], 'protocol': 'udp', 'port': '123'}] }}"
- name: "Allow http for outgoing connections on hetzner firewall"
ansible.builtin.set_fact:
hetzner_firewall_rules: "{{ hetzner_firewall_rules | default([]) + [{'direction': 'out', 'destination_ips': ['0.0.0.0/0', '::/0'], 'protocol': 'tcp', 'port': '80'}] }}"
- name: "Allow https for outgoing connections on hetzner firewall"
ansible.builtin.set_fact:
hetzner_firewall_rules: "{{ hetzner_firewall_rules | default([]) + [{'direction': 'out', 'destination_ips': ['0.0.0.0/0', '::/0'], 'protocol': 'tcp', 'port': '443'}] }}"
- name: "Adjust hetzner firewall"
hetzner.hcloud.firewall:
api_token: "{{ hcloud_api_token }}"
name: "fw-{{ inventory_hostname }}"
state: present
rules: "{{ hetzner_firewall_rules | default([]) }}"
delegate_to: localhost
- name: "Apply firewall onto cloud server"
hetzner.hcloud.server:
api_token: "{{ hcloud_api_token }}"
name: "{{ inventory_hostname }}"
firewalls:
- "fw-{{ inventory_hostname }}"
state: present
delegate_to: localhost