From 789789f2021981060b68aeacafae6fc32edde11c Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Sun, 31 May 2026 00:05:00 +0200 Subject: [PATCH] [PR #12137/5d62edc6 backport][stable-12] pamd: handle non-PAM lines in authselect profile files (#12144) pamd: handle non-PAM lines in authselect profile files (#12137) * fix(pamd): handle non-PAM lines in authselect profile files * test(pamd): add test for authselect directive lines * feat(changelog): add fragment for PR 12137 --------- (cherry picked from commit 5d62edc6731e8f76254d84d5a71b7d3317cb3c70) Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 --- changelogs/fragments/12137-pamd-authselect.yml | 4 ++++ plugins/modules/pamd.py | 4 +++- tests/unit/plugins/modules/test_pamd.py | 12 ++++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/12137-pamd-authselect.yml diff --git a/changelogs/fragments/12137-pamd-authselect.yml b/changelogs/fragments/12137-pamd-authselect.yml new file mode 100644 index 0000000000..44d345e84b --- /dev/null +++ b/changelogs/fragments/12137-pamd-authselect.yml @@ -0,0 +1,4 @@ +bugfixes: + - "pamd - handle non-PAM lines such as authselect template directives without crashing + (https://github.com/ansible-collections/community.general/issues/5850, + https://github.com/ansible-collections/community.general/pull/12137)." diff --git a/plugins/modules/pamd.py b/plugins/modules/pamd.py index b7fae88648..2a84c56a67 100644 --- a/plugins/modules/pamd.py +++ b/plugins/modules/pamd.py @@ -348,6 +348,8 @@ class PamdRule(PamdLine): @classmethod def rule_from_string(cls, line): rule_match = RULE_REGEX.search(line) + if rule_match is None: + return None rule_args = parse_module_arguments(rule_match.group("args")) return cls(rule_match.group("rule_type"), rule_match.group("control"), rule_match.group("path"), rule_args) @@ -432,7 +434,7 @@ class PamdService: elif line.strip() == "": pamd_line = PamdEmptyLine(line) else: - pamd_line = PamdRule.rule_from_string(line) + pamd_line = PamdRule.rule_from_string(line) or PamdLine(line) self.append(pamd_line) diff --git a/tests/unit/plugins/modules/test_pamd.py b/tests/unit/plugins/modules/test_pamd.py index cafa4e2aca..d94dbf0bfc 100644 --- a/tests/unit/plugins/modules/test_pamd.py +++ b/tests/unit/plugins/modules/test_pamd.py @@ -142,6 +142,13 @@ session required pam_unix.so""" auth sufficient pam_unix.so nullok try_first_pass auth requisite pam_succeed_if.so uid auth required pam_deny.so +""" + + self.authselect_system_auth_string = """{imply "with-smartcard" if "with-smartcard-required"} +auth required pam_env.so +auth required pam_faildelay.so delay=2000000 +password sufficient pam_unix.so yescrypt shadow use_authtok +password required pam_deny.so """ self.pamd = PamdService(self.system_auth_string) @@ -158,6 +165,11 @@ auth required pam_deny.so def test_doesnt_have_rule(self): self.assertFalse(self.pamd.has_rule("account", "requisite", "pam_permit.so")) + def test_authselect_directive_line_does_not_crash(self): + pamd = PamdService(self.authselect_system_auth_string) + self.assertTrue(pamd.has_rule("password", "sufficient", "pam_unix.so")) + self.assertIn('{imply "with-smartcard" if "with-smartcard-required"}', str(pamd)) + # Test Update def test_update_rule_type(self): self.assertTrue(self.pamd.update_rule("session", "optional", "pam_keyinit.so", new_type="account"))