Interoperability of RHEL 7/8/9 IdM server and RHEL 7/8/9 IdM client

As their IdM deployment expands over time with the addition of new IdM clients or new IdM servers and replicas, customers often have a mixed topology containing various RHEL versions.

This blog post describes the version requirements and limitations that can be seen in these mixed topologies.

  1. General version requirements
  2. FIPS mode
    1. Client installation in FIPS mode
      1. Installation of a RHEL 7.9 (or lower) client with RHEL 9.2 (or above) server in FIPS mode
      2. Installation of a RHEL 9+ client with a RHEL 8.6 (or lower) server in FIPS mode
    2. Replica installation/migration in FIPS mode
      1. Migration from RHEL 8.7+ to RHEL9
    3. Vault operations on a RHEL 9 client in FIPS mode
    4. Trust in FIPS mode
      1. Establish 2-way trust on a RHEL server in FIPS mode
      2. Establish trust with a shared secret in FIPS mode
      3. Use trust functionality from a RHEL 9 IdM client

General version requirements

In the general case, it is possible to install a client with a different version from the server (for instance a RHEL 7.9 IdM client with a RHEL 9.2 IdM server, or the opposite). There are some restrictions, though, when replicas are taken into consideration:

  • it is only possible to install a replica with the same or later version as the server (for instance a RHEL 8.8 replica can’t be created from a RHEL 9.2 server). The limitation is described in Replica version requirements
  • it is not supported to skip a major version for replica installation (for instance a RHEL 9.2 replica can’t be installed directly from a RHEL 7.9 server). The limitation is described in Migrating your IdM environment from RHEL 8 servers to RHEL 9 servers.

FIPS mode

The Federal Information Processing Standard (FIPS) publication is a security standard published by NIST (National Institute of Standards and Technology). The most recent versions for the Security Requirements for Cryptographic Modules are FIPS 140-2 and FIPS 140-3, and RHEL versions, depending on their age, have been certified for one or the other. The consequence is that they allow different sets of algorithms and interoperability issues may arise when no common algorithm is found.

The following sections list the known issues and their workaround (when available).

Client installation in FIPS mode

If the IdM servers are installed in FIPS mode, Red Hat recommends that the IdM clients are also FIPS-enabled (as they may be later promoted to replicas).

Installation of a RHEL 7.9 (or lower) client with RHEL 9.2 (or above) server in FIPS mode

RHEL 9.2 introduced a new requirement for EMS (Extended Master Secret) extension in TLS 1.2: Bug 2188046Support requiring EMS in TLS 1.2, default to it when in FIPS mode.

This means that the EMS extension is now mandatory for TLS 1.2 connections on FIPS-enabled RHEL 9 systems, in accordance with FIPS-140-3 requirements. TLS 1.3 is not affected.

RHEL 7.9 clients and lower do not support TLS 1.3, and their version of openssl does not support the EMS extension in TLS 1.2. The consequence is that the installation of a RHEL 7.9 (or lower) client with a RHEL 9.2 (or higher) server fails with a SSL hanshake failure:

# ipa-client-install --domain ipa.test --realm IPA.TEST --server server.ipa.test --principal admin --password Secret123 -U
WARNING: ntpd time&date synchronization service will not be configured as
conflicting service (chronyd) is enabled
Use --force-ntpd option to disable it and force configuration of ntpd

Client hostname: client.ipa.test
Realm: IPA.TEST
DNS Domain: ipa.test
IPA Server: server.ipa.test
BaseDN: dc=ipa,dc=test

Skipping synchronizing time with NTP server.
Successfully retrieved CA cert
    Subject:     CN=Certificate Authority,O=IPA.TEST
    Issuer:      CN=Certificate Authority,O=IPA.TEST
    Valid From:  2023-07-06 12:52:19
    Valid Until: 2043-07-06 12:52:19

Enrolled in IPA realm IPA.TEST
Created /etc/ipa/default.conf
New SSSD config will be created
Configured sudoers in /etc/nsswitch.conf
Configured /etc/sssd/sssd.conf
trying https://server.ipa.test/ipa/json
[try 1]: Forwarding 'schema' to json server 'https://server.ipa.test/ipa/json'
cannot connect to 'https://server.ipa.test/ipa/json': [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:618)
The ipa-client-install command failed. See /var/log/ipaclient-install.log for more information

Important: RHEL 8.x clients are not affected because they support TLS 1.3 and use this version of TLS during IdM client installation.

Workaround

If the customer has no other solution than using a higher RHEL client version, it is possible to relax the requirement for EMS by applying a specific crypto sub-policy on the RHEL 9.2 (or above) server: NO-ENFORCE-EMS.

Note that this crypto policy breaks the FIPS 140-3 requirement.

[rhel9server]# update-crypto-policies --set FIPS:NO-ENFORCE-EMS

It is recommended to reboot the system after applying the crypto policy. The installation of the RHEL 7.9 (or lower) client after the crypto policy update completes successfully.

Relevant bug

Bug 2220915 – RHEL 7.9 client installation fails in FIPS mode with 9.2 server

Installation of a RHEL 9+ client with a RHEL 8.6 (or lower) server in FIPS mode

When the IPA server has been setup initially on a RHEL 8.6 or lower version, the IdM master key was created with the AES HMAC-SHA1 encryption type. This encryption type is blocked on RHEL9 in FIPS mode and IdM client installer fails to find a common encryption type. The consequence is that IdM client fails to install:

# ipa-client-install --principal admin --password Secret123 -U
This program will set up IPA client.
Version 4.10.2

Discovery was successful!
Client hostname: client9.testrelm.test
Realm: TESTRELM.TEST
DNS Domain: testrelm.test
IPA Server: master.testrelm.test
BaseDN: dc=testrelm,dc=test

Synchronizing time
No SRV records of NTP servers found and no NTP server or pool address was provided.
Using default chrony configuration.
Attempting to sync time with chronyc.
Process chronyc waitsync failed to sync time!
Unable to sync time with chrony server, assuming the time is in sync. Please check that 123 UDP port is opened, and any time server is on network.
Please make sure the following ports are opened in the firewall settings:
     TCP: 80, 88, 389
     UDP: 88 (at least one of TCP/UDP ports 88 has to be open)
Also note that following ports are necessary for ipa-client working properly after enrollment:
     TCP: 464
     UDP: 464, 123 (if NTP enabled)
Installation failed. Rolling back changes.
Disabling client Kerberos and LDAP configurations
nscd daemon is not installed, skip configuration
nslcd daemon is not installed, skip configuration
Client uninstall complete.
Kerberos authentication failed: kinit: KDC has no support for encryption type while getting initial credentials

The ipa-client-install command failed. See /var/log/ipaclient-install.log for more information
# 

In order to check the encryption type of IdM master key on the RHEL 8 server:

# kadmin.local getprinc K/M | grep -E '^Key:'
Key: vno 1, aes256-cts-hmac-sha1-96

If the encryption type is aes256-cts-hmac-sha1-96, the installation of a RHEL9 client fails.

Workaround

If the customer has no other solution (for instance for a migration from RHEL 8 to RHEL9 using the installation of a RHEL9 replica), the workaround consists in enabling the use of AES HMAC-SHA1 on the RHEL 9 client. Note that this workaround might violate FIPS compliance:

[rhel9client]# update-crypto-policies --set FIPS:AD-SUPPORT
Relevant bug

Bug 2103327 – Generate AES SHA-2 HMAC keys on deployed IPA instances in FIPS mode

Important: this issue does not happen if the first IdM server was installed with RHEL 8.7 or above, as the IdM master key encryption type is aes256-cts-hmac-sha384-192.

Replica installation/migration in FIPS mode

If the initial IdM server was installed in FIPS mode, then it is mandatory to enable FIPS mode on the replica before starting the ipa-replica-install procedure.

Migration from RHEL 8.7+ to RHEL9

The installation of the RHEL 9 replica fails during replication setup because the replication requires GSS authentication but the session key is encrypted with a type that is not supported by the RHEL9 replica.

# ipa-replica-install 
...
  [26/40]: setting up initial replication
