LDAP Identity Stores

Overview

LDAP identity stores allow ISE to authenticate users against external LDAP directories like FreeIPA, OpenLDAP, or other LDAPv3-compliant servers.

ISE ERS API for LDAP requires the full XML schema with all connection settings fields. Minimal XML payloads return "Resource Initialization Failed(10)" even when connectivity works.

API Endpoints

Core Operations

Operation Method Endpoint

Create

POST

/ers/config/ldap

Get-All

GET

/ers/config/ldap

Get-By-Id

GET

/ers/config/ldap/{id}

Get-By-Name

GET

/ers/config/ldap/name/{name}

Update

PUT

/ers/config/ldap/{id}

Delete

DELETE

/ers/config/ldap/{id}

Get Version

GET

/ers/config/ldap/versioninfo

Connection Testing

Operation Method Endpoint

test-bind-primary

PUT

/ers/config/ldap/{id}/test

test-bind-secondary

PUT

/ers/config/ldap/{id}/test-secondary

get-hosts

GET

/ers/config/ldap/{id}/hosts

Certificate Operations

Operation Method Endpoint

get-issuerca-certificates

GET

/ers/config/ldap/issuercacertificates

get-rootca-certificates

GET

/ers/config/ldap/rootcacertificates

Group Operations

Operation Method Endpoint

Get Groups

GET

/ers/config/ldap/{id}/groups

Complete Attribute Reference

Root Attributes

Attribute Type Required Default Description

name

String

Yes

Resource name

id

String

No

Resource UUID (mandatory for update)

description

String

No

Description

enablePasswordChangeLDAP

Boolean

No

Allow password changes via LDAP

generalSettings (ERSLdapGeneralSettings)

Attribute Type Required Default Description

userObjectClass

String

No

User object class (e.g., person)

userNameAttribute

String

No

Username attribute (e.g., uid)

groupNameAttribute

String

No

Group name attribute (e.g., cn)

groupObjectClass

String

No

Group object class (e.g., groupOfNames)

groupMapAttributeName

String

No

Group membership attribute (e.g., memberOf)

certificate

String

No

Certificate attribute name

schema

Enum

Yes

Sun Directory Server

Values: CUSTOM, ACTIVE_DIRECTORY, SUN, NOVELL

groupMemberReference

Enum

No

UserName

Values: USERNAME, DN

groupReference

Enum

No

Values: GROUP_TO_USER, USER_TO_GROUP

generalSettings > userInfoAttributes

Attribute Type Required Description

firstName

String

No

First name LDAP attribute

department

String

No

Department LDAP attribute

lastName

String

No

Last name LDAP attribute

organizationalUnit

String

No

OU LDAP attribute

jobTitle

String

No

Job title LDAP attribute

locality

String

No

Locality LDAP attribute

email

String

No

Email LDAP attribute

stateOrProvince

String

No

State LDAP attribute

telephone

String

No

Telephone LDAP attribute

country

String

No

Country LDAP attribute

streetAddress

String

No

Street address LDAP attribute

additionalAttribute

String

No

Additional custom attribute

connectionSettings (ERSLdapConnectionSettings)

Attribute Type Required Default Description

failoverToSecondary

Boolean

No

false

Enable failover to secondary server

failbackRetryDelay

Integer

No

5

Minutes to wait before failback retry

specifyServerForEachISENode

Boolean

No

false

Configure per-PSN LDAP servers

alwaysAccessPrimaryFirst

Boolean

No

false

Always try primary server first

connectionSettings > primaryServer (ERSLdapServerSettings)

Attribute Type Required Default Description

hostName

String

Yes

LDAP server FQDN or IP

port

Integer

Yes

389

LDAP port (389 or 636)

maxConnections

Integer

No

20

Maximum concurrent connections

serverTimeout

Integer

No

10

Connection timeout in seconds

useAdminAccess

Boolean

No

false

Use admin credentials for queries

adminDN

String

No

Bind DN for LDAP queries

adminPassword

String

No

Bind password

enableSecureConnection

Boolean

No

false

Use LDAPS (TLS)

enableServerIdentityCheck

Boolean

No

false

Verify server certificate CN

trustCertificate

String

Yes (for LDAPS)

Trust certificate name

issuerCACertificate

String

No

Issuer CA certificate name

enableForceReconnect

Boolean

No

false

Force periodic reconnection

forceReconnectTime

Integer

No

0

Reconnect interval in minutes

connectionSettings > secondaryServer

Same attributes as primaryServer, all optional.

connectionSettings > ldapNodeData (List)

For per-PSN LDAP server configuration:

