Software Engineering Wiki

Security and identity

FreeIPA / Red Hat IdM

Identity, Kerberos, host enrolment, DNS and certificates in one domain, with the commands for enrolment, RBAC and replication problems.

Cheatsheet #

TaskCommand
Get a ticketkinit admin
Show ticketsklist
Server healthipactl status
Add a useripa user-add jbloggs --first=Jo --last=Bloggs
Reset a passwordipa passwd jbloggs
Add to a groupipa group-add-member ops --users=jbloggs
Enrol a hostipa-client-install --mkhomedir --domain=example.internal
Host keytabipa-getkeytab -s ipa-01 -p host/web-01@EXAMPLE.INTERNAL -k /etc/krb5.keytab
Service principalipa service-add HTTP/web-01.example.internal
Request a certificateipa-getcert request -f /etc/pki/tls/certs/web.crt -k /etc/pki/tls/private/web.key -K HTTP/web-01.example.internal
Certificate statusgetcert list
DNS recordipa dnsrecord-add example.internal web --a-rec=10.0.0.5
Sudo ruleipa sudorule-add ops-all
HBAC testipa hbactest --user=jbloggs --host=web-01 --service=sshd
Replication statusipa-replica-manage list -v ipa-01.example.internal
Client cache resetsss_cache -E then systemctl restart sssd

What the pieces are #

IdM bundles 389 Directory Server (identity), MIT Kerberos (authentication), Dogtag (certificates), BIND with a directory backend (DNS), and SSSD on the clients. One enrolment gives a host a Kerberos identity, a certificate path, DNS records and a policy source.

ComponentResponsibilityFails as
389-dsUsers, groups, hosts, policiesLDAP timeouts, replication conflicts
KDCTickets and service principalsClock skew, missing SPN, wrong realm
DogtagIssuing and renewing certificatesExpired CA subsystem certificates
BIND-DYNDB-LDAPForward and reverse DNSMissing PTR, stale SRV records
SSSD (client)Caching, HBAC, sudo, home directoriesStale cache, offline mode

Kerberos depends on DNS and on time. Skew beyond five minutes and a missing SRV record are the two causes behind most enrolment and login failures.

Users and groups #

ipa user-add jbloggs --first=Jo --last=Bloggs --email=jo@example.com --shell=/bin/bash
ipa user-mod jbloggs --title='Platform Engineer' --sshpubkey="$(cat ~/.ssh/id_ed25519.pub)"
ipa user-find --all --raw jbloggs
ipa user-disable jbloggs          # keeps the object and its group memberships
ipa user-del jbloggs --preserve   # moves to the deleted-users container, recoverable
ipa passwd jbloggs                # sets a password the user must change at next login

ipa group-add ops --desc='Platform on-call'
ipa group-add-member ops --users=jbloggs --groups=contractors
ipa group-show ops --all

Disable rather than delete when someone leaves: it revokes access immediately while leaving audit trails and file ownership intact.

ipa pwpolicy-add ops --maxlife=90 --minlength=14 --history=10 --priority=1
ipa pwpolicy-show ops

Hosts and services #

ipa host-add web-01.example.internal --ip-address=10.0.0.5
ipa-client-install --domain=example.internal --realm=EXAMPLE.INTERNAL \
  --principal=admin --mkhomedir --enable-dns-updates

ipa service-add HTTP/web-01.example.internal
ipa service-allow-retrieve-keytab HTTP/web-01.example.internal --hosts=web-01.example.internal
ipa-getkeytab -s ipa-01.example.internal -p HTTP/web-01.example.internal -k /etc/httpd.keytab
klist -kt /etc/httpd.keytab

Retrieving a keytab invalidates the previous one for that principal: two hosts sharing a principal will knock each other offline. One principal per host per service.

ipa-client-install --uninstall         # clean removal before re-enrolment
ipa host-del web-01.example.internal   # then remove the stale host entry

DNS #

ipa dnszone-add example.internal --dynamic-update=TRUE
ipa dnsrecord-add example.internal web --a-rec=10.0.0.5
ipa dnsrecord-add 0.0.10.in-addr.arpa 5 --ptr-rec=web.example.internal.
ipa dnsrecord-find example.internal
ipa dnsconfig-mod --forwarder=10.0.0.53 --forward-policy=only
dig +short SRV _kerberos._udp.example.internal

The _kerberos and _ldap SRV records are how clients find the servers. If they are wrong, enrolment fails with an unhelpful message about the realm.

Certificates #

ipa-getcert request -f /etc/pki/tls/certs/web.crt -k /etc/pki/tls/private/web.key \
  -K HTTP/web-01.example.internal -D web-01.example.internal
getcert list                      # tracked certificates, expiry, post-save command
getcert resubmit -i <request-id>  # force renewal
ipa cert-find --subject=web-01
ipa cert-show 12 --out=cert.pem
ipa cert-revoke 12 --revocation-reason=4