Starting replication, please wait until this has completed.
Update in progress, 15 seconds elapsed
[ldap://master.testrelm.test:389] reports: Update failed! Status: [Error (49) - LDAP error: Invalid credentials - no response received]

  [error] RuntimeError: Failed to start replication
Your system may be partly configured.
Run /usr/sbin/ipa-server-install --uninstall to clean up.

Failed to start replication
The ipa-replica-install command failed. See /var/log/ipareplica-install.log for more information

Workaround

  • On the server, edit /etc/krb5.conf.d/crypto-policies, so that permitted_enctypes uses aes256-cts-hmac-sha384-192 as first value
# cat /etc/krb5.conf.d/crypto-policies 
[libdefaults]
permitted_enctypes = aes256-cts-hmac-sha384-192 aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 aes128-cts-hmac-sha256-128
  • Restart IPA services on the server
  • Retry the replica installation
Relevant bugs
Bug 2220834 – Migration of a RHEL 8.8+ server to RHEL 9.2 fails in FIPS mode
Bug 2219912 – krb5 policy updates
Bug 2225222 – Ordering matters for permitted_enctypes

Vault operations on a RHEL 9 client in FIPS mode

The ipa vault-* commands fail on a RHEL 9 client in FIPS mode. The vault client uses RSA-PKCS1v15 padding encryption that is blocked in FIPS mode.

# ipa vault-add myvault
New password: 
Enter New password again to verify: 
ipa: ERROR: non-public: ValueError: Encryption/decryption failed.
Traceback (most recent call last):
  File "/usr/lib/python3.9/site-packages/ipalib/backend.py", line 141, in execute
    return self.Command[_name](*args, **options)
  File "/usr/lib/python3.9/site-packages/ipalib/frontend.py", line 471, in __call__
    return self.__do_call(*args, **options)
  File "/usr/lib/python3.9/site-packages/ipalib/frontend.py", line 499, in __do_call
    ret = self.run(*args, **options)
  File "/usr/lib/python3.9/site-packages/ipalib/frontend.py", line 1224, in run
    return self.forward(*args, **options)
  File "/usr/lib/python3.9/site-packages/ipaclient/plugins/vault.py", line 356, in forward
    self.api.Command.vault_archive(*args, **opts)
  File "/usr/lib/python3.9/site-packages/ipalib/frontend.py", line 471, in __call__
    return self.__do_call(*args, **options)
  File "/usr/lib/python3.9/site-packages/ipalib/frontend.py", line 499, in __do_call
    ret = self.run(*args, **options)
  File "/usr/lib/python3.9/site-packages/ipalib/frontend.py", line 1224, in run
    return self.forward(*args, **options)
  File "/usr/lib/python3.9/site-packages/ipaclient/plugins/vault.py", line 932, in forward
    self.api.Command.vault_retrieve(*args, **opts)
  File "/usr/lib/python3.9/site-packages/ipalib/frontend.py", line 471, in __call__
    return self.__do_call(*args, **options)
  File "/usr/lib/python3.9/site-packages/ipalib/frontend.py", line 499, in __do_call
    ret = self.run(*args, **options)
  File "/usr/lib/python3.9/site-packages/ipalib/frontend.py", line 1224, in run
    return self.forward(*args, **options)
  File "/usr/lib/python3.9/site-packages/ipaclient/plugins/vault.py", line 1127, in forward
    response = self.internal(algo, transport_cert, *args, **options)
  File "/usr/lib/python3.9/site-packages/ipaclient/plugins/vault.py", line 735, in internal
    result = self._do_internal(algo, transport_cert, False,
  File "/usr/lib/python3.9/site-packages/ipaclient/plugins/vault.py", line 712, in _do_internal
    wrapped_session_key = public_key.encrypt(
  File "/usr/lib64/python3.9/site-packages/cryptography/hazmat/backends/openssl/rsa.py", line 537, in encrypt
    return _enc_dec_rsa(self._backend, self, plaintext, padding)
  File "/usr/lib64/python3.9/site-packages/cryptography/hazmat/backends/openssl/rsa.py", line 87, in _enc_dec_rsa
    return _enc_dec_rsa_pkey_ctx(backend, key, data, padding_enum, padding)
  File "/usr/lib64/python3.9/site-packages/cryptography/hazmat/backends/openssl/rsa.py", line 151, in _enc_dec_rsa_pkey_ctx
    raise ValueError("Encryption/decryption failed.")
ValueError: Encryption/decryption failed.
ipa: ERROR: an internal error has occurred
# 

Note that it is possible to use a RHEL 8.x client (or lower) to execute ipa vault-* commands even if the server is a RHEL 9 system, because RHEL 8 does not block the RSA-PKCS1v15 padding encryption.

Relevant bug

Bug 2089907 – ‘ipa vault-add is failing with ipa: ERROR: an internal error has occurred in FIPS mode

Trust in FIPS mode

In order to establish a trust from a RHEL server in FIPS mode, the server must meet the following requirements:

Establish 2-way trust on a RHEL server in FIPS mode

It is not possible to establish a 2-way trust from an IdM server in FIPS mode because the IdM server does not accept the RC4 NTLM hash that the AD domain controller uses when attempting to authenticate.

# /usr/bin/ipa trust-add windows-n3em.test --admin Administrator --type=ad --two-way=true --external=true
ipa: ERROR: Insufficient access: IPA master denied trust validation requests from AD DC 10 times. Most likely AD DC contacted a replica that has no trust information replicated yet. Additionally, please check that AD DNS is able to resolve _ldap._tcp.testrealmext.test, _ldap._tcp.Default-First-Site-Name._sites.dc._msdcs.testrealmext.test SRV records to the correct IPA server.
Relevant bugs
Bug 2120572 – ipa trust-add fails with ipa: ERROR: Insufficient access in FIPS mode
Bug 2124243 – ipa trust-add fails with ipa: ERROR: Insufficient access in FIPS mode

Establish trust with a shared secret in FIPS mode

Establishing a cross-forest trust using a shared secret fails in FIPS mode because NTLMSSP authentication is not FIPS-compliant.

Workaround

Authenticate with an Active Directory (AD) administrative account when establishing a trust between an IdM domain with FIPS mode enabled and an AD domain: instead of using ipa trust-add –trust-secret […], use ipa trust-add –admin=<account> –password […]

Relevant bug
Bug 1924707 – Establishing trust with AD domain using shared secret fails in FIPS mode

Use trust functionality from a RHEL 9 IdM client

Active Directory (AD) uses AES SHA-1 HMAC encryption types, which are not allowed in FIPS mode on RHEL 9 by default. In order to authenticate as an AD user on a RHEL 9 IdM client and obtain a kerberos TGT, the AES SHA-1 HMAC encryption type must be enabled.

[root@client9 ~]# kinit testuser@ad.test
kinit: KDC has no support for encryption type while getting initial credentials

Workaround

If you want to use RHEL 9 IdM hosts with an AD trust, enable support for AES SHA-1 HMAC encryption types before installing IdM software. Note that this workaround might violate FIPS compliance:

[root@client9]# update-crypto-policies --set FIPS:AD-SUPPORT
Relevant bugs
Bug 2057471 – Consequences of FIPS crypto policy tightening in RHEL 9
Bug 2067971 – Consequences of FIPS crypto policy tightening in RHEL 9

ID range management in IPA

POSIX IDs and IPA

Local domain range

IPA is an identity management solution that allows to centrally define users and groups. As it operates in Linux environments, the users and groups are defined with a name and a POSIX ID (a numeric value), that are used for access control: each file belongs to a user and a group identified by their POSIX ID, sudo rules evaluation relies on POSIX IDs and so on.

When users and groups are created inside IPA, they can either be created with a provided id or the admin can let IPA assign an id. The range from which the ids can be picked is defined at the IPA level and is represented by a local ID range visible with the ipa idrange-find command:

[root@server ~]# ipa idrange-find
---------------
1 range matched
---------------
  Range name: IPA.TEST_id_range
  First Posix ID of the range: 936000000
  Number of IDs in the range: 200000
  Range type: local domain range
----------------------------
Number of entries returned 1
----------------------------

During the first IPA server installation, this ID range can either be provided through a base ID number (—idstart) and a max ID (—id max), or be picked randomly by the installer.

In the above example, the users and groups will get assigned IDs starting from 936000000, up to 936000000 + 200000 (not included).

When the ID range is depleted, the admin can extend the possible ID numbers by defining additional local ranges (ipa idrange-add --type ipa-local).

Other types of ranges

When IPA has configured a trust with an Active Directory forest, the users and groups defined in AD also need to have a POSIX ID for access control performed on IPA side. There are 2 different situations:

  • if AD has been extended with Identity Management for UNIX, and is also storing a uidNumber and a gidNumber for each user, and a gidNumber for each group, then IPA can directly re-use the POSIX IDs stored on AD side. The trust is established with a range type “Active Directory domain with POSIX attributes” (ipa-ad-trust-posix).
  • If AD doesn’t store POSIX IDs, IPA maps the unique SID value from AD users and groups to a POSIX ID based on settings defined for the trust. The trust is established with a range type “Active Directory domain” (ipa-ad-trust) and sets the first POSIX ID for the mapping.

As a summary, IPA manages 3 different types of ID ranges:

  • local domain
  • active directory domain
  • active directory domain with POSIX attributes

In any case, the various ranges must not overlap in order to guarantee that an ID corresponds to a unique user or group.

Next available ID

DNA range plugin

During the first server installation, the local ID range is set and defines the range from which IDs get picked for new IPA users and groups. This local ID range is used for the whole IPA deployment.

The server is then configured with the DNA range plugin (Dynamic Number Assignment), that provides a mechanism to automatically assign IDs but also ensure existing IDs are not re-used. The implementation is simple to understand: the DNA plugin stores the next available ID and assigns the IDs sequentially.

The existing DNA ranges can be seen using ipa-replica-manage dnarange-show. If the command is run when there is a single server, the output looks like the following:

[root@server ~]# ipa-replica-manage  dnarange-show
server.ipa.test: 936000000-936199999

The DNA range on the first server starts from the same value as the local domain ID range , and ends on first POSIX ID + number of IDs – 1. When the first user gets created, he is assigned a POSIX ID, and the DNA range plugin increments the next available value:

[root@server ~]# ipa user-add idmuser1 --first idm --last user1 
...
[root@server ~]# ipa-replica-manage  dnarange-show
server.ipa.test: 936000002-936199999

The above output shows that the available range has shrinked due to the new user taking one ID. Note that the first ID (936000000) is reserved for the admin user.

Splitting ranges between replicas

When additional servers (replicas) are set up, it is important to make sure that a given ID is not assigned at the same time by 2 different replicas to different users/groups. In order to avoid this type of conflict, each replica is also configured with the DNA range plugin (dynamic number assignment).

[root@server ~]# ipa-replica-manage  dnarange-show
server.ipa.test: 936000002-936199999
replica.ipa.test: No range set

The above command shows that the replica hasn’t created yet any user or group and didn’t request any DNA range. But as soon as the replica needs to assign an ID, it communicates with the server and grabs a sub-range:

[root@replica ~]# ipa user-add idmuser2 --first idm --last user2
...
[root@replica ~]# ipa-replica-manage dnarange-show
server.ipa.test: 936000002-936100499
replica.ipa.test: 936100501-936199999

The output shows that server.ipa.test abandoned part of its range to replica.ipa.test. From now on, server.ipa.test will be able to assign IDs up to 936100499, while replica.ipa.test will assign IDs starting from 936100501 (he assigned 936100500 to the new user).

The DNA range is configured locally to each replica, in a part of the configuration that is not replicated. The DNA range records the next available ID and the max available ID. Remember, the DNA range is constantly evolving: as soon as a replica assigns an ID to a new user, the next available ID is incremented and the range shrinks over time.

It is important to make sure that DNA ranges are not overlapping, and that each DNA range fits into local ID ranges.

Frequent issues

Issues can happen when a replica doesn’t have any assigned DNA range and fails to grab a range when it needs to (for instance because the only other server he knows is down).

In this case, manual remediation is possible using ldapmodify, by editing the DNA range plugin configuration on the replica. The DNA range plugin configuration can be seen within the following LDAP entry:

[root@replica ~]# ldapsearch -LLL -D "cn=directory manager" -W -o ldif-wrap=no -b "cn=Posix IDs,cn=Distributed Numeric Assignment Plugin,cn=plugins,cn=config" dnaMaxValue dnaNextValue 
Enter LDAP Password: 
dn: cn=Posix IDs,cn=Distributed Numeric Assignment Plugin,cn=plugins,cn=config
dnaMaxValue: 936199999
dnaNextValue: 936100501

Note that the DNA range plugin has different values on each replica, and the ranges must not overlap and must not include already assigned IDs.

Another type of issue arises when the ID ranges are depleted. In this case, a new local id range can be added with a new range of values.

The official documentation contains a whole chapter related to Adjusting ID ranges manually and is a recommended read. I would also like to point to Rob’s blog “FreeIPA and no DNA range” for more details.

Troubleshooting ipa commands: read Apache error log and 389-ds access log

IdM includes an internal LDAP directory server instance where all the IdM information is stored: 389-ds. For instance the user and host entries reside in 389-ds as LDAP entries..

Most of the ipa commands are either reading or writing data in 389-ds. When an ipa command fails, 389-ds access log is really useful in order to understand if the failure is related to an issue in the LDAP server. This post will show how to used both Apache log and 389-ds access log to troubleshoot an issue.

Issue description

A Bugzilla reports that the command ipa domainlevel set behaves badly when the user tries to change the domain level but specifies the current level by mistake:

$ ipa domainlevel-get
-----------------------
Current domain level: 1
-----------------------
$ ipa domainlevel-set 0
ipa: ERROR: Domain Level cannot be lowered.

This result is expected as it is not possible to lower the current domain level.

$ ipa domainlevel-set 1
ipa: ERROR: Domain Level cannot be raised to 1, server master.example.com does not support it.

This result is wrong, as the domain level is already 1 and the following output is expected:

$ ipa domainlevel-set 1
ipa: ERROR: no modifications to be performed

Reading httpd error logs

By default, httpd error logs do not provide a lot of information (only messages with INFO or above). The logging level needs to be raised in order to have a hint of the root cause:

Create a file /etc/ipa/server.conf with the following content:

$ cat /etc/ipa/server.conf
[global]
debug=True

Restart FreeIPA stack:

$ ipactl restart
Restarting Directory Service
Restarting krb5kdc Service
Restarting kadmin Service
Restarting named Service
Restarting httpd Service
Restarting ipa-custodia Service
Restarting ipa-otpd Service
Restarting ipa-dnskeysyncd Service
Starting pki-tomcatd Service
ipa: INFO: The ipactl command was successful

Re-run the ipa domainlevel-set 1 command, more information will get written in httpd error log:

$ tail -f /var/log/httpd/error_log [...] ipa: DEBUG: WSGI wsgi_dispatch.__call__: [...] ipa: DEBUG: WSGI jsonserver.__call__: [...] ipa: DEBUG: KerberosWSGIExecutioner.__call__: [...] ipa: DEBUG: Created connection context.ldap2_139798041384160 [...] ipa: DEBUG: WSGI WSGIExecutioner.__call__: [...] ipa: DEBUG: raw: domainlevel_set(1, version='2.230') [...] ipa: DEBUG: domainlevel_set(1, version='2.230') [...] ipa: DEBUG: retrieving schema for SchemaCache url=ldapi://%2fvar%2frun%2fslapd-DOMAIN-COM.socket conn=<ldap.ldapobject.SimpleLDAPObject object at 0x7f25440f1208> [...] ipa: DEBUG: WSGI wsgi_execute PublicError: Traceback (most recent call last): [...] File "/usr/lib/python3.7/site-packages/ipaserver/rpcserver.py", line 370, in wsgi_execute [...] result = command(*args, **options) [...] File "/usr/lib/python3.7/site-packages/ipalib/frontend.py", line 450, in __call__ [...] return self.__do_call(*args, **options) [...] File "/usr/lib/python3.7/site-packages/ipalib/frontend.py", line 478, in __do_call [...] ret = self.run(*args, **options) [...] File "/usr/lib/python3.7/site-packages/ipalib/frontend.py", line 800, in run [...] return self.execute(*args, **options) [...] File "/usr/lib/python3.7/site-packages/ipaserver/plugins/domainlevel.py", line 156, in execute [...] raise errors.InvalidDomainLevelError(reason=message) [...] ipalib.errors.InvalidDomainLevelError: Domain Level cannot be raised to 1, server master.domain.com does not support it. [...] [...] ipa: INFO: [jsonserver_kerb] host/master.domain.com@DOMAIN.COM: domainlevel_set/1(1, version='2.230'): InvalidDomainLevelError [...] ipa: DEBUG: Destroyed connection context.ldap2_139798041384160

The log displays the command that was run and its parameters:

[...] ipa: DEBUG: raw: domainlevel_set(1, version='2.230') [...] ipa: DEBUG: domainlevel_set(1, version='2.230')

and also the result:

[...] ipa: INFO: [jsonserver_kerb] host/master.domain.com@DOMAIN.COM: domainlevel_set/1(1, version='2.230'): InvalidDomainLevelError

The debug log shows a stack trace that can be examined, with the exact line where the failure occurred:

[...] File "/usr/lib/python3.7/site-packages/ipaserver/plugins/domainlevel.py", line 156, in execute [...] raise errors.InvalidDomainLevelError(reason=message)

The code around this line looks like the following:

# Check if every master supports the desired level for master in get_master_entries(ldap, self.api): supported = get_domainlevel_range(master) if supported.min > desired_value or supported.max < desired_value: message = _("Domain Level cannot be raised to {0}, server {1} " "does not support it." ).format(desired_value, master['cn'][0]) raise errors.InvalidDomainLevelError(reason=message)

The get_domainlevel_range function is defined in the same file:

def get_domainlevel_range(master_entry): try: return DomainLevelRange( int(master_entry['ipaMinDomainLevel'][0]), int(master_entry['ipaMaxDomainLevel'][0]) ) except KeyError: return DomainLevelRange(0, 0)

get_domainlevel_range is reading ipaMinDomainLevel and ipaMaxDomainLevel from the master_entry. If the attributes are missing, the default values are set to 0.

What is this master_entry, and how is it built? The get_master_entries function is also defined in the same file:

def get_master_entries(ldap, api): """ Returns list of LDAPEntries representing IPA masters. """ container_masters = DN( ('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn ) masters, _dummy = ldap.find_entries( filter="(cn=*)", base_dn=container_masters, scope=ldap.SCOPE_ONELEVEL, paged_search=True, # we need to make sure to get all of them ) return masters

The function is simply performing a one-level search below cn=masters,cn=ipa,cn=etc,$BASEDN with a search filter “(cn=*)”. From there it’s easy to understand that the entries below cn=masters are supposed to contain the attributes ipaMinDomainLevel and ipaMaxDomainLevel.

389-ds logs will also help understand what happened for this search.

Reading 389-ds access logs

In a default IdM installation, 389-ds logs LDAP operations in /var/log/dirsv/slapd-DOMAIN-COM/access (the access logs is buffered).
To troubleshoot the problem, tail the access log and re-launch the command ipa domainlevel-set 1:

$ tail -f /var/log/dirsrv/slapd-DOMAIN-COM/access [...] conn=23 fd=102 slot=102 connection from 10.37.171.82 to 10.37.171.82 [...] conn=23 op=0 BIND dn="" method=sasl version=3 mech=GSS-SPNEGO [...] conn=23 op=0 RESULT err=0 tag=97 nentries=0 etime=0.0009926457 dn="fqdn=master.domain.com,cn=computers,cn=accounts,dc=domain,dc=com" [...] conn=23 op=1 SRCH base="cn=ipaconfig,cn=etc,dc=domain,dc=com" scope=0 filter="(objectClass=*)" attrs=ALL [...] conn=23 op=1 RESULT err=0 tag=101 nentries=1 etime=0.0002818162 [...] conn=23 op=2 SRCH base="cn=schema" scope=0 filter="(objectClass=*)" attrs="attributeTypes objectClasses" [...] conn=23 op=2 RESULT err=0 tag=101 nentries=1 etime=0.0134877660 [...] conn=23 op=3 SRCH base="cn=Domain Level,cn=ipa,cn=etc,dc=domain,dc=com" scope=0 filter="(objectClass=*)" attrs=ALL [...] conn=23 op=3 RESULT err=0 tag=101 nentries=1 etime=0.0001469752 [...] conn=23 op=4 SRCH base="cn=masters,cn=ipa,cn=etc,dc=domain,dc=com" scope=1 filter="(cn=*)" attrs=ALL [...] conn=23 op=4 RESULT err=0 tag=101 nentries=1 etime=0.0002024975 notes=P pr_idx=0 pr_cookie=-1 [...] conn=23 op=5 UNBIND [...] conn=23 op=5 fd=102 closed - U1

Let’s analyse the log from the beginning:

[...] conn=23 fd=102 slot=102 connection from 10.37.171.82 to 10.37.171.82

A LDAP client has opened a new connection (the client is running on the same machine as the server because the IP addresses are identical). In the following lines, the logs with an identical connection id (conn=23) will refer to operations sent using the same connection, meaning the same client.

[...] conn=23 op=0 BIND dn="" method=sasl version=3 mech=GSS-SPNEGO

The first operation (with op=0) executed by the LDAP client is a BIND using Kerberos authentication (mech=GSS-SPNEGO). In order to see the operation’s result, one needs to find in the log a line with the same tuple (connection id, op id):

[...] conn=23 op=0 RESULT err=0 tag=97 nentries=0 etime=0.0009926457 dn="fqdn=master.domain.com,cn=computers,cn=accounts,dc=domain,dc=com"

The logs show that the BIND was successful (RESULT err=0) and authenticated the connection as fqdn=master.domain.com,cn=computers,cn=accounts,dc=domain,dc=com. This is the host entry associated to the master. The kinit was probably done using kinit -kt /etc/krb5.keytab as this keytab contains the key for the local host.

Then the client performed a few searches, and it’s easy to spot the search performed by Apache server:

[...] conn=23 op=4 SRCH base="cn=masters,cn=ipa,cn=etc,dc=domain,dc=com" scope=1 filter="(cn=*)" attrs=ALL

This log corresponds to a one-level search (scope=1) on cn=masters,cn=ipa,cn=etc,$BASEDN (base=…) with the filter “(cn=*)”. The search returned success (RESULT err=0) and found a single entry (nentries=1):

[...] conn=23 op=4 RESULT err=0 tag=101 nentries=1 etime=0.0002024975 notes=P pr_idx=0 pr_cookie=-1

The log doesn’t show the content that was returned… But it’s possible to manually reproduce the search with a simple ldapsearch command:

$ kinit -kt /etc/krb5.keytab $ ldapsearch -LLL -o ldif-wrap=no -Y GSSAPI -b cn=masters,cn=ipa,cn=etc,dc=domain,dc=com -s one "(cn=*)" SASL/GSSAPI authentication started SASL username: host/master.domain.com@DOMAIN.COM SASL SSF: 256 SASL data security layer installed. dn: cn=master.domain.com,cn=masters,cn=ipa,cn=etc,dc=domain,dc=com objectClass: top objectClass: nsContainer objectClass: ipaReplTopoManagedServer objectClass: ipaConfigObject objectClass: ipaSupportedDomainLevelConfig cn: master.domain.com

The above content is exactly the same as the content returned to Apache server. There is no ipaMinDomainLevel or ipaMaxDomainLevel in this entry, meaning that the code considered instead the default value of (0,0) for (supported.min, supported.max):

  if supported.min > desired_value or supported.max < desired_value: message = _("Domain Level cannot be raised to {0}, server {1} " "does not support it." ).format(desired_value, master['cn'][0]) raise errors.InvalidDomainLevelError(reason=message)

With supported.max = 0, we have supported.max < desired_value and raise the Exception.

But why didn’t the ldap search return these attributes? The same request but authenticated as cn=Directory Manager will show the full entry content (access control do not apply to this user):

$ ldapsearch -D "cn=directory manager" -W -LLL -o ldif-wrap=no -b cn=masters,cn=ipa,cn=etc,dc=domain,dc=com -s one "(cn=*)" Enter LDAP Password: dn: cn=master.domain.com,cn=masters,cn=ipa,cn=etc,dc=domain,dc=com objectClass: top objectClass: nsContainer objectClass: ipaReplTopoManagedServer objectClass: ipaConfigObject objectClass: ipaSupportedDomainLevelConfig cn: master.domain.com ipaReplTopoManagedSuffix: dc=domain,dc=com ipaReplTopoManagedSuffix: o=ipaca ipaMinDomainLevel: 1 ipaMaxDomainLevel: 1

The LDAP entry contains these attributes but they are filtered out from the entry returned if the search is authenticated as the local host. This is probably a simple ACI issue. To prove this assumption, repeat the ipa domainlevel-set 1 command, but this time authenticated as admin, who has more read permissions than the local host:

$ kinit admin
Password for admin@DOMAIN.COM:
$ ipa domainlevel-set 1
ipa: ERROR: no modifications to be performed

The mystery is solved! The operation was performed with the wrong user and did not have enough permissions to execute successfully.

Conclusion

When one is able to read both Apache error log and 389-ds access log, it is often easy to spot the exact cause for an issue within ipa commands. 389-ds logs display the command and the authenticated user, allowing to replay the same operation in order to see the actual result returned by 389-ds.

Demystifying the Certificate Authority component in FreeIPA

When I joined the FreeIPA team, I wanted to start by getting more familiar with the product from a user perspective and the first step was to install FreeIPA server.

I opened the Linux Domain Identity, Authentication, and Policy Guide, tried to figure out which options would be useful and… I froze when I reached the section Determining which CA configuration to use. I had literally no idea what the documentation meant by “Server with an integrated IdM CA” or “Server without a CA“. But I had to choose something to start with.
In this blog post, I will explain what this choice really means, and what are the consequences of picking one over the other.

Basic requirement: HTTP and LDAP server certificates

First of all, FreeIPA is composed of many services accessed through the network, among which a LDAP server and an HTTP server. These 2 services can be accessed through a standard port (in clear) or through a SSL port, meaning that they both need a server certificate.

The HTTP and LDAP server certificates are needed during the installation, because the installer will put them in the right NSS database and configure their nickname and location for the HTTP and LDAP servers to find them. There are multiple ways to obtain server certificates, but one needs to understand first the basic notions around Public Key Infrastructure (PKI).

I will use a comparison with the delivery of a passport: in order to have a passport issued with your name, you need to provide official documents (for instance a birth certificate and a photo) to the government agency that will validate the documents, make sure that you are who you claim to be, and then issue the passport. The server certificate can be compared to the passport, that will later prove your identity to whoever trusts the government agency, and the government agency can be compared to the Certificate Authority.

So in order to obtain server certificates, it is possible to:

  • request certificates to an official Certificate Authority. Many commercial or non-profit companies provide this type of service (Verisign, Let’sEncrypt, GoDaddy etc…)
  • request certificates to a home-made Certificate Authority. It is possible to create a home-made self-signed Certificate Authority with tools such as certutil or openssl. The main difference with the previous method is that people are less likely to trust your home-made CA (it’s like asking them to accept a passport that was issued by a newly founded country not recognized yet by the rest of the world). Self-signed here means that the Certificate Authority passport  is delivered by… the Certificate Authority itself!
  • install your own Certificate Authority with FreeIPA, that will sign the certificates needed by the HTTP and LDAP server.

The last option corresponds to a “Server with an integrated IdM CA” and has many advantages over the first options:

  • certificates have a limited lifetime and need to be renewed before they expire (otherwise the HTTP/LDAP servers stop working). The renewal process is time-consuming but also can be forgotten if the sysadmin does not carefully track the dates, leaving the deployment in a state where some services become unavailable.
    When FreeIPA is installed with an embedded Certificate Authority, FreeIPA automatically monitors the expiry dates of the certificates and triggers a renewal a few weeks before expiration, ensuring service continuity. This is the first advantage of the embedded CA, but not the only one.
  • FreeIPA with an embedded CA is also able to deliver certificates for the users, the hosts or the services managed by FreeIPA. Various certificates profiles can be defined, populating specific fields in each type of certificate (for instance extensions with the OCSP responder URL…)
    For more information on the embedded Certificate Authority, you can refer to Dogtag Certificate System documentation (the embedded CA in FreeIPA is a tailored version of Dogtag).

At this point, if you decide to install FreeIPA with an embedded Certificate Authority, there are 2 possible choices. The embedded CA can either be:

  • a self-signed CA: the Certificate Authority is created “from scratch” without the need for any external authority. It is the root CA, meaning that its own certificate was not delivered by anyone else but signed by itself.
  • a CA subordinate to an external CA. This means that FreeIPA CA certificate was signed by another CA, a sort of parent CA.

 

Corresponding installation options

CA-less installation

As said above, we need one certificate for the HTTP server and one for the LDAP server.  They have to be provided to ipa-server-install or ipa-replica-install with the options:

  • –http-cert-file / –http-pin: file containing the HTTP server certificate + private key and password protecting the file
  • –dirsrv-cert-file / –dirsrv-pin: file containing the LDAP server certificate + private key and password protecting the file

Installation with an embedded self-signed CA

FreeIPA CA is created during FreeIPA installation, and generates the HTTP and LDAP certificates. There is no need to provide any cert file! No options!

Installation with an externally-signed embedded CA

The installation is a 2-step process. In the first step, ipa-server-install must be called with –external-ca and generates a CSR file (Certificate Signing Request). This CSR file needs to be sent to the external CA that will perform a bunch of validations to authenticate the recipient of the certificate and issue a certificate for FreeIPA Certificate Authority.

In the second step, ipa-server-install is called with –external-cert-file to provide the certificate obtained from the external CA. The installer then configures FreeIPA certificate authority as a subCA of the external CA, and FreeIPA CA can issue the HTTP and LDAP server certificates.

 

What if…

I installed FreeIPA without any embedded CA but I change my mind?

FreeIPA allows to install an embedded CA at a later time, using ipa-ca-install. The tool provides the same options as ipa-server-install: you can either install a self-signed CA or an externally signed CA.

Important: installing an embedded CA with ipa-ca-install does not replace the HTTP and LDAP server certificates. If they were initially delivered by an external CA, they will not be automatically renewed.

I installed FreeIPA with a self-signed CA but I’d rather have an externally-signed CA?

FreeIPA allows to switch from self-signed CA to externally-signed CA using ipa-cacert-manage renew –external-ca. This is a 2-step process similar to ipa-server-install –external-ca, where the 1st step produces a CSR that needs to be supplied to an external CA. The external CA then issues a CA cert that is provided back to ipa-cacert-manage renew through the –external-cert-file option.

I installed FreeIPA with an externally signed CA but I’d rather have a self-signed CA?

FreeIPA allows to switch from externally signed CA to self-signed CA using ipa-cacert-manage renew –self-signed.

I want to replace HTTP and LDAP certificates with certificates signed by a third-party Certificate Authority?

FreeIPA provides the ipa-server-certinstall tool that will replace the current HTTP or LDAP certificates with the certs provided in the file.
Important: ipa-server-certinstall can be called to install externally signed certificates for HTTP and LDAP even if FreeIPA is installed with an embedded CA. In this case, FreeIPA CA still has the capability to issue certificates for users, hosts or services. The only difference is that HTTP and LDAP certificates are not issued by IPA CA.

 

Other FreeIPA commands related to certificates

When an embedded CA is installed, its certificate must be present in various files or NSS databases on all the FreeIPA hosts (master, replicas and clients) so that any FreeIPA machine trusts the certificates delivered by the embedded CA.

In addition to that, the HTTP and LDAP server certificates can be issued either by IPA CA or by an external CA, and the issuer can even be changed over time. In the external CA case, this means that the external CA needs to be trusted by all the FreeIPA machines for the IPA commands to work (the CLI communicates with the HTTP server using the https port, and this requires to trust the CA that issued the HTTP server certificate). Yet another CA certificate to add to files and databases on all the FreeIPA machines…

To ease this configuration, the tool ipa-certupdate is able to retrieve the CA certificates stored in LDAP (the embedded FreeIPA CA or the external CA certs), and install them in all the relevant files and NSS databases. It needs to be called when the CA cert is manually renewed or when a new external CA cert is added.

ipa-cacert-manage install is used to add a new external CA certificate in the LDAP store. It does not replace FreeIPA embedded CA but rather declares another certificate authority as trusted. This is useful when the HTTP and LDAP server certificates need to be replaced by certs signed by a new CA, not yet known by FreeIPA. After calling ipa-cacert-manage install (that puts the new CA in LDAP store), you need to call ipa-certupdate on all FreeIPA machines (to get the CA from the LDAP store and put it in the local NSS databases).

ipa cert-request is used to request new certificates for users, hosts or services. The certificate is signed by FreeIPA embedded CA (meaning that this command is available only when an embedded CA is configured).

Conclusion

By now you should be able to pick a deployment option and understand the differences between CA-less or with embedded CA, and self-signed CA or externally-signed CA.

You should also be aware that your choice is not definitive and that it is possible to install a CA at a later time or change your certificate chain from self-signed to externally-signed and vice-versa.

Troubleshooting FreeIPA: pki-tomcatd fails to start

When performing the upgrade of FreeIPA, you may encounter an issue with pki-tomcatd failing to start. At first this issue looks related to the upgrade, but often reveals a latent problem and gets detected only because the upgrade triggers a restart of pki-tomcatd.

So how to troubleshoot this type of issue?

 

Upgrade logs

The upgrade is using /var/log/ipaupgrade.log and may contain a lot of useful information. In this specific case, I could see:

[...] DEBUG The ipa-server-upgrade command failed,
exception: ScriptError: CA did not start in 300.0s
[...] ERROR CA did not start in 300.0s
[...] ERROR The ipa-server-upgrade command failed. See
/var/log/ipaupgrade.log for more information

 

CA debug logs

The first step is to understand why pki-tomcatd refuses to start. This process is launched inside Tomcat and corresponds to the CA component of FreeIPA. It is logging into /var/log/pki/pki-tomcat/ca/debug:

[...][localhost-startStop-2]: ============================================
[...][localhost-startStop-2]: ===== DEBUG SUBSYSTEM INITIALIZED =======
[...][localhost-startStop-2]: ============================================
[...][localhost-startStop-2]: CMSEngine: restart at autoShutdown? false
[...][localhost-startStop-2]: CMSEngine: autoShutdown crumb file path? /var/lib/pki/pki-tomcat/logs/autoShutdown.crumb
[...][localhost-startStop-2]: CMSEngine: about to look for cert for auto-shutdown support:auditSigningCert cert-pki-ca
[...][localhost-startStop-2]: CMSEngine: found cert:auditSigningCert cert-pki-ca
[...][localhost-startStop-2]: CMSEngine: done init id=debug
[...][localhost-startStop-2]: CMSEngine: initialized debug
[...][localhost-startStop-2]: CMSEngine: initSubsystem id=log
[...][localhost-startStop-2]: CMSEngine: ready to init id=log
[...][localhost-startStop-2]: Creating RollingLogFile(/var/lib/pki/pki-tomcat/logs/ca/signedAudit/ca_audit)
[...][localhost-startStop-2]: Creating RollingLogFile(/var/lib/pki/pki-tomcat/logs/ca/system)
[...][localhost-startStop-2]: Creating RollingLogFile(/var/lib/pki/pki-tomcat/logs/ca/transactions)
[...][localhost-startStop-2]: CMSEngine: restart at autoShutdown? false
[...][localhost-startStop-2]: CMSEngine: autoShutdown crumb file path? /var/lib/pki/pki-tomcat/logs/autoShutdown.crumb
[...][localhost-startStop-2]: CMSEngine: about to look for cert for auto-shutdown support:auditSigningCert cert-pki-ca
[...][localhost-startStop-2]: CMSEngine: found cert:auditSigningCert cert-pki-ca
[...][localhost-startStop-2]: CMSEngine: done init id=log
[...][localhost-startStop-2]: CMSEngine: initialized log
[...][localhost-startStop-2]: CMSEngine: initSubsystem id=jss
[...][localhost-startStop-2]: CMSEngine: ready to init id=jss
[...][localhost-startStop-2]: CMSEngine: restart at autoShutdown? false
[...][localhost-startStop-2]: CMSEngine: autoShutdown crumb file path? /var/lib/pki/pki-tomcat/logs/autoShutdown.crumb
[...][localhost-startStop-2]: CMSEngine: about to look for cert for auto-shutdown support:auditSigningCert cert-pki-ca
[...][localhost-startStop-2]: CMSEngine: found cert:auditSigningCert cert-pki-ca
[...][localhost-startStop-2]: CMSEngine: done init id=jss
[...][localhost-startStop-2]: CMSEngine: initialized jss
[...][localhost-startStop-2]: CMSEngine: initSubsystem id=dbs
[...][localhost-startStop-2]: CMSEngine: ready to init id=dbs
[...][localhost-startStop-2]: DBSubsystem: init() mEnableSerialMgmt=true
[...][localhost-startStop-2]: Creating LdapBoundConnFactor(DBSubsystem)
[...][localhost-startStop-2]: LdapBoundConnFactory: init
[...][localhost-startStop-2]: LdapBoundConnFactory:doCloning true
[...][localhost-startStop-2]: LdapAuthInfo: init()
[...][localhost-startStop-2]: LdapAuthInfo: init begins
[...][localhost-startStop-2]: LdapAuthInfo: init ends
[...][localhost-startStop-2]: init: before makeConnection errorIfDown is true
[...][localhost-startStop-2]: makeConnection: errorIfDown true
[...][localhost-startStop-2]: TCP Keep-Alive: true
[...][localhost-startStop-2]: SSLClientCertificateSelectionCB: Setting desired cert nickname to: subsystemCert cert-pki-ca
[...][localhost-startStop-2]: LdapJssSSLSocket: set client auth cert nickname subsystemCert cert-pki-ca
[...][localhost-startStop-2]: SSL handshake happened
Could not connect to LDAP server host ipaserver.ipadomain.com port 636 Error netscape.ldap.LDAPException: Authentication failed (49)
 at com.netscape.cmscore.ldapconn.LdapBoundConnFactory.makeConnection(LdapBoundConnFactory.java:205)
 at com.netscape.cmscore.ldapconn.LdapBoundConnFactory.init(LdapBoundConnFactory.java:166)
 at com.netscape.cmscore.ldapconn.LdapBoundConnFactory.init(LdapBoundConnFactory.java:130)
 at com.netscape.cmscore.dbs.DBSubsystem.init(DBSubsystem.java:654)
 at com.netscape.cmscore.apps.CMSEngine.initSubsystem(CMSEngine.java:1172)
 at com.netscape.cmscore.apps.CMSEngine.initSubsystems(CMSEngine.java:1078)
 at com.netscape.cmscore.apps.CMSEngine.init(CMSEngine.java:570)
 at com.netscape.certsrv.apps.CMS.init(CMS.java:188)
 at com.netscape.certsrv.apps.CMS.start(CMS.java:1621)
 at com.netscape.cms.servlet.base.CMSStartServlet.init(CMSStartServlet.java:114)
 at javax.servlet.GenericServlet.init(GenericServlet.java:158)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:498)
 at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:288)
 at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:285)
 at java.security.AccessController.doPrivileged(Native Method)
 at javax.security.auth.Subject.doAsPrivileged(Subject.java:549)
 at org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:320)
 at org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:175)
 at org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:124)
 at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1270)
 at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1195)
 at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1085)
 at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5318)
 at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5610)
 at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:147)
 at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:899)
 at org.apache.catalina.core.ContainerBase.access$000(ContainerBase.java:133)
 at org.apache.catalina.core.ContainerBase$PrivilegedAddChild.run(ContainerBase.java:156)

