Skip to content

Commit

Permalink
Merge pull request #392 from dev-sec/tally
Browse files Browse the repository at this point in the history
restructure PAM handling and update for currently supported Linux distributions
  • Loading branch information
schurzi committed Mar 15, 2021
2 parents eeedaea + b2dd73d commit 74c7294
Show file tree
Hide file tree
Showing 20 changed files with 430 additions and 162 deletions.
1 change: 1 addition & 0 deletions molecule/os_hardening/converge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
os_security_kernel_enable_core_dump: true
os_security_suid_sgid_remove_from_unknown: true
os_auth_pam_passwdqc_enable: false
os_auth_lockout_time: 15
os_desktop_enable: true
os_env_extra_user_paths: ['/home']
os_auth_allow_homeless: true
Expand Down
4 changes: 4 additions & 0 deletions molecule/os_hardening/verify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
name: procps
when: ansible_facts.os_family == 'Debian'

- name: include PAM tests
include: verify_pam.yml
when: ansible_facts.distribution in ['Debian', 'Ubuntu'] or ansible_facts.os_family == 'RedHat'

- name: download cinc-auditor
get_url:
url: https://omnitruck.cinc.sh/install.sh
Expand Down
59 changes: 59 additions & 0 deletions molecule/os_hardening/verify_pam.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
- name: download pam-tester
get_url:
url: https://github.com/schurzi/pam-tester/releases/download/latest/pam-tester
dest: /bin/pam-tester
mode: 0555

- name: set password for test
set_fact:
test_pw: "myTest!pw"

- name: set locale for test
set_fact:
locale: "en_US.UTF-8"
when:
- ansible_facts.os_family == 'RedHat'
- ansible_facts.distribution_major_version < '8'

- name: create testuser
user:
name: testuser
password: "{{ test_pw | password_hash('sha512') }}"

- name: check successfull login with correct password
shell:
cmd: "pam-tester --user testuser --password {{ test_pw }}"
environment:
TMPDIR: /var/tmp
LC_ALL: "{{ locale | default('C.UTF-8') }}"
LANG: "{{ locale | default('C.UTF-8') }}"

- name: check unsuccessfull login with incorrect password
shell:
cmd: "pam-tester --user testuser --password {{ test_pw }}fail --expectfail"
environment:
TMPDIR: /var/tmp
LC_ALL: "{{ locale | default('C.UTF-8') }}"
LANG: "{{ locale | default('C.UTF-8') }}"
with_sequence: count=6

- name: check unsuccessfull login, with correct password (lockout)
shell:
cmd: "pam-tester --user testuser --password {{ test_pw }} --expectfail"
environment:
TMPDIR: /var/tmp
LC_ALL: "{{ locale | default('C.UTF-8') }}"
LANG: "{{ locale | default('C.UTF-8') }}"

- name: wait for account to unlock
pause:
seconds: 20

