Configs we used for 1 AD server with multiple OU's

Daniel McDonald daniel.mcdonald at umb.edu
Thu Aug 25 17:00:38 EDT 2016


I didnt see alot of documentation for authenticating against multiple 
OU's in AD in shibboleth IdP v3.2.1 so I thought i'd share my setup in 
case anyone else is trying to do the same thing. In our AD these are all 
top level OU's and we have some OU's that we dont want searched so we 
cant use subtreeSearch. This is based on the example from the shibboleth 
LDAPAuthnConfiguration doc titled "Complete example with DN resolvers 
and authentication handlers for bindSearch" which is for 2 AD servers 
with 2 directories each. While this worked for us, we had 1 AD server 
with 4 directories so we changed it a bit to fit us better. After making 
the changes to ldap-authn-config.xml and ldap.properties we could login 
OK, but attributes werent being released. I realized it was because 
attribute-resolver.xml by default only had 1 dataconnector to release 
attributes for 1 directory so we had to modify that to add our other 3 
dataconnectors as failovers.

Active Directory doesnt support extensible match rules else we could of 
just done 
idp.authn.LDAP.userFilter=(&(|(ou:dn:=people)(ou:dn:=guests))(uid={user})) 
and saved ourselves alot of work.  :)

I actually dont know java beans (or really shibboleth for that matter), 
so if someone sees a more elegant way to do this plz let me know.

Added this config for adAuthenticator at the end of 
ldap-authn-config.xml, left the existing defined configs untouched:

     <!-- Active Directory Configuration for 1 server with 4 OU's -->
     <bean id="adAuthenticator" class="org.ldaptive.auth.Authenticator" 
p:authenticationResponseHandlers-ref="authenticationResponseHandler"
p:resolveEntryOnFailure="%{idp.authn.LDAP.resolveEntryOnFailure:false}">
         <constructor-arg index="0" ref="formatDnResolver" />
         <constructor-arg index="1" ref="authHandler" />
     </bean>
     <bean id="authenticationResponseHandler" 
class="org.ldaptive.auth.ext.ActiveDirectoryAuthenticationResponseHandler" 
/>

<!-- Define Directory1 connection pool -->
     <bean id="adConnectionPool" 
class="org.ldaptive.pool.BlockingConnectionPool" abstract="true"
         p:blockWaitTime="%{idp.pool.LDAP.blockWaitTime:3000}"
         p:poolConfig-ref="adPoolConfig"
         p:pruneStrategy-ref="adPruneStrategy"
         p:validator-ref="adSearchValidator"
p:failFastInitialize="%{idp.pool.LDAP.failFastInitialize:false}" />
     <bean id="adPoolConfig" class="org.ldaptive.pool.PoolConfig"
         p:minPoolSize="%{idp.pool.LDAP.minSize:3}"
         p:maxPoolSize="%{idp.pool.LDAP.maxSize:10}"
p:validateOnCheckOut="%{idp.pool.LDAP.validateOnCheckout:false}"
p:validatePeriodically="%{idp.pool.LDAP.validatePeriodically:true}"
         p:validatePeriod="%{idp.pool.LDAP.validatePeriod:300}" />
     <bean id="adPruneStrategy" class="org.ldaptive.pool.IdlePruneStrategy"
         p:prunePeriod="%{idp.pool.LDAP.prunePeriod:300}"
         p:idleTime="%{idp.pool.LDAP.idleTime:600}" />
     <bean id="adSearchValidator" 
class="org.ldaptive.pool.SearchValidator" />
<!-- Directory1 connection pool settings -->
     <bean id="adConnectionConfig" class="org.ldaptive.ConnectionConfig" 
abstract="true"
         p:ldapUrl="%{idp.authn.LDAP.ldapURL}"
         p:useStartTLS="%{idp.authn.LDAP.useStartTLS:true}"
         p:useSSL="%{idp.authn.LDAP.useSSL:false}"
         p:connectTimeout="%{idp.authn.LDAP.connectTimeout:3000}"
         p:sslConfig-ref="adSslConfig" />
     <alias name="%{idp.authn.LDAP.sslConfig:certificateTrust}" 
alias="adSslConfig" />
<!-- ldap.properties "idp.authn.LDAP.authenticator = 
adAggregateAuthenticator" -->
     <bean id="adAggregateAuthenticator" 