Attribute Type Required Default Description

name

String

Yes

name

ISE node name

primaryHostname

String

Yes

ipaddress

Primary LDAP server for this PSN

secondaryHostname

String

No

ipaddress

Secondary LDAP server for this PSN

primaryPort

Integer

Yes

389

Primary server port

secondaryPort

Integer

No

389

Secondary server port

directoryOrganization (ERSLdapDirectoryOrganization)

Attribute Type Required Default Description

userDirectorySubtree

String

Yes

Base DN for user searches

groupDirectorySubtree

String

Yes

Base DN for group searches

macFormat

Enum

Yes

DASH

Values: DASH, COLON, NO_DELIMITER

stripPrefix

Boolean

No

false

Strip prefix from username

stripSuffix

String

No

false

Strip suffix from username

prefixSeparator

String

No

//

Prefix separator character

suffixSeparator

String

No

Suffix separator character

groups (ERSLdapGroups)

Attribute Type Required Description

groupsNames

List

No

List of LDAP group DNs to import

attributes (ERSLdapAttributes)

Attribute Type Required Description

attributes

List

No

List of custom LDAP attributes to retrieve

Naming Convention

Follow the -01/-02 pattern for LDAP identity sources to support future HA deployments:

Name Description Use Case

ipa-01

FreeIPA LDAP identity source for EAP-TTLS authentication

Primary FreeIPA server

ipa-02

FreeIPA LDAP identity source for EAP-TTLS authentication (replica)

Secondary FreeIPA replica

openldap-01

OpenLDAP identity source

Generic LDAP server

ad-ldap-01

Active Directory LDAP (non-native)

AD via LDAP instead of native AD join

Full XML Schema (Working)

ISE requires the complete XML structure. Verified working with ISE 3.4:

<?xml version="1.0" encoding="UTF-8"?>
<ns0:ersLdap xmlns:ns0="identitystores.ers.ise.cisco.com"
             xmlns:xs="http://www.w3.org/2001/XMLSchema"
             xmlns:ns1="ers.ise.cisco.com"
             xmlns:ers="ers.ise.cisco.com"
             name="ipa-01"
             description="FreeIPA LDAP identity source for EAP-TTLS authentication">
   <connectionSettings>
      <alwaysAccessPrimaryFirst>true</alwaysAccessPrimaryFirst>
      <failbackRetryDelay>5</failbackRetryDelay>
      <failoverToSecondary>false</failoverToSecondary>
      <primaryServer>
         <adminDN>uid=ise-bind,cn=users,cn=accounts,dc=inside,dc=domusdigitalis,dc=dev</adminDN>
         <adminPassword>YOUR_PASSWORD_HERE</adminPassword>
         <enableForceReconnect>false</enableForceReconnect>
         <enableSecureConnection>false</enableSecureConnection>
         <enableServerIdentityCheck>false</enableServerIdentityCheck>
         <forceReconnectTime>20</forceReconnectTime>
         <hostName>10.50.1.100</hostName>
         <issuerCACertificate></issuerCACertificate>
         <maxConnections>20</maxConnections>
         <port>389</port>
         <serverTimeout>10</serverTimeout>
         <trustCertificate></trustCertificate>
         <useAdminAccess>true</useAdminAccess>
      </primaryServer>
      <specifyServerForEachISENode>false</specifyServerForEachISENode>
   </connectionSettings>
   <directoryOrganization>
      <groupDirectorySubtree>cn=groups,cn=accounts,dc=inside,dc=domusdigitalis,dc=dev</groupDirectorySubtree>
      <macFormat>DASH</macFormat>
      <prefixSeparator>\</prefixSeparator>
      <stripPrefix>false</stripPrefix>
      <stripSuffix>false</stripSuffix>
      <suffixSeparator> </suffixSeparator>
      <userDirectorySubtree>cn=users,cn=accounts,dc=inside,dc=domusdigitalis,dc=dev</userDirectorySubtree>
   </directoryOrganization>
   <enablePasswordChangeLDAP>false</enablePasswordChangeLDAP>
   <generalSettings>
      <certificate>userCertificate</certificate>
      <groupMapAttributeName>memberOf</groupMapAttributeName>
      <groupMemberReference>USERNAME</groupMemberReference>
      <groupNameAttribute>cn</groupNameAttribute>
      <groupObjectClass>groupOfNames</groupObjectClass>
      <groupReference>GROUP_TO_USER</groupReference>
      <schema>CUSTOM</schema>
      <userInfoAttributes>
         <country></country>
         <department></department>
         <email>mail</email>
         <firstName>givenName</firstName>
         <lastName>sn</lastName>
         <locality></locality>
         <organizationalUnit></organizationalUnit>
         <stateOrProvince></stateOrProvince>
         <streetAddress></streetAddress>
         <telephone>telephoneNumber</telephone>
      </userInfoAttributes>
      <userNameAttribute>uid</userNameAttribute>
      <userObjectClass>person</userObjectClass>
   </generalSettings>
