Overview
Part 4 of the Identity series tests FreeIPA password policies in practice: global policy, group policy, minimum length, character classes, history, minimum lifetime, password expiration, admin reset, failed login counters, account lockout, unlock and account expiration.
All CLI commands and outputs are rendered as selectable text and code blocks. Screenshots are used only for the FreeIPA Web UI.
FreeIPA Web UI after authenticated login. Screenshot from the isolated FreeIPA C2 lab with trusted lab CA.
Lab Setup
Server: ipa01.example.testClient: client01.example.testDomain: example.testRealm: EXAMPLE.TESTFreeIPA: 4.13.3SSSD: 2.13.1SELinux: Enforcing
Which Password Policy FreeIPA Uses
FreeIPA has a global password policy and can apply additional group-specific policies. The lab first captured the real defaults.
ipa pwpolicy-showipa pwpolicy-find
Group: global_policyMax lifetime (days): 90Min lifetime (hours): 1History size: 0Character classes: 0Min length: 8Max failures: 6Failure reset interval: 60Lockout duration: 600Grace login limit: -1
FreeIPA password policy overview with global_policy and policy-users. Screenshot from the isolated FreeIPA C2 lab with trusted lab CA.
Global FreeIPA password policy. Screenshot from the isolated FreeIPA C2 lab with trusted lab CA.
Group-specific Password Policy
The lab created the synthetic policy-users group and attached a group-specific policy. Priority controls which policy applies when a user belongs to multiple policy groups.
ipa group-add policy-users --desc='C2 password policy users'ipa pwpolicy-add policy-users \--priority=10 \--minlength=12 \--minclasses=2 \--history=2 \--minlife=0 \--maxlife=1 \--maxfail=3 \--failinterval=30 \--lockouttime=60
Group: policy-usersMax lifetime (days): 1Min lifetime (hours): 0History size: 2Character classes: 2Min length: 12Priority: 10Max failures: 3Failure reset interval: 30Lockout duration: 60Grace login limit: -1
Group-specific FreeIPA password policy policy-users. Screenshot from the isolated FreeIPA C2 lab with trusted lab CA.
FreeIPA group policy-users with test users. Screenshot from the isolated FreeIPA C2 lab with trusted lab CA.
Minimum Length and Character Classes
A deliberately invalid password was rejected. This output comes from the real kinit password-change flow on the client.
Password expired. You must change it now.Password change rejected: Password does not contain enough character classesPassword not changed.
Password History
After two valid changes, the lab attempted to reuse an earlier password. FreeIPA rejected the reuse.
Password change rejected: New password was used previously. Please choose a different password.
Minimum Lifetime
With minlife set to 1, an immediate user-initiated password change was blocked. The lab then restored minlife to 0 for the remaining tests.
Password change rejected: Current password's minimum life has not expiredPassword not changed.
Password Expiration
The lab forced policy-expired into the past. The next kinit required a password change and then issued a Kerberos ticket.
ipa user-mod policy-expired --password-expiration=20000101000000Z
Password expired. You must change it now.Ticket cache: KCM:1001Default principal: policy-expired@EXAMPLE.TEST
FreeIPA user policy-expired for password expiration. Screenshot from the isolated FreeIPA C2 lab with trusted lab CA.
Administrator Reset
An admin reset with ipa passwd was tested separately. The next user login had to change the temporary password.
ipa passwd policy-reset
FreeIPA user policy-reset after admin reset. Screenshot from the isolated FreeIPA C2 lab with trusted lab CA.
Failed Logins and Account Lockout
The lockout test separates two phases: failed attempts below the threshold, then three consecutive failures until lockout.
attempt_1_rc=1attempt_2_rc=1valid_before_threshold_rc=0attempt_3_rc=1attempt_4_rc=1attempt_5_rc=1valid_after_threshold_rc=1
Account disabled: FalseServer: ipa01.example.testFailed logins: 3Last failed authentication: 20260919225833Z
FreeIPA user policy-lock after lockout test and recovery. Screenshot from the isolated FreeIPA C2 lab with trusted lab CA.
Unlocking the Account
The locked user was recovered with ipa user-unlock. After unlock, kinit and SSH worked again.
ipa user-unlock policy-lockkinit policy-lockssh policy-lock@client01.example.test
Account Expiration
Account expiration was tested independently from password expiration. Identity lookup still worked, but kinit and SSH were denied.
ipa user-mod policy-account-expired --principal-expiration=20000101000000Z
policy-account-expired:*:40800010:40800010:Policy AccountExpired:/home/policy-account-expired:/bin/bashuid=40800010(policy-account-expired) gid=40800010(policy-account-expired) groups=40800010(policy-account-expired),40800003(policy-users)kinit: Client's entry in database has expired while getting initial credentialsssh_rc=5
FreeIPA user policy-account-expired with account expiration. Screenshot from the isolated FreeIPA C2 lab with trusted lab CA.
Disabled vs Locked vs Password Expired vs Account Expired
| State | Identity lookup | kinit | SSH | Recovery |
|---|---|---|---|---|
| Disabled user | Yes | Credentials revoked | Failure | ipa user-enable |
| Locked user | Yes | Failure after threshold | Failure in final run | ipa user-unlock or lockout expiry |
| Password expired | Yes | Password change required | Works after change | User change or admin reset |
| Account expired | Yes | Entry expired | Failure | Adjust principal expiration |
Disabled user
- Identity lookup
- Yes
- kinit
- Credentials revoked
- SSH
- Failure
- Recovery
- ipa user-enable
Locked user
- Identity lookup
- Yes
- kinit
- Failure after threshold
- SSH
- Failure in final run
- Recovery
- ipa user-unlock or lockout expiry
Password expired
- Identity lookup
- Yes
- kinit
- Password change required
- SSH
- Works after change
- Recovery
- User change or admin reset
Account expired
- Identity lookup
- Yes
- kinit
- Entry expired
- SSH
- Failure
- Recovery
- Adjust principal expiration
Disabled FreeIPA user policy-disabled. Screenshot from the isolated FreeIPA C2 lab with trusted lab CA.
What the Linux Client Sees
The client was tested with SSSD, Kerberos and SSH. The important distinction: identity resolution through getent or id is not the same as permitted authentication.
getent passwd policy-validid policy-validkinit policy-validklistssh policy-valid@client01.example.testsssctl user-checks policy-validjournalctl -u sssd --no-pager
FreeIPA user policy-valid with applied password policy. Screenshot from the isolated FreeIPA C2 lab with trusted lab CA.
Result Check
| Area | Check | Expected result | Status |
|---|---|---|---|
| Global policy | pwpolicy-show/find | Defaults visible | PASS |
| Group policy | policy-users | Group policy applies | PASS |
| Minimum length | invalid change | Policy violation is rejected | PASS |
| History | reuse password | Reuse is rejected | PASS |
| Expiration | expire password | kinit forces change | PASS |
| Admin reset | ipa passwd | User must change password | PASS |
| Lockout | failed attempts | User is locked | PASS |
| Recovery | ipa user-unlock | Login works again | PASS |
| Account expiration | expired principal | kinit/SSH fail | PASS |
| Web UI | trusted-CA login | screenshots authenticated | PASS |
| CLI | code/text instead of terminal images | copyable evidence | PASS |
Global policy
- Check
- pwpolicy-show/find
- Expected result
- Defaults visible
- Status
- PASS
Group policy
- Check
- policy-users
- Expected result
- Group policy applies
- Status
- PASS
Minimum length
- Check
- invalid change
- Expected result
- Policy violation is rejected
- Status
- PASS
History
- Check
- reuse password
- Expected result
- Reuse is rejected
- Status
- PASS
Expiration
- Check
- expire password
- Expected result
- kinit forces change
- Status
- PASS
Admin reset
- Check
- ipa passwd
- Expected result
- User must change password
- Status
- PASS
Lockout
- Check
- failed attempts
- Expected result
- User is locked
- Status
- PASS
Recovery
- Check
- ipa user-unlock
- Expected result
- Login works again
- Status
- PASS
Account expiration
- Check
- expired principal
- Expected result
- kinit/SSH fail
- Status
- PASS
Web UI
- Check
- trusted-CA login
- Expected result
- screenshots authenticated
- Status
- PASS
CLI
- Check
- code/text instead of terminal images
- Expected result
- copyable evidence
- Status
- PASS
Limits of This Lab
The Web UI screenshots used a documented lab-port workaround because the host could not bind privileged TCP/443.
The policy values are intentionally short and synthetic so expiration and lockout can be reproduced.
Production policies need coordinated helpdesk, recovery, MFA and emergency processes.
Identity Management with FreeIPA and Keycloak
Previous part: managing FreeIPA users and groups. We only link a next part once it is published.