class="org.ldaptive.auth.Authenticator"
p:authenticationResponseHandlers-ref="adAuthenticationResponseHandler">
         <constructor-arg index="0" ref="adAggregateDnResolver" />
         <constructor-arg index="1" ref="adAggregateAuthHandler" />
     </bean>
     <bean id="adAuthenticationResponseHandler" 
class="org.ldaptive.auth.ext.ActiveDirectoryAuthenticationResponseHandler" 
/>
     <bean id="adAggregateDnResolver" 
class="org.ldaptive.auth.AggregateDnResolver">
         <constructor-arg index="0" ref="adDnResolvers" />
     </bean>
     <bean id="adAggregateAuthHandler" 
class="org.ldaptive.auth.AggregateDnResolver$AuthenticationHandler"
         p:authenticationHandlers-ref="adAuthHandlers" />
     <util:map id="adDnResolvers">
         <entry key="directory_filter1" value-ref="adDnResolver1" />
         <entry key="directory_filter2" value-ref="adDnResolver2" />
         <entry key="directory_filter3" value-ref="adDnResolver3" />
         <entry key="directory_filter4" value-ref="adDnResolver4" />
     </util:map>
<!-- Define four DN resolvers that bind search against the Directory -->
     <bean id="adDnResolver1" 
class="org.ldaptive.auth.PooledSearchDnResolver"
         p:baseDn="%{idp.authn.LDAP.baseDN1}"
         p:subtreeSearch="%{idp.authn.LDAP.subtreeSearch:false}"
         p:userFilter="%{idp.authn.LDAP.userFilter}"
p:connectionFactory-ref="adBindSearchPooledConnectionFactory" />
     <bean id="adDnResolver2" 
class="org.ldaptive.auth.PooledSearchDnResolver"
         p:baseDn="%{idp.authn.LDAP.baseDN2}"
         p:subtreeSearch="%{idp.authn.LDAP.subtreeSearch:false}"
         p:userFilter="%{idp.authn.LDAP.userFilter}"
p:connectionFactory-ref="adBindSearchPooledConnectionFactory" />
     <bean id="adDnResolver3" 
class="org.ldaptive.auth.PooledSearchDnResolver"
         p:baseDn="%{idp.authn.LDAP.baseDN3}"
         p:subtreeSearch="%{idp.authn.LDAP.subtreeSearch:false}"
         p:userFilter="%{idp.authn.LDAP.userFilter}"
p:connectionFactory-ref="adBindSearchPooledConnectionFactory" />
     <bean id="adDnResolver4" 
class="org.ldaptive.auth.PooledSearchDnResolver"
         p:baseDn="%{idp.authn.LDAP.baseDN4}"
         p:subtreeSearch="%{idp.authn.LDAP.subtreeSearch:false}"
         p:userFilter="%{idp.authn.LDAP.userFilter}"
p:connectionFactory-ref="adBindSearchPooledConnectionFactory" />
<!-- Define Directory1 Search-pool -->
     <bean id="adBindSearchPooledConnectionFactory" 
class="org.ldaptive.pool.PooledConnectionFactory"
         p:connectionPool-ref="adBindSearchConnectionPool" />
     <bean id="adBindSearchConnectionPool" 
class="org.ldaptive.pool.BlockingConnectionPool"
         parent="adConnectionPool"
         p:connectionFactory-ref="adBindSearchConnectionFactory"
         p:name="adSearch-pool" />
     <bean id="adBindSearchConnectionFactory" 
class="org.ldaptive.DefaultConnectionFactory"
         p:connectionConfig-ref="adBindSearchConnectionConfig" />
     <bean id="adBindSearchConnectionConfig"
         parent="adConnectionConfig"
         p:connectionInitializer-ref="adBindConnectionInitializer" />
     <bean id="adBindConnectionInitializer" 
class="org.ldaptive.BindConnectionInitializer"
         p:bindDn="%{idp.authn.LDAP.bindDN}">
         <property name="bindCredential">
             <bean class="org.ldaptive.Credential">
                 <constructor-arg 