</ns0:ersLdap>

Create LDAP Store (FreeIPA)

Step 1: Create Dedicated Bind Account in FreeIPA

# On FreeIPA server
echo "YourSecurePassword" | ipa user-add ise-bind \
  --first="ISE" \
  --last="Bind Account" \
  --password

Step 2: Create XML File

cat > /tmp/ipa-01-ldap.xml << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<ns0:ersLdap xmlns:ns0="identitystores.ers.ise.cisco.com"
             xmlns:xs="http://www.w3.org/2001/XMLSchema"
             xmlns:ns1="ers.ise.cisco.com"
             xmlns:ers="ers.ise.cisco.com"
             name="ipa-01"
             description="FreeIPA LDAP identity source for EAP-TTLS authentication">
   <connectionSettings>
      <alwaysAccessPrimaryFirst>true</alwaysAccessPrimaryFirst>
      <failbackRetryDelay>5</failbackRetryDelay>
      <failoverToSecondary>false</failoverToSecondary>
      <primaryServer>
         <adminDN>uid=ise-bind,cn=users,cn=accounts,dc=dc=inside,dc=domusdigitalis,dc=dev</adminDN>
         <adminPassword>YOUR_PASSWORD</adminPassword>
         <enableForceReconnect>false</enableForceReconnect>
         <enableSecureConnection>false</enableSecureConnection>
         <enableServerIdentityCheck>false</enableServerIdentityCheck>
         <forceReconnectTime>20</forceReconnectTime>
         <hostName>10.50.1.100</hostName>
         <issuerCACertificate></issuerCACertificate>
         <maxConnections>20</maxConnections>
         <port>389</port>
         <serverTimeout>10</serverTimeout>
         <trustCertificate></trustCertificate>
         <useAdminAccess>true</useAdminAccess>
      </primaryServer>
      <specifyServerForEachISENode>false</specifyServerForEachISENode>
   </connectionSettings>
   <directoryOrganization>
      <groupDirectorySubtree>cn=groups,cn=accounts,dc=dc=inside,dc=domusdigitalis,dc=dev</groupDirectorySubtree>
      <macFormat>DASH</macFormat>
      <prefixSeparator>\</prefixSeparator>
      <stripPrefix>false</stripPrefix>
      <stripSuffix>false</stripSuffix>
      <suffixSeparator> </suffixSeparator>
      <userDirectorySubtree>cn=users,cn=accounts,dc=dc=inside,dc=domusdigitalis,dc=dev</userDirectorySubtree>
   </directoryOrganization>
   <enablePasswordChangeLDAP>false</enablePasswordChangeLDAP>
   <generalSettings>
      <certificate>userCertificate</certificate>
      <groupMapAttributeName>memberOf</groupMapAttributeName>
      <groupMemberReference>USERNAME</groupMemberReference>
      <groupNameAttribute>cn</groupNameAttribute>
      <groupObjectClass>groupOfNames</groupObjectClass>
      <groupReference>GROUP_TO_USER</groupReference>
      <schema>CUSTOM</schema>
      <userInfoAttributes>
         <country></country>
         <department></department>
         <email>mail</email>
         <firstName>givenName</firstName>
         <lastName>sn</lastName>
         <locality></locality>
         <organizationalUnit></organizationalUnit>
         <stateOrProvince></stateOrProvince>
         <streetAddress></streetAddress>
         <telephone>telephoneNumber</telephone>
      </userInfoAttributes>
      <userNameAttribute>uid</userNameAttribute>
      <userObjectClass>person</userObjectClass>
   </generalSettings>
</ns0:ersLdap>
EOF

Step 3: Submit to ISE

curl -k -X POST "https://${ISE_PAN_IP}:9060/ers/config/ldap" \
  -H "Content-Type: application/xml" \
  -H "Accept: application/xml" \
  -u "${ISE_API_USER}:${ISE_API_PASS}" \
  -d @/tmp/ipa-01-ldap.xml \
  -w "\nHTTP_STATUS: %\{http_code\}\n"

# Expected: HTTP_STATUS: 201

Step 4: Cleanup

shred -vuzn 3 /tmp/ipa-01-ldap.xml

List LDAP Stores

