5558cd0296aa25f0f56cc34493af5fa8d20b1314
[ta/infra-ansible.git] / roles / ops-hardening / tasks / main.yaml
1 ---
2
3 # Copyright 2019 Nokia
4
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 #     http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 #
18 # Linux password hardening
19 #
20
21 - name: "Set Password Strength Minimum Digit Characters."
22   lineinfile:
23     path: /etc/security/pwquality.conf
24     regexp: '^[#\s]*dcredit'
25     line: 'dcredit = -1'
26
27 - name: "Set Password Minimum Length."
28   lineinfile:
29     path: /etc/security/pwquality.conf
30     regexp: '^[#\s]*minlen'
31     line: 'minlen = 8'
32
33 - name: "Set Password Strength Minimum Uppercase Characters."
34   lineinfile:
35     path: /etc/security/pwquality.conf
36     regexp: '^[#\s]*ucredit'
37     line: 'ucredit = -1'
38
39 - name: "Set Password Strength Minimum Special Characters."
40   lineinfile:
41     path: /etc/security/pwquality.conf
42     regexp: '^[#\s]*ocredit'
43     line: 'ocredit = -1'
44
45 - name: "Set Password Strength Minimum Lowercase Characters."
46   lineinfile:
47     path: /etc/security/pwquality.conf
48     regexp: '^[#\s]*lcredit'
49     line: 'lcredit = -1'
50
51 - name: "Set Password Strength Minimum Different Categories."
52   lineinfile:
53     path: /etc/security/pwquality.conf
54     regexp: '^[#\s]*minclass'
55     line: 'minclass = 3'
56
57 - name: "Set Password Minimum Length in login.defs"
58   lineinfile:
59     path: /etc/login.defs
60     regexp: '^PASS_MIN_LEN[\s]*[0-9]*$'
61     line: 'PASS_MIN_LEN   8'
62
63 - name: "Set Password Minimum Age"
64   lineinfile:
65     path: /etc/login.defs
66     regexp: '^PASS_MIN_DAYS[\s]*[0-9]*$'
67     line: 'PASS_MIN_DAYS   0'
68
69 #
70 # Linux Failed password attempts
71 #
72
73 - name: "Set Deny for failed password attempts 1"
74   lineinfile:
75     path: "{{item}}"
76     insertbefore: '^auth[\s]*sufficient[\s]*pam_unix.so'
77     line: 'auth        required      pam_faillock.so preauth silent audit deny=3 unlock_time=3600 fail_interval=900'
78   with_items:
79     - /etc/pam.d/system-auth-ac
80     - /etc/pam.d/password-auth-ac
81   tags:
82     - REC-443
83
84 - name: "Set Deny for failed password attempts 2"
85   lineinfile:
86     path: "{{item}}"
87     insertafter: '^auth[\s]*sufficient[\s]*pam_unix.so'
88     line: 'auth        [default=die]  pam_faillock.so authfail audit deny=3 unlock_time=3600 fail_interval=900'
89   with_items:
90     - /etc/pam.d/system-auth-ac
91     - /etc/pam.d/password-auth-ac
92   tags:
93     - REC-443
94
95 - name: "Set Deny for failed password attempts 3"
96   lineinfile:
97     path: "{{item}}"
98     insertbefore: '^account[\s]*required[\s]*pam_unix.so'
99     line: 'account     required      pam_faillock.so'
100   with_items:
101     - /etc/pam.d/system-auth-ac
102     - /etc/pam.d/password-auth-ac
103   tags:
104     - REC-443
105
106 - name: "Set Account expiration following inactivity"
107   lineinfile:
108     create: yes
109     path: "/etc/default/useradd"
110     regexp: "^INACTIVE"
111     line: "INACTIVE=35"
112   tags:
113     - REC-443
114
115 #
116 # YUM config
117 #
118
119 - name: "Ensure YUM Removes Previous Package Versions"
120   lineinfile:
121     path: /etc/yum.conf
122     insertafter: '^[#\s]*\[main\]'
123     line: 'clean_requirements_on_remove = 1'
124
125 - name: "Ensure gpgcheck Enabled for Local Packages"
126   lineinfile:
127     path: /etc/yum.conf
128     insertafter: '^[#\s]*\[main\]'
129     line: 'localpkg_gpgcheck = 1'
130
131 #
132 # Setting Ctrl-Alt-Del action
133 #
134
135 - name: "Disable Ctrl-Alt-Del Burst Action"
136   lineinfile:
137     path: /etc/systemd/system.conf
138     insertafter: '^[#\s]*CtrlAltDelBurstAction'
139     line: 'CtrlAltDelBurstAction=none'
140
141 - name: "Disable Ctrl-Alt-Del Reboot Activation"
142   command: systemctl mask ctrl-alt-del.target
143
144 #
145 # Configure kernel modules
146 #
147
148 - name: "kernel module setting"
149   lineinfile:
150     create=yes
151     dest="/etc/modprobe.d/{{item}}.conf"
152     regexp="{{item}}"
153     line="install {{item}} /bin/true"
154   with_items:
155     - bluetooth
156     - dccp
157     - squashfs
158     - hfsplus
159     - hfs
160     - jffs2
161     - freevxfs
162     - cramfs
163     - usb-storage
164     - udf
165     - nfsd
166
167 #
168 # Disable interactive boot
169 #
170
171 - name:  Verify that Interactive Boot is Disabled GRUB_CMDLINE_LINUX Setting
172   lineinfile:
173     path: /etc/default/grub
174     backrefs: yes
175     regexp: '^GRUB_CMDLINE_LINUX=(.*)systemd\.confirm_spawn=(1|yes|true|on)\s*(.*)$'
176     line: 'GRUB_CMDLINE_LINUX=\1\3'
177
178 - name:  Verify that Interactive Boot is Disabled GRUB_CMDLINE_LINUX_DEFAULT Setting
179   lineinfile:
180     path: /etc/default/grub
181     backrefs: yes
182     regexp: '^GRUB_CMDLINE_LINUX_DEFAULT=(.*)systemd\.confirm_spawn=(1|yes|true|on)\s*(.*)$'
183     line: 'GRUB_CMDLINE_LINUX_DEFAULT=\1\3'
184
185 #
186 # Set file permissions
187 #
188
189 - name: "Check files exist to determine the proper location of grub.cfg on UEFI systems"
190   stat: path={{item}}
191   with_items:
192     - /boot/efi/EFI/centos/grub.cfg
193     - /boot/grub2/grub.cfg
194     - /var/log/boot.log
195     - /var/log/cron
196   register: file_stat
197
198 - name: "Set the 600 file permissions"
199   file:
200     path: "{{item.item}}"
201     state: touch
202     mode: "600"
203   with_items: "{{ file_stat.results }}"
204   when:
205     - item.stat.exists == true
206
207 #
208 # Disable direct root login
209 #
210
211 - name: "Direct root Logins Not Allowed"
212   shell: echo > /etc/securetty
213
214 - name: Change 'root' shell to nologin
215   user:
216     name: root
217     shell: /sbin/nologin
218
219 - name: Lock 'root' password
220   user:
221     name: root
222     password: '!!'
223
224 #
225 # Configure IPv6
226 #
227
228 - name: Disable ipv6 support if the ipv6 is not needed
229   when: ansible_default_ipv6|length == 0
230   sysctl:
231     name: net.ipv6.conf.all.disable_ipv6
232     value: 1
233     state: present
234     reload: yes
235
236 - name: Disable Support for udp6
237   when: ansible_default_ipv6|length == 0
238   lineinfile:
239     path: /etc/netconfig
240     state: absent
241     regexp: '^udp6.*'
242
243 - name: Disable Support for tcp6
244   when: ansible_default_ipv6|length == 0
245   lineinfile:
246     path: /etc/netconfig
247     state: absent
248     regexp: '^tcp6.*'
249
250 - name: Disable automatic ipv6 configuration
251   when: ansible_default_ipv6|length > 0
252   sysctl:
253     name: "{{ item.name }}"
254     value: "{{ item.value }}"
255     state: present
256     reload: yes
257   with_items:
258     - { name: 'net.ipv6.conf.all.accept_source_route', value: 0 }
259     - { name: 'net.ipv6.conf.all.accept_ra', value: 0 }
260     - { name: 'net.ipv6.conf.default.accept_ra', value: 0 }
261     - { name: 'net.ipv6.conf.all.accept_redirects', value: 0 }
262     - { name: 'net.ipv6.conf.default.accept_redirects', value: 0 }
263     - { name: 'net.ipv6.conf.default.accept_source_route', value: 0 }
264     - { name: 'net.ipv6.conf.all.forwarding', value: 0 }
265
266 #
267 # Configure kernel parameters
268 #
269
270 - name: Configure the kernel parameters
271   sysctl:
272     name: "{{ item.name }}"
273     value: "{{ item.value }}"
274     state: present
275     reload: yes
276   with_items:
277     - { name: 'net.ipv4.conf.default.send_redirects', value: 0 }
278     - { name: 'net.ipv4.conf.all.send_redirects', value: 0 }
279     - { name: 'net.ipv4.ip_forward', value: 0 }
280     - { name: 'net.ipv4.conf.all.accept_redirects', value: 0 }
281     - { name: 'net.ipv4.conf.all.secure_redirects', value: 0 }
282     - { name: 'net.ipv4.conf.all.log_martians', value: 1 }
283     - { name: 'net.ipv4.conf.default.log_martians', value: 1 }
284     - { name: 'net.ipv4.conf.default.accept_redirects', value: 0 }
285     - { name: 'net.ipv4.conf.default.secure_redirects', value: 0 }
286     - { name: 'net.ipv4.icmp_echo_ignore_broadcasts', value: 1 }
287     - { name: 'net.ipv4.icmp_ignore_bogus_error_responses', value: 1 }
288     - { name: 'net.ipv4.tcp_syncookies', value: 1 }
289     - { name: 'fs.suid_dumpable', value: 0 }
290     - { name: 'kernel.dmesg_restrict', value: 1 }
291     - { name: 'kernel.core_uses_pid', value: 1 }
292     - { name: 'kernel.randomize_va_space', value: 2 }
293     - { name: 'kernel.core_pattern', value: '/var/core/core'}
294
295 #
296 # Configure core dump
297 #
298
299 - name: "Disable core dump for all user"
300   lineinfile:
301     path: /etc/security/limits.conf
302     insertbefore: '^[a-z].*'
303     line: '*               hard    core            0'
304
305 - name: "Configure systemd not to store core dumps"
306   lineinfile:
307     path: /etc/systemd/coredump.conf
308     insertafter: '^\[Coredump\]'
309     line: 'Storage=none'
310
311 #
312 # Configure syslog
313 #
314 - name: "Stop rsyslog Service"
315   shell: systemctl stop rsyslog.service
316
317 - name: "Disable rsyslog Service"
318   shell: systemctl disable rsyslog.service
319
320 - name: "Ensure the /var/log/boot.log Rotated by logrotate"
321   lineinfile:
322     path: /etc/logrotate.d/syslog
323     insertbefore: 'cron$'
324     line: /var/log/boot.log
325
326 - name: "Set the umasks by profile file"
327   lineinfile:
328     path: /etc/profile
329     regexp: '{{ item.old }}'
330     line: '{{ item.new }}'
331   with_items:
332     - { old: 'umask 002', new: umask 027 }
333     - { old: 'umask 022', new: umask 077 }
334
335 #
336 # Keystone config
337 #
338
339 - name: Set the max_request_body_size in the keystone.conf
340   lineinfile:
341     path: /etc/keystone/keystone.conf
342     insertafter: 'DEFAULT'
343     line: "# enforced by optional sizelimit middleware (keystone.middleware:RequestBodySizeLimiter)\nmax_request_body_size = 114688\n"
344
345 - name: Set the insecure_debug in the keystone.conf
346   lineinfile:
347     path: /etc/keystone/keystone.conf
348     insertafter: 'DEFAULT'
349     line: "# If set to true, then the server will return information in HTTP responses\n# that may allow an unauthenticated or authenticated user to get more\n# information than normal, such as additional details about why authentication\n# failed. This may be useful for debugging but is insecure. (boolean value)\ninsecure_debug = false\n"
350
351 #
352 #Setting bootloader password
353 #
354 - name: set host os variable
355   when: host_os is defined
356   set_fact:
357     grub2_pass: "{{  host_os.grub2_password | default('Empty')  }}"
358
359 - name: protect grub with root password
360   when: grub2_pass is defined and grub2_pass != 'Empty'
361   blockinfile:
362     dest: /etc/grub.d/40_custom
363     state: present
364     insertafter: 'EOF'
365     content: |
366       # define superusers
367       set superusers="root"
368       #define users
369       password_pbkdf2 root "{{ grub2_pass }}"
370
371 - name: check whether grub-efi exists
372   stat:
373     path: /boot/efi/EFI/centos/grub.cfg
374   register: grub_efi_file_stat
375
376 - name: generate grub config
377   when: grub2_pass is defined and grub2_pass != 'Empty'
378   command: /usr/sbin/grub2-mkconfig -o /boot/grub2/grub.cfg
379
380 - name: generate grub-efi config
381   command: /usr/sbin/grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg
382   when:
383     - grub2_pass is defined and grub2_pass != 'Empty'
384     - grub_efi_file_stat.stat.exists == true
385
386 #
387 #Setting the noexec option to the /dev/shm mount dir
388 #
389
390 - name: get back device associated to mountpoint
391   shell: mount | grep ' /dev/shm ' |cut -d ' ' -f 1
392   register: device_name
393   check_mode: no
394
395 - name: get back device previous mount option
396   shell: mount | grep ' /dev/shm ' | sed -re 's:.*\((.*)\):\1:'
397   register: device_cur_mountoption
398   check_mode: no
399
400 - name: get back device fstype
401   shell: mount | grep ' /dev/shm ' | cut -d ' ' -f 5
402   register: device_fstype
403   check_mode: no
404
405 - name: Ensure permission noexec are set on /dev/shm
406   mount:
407     path: "/dev/shm"
408     src: "{{device_name.stdout}}"
409     opts: "{{device_cur_mountoption.stdout}},noexec"
410     state: "mounted"
411     fstype: "{{device_fstype.stdout}}"
412
413 #
414 # Disable NFS service
415 #
416
417 - name: disable NFS related services
418   service:
419     name: "{{ item }}"
420     enabled: no
421     state: stopped
422   ignore_errors: yes
423   with_items:
424     - nfslock
425     - rpcgssd
426     - rpcidmapd
427     - nfs-idmap
428     - nfs-server
429     - nfs
430
431 - name: remove nfs-utils package
432   yum:
433     name: nfs-utils
434     state: absent
435
436 #
437 # Setting file permissions
438 #
439
440 #- name: "Remove the other user write permission from the system directorys"
441 #  command: find / -xdev \( -perm -0002 -a ! -perm -1000 \) -type d -exec chmod o-w {} \;
442 #
443 #- name: "Remove the other user write permission from the system files"
444 #  command: find / -xdev -perm -0002 -type f -exec chmod o-w {} \;
445 #
446 #- name: "Modified the unauthorized SUID/SGID system executables"
447 #  command: sudo chmod -s $(sudo find / -xdev \( -perm -4000 -o -perm -2000 \) -type f | grep -v sudo)