The exception shows that LDAP authentication failed with return code 49: invalid credentials.

 

Communication between pki-tomcatd and the LDAP server

We can see that pki-tomcatd is trying to open a LDAP connection through SSL but fails to authenticate. Within FreeIPA, pki-tomcat is storing data in the 389-ds LDAP server and needs to communicate through LDAP with this server.

The configuration of this communication channel can be read in /etc/pki/pki-tomcat/ca/CS.cfg:

internaldb.ldapauth.authtype=SslClientAuth
internaldb.ldapauth.bindDN=cn=Directory Manager
internaldb.ldapauth.bindPWPrompt=internaldb
internaldb.ldapauth.clientCertNickname=subsystemCert cert-pki-ca
internaldb.ldapconn.host=ipaserver.ipadomain.com
internaldb.ldapconn.port=636
internaldb.ldapconn.secureConn

The connection is using port 636 (SSL port) with SSL Client authentication (authtype=SslClientAuth). This means that pki-tomcatd provides a user certificate to the LDAP server, and the LDAP server maps a user to this certificate in order to authenticate the communications.

Note: Authtype can either be SslClientAuth or BasicAuth (authentication with username and password).

In this case, the SSL client authentication is done with the certificate named ‘subsystemCert cert-pki-ca‘ that is stored in /etc/pki/pki-tomcat/alias. So what could be causing the authentication to fail? We need to check that the certificate is available in /etc/pki/pki-tomcat/alias and that pki-tomcat is able to use the associated private key, and that the LDAP server is able to map this certificate to a user.

 