curl -k -s "https://${ISE_PAN_IP}:9060/ers/config/ldap" \
  -H "Accept: application/json" \
  -u "${ISE_API_USER}:${ISE_API_PASS}" | jq '.SearchResult.resources'

Test Primary Connection

LDAP_ID=$(curl -k -s "https://${ISE_PAN_IP}:9060/ers/config/ldap" \
  -H "Accept: application/json" \
  -u "${ISE_API_USER}:${ISE_API_PASS}" | jq -r '.SearchResult.resources[] | select(.name=="ipa-01") | .id')

curl -k -X PUT "https://${ISE_PAN_IP}:9060/ers/config/ldap/${LDAP_ID}/test" \
  -H "Accept: application/xml" \
  -u "${ISE_API_USER}:${ISE_API_PASS}"

Test Secondary Connection

curl -k -X PUT "https://${ISE_PAN_IP}:9060/ers/config/ldap/${LDAP_ID}/test-secondary" \
  -H "Accept: application/xml" \
  -u "${ISE_API_USER}:${ISE_API_PASS}"

Get Hosts

curl -k -s "https://${ISE_PAN_IP}:9060/ers/config/ldap/${LDAP_ID}/hosts" \
  -H "Accept: application/json" \
  -u "${ISE_API_USER}:${ISE_API_PASS}"

Get Groups

curl -k -s "https://${ISE_PAN_IP}:9060/ers/config/ldap/${LDAP_ID}/groups" \
  -H "Accept: application/json" \
  -u "${ISE_API_USER}:${ISE_API_PASS}" | jq '.groups[]'

Get Available Certificates

Root CA Certificates

curl -k -s "https://${ISE_PAN_IP}:9060/ers/config/ldap/rootcacertificates" \
  -H "Accept: application/json" \
  -u "${ISE_API_USER}:${ISE_API_PASS}"

Issuer CA Certificates

curl -k -s "https://${ISE_PAN_IP}:9060/ers/config/ldap/issuercacertificates" \
  -H "Accept: application/json" \
  -u "${ISE_API_USER}:${ISE_API_PASS}"

Get Version Info

curl -k -s "https://${ISE_PAN_IP}:9060/ers/config/ldap/versioninfo" \
  -H "Accept: application/json" \
  -u "${ISE_API_USER}:${ISE_API_PASS}"

Common Errors

Error Cause Solution

Resource Initialization Failed(10)

Missing required XML fields

Use the full schema with all connectionSettings fields

Schema validation exception

Using JSON format

Use XML format with correct namespace

cvc-complex-type.2.4.a

Missing or wrong elements

Add all required elements per Cisco schema

Invalid credentials (49)

Wrong bind password

Verify LDAP bind works: ldapsearch -x -H ldap://host -D "dn" -w "pass"

Bad Ber Tag

ISE trying TLS on non-TLS port

Use port 636 with enableSecureConnection=true, or check firewall

LDAPS Configuration

For secure LDAP (port 636), add certificate references:

<primaryServer>
   ...
   <enableSecureConnection>true</enableSecureConnection>
   <enableServerIdentityCheck>true</enableServerIdentityCheck>
   <port>636</port>
   <trustCertificate>FreeIPA-CA</trustCertificate>
   <issuerCACertificate>FreeIPA-CA</issuerCACertificate>
   ...
</primaryServer>

The certificate names must match certificates already imported into ISE’s Trusted Certificates store. Use the get-rootca-certificates and get-issuerca-certificates endpoints to list available certificates.

FreeIPA-Specific Settings

Setting FreeIPA Value

User Search Base

cn=users,cn=accounts,dc=REALM

Group Search Base

cn=groups,cn=accounts,dc=REALM

User Object Class

person or posixAccount

Group Object Class

groupOfNames or posixGroup

Username Attribute

uid

Group Name Attribute

cn

Group Membership

memberOf

Schema

CUSTOM

Multi-PSN Configuration

When specifyServerForEachISENode is true, add ldapNodeData entries:

<connectionSettings>
   ...
   <ldapNodeData>
      <name>ise-01</name>
      <primaryHostname>10.50.1.100</primaryHostname>
      <primaryPort>389</primaryPort>
      <secondaryHostname>10.50.1.101</secondaryHostname>
      <secondaryPort>389</secondaryPort>
   </ldapNodeData>
   <ldapNodeData>
      <name>ise-02</name>
      <primaryHostname>10.50.1.101</primaryHostname>
      <primaryPort>389</primaryPort>
      <secondaryHostname>10.50.1.100</secondaryHostname>
      <secondaryPort>389</secondaryPort>
   </ldapNodeData>
   <specifyServerForEachISENode>true</specifyServerForEachISENode>
