SSSD should be configured to authenticate access to the system using smart cards.
To enable smart cards in SSSD, set pam_cert_auth to True under the
[pam] section in /etc/sssd/sssd.conf. For example:
[pam]
pam_cert_auth = True
Add or update "pam_sss.so" line in auth section of "/etc/pam.d/system-auth" file to include
"try_cert_auth" or "require_cert_auth" option, like in the following example:
Also add or update "pam_sss.so" line in auth section of "/etc/pam.d/smartcard-auth" file to
include the "allow_missing_name" option, like in the following example:
Using an authentication device, such as a CAC or token that is separate from
the information system, ensures that even if the information system is
compromised, that compromise will not affect credentials stored on the
authentication device.
Multi-Factor Authentication (MFA) solutions that require devices separate from
information systems gaining access include, for example, hardware tokens
providing time-based or challenge-response authenticators and smart cards such
as the U.S. Government Personal Identity Verification card and the DoD Common
Access Card.
- name: Gather the package facts
package_facts:
manager: auto
tags:
- DISA-STIG-RHEL-08-020250
- PCI-DSS-Req-8.3
- PCI-DSSv4-8.4
- configure_strategy
- low_complexity
- medium_disruption
- medium_severity
- no_reboot_needed
- sssd_enable_smartcards
- name: Test for domain group
command: grep '^\s*\[domain\/[^]]*]' /etc/sssd/sssd.conf
register: test_grep_domain
ignore_errors: true
changed_when: false
check_mode: false
when:
- '"sssd-common" in ansible_facts.packages'
- ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
tags:
- DISA-STIG-RHEL-08-020250
- PCI-DSS-Req-8.3
- PCI-DSSv4-8.4
- configure_strategy
- low_complexity
- medium_disruption
- medium_severity
- no_reboot_needed
- sssd_enable_smartcards
- name: Add default domain group (if no domain there)
ini_file:
path: /etc/sssd/sssd.conf
section: '{{ item.section }}'
option: '{{ item.option }}'
value: '{{ item.value }}'
create: true
mode: 384
with_items:
- section: sssd
option: domains
value: default
- section: domain/default
option: id_provider
value: files
when:
- '"sssd-common" in ansible_facts.packages'
- ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
- test_grep_domain.stdout is defined
- test_grep_domain.stdout | length < 1
tags:
- DISA-STIG-RHEL-08-020250
- PCI-DSS-Req-8.3
- PCI-DSSv4-8.4
- configure_strategy
- low_complexity
- medium_disruption
- medium_severity
- no_reboot_needed
- sssd_enable_smartcards
- name: Enable Smartcards in SSSD
ini_file:
dest: /etc/sssd/sssd.conf
section: pam
option: pam_cert_auth
value: 'True'
create: true
mode: 384
when:
- '"sssd-common" in ansible_facts.packages'
- ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
tags:
- DISA-STIG-RHEL-08-020250
- PCI-DSS-Req-8.3
- PCI-DSSv4-8.4
- configure_strategy
- low_complexity
- medium_disruption
- medium_severity
- no_reboot_needed
- sssd_enable_smartcards
- name: Enable Smartcards in SSSD - Check if system relies on authselect
ansible.builtin.stat:
path: /usr/bin/authselect
register: result_authselect_present
when:
- '"sssd-common" in ansible_facts.packages'
- ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
tags:
- DISA-STIG-RHEL-08-020250
- PCI-DSS-Req-8.3
- PCI-DSSv4-8.4
- configure_strategy
- low_complexity
- medium_disruption
- medium_severity
- no_reboot_needed
- sssd_enable_smartcards
- name: Enable Smartcards in SSSD - Remediate using authselect
block:
- name: Enable Smartcards in SSSD - Check integrity of authselect current profile
ansible.builtin.command:
cmd: authselect check
register: result_authselect_check_cmd
changed_when: false
failed_when: false
- name: Enable Smartcards in SSSD - Informative message based on the authselect
integrity check result
ansible.builtin.assert:
that:
- result_authselect_check_cmd.rc == 0
fail_msg:
- authselect integrity check failed. Remediation aborted!
- This remediation could not be applied because an authselect profile was not
selected or the selected profile is not intact.
- It is not recommended to manually edit the PAM files when authselect tool
is available.
- In cases where the default authselect profile does not cover a specific demand,
a custom authselect profile is recommended.
success_msg:
- authselect integrity check passed
- name: Enable Smartcards in SSSD - Get authselect current features
ansible.builtin.shell:
cmd: authselect current | tail -n+3 | awk '{ print $2 }'
register: result_authselect_features
changed_when: false
when:
- result_authselect_check_cmd is success
- name: Enable Smartcards in SSSD - Ensure "with-smartcard" feature is enabled using
authselect tool
ansible.builtin.command:
cmd: authselect enable-feature with-smartcard
register: result_authselect_enable_feature_cmd
when:
- result_authselect_check_cmd is success
- result_authselect_features.stdout is not search("with-smartcard")
- name: Enable Smartcards in SSSD - Ensure authselect changes are applied
ansible.builtin.command:
cmd: authselect apply-changes -b
when:
- result_authselect_enable_feature_cmd is not skipped
- result_authselect_enable_feature_cmd is success
when:
- '"sssd-common" in ansible_facts.packages'
- ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
- result_authselect_present.stat.exists
tags:
- DISA-STIG-RHEL-08-020250
- PCI-DSS-Req-8.3
- PCI-DSSv4-8.4
- configure_strategy
- low_complexity
- medium_disruption
- medium_severity
- no_reboot_needed
- sssd_enable_smartcards
- name: Enable Smartcards in SSSD - Remediate by directly editing PAM files
block:
- name: Enable Smartcards in SSSD - Check if expected PAM module line is present
in /etc/pam.d/smartcard-auth
ansible.builtin.lineinfile:
path: /etc/pam.d/smartcard-auth
regexp: ^\s*auth\s+{{ 'sufficient' | regex_escape() }}\s+pam_sss.so\s*.*
state: absent
check_mode: true
changed_when: false
register: result_pam_line_present
- name: Enable Smartcards in SSSD - Include or update the PAM module line in /etc/pam.d/smartcard-auth
block:
- name: Enable Smartcards in SSSD - Check if required PAM module line is present
in /etc/pam.d/smartcard-auth with different control
ansible.builtin.lineinfile:
path: /etc/pam.d/smartcard-auth
regexp: ^\s*auth\s+.*\s+pam_sss.so\s*
state: absent
check_mode: true
changed_when: false
register: result_pam_line_other_control_present
- name: Enable Smartcards in SSSD - Ensure the correct control for the required
PAM module line in /etc/pam.d/smartcard-auth
ansible.builtin.replace:
dest: /etc/pam.d/smartcard-auth
regexp: ^(\s*auth\s+).*(\bpam_sss.so.*)
replace: \1sufficient \2
register: result_pam_module_edit
when:
- result_pam_line_other_control_present.found == 1
- name: Enable Smartcards in SSSD - Ensure the required PAM module line is included
in /etc/pam.d/smartcard-auth
ansible.builtin.lineinfile:
dest: /etc/pam.d/smartcard-auth
line: auth sufficient pam_sss.so
register: result_pam_module_add
when:
- result_pam_line_other_control_present.found == 0 or result_pam_line_other_control_present.found
> 1
- name: Enable Smartcards in SSSD - Ensure authselect changes are applied
ansible.builtin.command:
cmd: authselect apply-changes -b
when:
- result_authselect_present is defined
- result_authselect_present.stat.exists
- |-
(result_pam_module_add is defined and result_pam_module_add.changed)
or (result_pam_module_edit is defined and result_pam_module_edit.changed)
when:
- result_pam_line_present.found is defined
- result_pam_line_present.found == 0
- name: Enable Smartcards in SSSD - Check if the required PAM module option is present
in /etc/pam.d/smartcard-auth
ansible.builtin.lineinfile:
path: /etc/pam.d/smartcard-auth
regexp: ^\s*auth\s+{{ 'sufficient' | regex_escape() }}\s+pam_sss.so\s*.*\sallow_missing_name\b
state: absent
check_mode: true
changed_when: false
register: result_pam_module_allow_missing_name_option_present
- name: Enable Smartcards in SSSD - Ensure the "allow_missing_name" PAM option for
"pam_sss.so" is included in /etc/pam.d/smartcard-auth
ansible.builtin.lineinfile:
path: /etc/pam.d/smartcard-auth
backrefs: true
regexp: ^(\s*auth\s+{{ 'sufficient' | regex_escape() }}\s+pam_sss.so.*)
line: \1 allow_missing_name
state: present
register: result_pam_allow_missing_name_add
when:
- result_pam_module_allow_missing_name_option_present.found == 0
- name: Enable Smartcards in SSSD - Check if expected PAM module line is present
in /etc/pam.d/system-auth
ansible.builtin.lineinfile:
path: /etc/pam.d/system-auth
regexp: ^\s*auth\s+{{ '\[success=done authinfo_unavail=ignore ignore=ignore
default=die\]' | regex_escape() }}\s+pam_sss.so\s*.*
state: absent
check_mode: true
changed_when: false
register: result_pam_line_present
- name: Enable Smartcards in SSSD - Include or update the PAM module line in /etc/pam.d/system-auth
block:
- name: Enable Smartcards in SSSD - Check if required PAM module line is present
in /etc/pam.d/system-auth with different control
ansible.builtin.lineinfile:
path: /etc/pam.d/system-auth
regexp: ^\s*auth\s+.*\s+pam_sss.so\s*
state: absent
check_mode: true
changed_when: false
register: result_pam_line_other_control_present
- name: Enable Smartcards in SSSD - Ensure the correct control for the required
PAM module line in /etc/pam.d/system-auth
ansible.builtin.replace:
dest: /etc/pam.d/system-auth
regexp: ^(\s*auth\s+).*(\bpam_sss.so.*)
replace: \1\[success=done authinfo_unavail=ignore ignore=ignore default=die\]
\2
register: result_pam_module_edit
when:
- result_pam_line_other_control_present.found == 1
- name: Enable Smartcards in SSSD - Ensure the required PAM module line is included
in /etc/pam.d/system-auth
ansible.builtin.lineinfile:
dest: /etc/pam.d/system-auth
line: auth \[success=done authinfo_unavail=ignore ignore=ignore default=die\] pam_sss.so
register: result_pam_module_add
when:
- result_pam_line_other_control_present.found == 0 or result_pam_line_other_control_present.found
> 1
- name: Enable Smartcards in SSSD - Ensure authselect changes are applied
ansible.builtin.command:
cmd: authselect apply-changes -b
when:
- result_authselect_present is defined
- result_authselect_present.stat.exists
- |-
(result_pam_module_add is defined and result_pam_module_add.changed)
or (result_pam_module_edit is defined and result_pam_module_edit.changed)
when:
- result_pam_line_present.found is defined
- result_pam_line_present.found == 0
- name: Enable Smartcards in SSSD - Check if the required PAM module option is present
in /etc/pam.d/system-auth
ansible.builtin.lineinfile:
path: /etc/pam.d/system-auth
regexp: ^\s*auth\s+{{ '\[success=done authinfo_unavail=ignore ignore=ignore
default=die\]' | regex_escape() }}\s+pam_sss.so\s*.*\stry_cert_auth\b
state: absent
check_mode: true
changed_when: false
register: result_pam_module_try_cert_auth_option_present
- name: Enable Smartcards in SSSD - Ensure the "try_cert_auth" PAM option for "pam_sss.so"
is included in /etc/pam.d/system-auth
ansible.builtin.lineinfile:
path: /etc/pam.d/system-auth
backrefs: true
regexp: ^(\s*auth\s+{{ '\[success=done authinfo_unavail=ignore ignore=ignore
default=die\]' | regex_escape() }}\s+pam_sss.so.*)
line: \1 try_cert_auth
state: present
register: result_pam_try_cert_auth_add
when:
- result_pam_module_try_cert_auth_option_present.found == 0
when:
- '"sssd-common" in ansible_facts.packages'
- ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
- not result_authselect_present.stat.exists
tags:
- DISA-STIG-RHEL-08-020250
- PCI-DSS-Req-8.3
- PCI-DSSv4-8.4
- configure_strategy
- low_complexity
- medium_disruption
- medium_severity
- no_reboot_needed
- sssd_enable_smartcards
Remediation - Shell Script
# Remediation is applicable only in certain platforms
if rpm --quiet -q sssd-common && { [ ! -f /.dockerenv ] && [ ! -f /run/.containerenv ]; }; then
# sssd configuration files must be created with 600 permissions if they don't exist
# otherwise the sssd module fails to start
OLD_UMASK=$(umask)
umask u=rw,go=
found=false
# set value in all files if they contain section or key
for f in $(echo -n "/etc/sssd/sssd.conf"); do
if [ ! -e "$f" ]; then
continue
fi
# find key in section and change value
if grep -qzosP "[[:space:]]*\[pam\]([^\n\[]*\n+)+?[[:space:]]*pam_cert_auth" "$f"; then
sed -i "s/pam_cert_auth[^(\n)]*/pam_cert_auth = True/" "$f"
found=true
# find section and add key = value to it
elif grep -qs "[[:space:]]*\[pam\]" "$f"; then
sed -i "/[[:space:]]*\[pam\]/a pam_cert_auth = True" "$f"
found=true
fi
done
# if section not in any file, append section with key = value to FIRST file in files parameter
if ! $found ; then
file=$(echo "/etc/sssd/sssd.conf" | cut -f1 -d ' ')
mkdir -p "$(dirname "$file")"
echo -e "[pam]\npam_cert_auth = True" >> "$file"
fi
umask $OLD_UMASK
if [ -f /usr/bin/authselect ]; then
if ! authselect check; then
echo "
authselect integrity check failed. Remediation aborted!
This remediation could not be applied because an authselect profile was not selected or the selected profile is not intact.
It is not recommended to manually edit the PAM files when authselect tool is available.
In cases where the default authselect profile does not cover a specific demand, a custom authselect profile is recommended."
exit 1
fi
authselect enable-feature with-smartcard
authselect apply-changes -b
else
if ! grep -qP '^\s*auth\s+'"sufficient"'\s+pam_sss.so\s*.*' "/etc/pam.d/smartcard-auth"; then
# Line matching group + control + module was not found. Check group + module.
if [ "$(grep -cP '^\s*auth\s+.*\s+pam_sss.so\s*' "/etc/pam.d/smartcard-auth")" -eq 1 ]; then
# The control is updated only if one single line matches.
sed -i -E --follow-symlinks 's/^(\s*auth\s+).*(\bpam_sss.so.*)/\1'"sufficient"' \2/' "/etc/pam.d/smartcard-auth"
else
echo 'auth '"sufficient"' pam_sss.so' >> "/etc/pam.d/smartcard-auth"
fi
fi
# Check the option
if ! grep -qP '^\s*auth\s+'"sufficient"'\s+pam_sss.so\s*.*\sallow_missing_name\b' "/etc/pam.d/smartcard-auth"; then
sed -i -E --follow-symlinks '/\s*auth\s+'"sufficient"'\s+pam_sss.so.*/ s/$/ allow_missing_name/' "/etc/pam.d/smartcard-auth"
fi
if ! grep -qP '^\s*auth\s+'"\[success=done authinfo_unavail=ignore ignore=ignore default=die\]"'\s+pam_sss.so\s*.*' "/etc/pam.d/system-auth"; then
# Line matching group + control + module was not found. Check group + module.
if [ "$(grep -cP '^\s*auth\s+.*\s+pam_sss.so\s*' "/etc/pam.d/system-auth")" -eq 1 ]; then
# The control is updated only if one single line matches.
sed -i -E --follow-symlinks 's/^(\s*auth\s+).*(\bpam_sss.so.*)/\1'"\[success=done authinfo_unavail=ignore ignore=ignore default=die\]"' \2/' "/etc/pam.d/system-auth"
else
echo 'auth '"\[success=done authinfo_unavail=ignore ignore=ignore default=die\]"' pam_sss.so' >> "/etc/pam.d/system-auth"
fi
fi
# Check the option
if ! grep -qP '^\s*auth\s+'"\[success=done authinfo_unavail=ignore ignore=ignore default=die\]"'\s+pam_sss.so\s*.*\stry_cert_auth\b' "/etc/pam.d/system-auth"; then
sed -i -E --follow-symlinks '/\s*auth\s+'"\[success=done authinfo_unavail=ignore ignore=ignore default=die\]"'\s+pam_sss.so.*/ s/$/ try_cert_auth/' "/etc/pam.d/system-auth"
fi
fi
else
>&2 echo 'Remediation is not applicable, nothing was done'
fi