Check the subsystemCert cert-pki-ca

The first step consists in making sure that this certificate is present in /etc/pki/pki-tomcat/alias:

$ sudo certutil -L -d /etc/pki/pki-tomcat/alias -n 'subsystemCert cert-pki-ca'
Certificate:
 Data:
 Version: 3 (0x2)
...

 

Then make sure that the private key can be read using the password found in /var/lib/pki/pki-tomcat/conf/password.conf (with the tag internal=…)

$ sudo grep internal /var/lib/pki/pki-tomcat/conf/password.conf | cut -d= -f2 > /tmp/pwdfile.txt
$ sudo certutil -K -d /etc/pki/pki-tomcat/alias -f /tmp/pwdfile.txt -n 'subsystemCert cert-pki-ca'
certutil: Checking token "NSS Certificate DB" in slot "NSS User Private Key and Certificate Services"
< 0> rsa 86a7fe00cc2a01ad085f35d4ed3e84e7b82ab4f5 subsystemCert cert-pki-ca

At this point we know that pki-tomcat is able to access the certificate and the private key. So the issue is likely to be on the LDAP server side.

Note: depending on your version, the nickname of the certificate may also be prefixed with ‘NSS Certificate DB:’. In this case, run the following command:

$ sudo certutil -K -d /etc/pki/pki-tomcat/alias -f /tmp/pwdfile.txt -n 'NSS Certificate DB: subsystemCert cert-pki-ca'

 

