522 lines
14 KiB
YAML
522 lines
14 KiB
YAML
---
|
|
# Copyright 2016, Rackspace US, Inc.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
- name: Get a list of users on the system to use throughout the auth tasks
|
|
action: get_users
|
|
register: user_list
|
|
check_mode: no
|
|
tags:
|
|
- always
|
|
|
|
- name: Check if /etc/security/pwquality.conf exists
|
|
stat:
|
|
path: /etc/security/pwquality.conf
|
|
check_mode: no
|
|
register: pwquality_config_check
|
|
tags:
|
|
- always
|
|
|
|
- name: Set password quality requirements
|
|
blockinfile:
|
|
dest: /etc/security/pwquality.conf
|
|
backup: yes
|
|
insertbefore: EOF
|
|
marker: "# {mark} Added by openstack-ansible-security role"
|
|
state: present
|
|
block: "{{ lookup('template', 'pwquality.conf.j2') }}"
|
|
when:
|
|
- pwquality_config_check.stat.exists
|
|
tags:
|
|
- auth
|
|
- medium
|
|
- RHEL-07-010090
|
|
- RHEL-07-010100
|
|
- RHEL-07-010110
|
|
- RHEL-07-010120
|
|
- RHEL-07-010130
|
|
- RHEL-07-010140
|
|
- RHEL-07-010150
|
|
- RHEL-07-010160
|
|
- RHEL-07-010250
|
|
|
|
- name: Check for SHA512 password storage in PAM
|
|
command: "grep pam_unix.so {{ pam_password_file }}"
|
|
register: password_sha512_check
|
|
changed_when: False
|
|
check_mode: no
|
|
tags:
|
|
- always
|
|
|
|
- name: RHEL-07-010170 - The PAM system service must be configured to store only encrypted representations of passwords.
|
|
debug:
|
|
msg: >
|
|
PAM is not using SHA512 for password storage. This is a security issue.
|
|
when:
|
|
- password_sha512_check is defined
|
|
- "'sha512' not in password_sha512_check.stdout"
|
|
tags:
|
|
- auth
|
|
- medium
|
|
- RHEL-07-010170
|
|
|
|
- name: Configure shadow-utils configuration
|
|
lineinfile:
|
|
dest: /etc/login.defs
|
|
regexp: "^{{ item.parameter }}"
|
|
line: "{{ item.parameter }} {{ item.value }}"
|
|
state: present
|
|
when:
|
|
- item.value != ''
|
|
with_items: "{{ shadow_utils_rhel7 }}"
|
|
tags:
|
|
- auth
|
|
- medium
|
|
- RHEL-07-010180
|
|
- RHEL-07-010200
|
|
- RHEL-07-010220
|
|
- RHEL-07-010420
|
|
- RHEL-07-020230
|
|
- RHEL-07-020630
|
|
|
|
- name: RHEL-07-010190 - User and group account administration utilities must be configured to store only encrypted representations of passwords.
|
|
ini_file:
|
|
dest: /etc/libuser.conf
|
|
section: defaults
|
|
option: crypt_style
|
|
value: sha512
|
|
backup: yes
|
|
when:
|
|
- security_libuser_crypt_style_sha512 | bool
|
|
- ansible_os_family | lower == 'redhat'
|
|
tags:
|
|
- auth
|
|
- medium
|
|
- RHEL-07-010190
|
|
|
|
- name: Get all user accounts with a password lifetime limit under 24 hours
|
|
shell: "awk -F: '$4 < 1 {print $1}' /etc/shadow"
|
|
check_mode: no
|
|
changed_when: False
|
|
register: password_lifetime_check
|
|
tags:
|
|
- auth
|
|
- medium
|
|
- RHEL-07-010210
|
|
- skip_ansible_lint
|
|
|
|
- name: RHEL-07-010210 - Passwords must be restricted to a 24 hours/1 day minimum lifetime.
|
|
debug:
|
|
msg: |
|
|
Accounts were found with a minimum password lifetime limit under 24 hours:
|
|
{{ password_lifetime_check.stdout_lines | join(', ') }}
|
|
when:
|
|
- password_lifetime_check.stdout_lines is defined
|
|
tags:
|
|
- auth
|
|
- medium
|
|
- RHEL-07-010210
|
|
|
|
- name: RHEL-07-010240 - Passwords must be prohibited from reuse for a minimum of five generations.
|
|
lineinfile:
|
|
dest: "{{ pam_password_file }}"
|
|
regexp: '^(password\s+[a-z0-9\=\[\] ]+\s+pam_unix\.so.+?)\s+(?:remember=\d+)?$'
|
|
line: '\1 remember={{ security_password_remember_password }}'
|
|
backrefs: yes
|
|
state: present
|
|
when:
|
|
- security_password_remember_password is defined
|
|
tags:
|
|
- auth
|
|
- medium
|
|
- RHEL-07-010240
|
|
|
|
- name: RHEL-07-010230 - Existing passwords must be restricted to a 60-day maximum lifetime.
|
|
debug:
|
|
msg: |
|
|
The following user accounts have an existing password with a lifetime of
|
|
greater than 60 days:
|
|
{%- for user in user_list.users %}
|
|
{% if user['shadow']['max_days'] > 60 %}
|
|
{{ user['name'] }} has an expiration of {{ user['shadow']['max_days'] }} days
|
|
{% endif %}
|
|
{% endfor %}
|
|
tags:
|
|
- auth
|
|
- medium
|
|
- RHEL-07-010230
|
|
|
|
- name: RHEL-07-010260 - The system must not have accounts configured with blank or null passwords
|
|
lineinfile:
|
|
dest: "{{ pam_auth_file }}"
|
|
state: present
|
|
regexp: "^(.*)nullok_secure(.*)$"
|
|
line: '\1\2'
|
|
backup: yes
|
|
backrefs: yes
|
|
when:
|
|
- ansible_os_family == 'Debian'
|
|
- security_disallow_blank_password_login | bool
|
|
tags:
|
|
- auth
|
|
- high
|
|
- RHEL-07-010260
|
|
|
|
- name: RHEL-07-010260 - The system must not have accounts configured with blank or null passwords
|
|
lineinfile:
|
|
dest: "{{ pam_auth_file }}"
|
|
state: present
|
|
regexp: "^({{ item }}.*sufficient.*)nullok(.*)$"
|
|
line: '\1\2'
|
|
backup: yes
|
|
backrefs: yes
|
|
with_items:
|
|
- auth
|
|
- password
|
|
when:
|
|
- ansible_os_family == 'RedHat'
|
|
- security_disallow_blank_password_login | bool
|
|
tags:
|
|
- auth
|
|
- high
|
|
- RHEL-07-010260
|
|
|
|
- name: RHEL-07-010280 - The operating system must disable account identifiers if the password expires.
|
|
lineinfile:
|
|
dest: /etc/default/useradd
|
|
regexp: '^[#\s]*INACTIVE'
|
|
line: 'INACTIVE=0'
|
|
when:
|
|
- security_disable_account_if_password_expires | bool
|
|
tags:
|
|
- auth
|
|
- medium
|
|
- RHEL-07-010280
|
|
|
|
- name: RHEL-07-010371 - If three unsuccessful logon attempts within 15 minutes occur the associated account must be locked.
|
|
blockinfile:
|
|
dest: pam_password_file
|
|
state: present
|
|
marker: "# {mark} MANAGED BY OPENSTACK-ANSIBLE-SECURITY"
|
|
insertbefore: EOF
|
|
block: "{{ lookup('template', 'pam_faillock.j2') }}"
|
|
when:
|
|
- ansible_os_family | lower == 'redhat'
|
|
- security_pam_faillock_enable | bool
|
|
tags:
|
|
- auth
|
|
- medium
|
|
- RHEL-07-010371
|
|
- RHEL-07-010372
|
|
- RHEL-07-010373
|
|
|
|
- name: Check for 'nopasswd' in sudoers files
|
|
shell: grep -ir nopasswd /etc/sudoers /etc/sudoers.d/ || echo 'not found'
|
|
register: sudoers_nopasswd_check
|
|
changed_when: False
|
|
tags:
|
|
- auth
|
|
- medium
|
|
- RHEL-07-010380
|
|
|
|
- name: RHEL-07-010380 - Users must provide a password for privilege escalation.
|
|
debug:
|
|
msg: >
|
|
The 'NOPASSWD' directive was found in the sudoers configuration files.
|
|
Remove the directive to ensure that all users must provide a password to
|
|
run commands as the root user.
|
|
when:
|
|
- not sudoers_nopasswd_check | skipped
|
|
- sudoers_nopasswd_check.stdout != 'not found'
|
|
tags:
|
|
- auth
|
|
- medium
|
|
- RHEL-07-010380
|
|
- skip_ansible_lint
|
|
|
|
- name: Check for '!authenticate' in sudoers files
|
|
shell: grep -ir '\!authenticate' /etc/sudoers /etc/sudoers.d/ || echo 'not found'
|
|
register: sudoers_authenticate_check
|
|
changed_when: False
|
|
tags:
|
|
- auth
|
|
- medium
|
|
- RHEL-07-010381
|
|
|
|
- name: RHEL-07-010381 - Users must re-authenticate for privilege escalation.
|
|
debug:
|
|
msg: >
|
|
The '!authenticate' directive was found in the sudoers configuration
|
|
files. Remove the directive to ensure that all users must provide a
|
|
password to run commands as the root user each time they use sudo.
|
|
when:
|
|
- not sudoers_authenticate_check | skipped
|
|
- sudoers_authenticate_check.stdout != 'not found'
|
|
tags:
|
|
- auth
|
|
- medium
|
|
- RHEL-07-010381
|
|
- skip_ansible_lint
|
|
|
|
- name: Check if sssd.conf exists
|
|
stat:
|
|
path: /etc/sssd/sssd.conf
|
|
register: sssd_conf_check
|
|
check_mode: no
|
|
tags:
|
|
- always
|
|
|
|
- name: RHEL-07-010400 - The operating system must prohibit the use of cached nss authenticators after one day.
|
|
ini_file:
|
|
dest: /etc/sssd/sssd.conf
|
|
section: nss
|
|
option: memcache_timeout
|
|
value: "{{ security_nss_cached_authenticator_timeout }}"
|
|
backup: yes
|
|
when:
|
|
- sssd_conf_check.stat.exists
|
|
- security_nss_cached_authenticator_timeout is defined
|
|
tags:
|
|
- auth
|
|
- medium
|
|
- RHEL-07-010400
|
|
|
|
- name: RHEL-07-010401 - The operating system must prohibit the use of cached PAM authenticators after one day.
|
|
ini_file:
|
|
dest: /etc/sssd/sssd.conf
|
|
section: pam
|
|
option: offline_credentials_expiration
|
|
value: "{{ security_pam_offline_credentials_expiration_days }}"
|
|
backup: yes
|
|
when:
|
|
- sssd_conf_check.stat.exists
|
|
- security_pam_offline_credentials_expiration_days is defined
|
|
tags:
|
|
- auth
|
|
- medium
|
|
- RHEL-07-010401
|
|
- RHEL-07-010402
|
|
|
|
- name: Set a GRUB 2 password for single-user/maintenance modes
|
|
lineinfile:
|
|
dest: "{{ grub_defaults_file }}"
|
|
regexp: '^(#)?GRUB_PASSWORD'
|
|
line: 'GRUB_PASSWORD="{{ security_grub_password_hash }}"'
|
|
state: present
|
|
when:
|
|
- security_require_grub_authentication | bool
|
|
notify:
|
|
- update grub config
|
|
tags:
|
|
- auth
|
|
- high
|
|
- RHEL-07-010460
|
|
- RHEL-07-010470
|
|
|
|
- name: Get all accounts with UID 0
|
|
shell: "awk -F: '$3 == 0 {print $1}' /etc/passwd"
|
|
changed_when: False
|
|
check_mode: no
|
|
register: root_user_check
|
|
tags:
|
|
- auth
|
|
- high
|
|
- RHEL-07-020310
|
|
- skip_ansible_lint
|
|
|
|
- name: Check for groups in /etc/passwd that are not in /etc/group
|
|
debug:
|
|
msg: >
|
|
The following users have GIDs in /etc/passwd that do not exist in /etc/group:
|
|
{{ user_list.users | selectattr('group', 'equalto', False) | map(attribute='name') | join(', ') }}
|
|
when:
|
|
- user_list is defined
|
|
- user_list.users | selectattr('group', 'equalto', False) | list | length > 0
|
|
tags:
|
|
- auth
|
|
- low
|
|
- RHEL-07-020300
|
|
|
|
- name: RHEL-07-020310 - The root account must be the only account having unrestricted access to the system
|
|
fail:
|
|
msg: |
|
|
Only the 'root' user should have UID 0. Other users were found:
|
|
{{ root_user_check.stdout_lines | join(', ') }}"
|
|
when:
|
|
- root_user_check.stdout != 'root'
|
|
tags:
|
|
- auth
|
|
- high
|
|
- RHEL-07-020310
|
|
|
|
- name: RHEL-07-020620 - All local interactive users must have a home directory assigned in the /etc/passwd file.
|
|
debug:
|
|
msg: |
|
|
The following users do not have a home directory assigned:
|
|
{{ user_list.users | selectattr('dir', 'equalto', '') | map(attribute='name') | join(', ') }}
|
|
when:
|
|
- user_list is defined
|
|
- user_list.users | selectattr('dir', 'equalto', '') | map(attribute='name') | list | length > 0
|
|
tags:
|
|
- auth
|
|
- medium
|
|
- RHEL-07-020620
|
|
|
|
- name: Check each user to see if its home directory exists on the filesystem
|
|
stat:
|
|
path: "{{ item['dir'] }}"
|
|
when:
|
|
- item['dir'] != ''
|
|
with_items: "{{ user_list.users }}"
|
|
register: home_directory_checks
|
|
tags:
|
|
- auth
|
|
- medium
|
|
- RHEL-07-020640
|
|
|
|
- name: RHEL-07-020640 - All local interactive user home directories defined in the /etc/passwd file must exist.
|
|
debug:
|
|
msg: |
|
|
These users have a home directory assigned, but the directory does not exist:
|
|
{% for check in home_directory_checks.results %}
|
|
{% if not check.stat.exists %}
|
|
{{ check.item.name }} ({{ check.item.dir }} does not exist)
|
|
{% endif %}
|
|
{% endfor %}
|
|
when:
|
|
- home_directory_checks.results | selectattr('stat.exists', 'sameas', false) | list | length > 0
|
|
tags:
|
|
- auth
|
|
- medium
|
|
- RHEL-07-020640
|
|
|
|
- name: RHEL-07-040010 - The operating system must limit the number of concurrent sessions to 10 for all accounts and/or account types.
|
|
blockinfile:
|
|
dest: /etc/security/limits.d/openstack-ansible-security-maxlogins.conf
|
|
create: yes
|
|
block: |
|
|
# Deployed by the openstack-ansible-security role
|
|
# RHEL-07-040010 - Limit concurrent sessions for all accounts/types
|
|
* hard maxlogins {{ security_rhel7_concurrent_session_limit }}
|
|
when:
|
|
- security_rhel7_concurrent_session_limit is defined
|
|
tags:
|
|
- auth
|
|
- low
|
|
- RHEL-07-040010
|
|
|
|
- name: Check for PAM PKCS 11 authentication configuration
|
|
stat:
|
|
path: /etc/pam_pkcs11/pam_pkcs11.conf
|
|
register: pkcs11_conf_check
|
|
check_mode: no
|
|
tags:
|
|
- always
|
|
|
|
- name: Check for ocsp_on in PAM PKCS 11 auth configuration
|
|
shell: 'grep cert_policy /etc/pam_pkcs11/pam_pkcs11.conf | grep -c ocsp_on'
|
|
register: oscp_on_check
|
|
changed_when: False
|
|
failed_when: False
|
|
check_mode: no
|
|
when:
|
|
- pkcs11_conf_check.stat.exists
|
|
tags:
|
|
- always
|
|
|
|
- name: RHEL-07-040030 - Must Validate PKI-based auth attempts with OCSP
|
|
debug:
|
|
msg: >
|
|
PKI-based authentication attempts must use OCSP for certificate
|
|
validation. Review the documentation for RHEL-07-040030.
|
|
when:
|
|
- pkcs11_conf_check.stat.exists
|
|
- oscp_on_check.stdout != 3
|
|
tags:
|
|
- medium
|
|
- auth
|
|
- RHEL-07-040030
|
|
|
|
- name: Check for cackey or coolkey in the PAM PKCS11 auth configuration
|
|
shell: 'egrep "use_pkcs11_module = (cackey|coolkey)" /etc/pam_pkcs11/pam_pkcs11.conf'
|
|
register: pkcs11_key_check
|
|
changed_when: False
|
|
failed_when: False
|
|
check_mode: no
|
|
when:
|
|
- pkcs11_conf_check.stat.exists
|
|
tags:
|
|
- always
|
|
|
|
- name: RHEL-07-040040 - Must use cackey/cookey for PKCS 11 auth
|
|
debug:
|
|
msg: >
|
|
PKI-based authentication attempts must use cackey or coolkey.
|
|
Review the documentation for RHEL-07-040040.
|
|
when:
|
|
- pkcs11_conf_check.stat.exists
|
|
- pkcs11_key_check.stdout.rc != 0
|
|
tags:
|
|
- medium
|
|
- auth
|
|
- RHEL-07-040040
|
|
|
|
- name: Check for pam_lastlog in PAM configuration
|
|
command: "grep pam_lastlog {{ pam_postlogin_file }}"
|
|
register: pam_lastlog_check
|
|
changed_when: False
|
|
failed_when: False
|
|
check_mode: no
|
|
tags:
|
|
- always
|
|
|
|
- name: RHEL-07-040300 - Display date/time of last logon after logon
|
|
debug:
|
|
msg: >
|
|
The 'pam_lastlog' directive is missing in {{ pam_postlogin_file }}.
|
|
This is required by RHEL-07-040300.
|
|
when:
|
|
- pam_lastlog_check.rc != 0
|
|
tags:
|
|
- low
|
|
- auth
|
|
- RHEL-07-040300
|
|
|
|
- name: Check for .shosts or shosts.equiv files
|
|
find:
|
|
paths: /
|
|
recurse: yes
|
|
hidden: yes
|
|
patterns: '.shosts,shosts.equiv'
|
|
register: shosts_find
|
|
when:
|
|
- security_rhel7_remove_shosts_files | bool
|
|
tags:
|
|
- always
|
|
|
|
- name: Remove .shosts or shosts.equiv files
|
|
file:
|
|
path: "{{ item.path }}"
|
|
state: absent
|
|
with_items: "{{ shosts_find.files }}"
|
|
when:
|
|
- security_rhel7_remove_shosts_files | bool
|
|
- shosts_find is defined
|
|
- shosts_find.files is defined
|
|
tags:
|
|
- high
|
|
- auth
|
|
- RHEL-07-040330
|
|
- RHEL-07-040331
|