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 |
|
Get-All |
GET |
|
Get-By-Id |
GET |
|
Get-By-Name |
GET |
|
Update |
PUT |
|
Delete |
DELETE |
|
Get Version |
GET |
|
Connection Testing
| Operation | Method | Endpoint |
|---|---|---|
test-bind-primary |
PUT |
|
test-bind-secondary |
PUT |
|
get-hosts |
GET |
|
Complete Attribute Reference
Root Attributes
| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
|
String |
Yes |
Resource name |
|
|
String |
No |
Resource UUID (mandatory for update) |
|
|
String |
No |
Description |
|
|
Boolean |
No |
Allow password changes via LDAP |
generalSettings (ERSLdapGeneralSettings)
| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
|
String |
No |
User object class (e.g., |
|
|
String |
No |
Username attribute (e.g., |
|
|
String |
No |
Group name attribute (e.g., |
|
|
String |
No |
Group object class (e.g., |
|
|
String |
No |
Group membership attribute (e.g., |
|
|
String |
No |
Certificate attribute name |
|
|
Enum |
Yes |
Sun Directory Server |
Values: |
|
Enum |
No |
UserName |
Values: |
|
Enum |
No |
Values: |
generalSettings > userInfoAttributes
| Attribute | Type | Required | Description |
|---|---|---|---|
|
String |
No |
First name LDAP attribute |
|
String |
No |
Department LDAP attribute |
|
String |
No |
Last name LDAP attribute |
|
String |
No |
OU LDAP attribute |
|
String |
No |
Job title LDAP attribute |
|
String |
No |
Locality LDAP attribute |
|
String |
No |
Email LDAP attribute |
|
String |
No |
State LDAP attribute |
|
String |
No |
Telephone LDAP attribute |
|
String |
No |
Country LDAP attribute |
|
String |
No |
Street address LDAP attribute |
|
String |
No |
Additional custom attribute |
connectionSettings (ERSLdapConnectionSettings)
| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
|
Boolean |
No |
false |
Enable failover to secondary server |
|
Integer |
No |
5 |
Minutes to wait before failback retry |
|
Boolean |
No |
false |
Configure per-PSN LDAP servers |
|
Boolean |
No |
false |
Always try primary server first |
connectionSettings > primaryServer (ERSLdapServerSettings)
| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
|
String |
Yes |
LDAP server FQDN or IP |
|
|
Integer |
Yes |
389 |
LDAP port (389 or 636) |
|
Integer |
No |
20 |
Maximum concurrent connections |
|
Integer |
No |
10 |
Connection timeout in seconds |
|
Boolean |
No |
false |
Use admin credentials for queries |
|
String |
No |
Bind DN for LDAP queries |
|
|
String |
No |
Bind password |
|
|
Boolean |
No |
false |
Use LDAPS (TLS) |
|
Boolean |
No |
false |
Verify server certificate CN |
|
String |
Yes (for LDAPS) |
Trust certificate name |
|
|
String |
No |
Issuer CA certificate name |
|
|
Boolean |
No |
false |
Force periodic reconnection |
|
Integer |
No |
0 |
Reconnect interval in minutes |
connectionSettings > ldapNodeData (List)
For per-PSN LDAP server configuration:
| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
|
String |
Yes |
name |
ISE node name |
|
String |
Yes |
ipaddress |
Primary LDAP server for this PSN |
|
String |
No |
ipaddress |
Secondary LDAP server for this PSN |
|
Integer |
Yes |
389 |
Primary server port |
|
Integer |
No |
389 |
Secondary server port |
directoryOrganization (ERSLdapDirectoryOrganization)
| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
|
String |
Yes |
Base DN for user searches |
|
|
String |
Yes |
Base DN for group searches |
|
|
Enum |
Yes |
DASH |
Values: |
|
Boolean |
No |
false |
Strip prefix from username |
|
String |
No |
false |
Strip suffix from username |
|
String |
No |
// |
Prefix separator character |
|
String |
No |
Suffix separator character |
Naming Convention
Follow the -01/-02 pattern for LDAP identity sources to support future HA deployments:
| Name | Description | Use Case |
|---|---|---|
|
FreeIPA LDAP identity source for EAP-TTLS authentication |
Primary FreeIPA server |
|
FreeIPA LDAP identity source for EAP-TTLS authentication (replica) |
Secondary FreeIPA replica |
|
OpenLDAP identity source |
Generic LDAP server |
|
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
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
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: |
Bad Ber Tag |
ISE trying TLS on non-TLS port |
Use port 636 with |
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 |
FreeIPA-Specific Settings
| Setting | FreeIPA Value |
|---|---|
User Search Base |
|
Group Search Base |
|
User Object Class |
|
Group Object Class |
|
Username Attribute |
|
Group Name Attribute |
|
Group Membership |
|
Schema |
|
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. |
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"
╭──────────────────────────────────────────────────────────────────────────────────────────╮
│ 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
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 |
|
Policy Set ID |
|
Condition |
|
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
╭─────────────────────────────────────────────────────────────────────────────╮
│ 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"
╭──────────────────────────────────────────────────────────────────────────────────────────╮
│ 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.
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
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.
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