LDAP server configuration

The LDAP configuration describes how a certificate can be mapped to a user in /etc/dirsrv/slapd-IPADOMAIN-COM/certmap.conf:

$ sudo cat /etc/dirsrv/slapd-IPADOMAIN-COM/certmap.conf 
[...]
certmap default default
[...]
default:DNComps
default:FilterComps uid
certmap ipaca CN=Certificate Authority,O=IPADOMAIN.COM
ipaca:CmapLdapAttr seeAlso
ipaca:verifycert on

This means that when the LDAP server receives an authentication request with a certificate issued by the CA CN=Certificate Authority,O=IPADOMAIN.COM, it will look for users that contain a seeAlso attribute equal to the subject of the certificate, and the user entry must contain the certificate in the usercertificate attribute (verifycert: on).

With a default config, the ‘subsystemCert cert-pki-ca‘ is mapped to the user uid=pkidbuser,ou=people,o=ipaca. So let’s compare the user entry and the certificate:

$ ldapsearch -LLL -D 'cn=directory manager' -W -b uid=pkidbuser,ou=people,o=ipaca userCertificate description seeAlso
Enter LDAP Password: 
dn: uid=pkidbuser,ou=people,o=ipaca
userCertificate:: MIID...uwab3
description: 2;4;CN=Certificate Authority,O=IPADOMAIN.COM;CN=CA Subsystem,O=IPADOMAIN.COM
seeAlso: CN=CA Subsystem,O=IPADOMAIN.COM