value="%{idp.authn.LDAP.bindDNCredential}" />
             </bean>
         </property>
     </bean>
     <util:map id="adAuthHandlers">
         <entry key="directory_filter1" value-ref="adAuthHandler1" />
         <entry key="directory_filter2" value-ref="adAuthHandler1" />
         <entry key="directory_filter3" value-ref="adAuthHandler1" />
         <entry key="directory_filter4" value-ref="adAuthHandler1" />
     </util:map>
<!-- authentication handler for Directory DN resolver -->
     <bean id="adAuthHandler1" 
class="org.ldaptive.auth.PooledBindAuthenticationHandler"
         p:connectionFactory-ref="adBindPooledConnectionFactory" />
     <bean id="adBindPooledConnectionFactory" 
class="org.ldaptive.pool.PooledConnectionFactory"
         p:connectionPool-ref="adBindConnectionPool" />
     <bean id="adBindConnectionPool" 
class="org.ldaptive.pool.BlockingConnectionPool"
         parent="adConnectionPool"
         p:connectionFactory-ref="adBindConnectionFactory"
         p:name="adBind-pool" />
     <bean id="adBindConnectionFactory" 
class="org.ldaptive.DefaultConnectionFactory"
         p:connectionConfig-ref="adBindConnectionConfig" />
     <bean id="adBindConnectionConfig"
         parent="adConnectionConfig" />

ldap.properties:

# LDAP authentication configuration, see authn/ldap-authn-config.xml
# Note, this doesn't apply to the use of JAAS

## Authenticator strategy, either anonSearchAuthenticator, 
bindSearchAuthenticator, directAuthenticator, adAuthenticator
idp.authn.LDAP.authenticator                   = adAggregateAuthenticator

## Connection properties ##
idp.authn.LDAP.ldapURL                         = 
ldaps://ad1.skool.edu:636 ldaps://ad2.skool.edu:636
idp.authn.LDAP.useStartTLS                     = false
idp.authn.LDAP.useSSL                          = true
idp.authn.LDAP.connectTimeout                  = 3000

## SSL configuration, either jvmTrust, certificateTrust, or keyStoreTrust
idp.authn.LDAP.sslConfig                       = certificateTrust
## If using certificateTrust above, set to the trusted certificate's path
idp.authn.LDAP.trustCertificates                = 
%{idp.home}/credentials/ldap-server.crt
## If using keyStoreTrust above, set to the truststore path
idp.authn.LDAP.trustStore                       = 
%{idp.home}/credentials/ldap-server.truststore

## Return attributes during authentication
## NOTE: there is a separate property used for attribute resolution
idp.authn.LDAP.returnAttributes                 = 
passwordExpirationTime,loginGraceRemaining

## DN resolution properties ##

# Search DN resolution, used by anonSearchAuthenticator, 
bindSearchAuthenticator
# for AD: CN=Users,DC=example,DC=org
#
idp.authn.LDAP.baseDN1                          = OU=folder1,DC=skool,DC=edu
idp.authn.LDAP.baseDN2                          = 
OU=subfolder1,OU=folder2,DC=skool,DC=edu
idp.authn.LDAP.baseDN3                          = OU=folder3,DC=skool,DC=edu
idp.authn.LDAP.baseDN4                          = OU=folder4,DC=skool,DC=edu
idp.authn.LDAP.subtreeSearch                    = false
#idp.authn.LDAP.userFilter                       = (uid={user})
idp.authn.LDAP.userFilter                      = (mail={user})
# bind search configuration
# for AD: idp.authn.LDAP.bindDN=adminuser at domain.com
idp.authn.LDAP.bindDN                           = 
CN=ADadmin,ou=managers,dc=skool,dc=edu
idp.authn.LDAP.bindDNCredential                 = secretsquirrel66!!!

# Format DN resolution, used by directAuthenticator, adAuthenticator
# for AD use idp.authn.LDAP.dnFormat=%s at domain.com
idp.authn.LDAP.dnFormat                         = 
uid=%s,ou=people,dc=example,dc=org

