Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PASSWORD Improvements #421

Merged
merged 6 commits into from
Oct 25, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 38 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -434,22 +434,57 @@ and packages to be removed (`packages_blocklist`).
### ./defaults/main/password.yml

```yaml
pwquality_config:
faillock_enable: true
faillock:
admin_group: []
audit: true
deny: 5
dir: /var/run/faillock
even_deny_root: true
fail_interval: 900
local_users_only: true
no_log_info: false
nodelay: true
root_unlock_time: 600
silent: false
unlock_time: 600
login_defs:
login_retries: 5
login_timeout: 60
pass_max_days: 60
pass_min_days: 1
pass_warn_age: 7
password_remember: 5
pwquality:
dcredit: -1
dictcheck: 1
dictpath: 1
difok: 8
enforce_for_root: true
enforcing: 1
gecoscheck: 1
lcredit: -1
local_users_only: true
maxclassrepeat: 4
maxrepeat: 3
minclass: 4
minlen: 15
ocredit: -1
retry: 3
ucredit: -1
usercheck: 1
usersubstr: 3
```

Configure the [libpwquality](https://manpages.ubuntu.com/manpages/jammy/man5/pwquality.conf.5.html)
library.
`faillock_enable` set to `false` for disable faillock library.

`password_remember` set the size of the password history that the user will not be able to reuse.

Configure the [pam_faillock](https://manpages.ubuntu.com/manpages/lunar/en/man5/faillock.conf.5.html) library.

Configure the [login.defs](https://manpages.ubuntu.com/manpages/lunar/en/man5/login.defs.5.html) configuration.

Configure the [libpwquality](https://manpages.ubuntu.com/manpages/jammy/man5/pwquality.conf.5.html) library.

### ./defaults/main/sshd.yml

Expand Down
30 changes: 29 additions & 1 deletion defaults/main/password.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,41 @@
---
pwquality_config:
faillock_enable: true
faillock:
admin_group: []
audit: true
deny: 5
dir: /var/run/faillock
even_deny_root: true
fail_interval: 900
local_users_only: true
no_log_info: false
nodelay: true
root_unlock_time: 600
silent: false
unlock_time: 600
login_defs:
login_retries: 5
login_timeout: 60
pass_max_days: 60
pass_min_days: 1
pass_warn_age: 7
password_remember: 5
pwquality:
dcredit: -1
dictcheck: 1
dictpath: 1
difok: 8
enforce_for_root: true
enforcing: 1
gecoscheck: 1
lcredit: -1
local_users_only: true
maxclassrepeat: 4
maxrepeat: 3
minclass: 4
minlen: 15
ocredit: -1
retry: 3
ucredit: -1
usercheck: 1
usersubstr: 3
6 changes: 4 additions & 2 deletions defaults/main/templates.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,26 @@ common_account_template: etc/pam.d/common-account.j2
common_auth_template: etc/pam.d/common-auth.j2
common_password_template: etc/pam.d/common-password.j2
coredump_conf_template: etc/systemd/coredump.conf.j2
faillock_conf_template: etc/security/faillock.conf.j2
hardening_rules_template: etc/audit/rules.d/hardening.rules.j2
hosts_allow_template: etc/hosts.allow.j2
hosts_deny_template: etc/hosts.deny.j2
initpath_sh_template: etc/profile.d/initpath.sh.j2
issue_template: etc/issue.j2
journald_conf_template: etc/systemd/journald.conf.j2
limits_conf_template: etc/security/limits.conf.j2
logind_conf_template: etc/systemd/logind.conf.j2
login_defs_template: etc/login.defs.j2
login_template: etc/pam.d/login.j2
logind_conf_template: etc/systemd/logind.conf.j2
logrotate_conf_template: etc/logrotate.conf.j2
motd_template: etc/motd.j2
pwquality_conf_template: etc/security/pwquality.conf.j2
resolved_conf_template: etc/systemd/resolved.conf.j2
rkhunter_template: etc/default/rkhunter.j2
ssh_config_template: etc/ssh/ssh_config.j2
sshd_config_template: etc/ssh/sshd_config.j2
system_conf_template: etc/systemd/system.conf.j2
timesyncd_conf_template: etc/systemd/timesyncd.conf.j2
tmp_mount_template: etc/systemd/tmp.mount.j2
useradd_template: etc/default/useradd.j2
user_conf_template: etc/systemd/user.conf.j2
useradd_template: etc/default/useradd.j2
200 changes: 173 additions & 27 deletions molecule/default/verify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -471,39 +471,100 @@
failed_when: mounts_tmp.rc != 0
changed_when: mounts_tmp.rc != 0

- name: Get PAM version
tags:
- fact
- common-account
- common-auth
- pam
block:
- name: Gather package facts
ansible.builtin.package_facts:

- name: Get libpam version in Debian family
ansible.builtin.set_fact:
pam_version: "{{ ansible_facts.packages['libpam-modules'][0].version }}"
when:
- ansible_os_family == "Debian"
- "'libpam-modules' in ansible_facts.packages"

- name: Get libpam version in RedHat family
ansible.builtin.set_fact:
pam_version: "{{ ansible_facts.packages['pam'][0].version }}"
when:
- ansible_os_family == "RedHat"
- "'pam' in ansible_facts.packages"

- name: Set hashing algorithm for password (yescrypt|sha512)
ansible.builtin.set_fact:
password_algorithm: "{{ 'yescrypt' if (pam_version is version('1.4.0', '>=')) else 'sha512' }}"
tags:
- fact
- pam
- CIS-UBUNTU2204-5.4.4
- M1041

- name: Verify login.defs settings
become: true
ansible.builtin.shell: grep "^{{ item }}$" /etc/login.defs
register: login_defs
failed_when: login_defs.rc != 0
changed_when: login_defs.rc != 0
with_items:
- ENCRYPT_METHOD SHA512
- ENCRYPT_METHOD {{ password_algorithm | upper }}
- FAILLOG_ENAB yes
- LOG_OK_LOGINS yes
- PASS_MAX_DAYS 60
- PASS_MIN_DAYS 1
- PASS_WARN_AGE 7
- LOGIN_RETRIES {{ login_defs.login_retries }}
- LOGIN_TIMEOUT {{ login_defs.login_timeout }}
- PASS_MAX_DAYS {{ login_defs.pass_max_days }}
- PASS_MIN_DAYS {{ login_defs.pass_min_days }}
- PASS_WARN_AGE {{ login_defs.pass_warn_age }}
- SHA_CRYPT_MAX_ROUNDS 65536
konstruktoid marked this conversation as resolved.
Show resolved Hide resolved
- SHA_CRYPT_MIN_ROUNDS 10000
- SU_NAME su
- SYSLOG_SG_ENAB yes
- SYSLOG_SU_ENAB yes
- UMASK {{ umask_value }}

- name: Set pwquality_parameters
ansible.builtin.set_fact:
pwquality_parameters:
- dcredit = {{ pwquality.dcredit }}
- dictcheck = {{ pwquality.dictcheck }}
- dictpath = {{ pwquality.dictpath }}
- difok = {{ pwquality.difok }}
- >-
{%- if (pwquality.enforce_for_root | bool) -%}
enforce_for_root
{%- endif -%}
- enforcing = {{ pwquality.enforcing }}
- gecoscheck = {{ pwquality.gecoscheck }}
- lcredit = {{ pwquality.lcredit }}
- >-
{%- if (pwquality.local_users_only | bool) -%}
local_users_only
{%- endif -%}
- maxclassrepeat = {{ pwquality.maxclassrepeat }}
- maxrepeat = {{ pwquality.maxrepeat }}
- minclass = {{ pwquality.minclass }}
- minlen = {{ pwquality.minlen }}
- ocredit = {{ pwquality.ocredit }}
- retry = {{ pwquality.retry }}
- ucredit = {{ pwquality.ucredit }}
- usercheck = {{ pwquality.usercheck }}
- usersubstr = {{ pwquality.usersubstr }}

- name: Verify pwquality.conf settings
become: true
ansible.builtin.lineinfile:
path: /etc/security/pwquality.conf
line: "{{ item.key }} = {{ item.value }}"
state: present
dest: /etc/security/pwquality.conf
mode: "0644"
owner: root
group: root
state: present
line: "{{ item }}"
check_mode: true
register: pwquality_conf
failed_when: pwquality_conf is changed
with_dict: "{{ pwquality_config }}"
register: verify_pwquality
failed_when: verify_pwquality is changed
loop: "{{ pwquality_parameters | select() }}"

- name: Verify RedHat GRUB audit settings
become: true
Expand Down Expand Up @@ -725,6 +786,53 @@
path: /etc/security/faillock.conf
register: faillockconf

- name: Get PAM version
when: faillockconf.stat.exists
tags:
- common-account
- common-auth
- pam
block:
- name: Gather package facts
ansible.builtin.package_facts:

- name: Get libpam version in Debian family
ansible.builtin.set_fact:
pam_version: "{{ ansible_facts.packages['libpam-modules'][0].version }}"
when:
- ansible_os_family == "Debian"
- "'libpam-modules' in ansible_facts.packages"

- name: Get libpam version in RedHat family
ansible.builtin.set_fact:
pam_version: "{{ ansible_facts.packages['pam'][0].version }}"
when:
- ansible_os_family == "RedHat"
- "'pam' in ansible_facts.packages"

- name: Set faillock_parameters
ansible.builtin.set_fact:
faillock_parameters:
- dir = {{ faillock.dir }}
- "{{ 'audit' if (faillock.audit | bool) }}"
- "{{ 'silent' if (faillock.silent | bool) }}"
- "{{ 'no_log_info' if (faillock.no_log_info | bool) }}"
- "{{ 'local_users_only' if (faillock.local_users_only | bool) }}"
- >-
{%- if (pam_version is version('1.5.1', '>=')) -%}
{{ 'nodelay' if (faillock.nodelay | bool) }}
{%- endif -%}
- deny = {{ faillock.deny }}
- fail_interval = {{ faillock.fail_interval }}
- unlock_time = {{ faillock.unlock_time }}
- "{{ 'even_deny_root' if (faillock.even_deny_root | bool) }}"
- root_unlock_time = {{ faillock.root_unlock_time }}
- >-
{%- for group in faillock.admin_group -%}
admin_group = {{ group }}
{%- endfor -%}
when: faillockconf.stat.exists

- name: Verify faillock.conf
become: true
ansible.builtin.lineinfile:
Expand All @@ -735,11 +843,7 @@
check_mode: true
register: verify_faillock
failed_when: verify_faillock is changed
with_items:
- audit
- local_users_only
- deny = 5
- fail_interval = 900
loop: "{{ faillock_parameters | select() }}"
when: faillockconf.stat.exists

- name: Verify wireless state
Expand Down Expand Up @@ -809,29 +913,71 @@
- "!/var/log/audit"
- "!/var/log/journal"

- name: Create hash password
block:
- name: Install mkpasswd RedHat family
become: true
ansible.builtin.package:
name: mkpasswd
when:
- password_algorithm == "yescrypt"
- ansible_os_family == "RedHat"
- ansible_distribution_major_version | int >= 9

- name: Install mkpasswd Debian family
become: true
ansible.builtin.package:
name: whois
when:
- password_algorithm == "yescrypt"
- ansible_os_family == "Debian"

- name: Create yescrypt password hash
ansible.builtin.shell: |
set -o pipefail
echo -n '{{ item }}' | mkpasswd --stdin --method=yescrypt --rounds=8
args:
executable: /bin/bash
register: mkpasswd
changed_when: false
failed_when: mkpasswd.rc != 0
loop:
- 'Ansible Role Test User'
- 'Change Ansible Role Test User'
when: password_algorithm == "yescrypt"

- name: Set passwords
ansible.builtin.set_fact:
passwords: "{{ mkpasswd.results | map(attribute='stdout') | list }}"
when:
- password_algorithm == "yescrypt"
- mkpasswd.rc == 0

- name: Create sha512 password hash
vars:
salt: "{{ lookup('password', '/dev/null chars=ascii_lowercase,ascii_uppercase,digits length=16') }}"
ansible.builtin.set_fact:
passwords: "{{ passwords | default([]) | union([item | password_hash('sha512', salt, rounds=65536)]) }}"
loop:
- 'Ansible Role Test User'
- 'Change Ansible Role Test User'
when: password_algorithm == "sha512"

- name: Create test user
become: true
ansible.builtin.user:
name: roletestuser
password: "{{ 'Ansible Role Test User' | password_hash('sha512') }}"
password: "{{ passwords[0] }}"
state: present
shell: /bin/bash

- name: Create test user salt
ansible.builtin.set_fact:
test_user_salt: "{{ lookup('password', '/dev/null chars=ascii_lowercase,ascii_uppercase,digits length=16') }}"

- name: Change test user password
become: true
ansible.builtin.user:
name: roletestuser
password: "{{ 'roletestuser' | password_hash('sha512', test_user_salt, rounds=656000) }}"
password: "{{ passwords[1] }}"
register: test_user_pass

- name: Debug test user salt
ansible.builtin.debug:
msg: "{{ test_user_salt }}"

- name: Debug test user password
ansible.builtin.debug:
msg: "{{ test_user_pass }}"
Loading