</connectionSettings>

High Availability Configuration

For HA setups with secondary server:

<connectionSettings>
   <alwaysAccessPrimaryFirst>true</alwaysAccessPrimaryFirst>
   <failbackRetryDelay>5</failbackRetryDelay>
   <failoverToSecondary>true</failoverToSecondary>
   <primaryServer>
      <hostName>ldap-primary.example.com</hostName>
      <port>389</port>
      ...
   </primaryServer>
   <secondaryServer>
      <hostName>ldap-secondary.example.com</hostName>
      <port>389</port>
      <maxConnections>20</maxConnections>
      <serverTimeout>10</serverTimeout>
      <useAdminAccess>true</useAdminAccess>
      <adminDN>uid=ise-bind,cn=users,cn=accounts,dc=example,dc=com</adminDN>
      <adminPassword>PASSWORD</adminPassword>
      <enableSecureConnection>false</enableSecureConnection>
      <enableServerIdentityCheck>false</enableServerIdentityCheck>
      <trustCertificate></trustCertificate>
      <issuerCACertificate></issuerCACertificate>
      <enableForceReconnect>false</enableForceReconnect>
      <forceReconnectTime>0</forceReconnectTime>
   </secondaryServer>
   <specifyServerForEachISENode>false</specifyServerForEachISENode>
</connectionSettings>

Group Import Configuration

ISE can import LDAP groups for use in authorization policies. Groups must be specified during LDAP store creation - the ERS API PUT update for groups returns HTTP 500.

Create LDAP Store with Groups

Include the <groups> section in the initial POST request:

<?xml version="1.0" encoding="UTF-8"?>
<ns0:ersLdap xmlns:ns0="identitystores.ers.ise.cisco.com"
             xmlns:xs="http://www.w3.org/2001/XMLSchema"
             xmlns:ns1="ers.ise.cisco.com"
             xmlns:ers="ers.ise.cisco.com"
             name="ipa-01"
             description="FreeIPA LDAP identity source for EAP-TTLS authentication">
   <connectionSettings>
      <!-- ... connection settings ... -->
   </connectionSettings>
   <directoryOrganization>
      <!-- ... directory settings ... -->
   </directoryOrganization>
   <enablePasswordChangeLDAP>false</enablePasswordChangeLDAP>
   <generalSettings>
      <!-- ... general settings ... -->
   </generalSettings>
   <groups>
      <groupsNames>cn=printers,cn=groups,cn=accounts,dc=inside,dc=domusdigitalis,dc=dev</groupsNames>
      <groupsNames>cn=ipausers,cn=groups,cn=accounts,dc=inside,dc=domusdigitalis,dc=dev</groupsNames>
   </groups>
</ns0:ersLdap>

Update Groups (DELETE + POST Pattern)

Since PUT updates fail for groups, use the delete-and-recreate pattern:

# 1. Get current LDAP store ID
LDAP_ID=$(curl -k -s "https://${ISE_PAN_IP}:9060/ers/config/ldap" \
  -H "Accept: application/json" \
  -u "${ISE_API_USER}:${ISE_API_PASS}" | \
  jq -r '.SearchResult.resources[] | select(.name=="ipa-01") | .id')

# 2. Delete existing store
curl -k -X DELETE "https://${ISE_PAN_IP}:9060/ers/config/ldap/${LDAP_ID}" \
  -H "Accept: application/xml" \
  -u "${ISE_API_USER}:${ISE_API_PASS}"

# 3. Recreate with updated groups
curl -k -X POST "https://${ISE_PAN_IP}:9060/ers/config/ldap" \
  -H "Content-Type: application/xml" \
  -H "Accept: application/xml" \
  -u "${ISE_API_USER}:${ISE_API_PASS}" \
  -d @/tmp/ipa-01-with-groups.xml

Live Network Caution: Deleting and recreating LDAP stores will temporarily disrupt authentications using that identity source. Schedule during maintenance windows.

Verify Imported Groups

After creation, verify groups are imported:

curl -k -s "https://${ISE_PAN_IP}:9060/ers/config/ldap/${LDAP_ID}/groups" \
  -H "Accept: application/json" \
  -u "${ISE_API_USER}:${ISE_API_PASS}" | jq '.groups[]'

Authentication Policy Integration

Before authorization rules can use LDAP groups, the LDAP identity source must be added to the authentication policy.

Step 1: Create Authentication Rule

Add authentication rule to use ipa-01 LDAP as the identity source for EAP-TTLS:

# Create authentication rule using ipa-01 LDAP
# Policy Set: Domus-Secure 802.1X
# Current rules: Rank 0-2 are EAP-TLS and iPSK - add at rank 3
netapi ise add-auth-rule "Domus-Secure 802.1X" \
  "FreeIPA_EAP-TTLS_Auth" \
  "ipa-01" \
  --dict "Network Access" \
  --attr "EapTunnel" \
  --value "EAP-TTLS" \
  --rank 3

Step 2: Verify Authentication Rule

netapi ise get-auth-rules "Domus-Secure 802.1X"
Actual Output (2026-02-15)
╭──────────────────────────────────────────────────────────────────────────────────────────╮
│ Authentication Rules                                                                     │
╰────────────────────────────────── Domus-Secure 802.1X ───────────────────────────────────╯
    #    Rule Name                Identity Source       If Fail    If Not Found    State
    0    BYOD_Certificate_Auth    BYOD_Cert_Profile     REJECT     REJECT          enabled
    1    EAP_TLS_Certificate_…    AD_Cert_Profile       REJECT     REJECT          enabled
    2    iPSK AuthC               iPSKManager           REJECT     REJECT          enabled
    3    FreeIPA_EAP-TTLS_Auth    ipa-01                REJECT     REJECT          enabled  <-- FreeIPA LDAP
    4    Default                  Internal Endpoints    REJECT     CONTINUE        enabled

Authentication vs Authorization

  • Authentication Rule: Determines which identity source validates credentials (e.g., ipa-01 LDAP)

  • Authorization Rule: Determines what access the user gets after authentication (VLAN, dACL)

Both are required for FreeIPA printer authentication to work.

Authorization Policy Integration

After the authentication rule uses ipa-01 as the identity source, create authorization rules to assign profiles based on group membership.

Target Policy Set

For FreeIPA printer authentication via EAP-TTLS on wireless:

Attribute Value

Policy Set

Domus-Secure 802.1X

Policy Set ID

9557d91c-591b-4d8d-9898-657a62f28d76

Condition

Called-Station-ID endsWith 'Domus-Secure'

Service

Default Network Access

Use Case

Corporate wireless EAP-TLS authentication

Workflow Overview

FreeIPA Group (printers)
        ↓
ISE LDAP Store (ipa-01) imports group
        ↓
Authorization Rule matches: ipa-01:ExternalGroups contains "printers"
        ↓
Authorization Profile assigned (e.g., Domus_IoT_Profile)
        ↓
Device gets VLAN + dACL

Step 3: Create Authorization Profile for Printers

# Create authorization profile with DATA_VLAN (VLAN 10)
# Domus-Secure is 802.1X Enterprise on VLAN 10
netapi ise create-authz-profile FreeIPA_Printers \
  --vlan DATA_VLAN \
  --descr "FreeIPA-authenticated printers - EAP-TTLS on Domus-Secure"

Step 4: Verify Authorization Profile

netapi ise get-authz-profile FreeIPA_Printers
Expected Output
╭─────────────────────────────────────────────────────────────────────────────╮
│ Authorization Profile: FreeIPA_Printers                                     │
╰─────────────────────────────────────────────────────────────────────────────╯
  name        FreeIPA_Printers
  vlan        {'nameID': 'DATA_VLAN', 'tagID': 10}
  accessType  ACCESS_ACCEPT

Step 5: Create Authorization Rule

# Add authorization rule matching FreeIPA printers group
# Policy Set: Domus-Secure 802.1X (wireless EAP-TLS)
netapi ise add-authz-rule "Domus-Secure 802.1X" \
  "FreeIPA_Printers_EAP-TTLS" \
  "FreeIPA_Printers" \
  --dict "ipa-01" \
  --attr "ExternalGroups" \
  --value "cn=printers,cn=groups,cn=accounts,dc=inside,dc=domusdigitalis,dc=dev" \
  --operator "contains" \
  --rank 2

Step 6: Verify Authorization Rule

netapi ise get-authz-rules "Domus-Secure 802.1X"
Actual Output (2026-02-15)
╭──────────────────────────────────────────────────────────────────────────────────────────╮
│ Authorization Rules                                                                      │
╰────────────────────────────────── Domus-Secure 802.1X ───────────────────────────────────╯
    #    Rule Name                Condition               Profile(s)               State
    0    BYOD_Registered_Devi…    EndPoints:BYODRegis…    Domus_BYOD_Full_Acce…    enabled
                                  equals 'Yes'
    1    EAP_TLS_Trusted_Users    Network                 Domus_Secure_Profile     enabled
                                  Access:EapAuthentic…
                                  equals 'EAP-TLS'
    2    FreeIPA_Printers_EAP…    ipa-01:ExternalGrou…    FreeIPA_Printers         enabled  <-- FreeIPA printers
                                  contains
                                  'cn=printers,cn=gro…
    3    iPSK Trusted Data        iPSKManager:Externa…    iPSK-Auth                enabled
                                  equals 'Trust-Data'
    4    Default                  (default)               DenyAccess               enabled