certmonger renews tracked certificates automatically and runs the post-save command to reload the service. Certificates issued outside this tracking are the ones that expire at 2am.

ipa-cacert-manage renew            # CA certificate renewal, on the CA renewal master
ipa-certupdate                     # refresh the local trust store after a CA change

Access control #

HBAC decides who may access which service on which host; sudo rules decide what they may then run. Both are evaluated by SSSD on the client with cached data.

ipa hbacrule-add ops-ssh
ipa hbacrule-add-user ops-ssh --groups=ops
ipa hbacrule-add-host ops-ssh --hostgroups=web-servers
ipa hbacrule-add-service ops-ssh --hbacsvcs=sshd
ipa hbactest --user=jbloggs --host=web-01.example.internal --service=sshd

ipa sudorule-add ops-restart
ipa sudorule-add-user ops-restart --groups=ops
ipa sudorule-add-host ops-restart --hostgroups=web-servers
ipa sudorule-add-allow-command ops-restart --sudocmds='/bin/systemctl restart nginx'
ipa sudorule-mod ops-restart --sudoopt='!authenticate'

The default allow_all HBAC rule permits everything; disable it only after the replacement rules are tested with hbactest, or nobody logs in.

ipa hbacrule-disable allow_all

Delegate administration with roles rather than handing out admins:

ipa role-add 'Helpdesk'
ipa privilege-add 'Password Reset'
ipa permission-add 'Reset user password' --type=user --right=write --attrs=userPassword
ipa privilege-add-permission 'Password Reset' --permissions='Reset user password'
ipa role-add-privilege 'Helpdesk' --privileges='Password Reset'
ipa role-add-member 'Helpdesk' --groups=helpdesk

Replication #

ipa-replica-manage list -v ipa-01.example.internal
ipa-replica-manage force-sync --from ipa-01.example.internal
ipa-csreplica-manage list                      # certificate server replication
ipa-healthcheck --failures-only

Replication conflicts appear as entries with nsds5ReplConflict in the directory. They need manual resolution — pick the surviving entry and delete the conflict copy.

ldapsearch -Y GSSAPI -b "dc=example,dc=internal" "(nsds5ReplConflict=*)" \* nsds5ReplConflict

Keep at least two replicas with CA capability, and verify that the CA renewal master exists and is healthy before certificates approach expiry.

Client troubleshooting #

klist -e                                   # tickets and encryption types
kinit -V jbloggs                           # verbose ticket request
KRB5_TRACE=/dev/stderr kinit jbloggs       # every step of the exchange
id jbloggs                                 # does the client resolve the user at all
getent passwd jbloggs
sss_cache -E && systemctl restart sssd     # clear the cache after a policy change
journalctl -u sssd -f
realm list                                 # domain membership from the client's view
chronyc tracking                           # clock skew: the silent killer
SymptomCause
Clock skew too greatTime drift beyond five minutes — fix NTP first
Server not found in Kerberos databaseMissing SPN, or the client used a name with no matching principal
KDC has no support for encryption typeMismatched enctypes after an upgrade; regenerate the keytab
Login works, sudo does notSudo rule not matched, or SSSD cache stale
User exists in IdM, id failsSSSD domain not enabled, or the host is not enrolled
Everything fails after a CA renewalRun ipa-certupdate on clients to refresh trust
Intermittent failuresOne replica unhealthy; check ipa-healthcheck on each

Oneliners #

# Last successful Kerberos authentication per user
ipa user-find --all --raw | awk '/^ *uid:/ {u=$2} /^ *krbLastSuccessfulAuth:/ {print u, $2}'

# Every member of a group, flattened
ipa group-show ops --all --raw | grep -E '^ *member(user|group):'

# Hosts that exist but were never enrolled (no keytab)
ipa host-find | awk '/Host name:/ {h=$3} /Keytab: False/ {print h}'

# Tracked certificates with their expiry and status
getcert list | grep -E 'Request ID|status:|expires:|certificate:'

# All HBAC rules and who they apply to
ipa hbacrule-find --all --raw | grep -E '^ *(cn|memberuser|memberhost|memberservice):'

# Test access for a user before telling them it works
ipa hbactest --user=jbloggs --host=web-01.example.internal --service=sshd

# Replication agreements and their last update
ipa-replica-manage list -v ipa-01.example.internal | grep -E 'last update|status'

# Kerberos ticket lifetime for a principal
klist | awk '/krbtgt/ {print $1, $2}'

# Confirm DNS SRV records a client will use
dig +short SRV _ldap._tcp.example.internal _kerberos._tcp.example.internal

# Force a full client refresh after policy changes
sss_cache -E && systemctl restart sssd && id jbloggs

Last updated 15 September 2026 · Edit this page