pam_faillock, A Lockout Proven To Lock And To Let Go

An account lockout on EL 10, put into the authentication stack through authselect because /etc/pam.d/system-auth is a generated symlink. The live test fails one account past the limit and watches the RIGHT password be refused, fails a second one short of the limit and watches it keep working, then resets the first and watches it come back. Original role, live-tested on Rocky Linux 10.

ansibleSecurity & Secrets

Verification

Live-tested

Really deployed to a container sandbox, proven idempotent (a second run changes nothing), verified against the role’s assertions, then torn down.

Conformance

  • Static validation (yamllint · ansible-lint)

Provenance

  • SHA-256 checksum
  • Signature (pending)

Functional

  • Live-tested - applied, verified, destroyed

Last verified 2026-09-26 · podman 4.9.3 · ansible 2.21.4 · how we verify

Cite it in your README

badge · attribution

Paste this beside the module in the repository that uses it. The badge is rendered from this artifact's verification record, so it reads live-tested because the record says so, and the link lands on this page.

README.md, GitLab, Gitea
[![IaC Bazaar: live-tested](https://www.iac-bazaar.com/api/artifacts/ansible-pam-faillock/badge)](https://www.iac-bazaar.com/catalog/ansible-pam-faillock?utm_source=syndication&utm_medium=readme&utm_campaign=artifact)

Ansible role 1.0.0, live-tested on IaC Bazaar: [pam_faillock, A Lockout Proven To Lock And To Let Go](https://www.iac-bazaar.com/catalog/ansible-pam-faillock?utm_source=syndication&utm_medium=readme&utm_campaign=artifact)

```yaml
# pam_faillock, A Lockout Proven To Lock And To Let Go: https://www.iac-bazaar.com/catalog/ansible-pam-faillock (download from your IaC Bazaar account)
```

Preview:IaC Bazaar: live-tested

Documentation

pam-faillock

A lockout that is proven to lock, and proven to let go. The role writes the faillock policy and puts pam_faillock into the authentication stack through authselect, which is the only supported way in on EL 10. The live test fails one account past the limit and watches the RIGHT password get refused, fails a second account one short of the limit and watches it keep working, then resets the first and watches it come back.

No download, and no version to pin. PAM and authselect are part of EL 10, so the role installs them by name and works through the tooling the distribution provides. What the role owns is the policy: how many failures, in what window, for how long, and whether root is included.

/etc/pam.d/system-auth is a symlink into /etc/authselect. Editing it is editing a generated file, and the next authselect apply-changes discards the edit without a word. The role uses authselect enable-feature with-faillock, keeps whatever profile the host already has, and runs authselect check on every pass rather than only after a change - because a stack that does not apply cleanly is a host that cannot authenticate at all.

Nothing validates faillock.conf, and a typo fails OPEN. With deny = notanumber, PAM printed "Bad number supplied for deny argument", let the authentication through, and applied no lockout at all. There is no checker to run and no error to notice: the policy is simply absent. That is the reason this role's live test exists in the form it does, and why it counts to the limit rather than asserting that the file contains the right words.

even_deny_root can lock an operator out of a host. It is on by default here because a lockout that exempts the account everyone attacks is not a lockout, but root_unlock_time is then the only way back in that does not need a console. Decide that before rolling it out, not after.

License

Commercial - IaC Bazaar EULA. (c) IaC Bazaar.

Usage code & full reference need an account

The complete copy-paste usage, the full input/output reference, and operational notes are free with an account - shown here and bundled in the download. Sign in and this section fills in.

  • Variables
  • Test

Related modules

Live-tested

ansible-lynis

Lynis from EPEL on a systemd timer, with the units the package keeps only in its docs, your skipped tests in custom.prf, and a minimum hardening index below which the audit unit fails, so a falling score shows as a failed unit. The live test runs the audit, reads the index and the tests that ran, and finds the timer enabled. Original role, live-tested on Rocky Linux 10.

View module
Live-tested

ansible-suricata

Suricata from EPEL watching the default-route interface as the suricata user, ET Open fetched at install and refreshed daily, plus a canary rule that proves the sensor is alive. A root-run check left root-owned logs and a daemon recording nothing; the role prevents it. The live test raises the canary alert while a second lookup is logged, not alerted. Original role, live-tested on Rocky Linux 10.

View module
Live-tested

ansible-aide

AIDE from AppStream on EL 10: a watched tree, a baseline database built once, and the oneshot unit and timer the package does not ship. The live test passes on an unchanged host, FAILS when a file appears inside a watched path and names it, ignores one inside an excluded path, and passes again once the change is gone. Original role, live-tested on Rocky Linux 10.

View module
Live-tested

ansible-389-ds

389 Directory Server from AppStream. A fresh instance listens on every interface and lets anonymous clients read the tree; this role binds both listeners to loopback and limits anonymous clients to the rootDSE. The live test adds a user who binds, sees a wrong password and an anonymous search refused, and reads the LDAPS certificate. Original role, live-tested on Rocky Linux 10.

View module
Live-tested

ansible-krb5-kdc

An MIT Kerberos KDC: the realm created once with a stash, kadmind behind an ACL, a default policy that locks an account after five wrong passwords, every listener on loopback. The KDC starts on a broken config without a word, so the live test proves each setting by behaviour: the ticket lifetime, the refusals, the lockout. Original role, live-tested on Rocky Linux 10.

View module
Live-tested

ansible-authelia

Authelia from the upstream release (sha256-verified) as a hardened system service on loopback with file users and sqlite; its secrets are generated once on the host and reach the service as AUTHELIA_*_FILE variables. The live test hashes a password with Authelia's hasher, logs in, sees a wrong password refused and an anonymous visitor sent to the portal. Original role, live-tested on Rocky 10.

View module