Execution
Date 15 Dec 2025 09:38:00 +0000
Duration 00:17:22.68
Controller aio1.openstack.local
User root
Versions
Ansible 2.18.6
ara 1.7.4 / 1.7.4
Python 3.12.3
Summary
18 Hosts
603 Tasks
2798 Results
18 Plays
138 Files
0 Records

File: /home/zuul/src/opendev.org/openstack/ansible-hardening/tasks/rhel7stig/auth.yml

---
# 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.

# NOTE(mhayden): pam_faildelay expects the `delay` parameter to be in
# microseconds.
- name: Set pam_faildelay configuration on Ubuntu
  ansible.builtin.lineinfile:
    dest: /etc/pam.d/login
    regexp: "^(auth[\\s]+optional[\\s]+pam_faildelay.so).*$"
    line: "\\1 delay={{ (security_shadow_utils_fail_delay | int) * 10**6 }}"
    state: present
    backrefs: true
  when:
    - security_shadow_utils_fail_delay is defined
    - ansible_facts['os_family'] | lower == 'debian'
  tags:
    - auth
    - medium
    - V-71951

- name: Prevent users with blank or null passwords from authenticating (Debian/Ubuntu)
  ansible.builtin.lineinfile:
    dest: "{{ pam_auth_file }}"
    state: present
    regexp: "^(.*)nullok_secure(.*)$"
    line: "\\1\\2"
    backup: true
    backrefs: true
  when:
    - ansible_facts['os_family'] == 'Debian'
    - security_disallow_blank_password_login | bool
  tags:
    - auth
    - high
    - V-71937

- name: Prevent users with blank or null passwords from authenticating (Red Hat)
  ansible.builtin.lineinfile:
    dest: "{{ item[1] }}"
    state: present
    regexp: "^({{ item[0] }}.*sufficient.*)nullok(.*)$"
    line: "\\1\\2"
    backup: true
    backrefs: true
  loop: "{{ ['auth', 'password'] | product(['{{ pam_auth_file }}', '{{ pam_password_file }}']) | list }}"
  when:
    - ansible_facts['os_family'] == 'RedHat'
    - security_disallow_blank_password_login | bool
  tags:
    - auth
    - high
    - V-71937

- name: Lock accounts after three failed login attempts a 15 minute period
  ansible.builtin.blockinfile:
    dest: "{{ pam_password_file }}"
    state: present
    marker: "# {mark} MANAGED BY ANSIBLE-HARDENING"
    insertbefore: EOF
    block: "{{ lookup('template', 'pam_faillock.j2') }}"
  when:
    - ansible_facts['pkg_mgr'] == 'dnf'
    - security_pam_faillock_enable | bool
  tags:
    - auth
    - medium
    - V-71943
    - V-71945

# NOTE(mhayden): The unusual regex here ensures that we're omitting any lines
# that are commented out. Some commented lines may be preprended with spaces,
# so we need to account for that as well.
#
# First step is to find lines with 'nopasswd' in them and then omit any of
# those lines that have a '#' as the first character or '#' as the first
# character following a space (or series of spaces).
- name: Check for 'nopasswd' in sudoers files
  ansible.builtin.shell: 'grep -ir nopasswd /etc/sudoers /etc/sudoers.d/ | grep -Ev "^([[:space:]]*)?(#|$)" || echo "not found"'
  register: sudoers_nopasswd_check
  changed_when: false
  when:
    - security_sudoers_nopasswd_check_enable | bool
  tags:
    - auth
    - medium
    - V-71947

- name: V-71947 - 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:
    - sudoers_nopasswd_check is not skipped
    - sudoers_nopasswd_check.stdout != 'not found'
  tags:
    - auth
    - medium
    - V-71947
    - skip_ansible_lint

- name: Check for '!authenticate' in sudoers files
  ansible.builtin.shell: grep -ir '\!authenticate' /etc/sudoers /etc/sudoers.d/ || echo 'not found'
  register: sudoers_authenticate_check
  changed_when: false
  tags:
    - auth
    - medium
    - V-71949

- name: V-71949 - 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:
    - sudoers_authenticate_check is not skipped
    - sudoers_authenticate_check.stdout != 'not found'
  tags:
    - auth
    - medium
    - V-71949
    - skip_ansible_lint

- name: Check if sssd.conf exists
  ansible.builtin.stat:
    path: /etc/sssd/sssd.conf
  register: sssd_conf_check
  check_mode: false
  tags:
    - always

# NOTE(mhayden): Some systems, such as ARM, don't have grub at all. This task
# should be skipped on those systems.
- name: Check if GRUB2 custom file exists
  ansible.builtin.stat:
    path: "{{ grub_custom_file }}"
  register: grub_custom_file_check
  check_mode: false
  tags:
    - always

- name: Set a GRUB 2 password for single-user/maintenance modes
  block:
    - name: Define password options for grub
      ansible.builtin.blockinfile:
        path: "{{ grub_custom_file }}"
        insertbefore: EOF
        marker: "# {mark} MANAGED BY ANSIBLE-HARDENING"
        block: |
          set superusers="root"
          password_pbkdf2 root {{ security_grub_password_hash }}
        state: present
      notify:
        - Update grub config
    - name: Set CLASS for grub file
      ansible.builtin.lineinfile:
        path: "{{ grub_linux_file }}"
        regexp: "^CLASS=.*"
        line: 'CLASS="--class gnu-linux --class gnu --class os --unrestricted"'
        state: present
        backrefs: true
      notify:
        - Update grub config
  when:
    - grub_custom_file_check.stat.exists | bool
    - security_require_grub_authentication | bool
  tags:
    - auth
    - high
    - V-71961
    - V-71963

- name: V-72217 - The operating system must limit the number of concurrent sessions to 10 for all accounts and/or account types
  ansible.builtin.blockinfile:
    dest: /etc/security/limits.d/ansible-hardening-maxlogins.conf
    create: true
    mode: "0644"
    block: |
      # Deployed by the ansible-hardening role
      # V-72217 - 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
    - V-72217

- name: Check for pam_lastlog in PAM configuration
  ansible.builtin.command: "grep pam_lastlog {{ pam_postlogin_file }}"
  register: pam_lastlog_check
  changed_when: false
  failed_when: false
  check_mode: false
  tags:
    - always

- name: V-72275 - Display date/time of last logon after logon
  ansible.builtin.debug:
    msg: >
      The 'pam_lastlog' directive is missing in {{ pam_postlogin_file }}.
      This is required by V-72275.
  when:
    - pam_lastlog_check.rc != 0
  tags:
    - low
    - auth
    - V-72275

- name: Ensure .shosts find has finished
  ansible.builtin.async_status:
    jid: "{{ shosts_find.ansible_job_id }}"
  failed_when: false
  changed_when: false
  register: job_result
  until: job_result.finished
  retries: 60
  when:
    - shosts_find is not skipped
  tags:
    - high
    - auth
    - V-72277
    - V-72279

- name: Remove .shosts or shosts.equiv files
  ansible.builtin.file:
    path: "{{ item.path }}"
    state: absent
  with_items: "{{ job_result.files }}"
  when:
    - job_result is not skipped
    - security_rhel7_remove_shosts_files | bool
  tags:
    - high
    - auth
    - V-72277
    - V-72279