Rule Ranking Strategy

Rule Ordering is Critical for Live Networks

ISE evaluates authorization rules top-to-bottom. First match wins.

Rank Rule Purpose

0

Linux_EAP-TLS_Permit

Existing - Linux workstations with EAP-TLS

1

Linux_Admin_EAP-TLS

Existing - Admin workstations (disabled)

2

FreeIPA_Printers_EAP-TTLS

NEW - Printers via FreeIPA LDAP

3

Linux_Posture_*

Future - Posture checks

N

Default

Catch-all deny

Add new rules at rank 2 or higher to avoid disrupting existing EAP-TLS rules.

Compound Conditions (EAP-TTLS + Group)

For more specific matching:

netapi ise add-authz-rule "Domus-Secure 802.1X" \
  "FreeIPA_Printers_EAP-TTLS" \
  "FreeIPA_Printers" \
  --and "Network Access:EapTunnel:equals:EAP-TTLS" \
  --and "ipa-01:ExternalGroups:contains:cn=printers,cn=groups,cn=accounts,dc=inside,dc=domusdigitalis,dc=dev" \
  --rank 2

Complete FreeIPA Integration Example

Full workflow for adding a printer to FreeIPA and ISE:

1. Create FreeIPA User for Printer

# On FreeIPA server
ipa user-add brother-mfc \
  --first="Brother" \
  --last="MFC-L2750DW" \
  --password

2. Add Printer to FreeIPA Group

ipa group-add-member printers --users=brother-mfc

3. Create ISE LDAP Store with Groups

# Create XML with groups included
cat > /tmp/ipa-01-with-groups.xml << 'XMLEOF'
<?xml version="1.0" encoding="UTF-8"?>
<ns0:ersLdap xmlns:ns0="identitystores.ers.ise.cisco.com"
             xmlns:xs="http://www.w3.org/2001/XMLSchema"
             xmlns:ns1="ers.ise.cisco.com"
             xmlns:ers="ers.ise.cisco.com"
             name="ipa-01"
             description="FreeIPA LDAP identity source for EAP-TTLS authentication">
   <connectionSettings>
      <alwaysAccessPrimaryFirst>true</alwaysAccessPrimaryFirst>
      <failbackRetryDelay>5</failbackRetryDelay>
      <failoverToSecondary>false</failoverToSecondary>
      <primaryServer>
         <adminDN>uid=ise-bind,cn=users,cn=accounts,dc=inside,dc=domusdigitalis,dc=dev</adminDN>
         <adminPassword>YOUR_ISE_BIND_PASSWORD</adminPassword>
         <enableForceReconnect>false</enableForceReconnect>
         <enableSecureConnection>false</enableSecureConnection>
         <enableServerIdentityCheck>false</enableServerIdentityCheck>
         <forceReconnectTime>20</forceReconnectTime>
         <hostName>10.50.1.100</hostName>
         <issuerCACertificate></issuerCACertificate>
         <maxConnections>20</maxConnections>
         <port>389</port>
         <serverTimeout>10</serverTimeout>
         <trustCertificate></trustCertificate>
         <useAdminAccess>true</useAdminAccess>
      </primaryServer>
      <specifyServerForEachISENode>false</specifyServerForEachISENode>
   </connectionSettings>
   <directoryOrganization>
      <groupDirectorySubtree>cn=groups,cn=accounts,dc=inside,dc=domusdigitalis,dc=dev</groupDirectorySubtree>
      <macFormat>DASH</macFormat>
      <prefixSeparator>\</prefixSeparator>
      <stripPrefix>false</stripPrefix>
      <stripSuffix>false</stripSuffix>
      <suffixSeparator> </suffixSeparator>
      <userDirectorySubtree>cn=users,cn=accounts,dc=inside,dc=domusdigitalis,dc=dev</userDirectorySubtree>
   </directoryOrganization>
   <enablePasswordChangeLDAP>false</enablePasswordChangeLDAP>
   <generalSettings>
      <certificate>userCertificate</certificate>
      <groupMapAttributeName>memberOf</groupMapAttributeName>
      <groupMemberReference>USERNAME</groupMemberReference>
      <groupNameAttribute>cn</groupNameAttribute>
      <groupObjectClass>groupOfNames</groupObjectClass>
      <groupReference>GROUP_TO_USER</groupReference>
      <schema>CUSTOM</schema>
      <userInfoAttributes>
         <country></country>
         <department></department>
         <email>mail</email>
         <firstName>givenName</firstName>
         <lastName>sn</lastName>
         <locality></locality>
         <organizationalUnit></organizationalUnit>
         <stateOrProvince></stateOrProvince>
         <streetAddress></streetAddress>
         <telephone>telephoneNumber</telephone>
      </userInfoAttributes>
      <userNameAttribute>uid</userNameAttribute>
      <userObjectClass>person</userObjectClass>
   </generalSettings>
   <groups>
      <groupsNames>cn=printers,cn=groups,cn=accounts,dc=inside,dc=domusdigitalis,dc=dev</groupsNames>
      <groupsNames>cn=ipausers,cn=groups,cn=accounts,dc=inside,dc=domusdigitalis,dc=dev</groupsNames>
   </groups>