# LDAP attribute configuration, see attribute-resolver.xml
# Note, this likely won't apply to the use of legacy V2 resolver 
configurations
idp.attribute.resolver.LDAP.ldapURL             = %{idp.authn.LDAP.ldapURL}
idp.attribute.resolver.LDAP.baseDN1              = 
%{idp.authn.LDAP.baseDN1:undefined}
idp.attribute.resolver.LDAP.baseDN2              = 
%{idp.authn.LDAP.baseDN2:undefined}
idp.attribute.resolver.LDAP.baseDN3              = 
%{idp.authn.LDAP.baseDN3:undefined}
idp.attribute.resolver.LDAP.baseDN4              = 
%{idp.authn.LDAP.baseDN4:undefined}
idp.attribute.resolver.LDAP.bindDN              = 
%{idp.authn.LDAP.bindDN:undefined}
idp.attribute.resolver.LDAP.bindDNCredential    = 
%{idp.authn.LDAP.bindDNCredential:undefined}
idp.attribute.resolver.LDAP.useStartTLS         = 
%{idp.authn.LDAP.useStartTLS:true}
idp.attribute.resolver.LDAP.trustCertificates   = 
%{idp.authn.LDAP.trustCertificates:undefined}
#idp.attribute.resolver.LDAP.searchFilter        = 
(uid=$resolutionContext.principal)
idp.attribute.resolver.LDAP.searchFilter        = 
(mail=$requestContext.principalName)
idp.attribute.resolver.LDAP.returnAttributes    = 
givenname,mail,miservice,samaccountname,sn

The dataconnectors from attribute-resolver.xml. Basically if the search 
doesnt match in an OU it fails to the next.

<resolver:DataConnector id="myLDAP" xsi:type="dc:LDAPDirectory"
         ldapURL="%{idp.attribute.resolver.LDAP.ldapURL}"
         baseDN="%{idp.attribute.resolver.LDAP.baseDN1}"
         principal="%{idp.attribute.resolver.LDAP.bindDN}"
principalCredential="%{idp.attribute.resolver.LDAP.bindDNCredential}"
         noResultIsError="True"
useStartTLS="%{idp.attribute.resolver.LDAP.useStartTLS::true}">

         <resolver:FailoverDataConnector ref="myLDAP2" />

         <dc:FilterTemplate>
             <![CDATA[
                 %{idp.attribute.resolver.LDAP.searchFilter}
             ]]>
         </dc:FilterTemplate>
<dc:ReturnAttributes>%{idp.attribute.resolver.LDAP.returnAttributes}</dc:ReturnAttributes>
         <dc:LDAPProperty name="java.naming.referral" value="follow"/>
         <dc:StartTLSTrustCredential id="LDAPtoIdPCredential" 
xsi:type="sec:X509ResourceBacked">
<sec:Certificate>%{idp.attribute.resolver.LDAP.trustCertificates}</sec:Certificate>
         </dc:StartTLSTrustCredential>

     </resolver:DataConnector>

     <resolver:DataConnector id="myLDAP2" xsi:type="dc:LDAPDirectory"
         ldapURL="%{idp.attribute.resolver.LDAP.ldapURL}"
         baseDN="%{idp.attribute.resolver.LDAP.baseDN2}"
         principal="%{idp.attribute.resolver.LDAP.bindDN}"
principalCredential="%{idp.attribute.resolver.LDAP.bindDNCredential}"
         noResultIsError="True"
useStartTLS="%{idp.attribute.resolver.LDAP.useStartTLS::true}">

         <resolver:FailoverDataConnector ref="myLDAP3" />
         <dc:FilterTemplate>
             <![CDATA[
                 %{idp.attribute.resolver.LDAP.searchFilter}
             ]]>
         </dc:FilterTemplate>
<dc:ReturnAttributes>%{idp.attribute.resolver.LDAP.returnAttributes}</dc:ReturnAttributes>
         <dc:LDAPProperty name="java.naming.referral" value="follow"/>
         <dc:StartTLSTrustCredential id="LDAPtoIdPCredential" 
xsi:type="sec:X509ResourceBacked">
<sec:Certificate>%{idp.attribute.resolver.LDAP.trustCertificates}</sec:Certificate>
         </dc:StartTLSTrustCredential>

     </resolver:DataConnector>

And so on for myLDAP3 & 4. On The last entry leave out the 
<resolver:FailoverDataConnector>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://shibboleth.net/pipermail/users/attachments/20160825/80dd4a69/attachment-0001.html>


More information about the users mailing list