Directory Sync with idM


#1

Hi everyone,

Is is possible to add users (via Directory Sync) from RedHat idM (essentially FreeIPA)?

I have a team member who has completed the first 2 steps in Directory Sync (Directory Settings and DUO Authentication Proxy) but no groups are available in step 3 (Choose Groups). Instead we see “Note: 79 groups can’t be shown. Please upgrade your Duo Authentication Proxy to show all groups.”

We have the latest version of Duo Authentication Proxy (v2.7.0) installed and the debug log shows successful LDAP STARTTLS connections to our idM server with groups successfully returned.


#2

We have some very specific prerequisites for syncing any OpenLDAP type directory (i.e., an LDAP directory that isn’t Active Directory).

Copied from https://duo.com/docs/ldapsync#prerequisites:

  • Synced groups must have the groupOfNames object class.
  • Synced groups must list their members by DN (directoryName) via themember attribute.
  • Synced groups must have a cn attribute, used as the Duo group name after import.
  • Synced users must have the organizationalPerson object class.

Does RedHat idM support these requirements?

What is the next LDAP search operation after you see a list of groups returned in the Authentication Proxy debug log?


#3

Hi Kristina,

I’m using the default idM settings and I think RedHat idM supports those requirements. Full disclosure, I could be misinterpreting the ldapsearch output below for a test user and test group.

ldapsearch results for the developers group:

SASL/GSSAPI authentication started
SASL username: admin@CORP.TEST.LAB
SASL SSF: 56
SASL data security layer installed.
dn: cn=developers,cn=groups,cn=accounts,dc=corp,dc=test,dc=lab
member: uid=testuser,cn=users,cn=accounts,dc=corp,dc=test,dc=lab        <--- members listed by member attribute
member: uid=testuser1,cn=users,cn=accounts,dc=corp,dc=test,dc=lab        <--- members listed by member attribute
objectClass: top
objectClass: groupofnames        <--- groupOfNames object class
objectClass: nestedgroup
objectClass: ipausergroup
objectClass: ipaobject
objectClass: posixgroup
cn: developers        <--- cn attribute used as Duo group name after import
ipaUniqueID: *****REDACTED*****
gidNumber: 400001

ldapsearch results for the user “testuser”:

SASL/GSSAPI authentication started
SASL username: admin@CORP.TEST.LAB
SASL SSF: 56
SASL data security layer installed.
dn: uid=testuser,cn=users,cn=accounts,dc=corp,dc=test,dc=lab
krbLastAdminUnlock: 20180213122820Z
krbLoginFailedCount: 0
krbLastFailedAuth: 20180213122633Z
telephoneNumber: 1234567890
memberOf: cn=ipausers,cn=groups,cn=accounts,dc=corp,dc=test,dc=lab
memberOf: cn=developers,cn=groups,cn=accounts,dc=corp,dc=test,dc=lab
memberOf: cn=test_user_group1,cn=groups,cn=accounts,dc=corp,dc=test,dc=lab
mobile: 1234567890
ipaUserAuthType: password
krbPasswordExpiration: 20180510203423Z
krbExtraData:: *****REDACTED*****
krbTicketFlags: 128
krbLastPwdChange: 20180209203423Z
employeeType: Staff
mepManagedEntry: cn=testuser,cn=groups,cn=accounts,dc=corp,dc=test,dc=lab
displayName: Test User
uid: testuser
krbCanonicalName: testuser@CORP.TEST.LAB
objectClass: top
objectClass: person
objectClass: organizationalperson        <--- organizationalPerson object class
objectClass: inetorgperson
objectClass: inetuser
objectClass: posixaccount
objectClass: krbprincipalaux
objectClass: krbticketpolicyaux
objectClass: ipaobject
objectClass: ipasshuser
objectClass: ipaSshGroupOfPubKeys
objectClass: mepOriginEntry
objectClass: ipauserauthtypeclass
loginShell: /bin/sh
initials: TU
gecos: Test User
sn: User
homeDirectory: /home/testuser
mail: testuser@corp.test.lab
krbPrincipalName: testuser@CORP.TEST.LAB
givenName: Test
cn: Test User
ipaUniqueID: *****REDACTED*****
uidNumber: 400004
gidNumber: 400004

After the groups are returned, the Authentication Proxy debug log shows a LDAPSearchResultDone message. Snippet of the redacted debug log follows:

2018-02-12T21:27:06+0000 [-] Duo Security Authentication Proxy 2.7.0 - Init Complete
2018-02-12T21:27:06+0000 [-] DRPC Disconnected: no rpc server
2018-02-12T21:27:06+0000 [-] (Re)connecting to service...
2018-02-12T21:27:06+0000 [-] http GET to https://******REDACTED******.duosecurity.com:443/auth/v2/ping: 
2018-02-12T21:27:06+0000 [duoauthproxy.lib.http._DuoHTTPClientFactory#info] Starting factory <_DuoHTTPClientFactory: https://******REDACTED******.duosecurity.com:443/auth/v2/ping>
2018-02-12T21:27:06+0000 [HTTPPageGetter (TLSMemoryBIOProtocol),client] http POST to https://******REDACTED******.duosecurity.com:443/: 
2018-02-12T21:27:06+0000 [duoauthproxy.lib.http._DuoHTTPClientFactory#info] Starting factory <_DuoHTTPClientFactory: https://******REDACTED******.duosecurity.com:443/>
2018-02-12T21:27:06+0000 [duoauthproxy.lib.http._DuoHTTPClientFactory#info] Stopping factory <_DuoHTTPClientFactory: https://******REDACTED******.duosecurity.com:443/auth/v2/ping>
2018-02-12T21:27:18+0000 [duoauthproxy.lib.ldap.client.ADClientFactory#info] Starting factory <duoauthproxy.lib.ldap.client.ADClientFactory object at 0x3262b90>
2018-02-12T21:27:18+0000 [-] C->S LDAPMessage(id=1, value=LDAPStartTLSRequest())
2018-02-12T21:27:19+0000 [ADClientProtocol,client] C<-S LDAPMessage(id=1L, value=LDAPExtendedResponse(resultCode=0L, errorMessage='Start TLS request accepted.Server willing to negotiate SSL.'))
2018-02-12T21:27:19+0000 [ADClientProtocol,client] C->S LDAPMessage(id=2, value=LDAPBindRequest(version=3, dn='uid=duoauthproxysvcuser,cn=users,cn=compat,dc=corp,dc=test,dc=lab', auth='*****', sasl=False))
2018-02-12T21:27:19+0000 [ADClientProtocol,client] C<-S LDAPMessage(id=2L, value=LDAPBindResponse(resultCode=0L))
2018-02-12T21:27:19+0000 [ADClientProtocol,client] C->S LDAPMessage(id=3, value=LDAPSearchRequest(baseObject=u'dc=corp,dc=test,dc=lab', scope=2, derefAliases=0, sizeLimit=0, timeLimit=0, typesOnly=0, filter=LDAPFilter_equalityMatch(attributeDesc=LDAPAttributeDescription(value='objectclass'), assertionValue=LDAPAssertionValue(value='groupofnames')), attributes=['entrydn', 'entryuuid', 'cn']))
2018-02-12T21:27:19+0000 [ADClientProtocol,client] C<-S LDAPMessage(id=3L, value=LDAPSearchResultEntry(objectName='cn=ipausers,cn=groups,cn=accounts,dc=corp,dc=test,dc=lab', attributes=[('cn', ['ipausers'])])
2018-02-12T21:27:19+0000 [ADClientProtocol,client] C<-S LDAPMessage(id=3L, value=LDAPSearchResultEntry(objectName='cn=developers,cn=groups,cn=accounts,dc=corp,dc=test,dc=lab', attributes=[('cn', ['developers'])])
2018-02-12T21:27:19+0000 [ADClientProtocol,client] C<-S LDAPMessage(id=3L, value=LDAPSearchResultDone(resultCode=0L))
2018-02-12T21:27:19+0000 [duoauthproxy.lib.ldap.client.ADClientFactory#info] Stopping factory <duoauthproxy.lib.ldap.client.ADClientFactory object at 0x3262b90>

#4

The LDAP search for group objects is looking for the attributes attributes=['entrydn', 'entryuuid', 'cn'], but the LDAP search result only returns the cn for those groups. It turns out we require all three of those attributes in the search result to present a group for selection in the sync config.

The “Please upgrade your Duo Authentication Proxy to show all groups” message is misleading, and I’ve filed this for correction to a more helpful message. I’ll also add this additional requirement to the OpenLDAP sync page.

Do the entrydn and entryuuid attributes for groups exist in your directory? Unfortunately, we don’t let you specify the source attributes for group searches at this time like you do for users when configuring the sync. I’ve filed this as an enhancement request as well.


#5

This makes sense and explains why LDAP authentications via Duo Access Gateway work but the directory sync functionality using the Authentication Proxy does not.

I ran a few ldapsearch queries to check on the attributes for the developers group… The exact queries were:

  1. ldapsearch -LLL -Y GSSAPI -b dc=corp,dc=test,dc=lab developers
  2. ldapsearch -LLL -Y GSSAPI -b dc=corp,dc=test,dc=lab developers +

entryDN exists in the directory as an operational attribute (only visible from ldapsearch #2 above). I ran a quick test with ldaptor code from StackOverflow and ldaptor appears to treat operational attributes differently from “normal” attributes. That may explain why I’m not seeing the entrydn in the authentication proxy log.

The entryuuid attribute does not appear to be available within the directory. idM/FreeIPA (both use 389ds as the underlying directory server) have a nsUniqueId operational attribute that seems to fulfill the same role.

It looks like other vendors integrating with idM have run into the same issue with entryuuid missing. I’ll keep digging.


#6

@DuoKristina

Is there an additional requirement that synced users must have the memberOf attribute?


#7

Yes, they do. It looked like your ldapsearch output for testuser did include memberof.


#8

I’m evaluating Duo against FreeIPA, and running into this same problem, for what it’s worth.

It seems like with the right permissions, the Duo auth proxy client returns entryDN, but as artemis already point out, there’s no “entryUUID” attribute (“ipaUniqueID” or “nsUniqueId” would be appropriate in FreeIPA).

2018-02-27T17:17:38-0600 [ADClientProtocol,client] C<-S LDAPMessage(id=4L, value=L■■■■(objectName=‘cn=somegroup,cn=groups,cn=accounts,dc=contoso,dc=com’, attributes=[(‘entrydn’, [‘cn=somegroup,cn=groups,cn=accounts,dc=contoso,dc=com’]), (‘cn’, [‘somegroup’])])


#9

Thanks for commenting. We are aware that LDAP directories can vary in what attributes are included in the schema and how customizable they are. When we released LDAP sync late last year we specifically targeted OpenLDAP for the widest compatibility (as that would also work with most OpenLDAP derivatives), but it looks like there’s some incompatibility with 389 DS based directories.

While we may make the group source attributes customizable in the future (as we have done for the user attributes), but for now, the required attributes for LDAP sync are the required attributes.

Please contact Duo Support to submit a feature request for FreeIPA/389 compatibility, or for group attribute mapping. We’ll be looking to those FRs to determine what other directory support to implement in the future.

Thanks for trying Duo!


#10

This is a hack, but I added “entryUUID” as an alternate name for ipaUniqueID in the base schema definition for my FreeIPA instance:

dc1:/etc/dirsrv/slapd-CONTOSO-COM/schema/60basev2.ldif

dn: cn=schema
attributeTypes: (2.16.840.1.113730.3.8.3.1 NAME ( ‘ipaUniqueID’ ‘entryUUID’ ) DESC ‘Unique identifier’ EQUALITY caseIgn
oreMatch ORDERING caseIgnoreOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN ‘IPA v2’ )

The Duo connector seems to be functioning now.


#11

That’s great! Thanks for sharing this workaround.


#12

What permissions did you apply to get entryDN returned?


#13

Aha! I figured it out rgiles. I had to add entrydn as a custom attribute target in System: Read Groups.


#14

Cool; I was lazy for this particular test and gave some pretty wide-ranging permissions.


#15

Even after making this change I am not able to query for entryUUID. There is nothing in the error log that seems relevant to the change, and Duo still gives the same problem described above. Do you have any recommendations to test this schema change? Do I need to do anything with ipa config-mod or ldapmodify?

$ ldapsearch -D uid=blahblah -w secret cn=testgroup entrydn entryuuid cn
# testgroup, groups, accounts, msap.io
dn: cn=testgroup,cn=groups,cn=accounts,dc=msap,dc=io
entrydn: cn=testgroup,cn=groups,cn=accounts,dc=msap,dc=io
cn: testgroup

Otherwise this thread has been very helpful, so thank you!


#16

After you make the change in 60basev2.ldif, you will need to run the following command to commit the schema change:

sudo ipa-ldap-updater -u -schema-file=/etc/dirsrv/slapd-CONTOSO-COM/schema/60basev2.ldif

Then run your ldapsearch command again with an addition sign at the end to retrieve the operational attributes:

ldapsearch -D uid=blahblah -w secret cn=testgroup entrydn entryuuid cn +

On a side note, we’ve observed some weirdness where the directory sync initially works but then on the periodic schedule (every 24 hours), the directory sync attempts to delete all LDAP accounts from Duo. I’m still trying to run down exactly what is going on. Our temp fix has been to disable the Duo authentication proxy service after the initial sync.


#17

You may also need to login to the idM/FreeIPA web interface and navigate to IPA Server | Role Based Access Controls | Permissions | System: Read Groups where you can add “entrydn” under Target | Effective attributes.


#18

@artemis Is it possible that the schema change isn’t persisting, so the group isn’t presenting the expected attributes at the next scheduled sync?

LDAP sync would put users into pending deletion if it thinks the synced group is no longer present in the source directory or was deleted from the configuration. Directory Sync - Troubleshooting and FAQ | Duo Security?