</ns0:ersLdap>
XMLEOF

# Submit to ISE
curl -k -X POST "https://${ISE_PAN_IP}:9060/ers/config/ldap" \
  -H "Content-Type: application/xml" \
  -H "Accept: application/xml" \
  -u "${ISE_API_USER}:${ISE_API_PASS}" \
  -d @/tmp/ipa-01-with-groups.xml \
  -w "\nHTTP_STATUS: %\{http_code\}\n"

# Cleanup
shred -vuzn 3 /tmp/ipa-01-with-groups.xml

4. Create Authentication Rule

# Create authentication rule to use ipa-01 for EAP-TTLS
netapi ise add-auth-rule "Domus-Secure 802.1X" \
  "FreeIPA_EAP-TTLS_Auth" \
  "ipa-01" \
  --dict "Network Access" \
  --attr "EapTunnel" \
  --value "EAP-TTLS" \
  --rank 3

5. Create Authorization Profile

# Create authorization profile for printers (DATA_VLAN = VLAN 10)
netapi ise create-authz-profile FreeIPA_Printers \
  --vlan DATA_VLAN \
  --descr "FreeIPA-authenticated printers - EAP-TTLS on Domus-Secure"

6. Create Authorization Rule

# Add authorization rule to Domus-Secure 802.1X policy set
netapi ise add-authz-rule "Domus-Secure 802.1X" \
  "FreeIPA_Printers_EAP-TTLS" \
  "FreeIPA_Printers" \
  --dict "ipa-01" \
  --attr "ExternalGroups" \
  --value "cn=printers,cn=groups,cn=accounts,dc=inside,dc=domusdigitalis,dc=dev" \
  --operator "contains" \
  --rank 2

7. Configure Printer for EAP-TTLS

On the printer, configure 802.1X with: - SSID: Domus-Secure - EAP Method: EAP-TTLS - Inner Authentication: MSCHAPv2 (requires NT hashes - see below) - Identity: brother-mfc - Password: (the password set in FreeIPA)

Known Issue: TLS 1.0 on Older Printers

Many printers (including Brother MFC-J5945DW) only support TLS 1.0, which ISE blocks by default.

Error 11639
Failure Reason: 11639 Client requested TLSv1.0 that is not allowed
Root cause: Client requested TLSv1.0 as the highest version. This version is not allowed by ISE.

Fix: Enable TLS 1.0 on ISE (Administration → System → Settings → Security Settings → TLS Versions)

MSCHAPv2 Requires NT Hashes in FreeIPA

FreeIPA doesn’t store NT hashes by default. For MSCHAPv2 inner authentication:

# On FreeIPA server - enable AD trust (stores NT hashes)
ipa-adtrust-install --add-sids

# Reset user password to generate NT hash
ipa user-mod brother-mfc --password

Without NT hashes, only PAP works as inner auth (password sent in cleartext inside encrypted TTLS tunnel).

8. Verify Authentication

# Check ISE authentication rules
netapi ise get-auth-rules "Domus-Secure 802.1X"

# Check ISE authorization rules
netapi ise get-authz-rules "Domus-Secure 802.1X"

# Check ISE live logs for printer MAC
netapi ise mnt session "PRINTER_MAC_ADDRESS"

# Or via ISE GUI
# Operations → RADIUS → Live Logs

References

  • Active Directory Integration (ad.adoc)

  • ISE Identity Store Sequences (infra-ops)

  • FreeIPA Deployment runbook (infra-ops)

  • Authorization Policy Guide (ise-ops)