More security compliance modifications
[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 - name: "Set password hash to SHA512"
70   lineinfile:
71     path: /etc/login.defs
72     regexp: '^ENCRYPT_METHOD[\s]*[a-z0-9]*$'
73     line: 'ENCRYPT_METHOD   SHA512'
74
75 - name: "Set minimum number of password hash rounds"
76   lineinfile:
77     path: /etc/login.defs
78     regexp: '^SHA_CRYPT_MIN_ROUNDS[\s]*[0-9]*$'
79     line: 'SHA_CRYPT_MIN_ROUNDS   5000'
80
81 - name: "Set maximum number of password hash rounds"
82   lineinfile:
83     path: /etc/login.defs
84     regexp: '^SHA_CRYPT_MAX_ROUNDS[\s]*[0-9]*$'
85     line: 'SHA_CRYPT_MAX_ROUNDS   10000'
86
87 #
88 # Linux Failed password attempts
89 #
90 - name: "Ensure authconfig is properly configured"
91   command: authconfig --updateall
92   with_items:
93     - /etc/pam.d/system-auth-ac
94     - /etc/pam.d/password-auth-ac
95   when: not (item|exists and item|is_file)
96   tags:
97     - REC-443
98
99 - name: "Set Deny for failed password attempts 1"
100   lineinfile:
101     path: "{{item}}"
102     insertbefore: '^auth[\s]*sufficient[\s]*pam_unix.so'
103     line: 'auth        required      pam_faillock.so preauth silent audit deny=3 unlock_time=3600 fail_interval=900'
104   with_items:
105     - /etc/pam.d/system-auth-ac
106     - /etc/pam.d/password-auth-ac
107   tags:
108     - REC-443
109
110 - name: "Set Deny for failed password attempts 2"
111   lineinfile:
112     path: "{{item}}"
113     insertafter: '^auth[\s]*sufficient[\s]*pam_unix.so'
114     line: 'auth        [default=die]  pam_faillock.so authfail audit deny=3 unlock_time=3600 fail_interval=900'
115   with_items:
116     - /etc/pam.d/system-auth-ac
117     - /etc/pam.d/password-auth-ac
118   tags:
119     - REC-443
120
121 - name: "Set Deny for failed password attempts 3"
122   lineinfile:
123     path: "{{item}}"
124     insertbefore: '^account[\s]*required[\s]*pam_unix.so'
125     line: 'account     required      pam_faillock.so'
126   with_items:
127     - /etc/pam.d/system-auth-ac
128     - /etc/pam.d/password-auth-ac
129   tags:
130     - REC-443
131
132 - name: "Set Account expiration following inactivity"
133   lineinfile:
134     create: yes
135     path: "/etc/default/useradd"
136     regexp: "^INACTIVE"
137     line: "INACTIVE=35"
138   tags:
139     - REC-443
140
141 #
142 # YUM config
143 #
144
145 - name: "Ensure YUM Removes Previous Package Versions"
146   lineinfile:
147     path: /etc/yum.conf
148     insertafter: '^[#\s]*\[main\]'
149     line: 'clean_requirements_on_remove = 1'
150
151 - name: "Ensure gpgcheck Enabled for Local Packages"
152   lineinfile:
153     path: /etc/yum.conf
154     insertafter: '^[#\s]*\[main\]'
155     line: 'localpkg_gpgcheck = 1'
156
157 #
158 # Setting Ctrl-Alt-Del action
159 #
160
161 - name: "Disable Ctrl-Alt-Del Burst Action"
162   lineinfile:
163     path: /etc/systemd/system.conf
164     insertafter: '^[#\s]*CtrlAltDelBurstAction'
165     line: 'CtrlAltDelBurstAction=none'
166
167 - name: "Disable Ctrl-Alt-Del Reboot Activation"
168   command: systemctl mask ctrl-alt-del.target
169
170 #
171 # Configure kernel modules
172 #
173
174 - name: "kernel module setting"
175   lineinfile:
176     create=yes
177     dest="/etc/modprobe.d/{{item}}.conf"
178     regexp="{{item}}"
179     line="install {{item}} /bin/true"
180   with_items:
181     - bluetooth
182     - dccp
183     - squashfs
184     - hfsplus
185     - hfs
186     - jffs2
187     - freevxfs
188     - cramfs
189     - usb-storage
190     - udf
191     - nfsd
192
193 #
194 # Disable interactive boot
195 #
196
197 - name:  Verify that Interactive Boot is Disabled GRUB_CMDLINE_LINUX Setting
198   lineinfile:
199     path: /etc/default/grub
200     backrefs: yes
201     regexp: '^GRUB_CMDLINE_LINUX=(.*)systemd\.confirm_spawn=(1|yes|true|on)\s*(.*)$'
202     line: 'GRUB_CMDLINE_LINUX=\1\3'
203
204 - name:  Verify that Interactive Boot is Disabled GRUB_CMDLINE_LINUX_DEFAULT Setting
205   lineinfile:
206     path: /etc/default/grub
207     backrefs: yes
208     regexp: '^GRUB_CMDLINE_LINUX_DEFAULT=(.*)systemd\.confirm_spawn=(1|yes|true|on)\s*(.*)$'
209     line: 'GRUB_CMDLINE_LINUX_DEFAULT=\1\3'
210
211 #
212 # Set file permissions
213 #
214
215 - name: "Check files exist to determine the proper location of grub.cfg on UEFI systems"
216   stat: path={{item}}
217   with_items:
218     - /boot/efi/EFI/centos/grub.cfg
219     - /boot/grub2/grub.cfg
220     - /var/log/boot.log
221     - /var/log/cron
222   register: file_stat
223
224 - name: "Set the 600 file permissions"
225   file:
226     path: "{{item.item}}"
227     state: touch
228     mode: "600"
229   with_items: "{{ file_stat.results }}"
230   when:
231     - item.stat.exists == true
232
233 #
234 # Disable direct root login
235 #
236
237 - name: "Direct root Logins Not Allowed"
238   shell: echo > /etc/securetty
239
240 - name: Change 'root' shell to nologin
241   user:
242     name: root
243     shell: /sbin/nologin
244
245 - name: Lock 'root' password
246   user:
247     name: root
248     password: '!!'
249
250 #
251 # Configure IPv6
252 #
253
254 - name: Disable ipv6 support if the ipv6 is not needed
255   when: ansible_default_ipv6|length == 0
256   sysctl:
257     name: net.ipv6.conf.all.disable_ipv6
258     value: 1
259     state: present
260     reload: yes
261
262 - name: Disable Support for udp6
263   when: ansible_default_ipv6|length == 0
264   lineinfile:
265     path: /etc/netconfig
266     state: absent
267     regexp: '^udp6.*'
268
269 - name: Disable Support for tcp6
270   when: ansible_default_ipv6|length == 0
271   lineinfile:
272     path: /etc/netconfig
273     state: absent
274     regexp: '^tcp6.*'
275
276 - name: Disable automatic ipv6 configuration
277   when: ansible_default_ipv6|length > 0
278   sysctl:
279     name: "{{ item.name }}"
280     value: "{{ item.value }}"
281     state: present
282     reload: yes
283   with_items:
284     - { name: 'net.ipv6.conf.all.accept_source_route', value: 0 }
285     - { name: 'net.ipv6.conf.all.accept_ra', value: 0 }
286     - { name: 'net.ipv6.conf.default.accept_ra', value: 0 }
287     - { name: 'net.ipv6.conf.all.accept_redirects', value: 0 }
288     - { name: 'net.ipv6.conf.default.accept_redirects', value: 0 }
289     - { name: 'net.ipv6.conf.default.accept_source_route', value: 0 }
290     - { name: 'net.ipv6.conf.all.forwarding', value: 0 }
291
292 #
293 # Configure kernel parameters
294 #
295
296 - name: Configure the kernel parameters
297   sysctl:
298     name: "{{ item.name }}"
299     value: "{{ item.value }}"
300     state: present
301     reload: yes
302   with_items:
303     - { name: 'net.ipv4.conf.default.send_redirects', value: 0 }
304     - { name: 'net.ipv4.conf.all.send_redirects', value: 0 }
305     - { name: 'net.ipv4.ip_forward', value: 0 }
306     - { name: 'net.ipv4.conf.all.accept_redirects', value: 0 }
307     - { name: 'net.ipv4.conf.all.secure_redirects', value: 0 }
308     - { name: 'net.ipv4.conf.all.log_martians', value: 1 }
309     - { name: 'net.ipv4.conf.default.log_martians', value: 1 }
310     - { name: 'net.ipv4.conf.default.accept_redirects', value: 0 }
311     - { name: 'net.ipv4.conf.default.secure_redirects', value: 0 }
312     - { name: 'net.ipv4.icmp_echo_ignore_broadcasts', value: 1 }
313     - { name: 'net.ipv4.icmp_ignore_bogus_error_responses', value: 1 }
314     - { name: 'net.ipv4.tcp_syncookies', value: 1 }
315     - { name: 'fs.suid_dumpable', value: 0 }
316     - { name: 'kernel.dmesg_restrict', value: 1 }
317     - { name: 'kernel.core_uses_pid', value: 1 }
318     - { name: 'kernel.randomize_va_space', value: 2 }
319     - { name: 'kernel.core_pattern', value: '/var/core/core'}
320     - { name: 'kernel.kptr_restrict', value: 2 }
321     - { name: 'kernel.sysrq', value: 0 }
322     - { name: 'kernel.yama.ptrace_scope', value: 3 }
323
324 #
325 # Configure core dump
326 #
327
328 - name: "Disable core dump for all user"
329   lineinfile:
330     path: /etc/security/limits.conf
331     insertbefore: '^[a-z].*'
332     line: '*               hard    core            0'
333
334 - name: "Configure systemd not to store core dumps"
335   lineinfile:
336     path: /etc/systemd/coredump.conf
337     insertafter: '^\[Coredump\]'
338     line: 'Storage=none'
339
340 #
341 # Confingure kernel dump
342 - name: "Disable kernel dump service"
343   shell: systemctl stop kdump.service
344
345 - name: "Disable kernel dump service"
346   shell: systemctl disable kdump.service
347
348 # Configure syslog
349 #
350 - name: "Stop rsyslog Service"
351   shell: systemctl stop rsyslog.service
352
353 - name: "Disable rsyslog Service"
354   shell: systemctl disable rsyslog.service
355
356 - name: "Ensure the /var/log/boot.log Rotated by logrotate"
357   lineinfile:
358     path: /etc/logrotate.d/syslog
359     insertbefore: 'cron$'
360     line: /var/log/boot.log
361
362 - name: "Set the umasks by profile file"
363   lineinfile:
364     path: /etc/profile
365     regexp: '{{ item.old }}'
366     line: '{{ item.new }}'
367   with_items:
368     - { old: 'umask 002', new: umask 027 }
369     - { old: 'umask 022', new: umask 077 }
370
371 #
372 # Keystone config
373 #
374
375 - name: Set the max_request_body_size in the keystone.conf
376   lineinfile:
377     path: /etc/keystone/keystone.conf
378     insertafter: 'DEFAULT'
379     line: "# enforced by optional sizelimit middleware (keystone.middleware:RequestBodySizeLimiter)\nmax_request_body_size = 114688\n"
380
381 - name: Set the insecure_debug in the keystone.conf
382   lineinfile:
383     path: /etc/keystone/keystone.conf
384     insertafter: 'DEFAULT'
385     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"
386
387 #
388 #Setting bootloader password
389 #
390 - name: set host os variable
391   when: host_os is defined
392   set_fact:
393     grub2_pass: "{{  host_os.grub2_password | default('Empty')  }}"
394
395 - name: protect grub with root password
396   when: grub2_pass is defined and grub2_pass != 'Empty'
397   blockinfile:
398     dest: /etc/grub.d/40_custom
399     state: present
400     insertafter: 'EOF'
401     content: |
402       # define superusers
403       set superusers="root"
404       #define users
405       password_pbkdf2 root "{{ grub2_pass }}"
406
407 - name: check whether grub-efi exists
408   stat:
409     path: /boot/efi/EFI/centos/grub.cfg
410   register: grub_efi_file_stat
411
412 - name: generate grub config
413   when: grub2_pass is defined and grub2_pass != 'Empty'
414   command: /usr/sbin/grub2-mkconfig -o /boot/grub2/grub.cfg
415
416 - name: generate grub-efi config
417   command: /usr/sbin/grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg
418   when:
419     - grub2_pass is defined and grub2_pass != 'Empty'
420     - grub_efi_file_stat.stat.exists == true
421
422 #
423 #Setting the noexec option to the /dev/shm mount dir
424 #
425
426 - name: get back device associated to mountpoint
427   shell: mount | grep ' /dev/shm ' |cut -d ' ' -f 1
428   register: device_name
429   check_mode: no
430
431 - name: get back device previous mount option
432   shell: mount | grep ' /dev/shm ' | sed -re 's:.*\((.*)\):\1:'
433   register: device_cur_mountoption
434   check_mode: no
435
436 - name: get back device fstype
437   shell: mount | grep ' /dev/shm ' | cut -d ' ' -f 5
438   register: device_fstype
439   check_mode: no
440
441 - name: Ensure permission noexec are set on /dev/shm
442   mount:
443     path: "/dev/shm"
444     src: "{{device_name.stdout}}"
445     opts: "{{device_cur_mountoption.stdout}},noexec"
446     state: "mounted"
447     fstype: "{{device_fstype.stdout}}"
448
449 #
450 # Disable NFS service
451 #
452
453 - name: disable NFS related services
454   service:
455     name: "{{ item }}"
456     enabled: no
457     state: stopped
458   ignore_errors: yes
459   with_items:
460     - nfslock
461     - rpcgssd
462     - rpcidmapd
463     - nfs-idmap
464     - nfs-server
465     - nfs
466
467 - name: remove nfs-utils package
468   yum:
469     name: nfs-utils
470     state: absent
471
472 #
473 # tighten USB permissions
474 #
475 - name: Set USBGuard RestoreControllerDeviceState to false
476   lineinfile:
477     path: /etc/usbguard/usbguard-daemon.conf
478     regexp: '^[#\s]*RestoreControllerDeviceState\s*=\s*[a-z\-]*\s*$'
479     line: 'RestoreControllerDeviceState=false'
480
481 - name: Set USBGuard ImplicitPolicyTarget to block
482   lineinfile:
483     path: /etc/usbguard/usbguard-daemon.conf
484     regexp: '^[#\s]*ImplicitPolicyTarget\s*=\s*[a-z\-]*\s*$'
485     line: 'ImplicitPolicyTarget=block'
486
487 - name: Apply USBGuard policy in all cases
488   lineinfile:
489     path: /etc/usbguard/usbguard-daemon.conf
490     regexp: "^[#\\s]*{{ item }}\\s*=\\s*[a-z\\-]*\\s*$"
491     line: "{{ item }}=apply-policy"
492   with_items:
493     - PresentControllerPolicy
494     - PresentDevicePolicy
495     - InsertedDevicePolicy
496
497 - name: Limit USBGuard IPC to root
498   lineinfile:
499     path: /etc/usbguard/usbguard-daemon.conf
500     regexp: "^[#\\s]*IPCAllowed{{item}}\\s*="
501     line: "IPCAllowed{{item}}=root"
502   with_items:
503     - Users
504     - Groups
505
506 - Name: Ban suspect USB devices
507   blockinfile:
508     # this isn't the optimal way to do this, i know, but i don't
509     # want to create a whole new template tree just to add this.
510     path: /etc/usbguard/rules.conf
511     create: yes
512     owner: root
513     group: root
514     mode: 0700
515     insertbefore: BOF
516     # rules.conf doesn't seem to allow comments
517     marker: ''
518     block: |
519      # the akraino REC is targeted at server installs; as such
520      # we're liberal about allowing standard devices on the
521      # assumption we will be deployed in a relatively secure
522      # environment.  The values below were chosen based on the
523      # devices that appear on a nokia OE19 with the virtual console
524      # enabled:
525      # xHCI controller/hub
526      allow with-interface equals { 09:00:00 }
527      # mass media — sites may want to consider restricting
528      # this to 08:06:50 to just get the virtual CDROM and ban
529      # other USB media
530      allow with-interface equals { 08:*:* }
531      # ethernet
532      allow with-interface equals { 02:02:ff }
533      # keyboard/mouse
534      allow with-interface one-of { 03:00:01 03:01:01 }
535      # per usbguard-rules.conf manpage: ban keyboard devices
536      # that expose other, suspicious, interfaces
537      reject with-interface all-of { 08:*:* 03:00:* }
538      reject with-interface all-of { 08:*:* 03:01:* }
539      reject with-interface all-of { 08:*:* e0:*:* }
540      reject with-interface all-of { 08:*:* 02:*:* }
541
542 # Setting file permissions
543 #
544
545 #- name: "Remove the other user write permission from the system directorys"
546 #  command: find / -xdev \( -perm -0002 -a ! -perm -1000 \) -type d -exec chmod o-w {} \;
547 #
548 #- name: "Remove the other user write permission from the system files"
549 #  command: find / -xdev -perm -0002 -type f -exec chmod o-w {} \;
550 #
551 #- name: "Modified the unauthorized SUID/SGID system executables"
552 #  command: sudo chmod -s $(sudo find / -xdev \( -perm -4000 -o -perm -2000 \) -type f | grep -v sudo)