- name: check successfull login
shell:
cmd: "pam-tester --user testuser --password {{ test_pw }}"
environment:
TMPDIR: /var/tmp
LC_ALL: "{{ locale | default('C.UTF-8') }}"
LANG: "{{ locale | default('C.UTF-8') }}"
10 changes: 10 additions & 0 deletions roles/os_hardening/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ We know that this is the case on Raspberry Pi.
- `os_auth_pam_passwdqc_options`
- Default: `min=disabled,disabled,16,12,8`
- Description: set to any option line (as a string) that you want to pass to passwdqc.
- `os_auth_pam_sssd_enable`
- Default: `false` (on RHEL8/CentOS8/Fedora `true`)
- Description: activate PAM auth support for sssd
- `os_security_users_allow`
- Default: `[]`
- Description: list of things, that a user is allowed to do. May contain `change_user`.
Expand Down Expand Up @@ -249,6 +252,13 @@ For more information, please see this [upstream documentation](https://www.kerne

## More information

We use specific PAM configuration for every linux distribution. This is a very diverse area, since every vendor seems to push their own system for managing PAM. We used following guides and sources for our configuration.

- on Debian/Ubuntu we use [pam-config-framework](https://wiki.ubuntu.com/PAMConfigFrameworkSpec)
- RHEL8 and compatible use information from [authselect](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/configuring_authentication_and_authorization_in_rhel/configuring-user-authentication-using-authselect_configuring-authentication-and-authorization-in-rhel), but our setup disables the configuration from authselect
- RHEL 6/7 and compatible use [authconfig](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/system-level_authentication_guide/authconfig-install), but our setup disables the configuration from authconfig
- for RHEL 6/7 we also use information from [Desktop Security](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/security_guide/chap-hardening_your_system_with_tools_and_services#sec-Desktop_Security)

This role is mostly based on guides by:

- [Arch Linux wiki, Sysctl hardening](https://wiki.archlinux.org/index.php/Sysctl)
Expand Down
118 changes: 8 additions & 110 deletions roles/os_hardening/tasks/pam.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
---
- name: update pam on Debian systems
command: 'pam-auth-update --package'
when: ansible_facts.distribution in ['Debian', 'Ubuntu']
changed_when: false
environment:
DEBIAN_FRONTEND: noninteractive
- name: Gather package facts
package_facts:
manager: auto
when:
- ansible_facts.os_family != 'Suse'
- ansible_facts.os_family != 'Archlinux'

# the reason for this is so a user cannot connect to a server,
# that isn't connected to an LDAP server anymore.
Expand All @@ -17,115 +17,13 @@
when:
- ansible_facts.os_family != 'Archlinux'

- name: remove pam_cracklib, because it does not play nice with passwdqc
apt:
name: '{{ os_packages_pam_cracklib }}'
state: 'absent'
when:
- ansible_facts.distribution in ['Debian', 'Ubuntu']
- os_auth_pam_passwdqc_enable

- name: install the package for strong password checking
apt:
name: '{{ os_packages_pam_passwdqc }}'
state: 'present'
update_cache: 'yes'
- import_tasks: pam_debian.yml
when:
- ansible_facts.distribution in ['Debian', 'Ubuntu']
- os_auth_pam_passwdqc_enable

- name: configure passwdqc
template:
src: 'usr/share/pam-configs/pam_passwdqd.j2'
dest: '{{ passwdqc_path }}'
mode: '0644'
owner: 'root'
group: 'root'
when:
- ansible_facts.distribution in ['Debian', 'Ubuntu']
- os_auth_pam_passwdqc_enable

- name: remove passwdqc
apt:
name: '{{ os_packages_pam_passwdqc }}'
state: 'absent'
when:
- ansible_facts.distribution in ['Debian', 'Ubuntu']
- not os_auth_pam_passwdqc_enable

- name: install tally2
apt:
name: 'libpam-modules'
state: 'present'
when:
- ansible_facts.distribution in ['Debian', 'Ubuntu']
- not os_auth_pam_passwdqc_enable
- os_auth_retries > 0

- name: configure tally2
template:
src: 'usr/share/pam-configs/pam_tally2.j2'
dest: '{{ tally2_path }}'
mode: '0644'
owner: 'root'
group: 'root'
when:
- ansible_facts.distribution in ['Debian', 'Ubuntu']
- not os_auth_pam_passwdqc_enable
- os_auth_retries > 0

- name: delete tally2 when retries is 0
file:
path: '{{ tally2_path }}'
state: 'absent'
when:
- ansible_facts.distribution in ['Debian', 'Ubuntu']
- not os_auth_pam_passwdqc_enable
- os_auth_retries == 0

- name: remove pam_cracklib, because it does not play nice with passwdqc
yum:
name: '{{ os_packages_pam_cracklib }}'
state: 'absent'
when:
- ansible_facts.os_family == 'RedHat'
- ansible_facts.distribution_major_version|int is version('7', '<')
- ansible_facts.distribution != 'Amazon'
- os_auth_pam_passwdqc_enable

- name: install the package for strong password checking
yum:
name: '{{ os_packages_pam_passwdqc }}'
state: 'present'
when:
- ansible_facts.os_family == 'RedHat'
- ansible_facts.distribution_major_version|int is version('7', '<')
- ansible_facts.distribution != 'Amazon'
- os_auth_pam_passwdqc_enable

- name: remove passwdqc
yum:
name: '{{ os_packages_pam_passwdqc }}'
state: 'absent'
- import_tasks: pam_rhel.yml
when:
- ansible_facts.os_family == 'RedHat'
- not os_auth_pam_passwdqc_enable

- name: configure passwdqc and tally via central system-auth confic
template:
src: 'etc/pam.d/rhel_system_auth.j2'
dest: '/etc/pam.d/system-auth-ac'
mode: '0640'
owner: 'root'
group: 'root'
when: ansible_facts.os_family == 'RedHat'

- name: Gather package facts
package_facts:
manager: auto
when:
- ansible_facts.os_family != 'Suse'
- ansible_facts.os_family != 'Archlinux'

- name: NSA 2.3.3.5 Upgrade Password Hashing Algorithm to SHA-512
template:
Expand Down
120 changes: 120 additions & 0 deletions roles/os_hardening/tasks/pam_debian.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
---
- name: install the package for strong password checking
apt:
name: 'libpam-passwdqc'
state: 'present'
update_cache: 'yes'
when:
- os_auth_pam_passwdqc_enable

- name: configure passwdqc
template:
src: 'usr/share/pam-configs/pam_passwdqc.j2'
dest: '{{ passwdqc_path }}'
mode: '0644'
owner: 'root'
group: 'root'
when:
- os_auth_pam_passwdqc_enable

- name: install tally2
apt:
name: 'libpam-modules'
state: 'present'
when:
- os_auth_retries > 0

- name: manage tally on Debian stable
block:
- name: configure tally2
template:
src: 'usr/share/pam-configs/pam_tally2.j2'
dest: '{{ tally2_path }}'
mode: '0644'
owner: 'root'
group: 'root'
when:
- os_auth_retries > 0

- name: delete tally2 when retries is 0
file:
path: '{{ tally2_path }}'
state: 'absent'
when:
- os_auth_retries == 0
when:
- "'libpam-modules' in ansible_facts.packages"
- "ansible_facts.packages['libpam-modules'][0].version is version('1.4.0', '<')"

- name: manage tally/faillock on Debian unstable
block:
- name: delete tally2
file:
path: '{{ tally2_path }}'
state: 'absent'

- name: create tally directory
file:
path: '/var/run/faillock'
state: 'directory'
mode: '0755'
owner: 'root'
group: 'root'

- name: configure faillock
template:
src: 'etc/security/faillock.conf.j2'
dest: '/etc/security/faillock.conf'
mode: '0644'
owner: 'root'
group: 'root'

- name: configure faillock pam
template:
src: 'usr/share/pam-configs/pam_faillock.j2'
dest: '/usr/share/pam-configs/faillock'
mode: '0644'
owner: 'root'
group: 'root'
when:
- os_auth_retries > 0

- name: configure faillock pam authfail
template:
src: 'usr/share/pam-configs/pam_faillock_authfail.j2'
dest: '/usr/share/pam-configs/faillock_authfail'
mode: '0644'
owner: 'root'
group: 'root'
when:
- os_auth_retries > 0

- name: delete faillock when retries is 0
file:
path: '/usr/share/pam-configs/faillock'
state: 'absent'
when:
- os_auth_retries == 0

- name: delete faillock authfail when retries is 0
file:
path: '/usr/share/pam-configs/faillock_authfail'
state: 'absent'
when:
- os_auth_retries == 0
when:
- "'libpam-modules' in ansible_facts.packages"
- "ansible_facts.packages['libpam-modules'][0].version is version('1.4.0', '>=')"

- name: update pam on Debian systems
command: 'pam-auth-update --package'
environment:
DEBIAN_FRONTEND: noninteractive
changed_when: false

- name: remove passwdqc
apt:
name: 'libpam-passwdqc'
state: 'absent'
when:
- not os_auth_pam_passwdqc_enable

0 comments on commit 74c7294

Please sign in to comment.