$ sudo certutil -L -d /etc/pki/pki-tomcat/alias -n 'subsystemCert cert-pki-ca' -a
-----BEGIN CERTIFICATE-----
MIID...e5QAR
-----END CERTIFICATE-----

The certificate in the userCertificate attribute is different from the one in the NSS database! This can also be seen by comparing the serial number with the value from the ldap entry (in description: 2;<serial>;<issuer>;<subject>):

$ sudo certutil -L -d /etc/pki/pki-tomcat/alias -n 'subsystemCert cert-pki-ca' | grep Serial
 Serial Number: 1341718541 (0x4ff9000d

This explains why pki-tomcat could not authenticate to the LDAP server. The fix consists in updating the LDAP entry with the right certificate (and do not forget to update the description attribute with the right serial number!):

$ cat updatecert.ldif
dn: uid=pkidbuser,ou=people,o=ipaca
changetype: modify
replace: usercertificate
usercertificate::MII... <here put the new cert in a single line. The double colon :: is important as the format is binary>
-
replace: description
description: 2;<here put the new serial number>;CN=Certificate Authority,O=IPADOMAIN.COM;CN=CA Subsystem,O=IPADOMAIN.COM


$ ldapmodify -D "cn=directory manager" -W -f updatecert.ldif

But we still do not know the root cause for the inconsistency between the NSS database /etc/pki/pki-tomcat/alias and the user entry for uid=pkidbuser. This could be described in another blog post (for the impatients, the automatic renewal of the certificate failed to update the LDAP server entry…)

Troubleshooting: mapping between a SmartCard certificate and an IdM user

Authentication with a SmartCard may fail when the SmartCard certificate is not linked to any IdM user, or to a user different from the one specified on the console.

In order to find which user is associated to a given SmartCard certificate, you can run the following command:

ipaclient$ ipa certmap-match cert.pem
--------------
1 user matched
--------------
 Domain: IPADOMAIN.COM
 User logins: demosc1
----------------------------
Number of entries returned 1
----------------------------

If the result is not what you were expecting, you need first to check how certificates are mapped to users.

By default, a certificate is associated to a user when the user entry contains the full certificate in its usercertificate attribute. But this behavior can be modified by defining certificate mapping rules:

ipaclient$ ipa certmaprule-find
-------------------------------------------
1 Certificate Identity Mapping Rule matched
-------------------------------------------
 Rule name: rulesmartcard
 Mapping rule: (ipacertmapdata=X509:<I>{issuer_dn}<S>{subject_dn})
 Matching rule: <ISSUER>CN=Smart Card CA,O=EXAMPLE.ORG
 Enabled: FALSE
----------------------------
Number of entries returned 1
----------------------------

 

Mapping with full certificate content

When the mapping is based on the full certificate content, you can check if the user entry contains the certificate:

root@ipaclient$ ipa user-show demosc1
 User login: demosc1
[...]
Certificate: MIIC...

If it is not the case, associate the certificate with the user entry using:

ipaclient$ CERT=`cat cert.pem | tail -n +2 | head -n -1 | tr -d '\r\n'`
ipaclient$ ipa user-add-cert demosc1 --certificate $CERT

Once this is done, you may need to clear sssd cache to force SSSD to reload the entries before retrying ipa certmap-match:

ipaclient$ sudo sss_cache -E

 

Flexible mapping with certificate identity mapping rule

When the mapping is based on certificate mapping rules, the same tool ipa certmap-match can be used to check which user entry is associated to a certificate. When the result is not what you expect, you can enable sssd domain logs by adding the following in /etc/sssd/sssd.conf on IdM master:

[domain/ipadomain.com]
...
debug_level = 9

then restart sssd with

root@ipaserver$ systemctl restart sssd

The logs will be located in /var/log/sssd/sssd_ipadomain.log.

 

Check that the certificate identity mapping rules are properly loaded

When sssd is restarted, it reads the mapping rules and should print the following in /var/log/sssd/sssd_ipadomain.log:

[sssd[be[ipadomain.com]]] [sss_certmap_init] (0x0040): sss_certmap initialized.
[sssd[be[ipadomain.com]]] [ipa_certmap_parse_results] (0x4000): Trying to add rule [rulesmartcard][-1][<ISSUER>CN=Smart Card CA,O=EXAMPLE.ORG][(ipacertmapdata=X509:<I>{issuer_dn!nss_x500}<S>{subject_dn!nss_x500})].

If the rule has an invalid syntax, you will see instead:

[sssd[be[ipadomain.com]]] [sss_certmap_init] (0x0040): sss_certmap initialized.
[sssd[be[ipadomain.com]]] [ipa_certmap_parse_results] (0x4000): Trying to add rule [rulesmartcard][-1][<ISSUER>CN=Smart Card CA,O=EXAMPLE.ORG][(ipacertmapdata=X509:<I>{issuer_dn!x509}<S>{subject_dn})].
[sssd[be[ipadomain.com]]] [parse_template] (0x0040): Parse template invalid.
[sssd[be[ipadomain.com]]] [parse_ldap_mapping_rule] (0x0040): Failed to add template.
[sssd[be[ipadomain.com]]] [parse_mapping_rule] (0x0040): Failed to parse LDAP mapping rule.
[sssd[be[ipadomain.com]]] [ipa_certmap_parse_results] (0x0020): sss_certmap_add_rule failed for rule [rulesmartcard], skipping. Please check for typos and if rule syntax is supported.
[sssd[be[ipadomain.com]]] [ipa_subdomains_certmap_done] (0x0040): Unable to parse certmap results [22]: Invalid argument
[sssd[be[ipadomain.com]]] [ipa_subdomains_refresh_certmap_done] (0x0020): Failed to read certificate mapping rules [22]: Invalid argument

The log shows that the rule named rulesmartcard is invalid. Check the rule (see man page for sss-certmap for the supported syntax) and fix if needed:

ipaclient$ ipa certmaprule-show rulesmartcard
 Rule name: rulesmartcard
 Mapping rule: (ipacertmapdata=X509:<I>{issuer_dn!x509}<S>{subject_dn})
 Matching rule: <ISSUER>CN=Smart Card CA,O=EXAMPLE.ORG
 Enabled: TRUE
ipaclient$ ipa certmaprule-mod rulesmartcard --maprule '(ipacertmapdata=X509:<I>{issuer_dn}<S>{subject_dn})'

 

Check that the matching rule corresponds to the certificate

When SSSD tries to associate the certificate to a user, it starts by finding which rule can be applied based on the matching rule (for instance rulesmartcard applies to all certificates issued by CN=Smart Card CA,O=EXAMPLE.ORG because its matching rule is <ISSUER>CN=Smart Card CA,O=EXAMPLE.ORG).

If no matching rule applies to the certificate, SSSD will not be able to associate the certificate with a user, and will display the following in /var/log/sssd/sssd_ipadomain.log:

[sssd[be[ipadomain.com]]] [sss_cert_derb64_to_ldap_filter] (0x0040): Certificate does not match matching-rules.

In this case, you need to create or modify an identity mapping rule, so that the match rule applies to your certificate. See sss-certmap man page for the supported syntax of the –matchrule option of ipa certmaprule-add command.

Check that the expected certificate identity mapping rule is used

When SSSD tries to find the user associated to the certificate, you will see the following logs in /var/log/sssd/sssd_ipadomain.log:

[sssd[be[ipadomain.com]]] [dp_get_account_info_handler] (0x0200): Got request for [0x14][BE_REQ_BY_CERT][cert=MII..]
...
[sssd[be[ipadomain.com]]] [sdap_search_user_next_base] (0x0400): Searching for users with base [cn=accounts,dc=ipadomain,dc=com]
[sssd[be[ipadomain.com]]] [sdap_print_server] (0x2000): Searching 10.34.58.20:389
[sssd[be[ipadomain.com]]] [sdap_get_generic_ext_step] (0x0400): calling ldap_search_ext with [(&(ipacertmapdata=X509:<I>O=EXAMPLE.ORG,CN=Smart Card CA<S>CN=test,O=EXAMPLE.ORG)(objectclass=posixAccount)(uid=*)(&(uidNumber=*)(!(uidNumber=0))))][cn=accounts,dc=ipadomain,dc=com].
...
[sssd[be[ipadomain.com]]] [sdap_search_user_process] (0x0400): Search for users, returned 0 results.

The logs show the LDAP search performed by SSSD: IP address of the LDAP server, base and search filter. Carefully review this information and compare with what you would expect.

Check that the mapping rule defines a valid search filter

If the rule cannot be transformed to a valid search filter, you will see in /var/log/sssd/sssd_ipadomain.log:

[sssd[be[ipadomain.com]]] [sdap_get_generic_ext_step] (0x0400): calling ldap_search_ext with [(&(ipacertmapdata=X509:<I>O=EXAMPLE.ORG,CN=Smart Card CA<S>CN=test,O=EXAMPLE.ORG(objectclass=posixAccount)(uid=*)(&(uidNumber=*)(!(uidNumber=0))))][cn=accounts,dc=ipadomain,dc=com].
[...]
[sssd[be[ipadomain.com]]] [sdap_get_generic_ext_step] (0x0080): ldap_search_ext failed: Bad search filter

If it is the case, you need to fix the certmap rule using

ipaclient$ ipa certmaprule-mod rulesmartcard –maprule …

 

 

Troubleshooting: authentication to the system console or Gnome Desktop Manager of an IdM host with a SmartCard

IdM allows to authenticate to an IdM enrolled-host by providing a SmartCard certificate instead of a username/password. The below steps are based on system console authentication but the process is similar when using Gnome desktop  login authentication.

When the authentication fails, the issue usually comes from a wrong configuration of the IdM system for SmartCard, or of PKINIT.

 

Configuration of the IdM host for SmartCard authentication

If the console does not even prompt for the SmartCard PIN, chances are high that the system was not properly configured for SmartCard authentication.

SSSD configuration for smart card

Check that /etc/sssd.conf contains

[pam]
pam_cert_auth = True

If you need to update the file, do not forget to restart sssd with

root@ipaclient$ systemctl restart sssd

 

SmartCard CA must be trusted

Check that the SmartCard CA is trusted in the /etc/pki/nssdb database:

root@ipaclient$ certutil -L -d /etc/pki/nssdb/

Certificate Nickname Trust Attributes     SSL,S/MIME,JAR/XPI

SmartCardCA                               CT,C,C

If the CA is not present, add it using:

root@ipaclient$ certutil -A -d /etc/pki/nssdb -n SmartCardCA -t CT,C,C -i ca.pem

 

IdM host PKCS#11 module

Check that the IdM host is properly configured for Smart Cards. The opensc package must be installed, the the SmartCard daemon must be running, and the PKCS#11 module must be loaded

root@ipaclient$ dnf install opensc
root@ipaclient$ systemctl start pcscd.service pcscd.socket
root@ipaclient$ modutil -dbdir /etc/pki/nssdb -add "OpenSC" -libfile /usr/lib64/opensc-pkcs11.so

 

Configuration for PKINIT

If the console prompts for the SmartCard PIN but displays

ipaclient login: demosc1
Pin for PIV Card:
Login incorrect

it is possible that the authentication fails trying to acquire a Kerberos ticket with PKINIT. In this case, login with username/password to the IdM host and try to manually perform kinit in order to get more information:

root@ipaclient$ kinit -X X509_user_identity='PKCS11:opensc-pkcs11.so' demosc1

 

If  the command outputs the following:

kinit: Pre-authentication failed: Failed to verify own certificate (depth 1): self signed certificate in certificate chain while getting initial credentials

then check the content of /etc/krb5.conf on the IdM host. The realms section must contain a configuration for ipadomain with pkinit_anchors:

[realms]
 IPADOMAIN.COM = {
 pkinit_anchors = FILE:/var/lib/ipa-client/pki/kdc-ca-bundle.pem
 pkinit_pool = FILE:/var/lib/ipa-client/pki/ca-bundle.pem

}

The file defined in pkinit_anchors must exist, be readable and contain the certificate of the CA which signed the SmartCard certificate. If it is not the case, run the following commands on any IPA server:

root@ipaserver$ ipa-cacert-manage install -n SmartCardCA -t CT,C,C -p $DM_PWD ca.pem
root@ipaserver$ ipa-certupdate

And run the ipa-certupdate command on all IdM hosts in order to download the certificate.

If the kinit command output the following:

kinit: Certificate mismatch while getting initial credentials

check that the SmartCard certificate is associated to the username provided in the console (see mapping between a SmartCard certificate and an IdM user).

Troubleshooting: ssh to an IdM host with a SmartCard

IdM allows to perform ssh from a non-enrolled host into an IdM enrolled host, using Smart Card authentication instead of ssh authorized keys. The ssh command would be the following to log as demosc1 into the host ipaclient.ipadomain.com:

localuser@localhost$ ssh -I /usr/lib64/opensc-pkcs11.so -l demosc1 ipaclient.ipadomain.com
Enter PIN for 'PIV_II (PIV Card Holder pin)':

The -I option specifies a PKCS#11 shared library, and -l the username on the remote host.

 

Configuration of the local host

First check that the local host is properly configured for Smart Cards. The opensc package must be installed, and the the SmartCard daemon must be running.

localuser@localhost$ sudo dnf install opensc
localuser@localhost$ sudo systemctl start pcscd.service pcscd.socket

 

Configuration of the remote (IdM) host

When IdM is properly configured, ssh will prompt for the SmartCard PIN and authenticate the user. If there is an issue with the certificate, ssh will revert to another authentication type (private keys or username/password).

In this case, enable debug logs for ssh authentication on IdM host. Edit /etc/sssd/sssd.conf and add the following line in [ssh] section:

[ssh]
debug_level = 9

then restart sssd using

root@ipaclient$ systemctl restart sssd

The logs will be located on the IdM host in /var/log/sssd/sssd_ssh.log.

 

The Smart Card CA is not trusted by SSSD

If you see the following in /var/log/sssd/sssd_ssh.log:

[sssd[ssh]] [cert_to_ssh_key] (0x0020): CERT_VerifyCertificateNow failed [-8179].
[sssd[ssh]] [get_valid_certs_keys] (0x0040): cert_to_ssh_key failed, ignoring.

then it means that the CA that signed the Smart Card certificate is not trusted. The trusted certs are stored in /etc/pki/nssdb and can be found using:

root@ipaclient$ certutil -L -d /etc/pki/nssdb

Certificate Nickname Trust Attributes     SSL,S/MIME,JAR/XPI

SmartCardCA                               CT,C,C

 

If the CA cert is missing, add it using

root@ipaclient$ certutil -A -d /etc/pki/nssdb -n SmartCardCA -t CT,C,C -i ca.pem

 

The user is not an IdM user

If the ssh operation does not log any line in /var/log/sssd/sssd_ssh.log, it probably means that the supplied user name is not a user defined in IdM. You can check with:

root@ipaclient$ ipa user-find demosc1
---------------
0 users matched
---------------
----------------------------
Number of entries returned 0
----------------------------

Check that you provided the right user name, or define an IdM user and associate the SmartCard certificate with this user.

 

The certificate is not mapped to the IdM user

If you see the following in /var/log/sssd/sssd_ssh.log:

Found 1 entries in domain ipadomain.com

but the authentication fails, check that the SmartCard certificate is associated to the provided username (refer to mapping between a SmartCard certificate and an IdM user)

Troubleshooting: Authentication to IdM WebGUI with a SmartCard

IdM web GUI can be accessed at the following url: https://ipaserver.ipadomain.com/ipa/ui

The authentication can be done either through Kerberos, by providing a username and password, or with a certificate. If the certificate authentication fails, the issue can either come from your local browser configuration, or from IdM configuration.

The browser does not prompt for the SmartCard PIN

In this case, it is likely that your browser is not properly configured for Smart Card authentication. Please refer to the browser documentation.

 

The browser prompts for the SmartCard PIN but authentication fails

The issue is likely to be a configuration problem on IdM server. The file /var/log/http/error_log will be your best friend to diagnose and fix the issue.

The root CA is not trusted by IdM server

If you see the following in /var/log/http/error_log:

[:error] [pid 50892] Re-negotiation handshake failed: Not accepted by client!?
[:error] [pid 50892] SSL Library Error: -12285 Unable to find the certificate or key necessary for authentication

then it means that the CA that issued your Smart Card certificate is not trusted by Apache httpd server. You need to run the following command on IdM master:

root@ipaserver$ ipa-cacert-manage install -n SmartCardCA -t CT,C,C -p $DM_PWD ca.pem
root@ipaserver$ ipa-certupdate
root@ipaserver$ systemctl restart httpd

The first command adds the Smart Card CA as a trusted CA into IdM. The second command installs the certificate in the various databases used by IdM, especially in /etc/httpd/alias used by Apache. The third command restarts Apache Web server.

The ipa-certupdate step must be run on all IdM hosts, and Apache must be restarted on all IdM servers.

 

Apache is not allowed to authenticate on behalf of a client

If you see the following log in /var/log/http/error_log:

[auth_gssapi:error] [pid 55807] [client 10.40.204.99:60644] GSS ERROR gss_init_sec_context(): [Unspecified GSS failure. Minor code may provide more information (Credential cache is empty)], referer: https://ipaserver.ipadomain.com/ipa/ui/
[:error] [pid 55743] ipa: INFO: 401 Unauthorized: KRB5CCNAME not set

then it means that you forgot to configure apache for delegation. You need to run the following command:

root@ipaserver$ ipa service-mod --ok-to-auth-as-delegate=True HTTP/$(hostname)
root@ipaserver$ systemctl restart httpd

on each IdM server.

 

The SmartCard certificate does not match any IdM user

If you see the following log in /var/log/http/error_log:

[lookup_identity:error] [pid 69382] [client 10.40.204.99:39400] lookup_user_by_certificate failed [dbus_connection_send_with_reply_and_block(org.freedesktop.sssd.infopipe.Users.FindByNameAndCertificate)]: [User not found], referer: https://ipaserver.ipadomain.com/ipa/ui/
[lookup_identity:error] [pid 69382] [client 10.40.204.99:39400] lookup_user_by_certificate cleared r->user, referer: https://ipaserver.ipadomain.com/ipa/ui/
[core:error] [pid 69382] [client 10.40.204.99:39400] AH00027: No authentication done but request not allowed without authentication for /ipa/session/login_x509. Authentication not configured?, referer: https://ipaserver.ipadomin.com/ipa/ui/

then it means that IPA did not find any user associated to the provided certificate. Check  mapping between a SmartCard certificate and an IdM user.

 

The SmartCard certificate matches more than one user

If you see the following log in /var/log/http/error_log:

[lookup_identity:error] [pid 70244] [client 10.40.204.99:39458] lookup_user_by_certificate failed [dbus_connection_send_with_reply_and_block(org.freedesktop.sssd.infopipe.Users.FindByNameAndCertificate)]: [More than one user found. Use ListByCertificate to get all.], referer: https://ipaserver.ipadomain.com/ipa/ui/
[lookup_identity:error] [pid 70244] [client 10.40.204.99:39458] lookup_user_by_certificate cleared r->user, referer: https://ipaserver.ipadomain.com/ipa/ui/
[core:error] [pid 70244] [client 10.40.204.99:39458] AH00027: No authentication done but request not allowed without authentication for /ipa/session/login_x509. Authentication not configured?, referer: https://ipaserver.ipadomain.com/ipa/ui/

then check if the certificate is mapped to a single user using

root@ipaserver$ ipa certmap-match cert.pem
--------------
1 user matched
--------------
 Domain: IPADOMAIN.COM
 User logins: demosc1
----------------------------
Number of entries returned 1
----------------------------

If the certificate matches multiple users, you need to specify the username in the Web GUI.

Apache mod_lookup_identity badly configured

If you see the following in /var/log/http/error_log:

[lookup_identity:error] [pid 70069] [client 10.40.204.99:39444] lookup_user_by_certificate failed [dbus_connection_send_with_reply_and_block(org.freedesktop.sssd.infopipe.Users.FindByNameAndCertificate)]: [More than one user found. Use ListByCertificate to get all.], referer: https://ipaserver.ipadomain/ipa/ui/
[lookup_identity:error] [pid 70069] [client 10.40.204.99:39444] lookup_user_by_certificate cleared r->user, referer: https://ipaserver.ipadomain.com/ipa/ui/
[core:error] [pid 70069] [client 10.40.204.99:39444] AH00027: No authentication done but request not allowed without authentication for /ipa/session/login_x509. Authentication not configured?, referer: https://ipaserver.ipadomain.com/ipa/ui/

then check that /etc/httpd/conf.d/ipa.conf contains the following:

<Location "/ipa/session/login_x509">
...
 LookupUserByCertificate On
 LookupUserByCertificateParamName "username"
...

 

If you see the following in /var/log/http/error_log:

[auth_gssapi:error] [pid 70144] [client 10.40.204.99:39454] GSS ERROR In S4U2Self: gss_acquire_cred_impersonate_name(): [A required input parameter could not be read, No credentials were supplied, or the credentials were unavailable or inaccessible (Unknown error)], referer: https://ipaserver.ipadomain.com/ipa/ui/
[:error] [pid 70141] ipa: INFO: 401 Unauthorized: KRB5CCNAME not set

then check that /etc/httpd/conf.d/ipa.conf contains the following:

<Location "/ipa/session/login_x509">
...
 LookupUserByCertificate On
 LookupUserByCertificateParamName "username"
...

FreeIPA: troubleshooting SmartCard authentication

RHEL 7.4 beta is now available, delivering a new version of IPA which contains the support for Smart Card authentication. This feature allows to use a certificate contained in a SmartCard in order to login to IdM WebUI, to ssh to an IdM-enrolled host, or to login to the console or Gnome Desktop Manager of an IdM-enrolled host.

This feature is really powerful but may also seem difficult to troubleshoot. I will explain where to look for additional information when authentication fails, and how to fix the most common issues.

The information is split into posts specific to each authentication method:

 

 

Design a site like this with WordPress.com
Get started