active-directory - name - ldap base dn ou
Sintaxis de consulta de raíz LDAP para buscar más de una OU específica (5)
Necesito ejecutar una única consulta LDAP que buscará a través de dos unidades de organización específicas (OU) en la consulta raíz, sin embargo, estoy teniendo problemas. He intentado las siguientes consultas a continuación y ninguno fue exitoso:
(|(OU=Staff,DC=my,DC=super,DC=org)(OU=Vendors,DC=my,DC=super,DC=org))
((OU=Staff,DC=my,DC=super,DC=org) | (OU=Vendors,DC=my,DC=super,DC=org))
Mi pregunta es; ¿es posible consultar más de una única unidad organizativa en una sola consulta? Suponiendo que es la sintaxis adecuada para este tipo de expresión en la consulta LDAP raíz.
¡¡¡Usted puede!!! En resumen usa esto como la cadena de conexión:
ldap://<host>:3268/DC=<my>,DC=<domain>?cn
junto con su filtro de búsqueda, por ejemplo
(&(sAMAccountName={0})(&((objectCategory=person)(objectclass=user)(mail=*)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(memberOf:1.2.840.113556.1.4.1941:=CN=<some-special-nested-group>,OU=<ou3>,OU=<ou2>,OU=<ou1>,DC=<dc3>,DC=<dc2>,DC=<dc1>))))
Eso buscará en el llamado Catálogo Global , que había estado disponible fuera de la caja en nuestro entorno.
En lugar de las otras versiones conocidas / comunes (o combinaciones de las mismas) que NO funcionaron en nuestro entorno con varias unidades organizativas:
ldap://<host>/DC=<my>,DC=<domain>
ldap://<host>:389/DC=<my>,DC=<domain> (standard port)
ldap://<host>/OU=<someOU>,DC=<my>,DC=<domain>
ldap://<host>/CN=<someCN>,DC=<my>,DC=<domain>
ldap://<host>/(|(OU=<someOU1>)(OU=<someOU2>)),DC=<my>,DC=<domain> (search filters here shouldn''t work at all by definition)
(Soy un desarrollador, no un gurú de AD / LDAP :) Maldición, he estado buscando esta solución en todas partes durante casi 2 días y casi me he rendido, acostumbrándome a la idea de que podría tener que implementar este escenario muy común a mano ( con Jasperserver / Spring security (/ Tomcat)). (Entonces, esto será un recordatorio si alguien más o yo debería tener este problema nuevamente en el futuro: O))
Aquí algunos otros temas relacionados que encontré durante mi investigación que en su mayoría fueron de poca ayuda:
- La solución oculta en un comentario de LarreDo de 2006.
- Algunas preguntas de Microsoft sobre las mejores prácticas acerca de cómo diseñar su organización en el directorio , indicando que el uso de varias unidades organizativas de alto nivel en compañías más grandes no son inusuales ni adecuadas.
- Tim Wong (2011) agregó que esto puede ser un problema de nombres de DNS sin resolución en ForestDNSZones (parte del dominio de nivel superior AD usado)
- código de ejemplo para implementarlo a mano cuando se usa la seguridad Spring (por ejemplo, también se usa en Jasper)
- John Morrissey (2012) sugirió que podría estar relacionado con algunas configuraciones de seguridad y podría funcionar si usa TLS (supongo que si el servidor LDAP quiere restringir tales búsquedas globales de conexiones no seguras, lo que no parecería una buena opción) de medio horneado) seguridad me acerco)
- awatkins (2012) utilizó algún enfoque de piratería en algún código mod_ldap.c (de cualquier software)
Y aquí proporcionaré nuestra configuración anonimizada de LDAP de Tomcat en caso de que sea de utilidad ( /var/lib/tomcat7/webapps/jasperserver/WEB-INF/applicationContext-externalAUTH-LDAP.xml
):
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<!-- ############ LDAP authentication ############ - Sample configuration
of external authentication via an external LDAP server. -->
<bean id="proxyAuthenticationProcessingFilter"
class="com.jaspersoft.jasperserver.api.security.externalAuth.BaseAuthenticationProcessingFilter">
<property name="authenticationManager">
<ref local="ldapAuthenticationManager" />
</property>
<property name="externalDataSynchronizer">
<ref local="externalDataSynchronizer" />
</property>
<property name="sessionRegistry">
<ref bean="sessionRegistry" />
</property>
<property name="internalAuthenticationFailureUrl" value="/login.html?error=1" />
<property name="defaultTargetUrl" value="/loginsuccess.html" />
<property name="invalidateSessionOnSuccessfulAuthentication"
value="true" />
<property name="migrateInvalidatedSessionAttributes" value="true" />
</bean>
<bean id="proxyAuthenticationSoapProcessingFilter"
class="com.jaspersoft.jasperserver.api.security.externalAuth.DefaultAuthenticationSoapProcessingFilter">
<property name="authenticationManager" ref="ldapAuthenticationManager" />
<property name="externalDataSynchronizer" ref="externalDataSynchronizer" />
<property name="invalidateSessionOnSuccessfulAuthentication"
value="true" />
<property name="migrateInvalidatedSessionAttributes" value="true" />
<property name="filterProcessesUrl" value="/services" />
</bean>
<bean id="proxyRequestParameterAuthenticationFilter"
class="com.jaspersoft.jasperserver.war.util.ExternalRequestParameterAuthenticationFilter">
<property name="authenticationManager">
<ref local="ldapAuthenticationManager" />
</property>
<property name="externalDataSynchronizer" ref="externalDataSynchronizer" />
<property name="authenticationFailureUrl">
<value>/login.html?error=1</value>
</property>
<property name="excludeUrls">
<list>
<value>/j_spring_switch_user</value>
</list>
</property>
</bean>
<bean id="proxyBasicProcessingFilter"
class="com.jaspersoft.jasperserver.api.security.externalAuth.ExternalAuthBasicProcessingFilter">
<property name="authenticationManager" ref="ldapAuthenticationManager" />
<property name="externalDataSynchronizer" ref="externalDataSynchronizer" />
<property name="authenticationEntryPoint">
<ref local="basicProcessingFilterEntryPoint" />
</property>
</bean>
<bean id="proxyAuthenticationRestProcessingFilter"
class="com.jaspersoft.jasperserver.api.security.externalAuth.DefaultAuthenticationRestProcessingFilter">
<property name="authenticationManager">
<ref local="ldapAuthenticationManager" />
</property>
<property name="externalDataSynchronizer">
<ref local="externalDataSynchronizer" />
</property>
<property name="filterProcessesUrl" value="/rest/login" />
<property name="invalidateSessionOnSuccessfulAuthentication"
value="true" />
<property name="migrateInvalidatedSessionAttributes" value="true" />
</bean>
<bean id="ldapAuthenticationManager" class="org.springframework.security.providers.ProviderManager">
<property name="providers">
<list>
<ref local="ldapAuthenticationProvider" />
<ref bean="${bean.daoAuthenticationProvider}" />
<!--anonymousAuthenticationProvider only needed if filterInvocationInterceptor.alwaysReauthenticate
is set to true <ref bean="anonymousAuthenticationProvider"/> -->
</list>
</property>
</bean>
<bean id="ldapAuthenticationProvider"
class="org.springframework.security.providers.ldap.LdapAuthenticationProvider">
<constructor-arg>
<bean
class="org.springframework.security.providers.ldap.authenticator.BindAuthenticator">
<constructor-arg>
<ref local="ldapContextSource" />
</constructor-arg>
<property name="userSearch" ref="userSearch" />
</bean>
</constructor-arg>
<constructor-arg>
<bean
class="org.springframework.security.ldap.populator.DefaultLdapAuthoritiesPopulator">
<constructor-arg index="0">
<ref local="ldapContextSource" />
</constructor-arg>
<constructor-arg index="1">
<value></value>
</constructor-arg>
<property name="groupRoleAttribute" value="cn" />
<property name="convertToUpperCase" value="true" />
<property name="rolePrefix" value="ROLE_" />
<property name="groupSearchFilter"
value="(&(member={0})(&(objectCategory=Group)(objectclass=group)(cn=my-nested-group-name)))" />
<property name="searchSubtree" value="true" />
<!-- Can setup additional external default roles here <property name="defaultRole"
value="LDAP"/> -->
</bean>
</constructor-arg>
</bean>
<bean id="userSearch"
class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
<constructor-arg index="0">
<value></value>
</constructor-arg>
<constructor-arg index="1">
<value>(&(sAMAccountName={0})(&((objectCategory=person)(objectclass=user)(mail=*)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(memberOf:1.2.840.113556.1.4.1941:=CN=my-nested-group-name,OU=ou3,OU=ou2,OU=ou1,DC=dc3,DC=dc2,DC=dc1))))
</value>
</constructor-arg>
<constructor-arg index="2">
<ref local="ldapContextSource" />
</constructor-arg>
<property name="searchSubtree">
<value>true</value>
</property>
</bean>
<bean id="ldapContextSource"
class="com.jaspersoft.jasperserver.api.security.externalAuth.ldap.JSLdapContextSource">
<constructor-arg value="ldap://myhost:3268/DC=dc3,DC=dc2,DC=dc1?cn" />
<!-- manager user name and password (may not be needed) -->
<property name="userDn" value="CN=someuser,OU=ou4,OU=1,DC=dc3,DC=dc2,DC=dc1" />
<property name="password" value="somepass" />
<!--End Changes -->
</bean>
<!-- ############ LDAP authentication ############ -->
<!-- ############ JRS Synchronizer ############ -->
<bean id="externalDataSynchronizer"
class="com.jaspersoft.jasperserver.api.security.externalAuth.ExternalDataSynchronizerImpl">
<property name="externalUserProcessors">
<list>
<ref local="externalUserSetupProcessor" />
<!-- Example processor for creating user folder -->
<!--<ref local="externalUserFolderProcessor"/> -->
</list>
</property>
</bean>
<bean id="abstractExternalProcessor"
class="com.jaspersoft.jasperserver.api.security.externalAuth.processors.AbstractExternalUserProcessor"
abstract="true">
<property name="repositoryService" ref="${bean.repositoryService}" />
<property name="userAuthorityService" ref="${bean.userAuthorityService}" />
<property name="tenantService" ref="${bean.tenantService}" />
<property name="profileAttributeService" ref="profileAttributeService" />
<property name="objectPermissionService" ref="objectPermissionService" />
</bean>
<bean id="externalUserSetupProcessor"
class="com.jaspersoft.jasperserver.api.security.externalAuth.processors.ExternalUserSetupProcessor"
parent="abstractExternalProcessor">
<property name="userAuthorityService">
<ref bean="${bean.internalUserAuthorityService}" />
</property>
<property name="defaultInternalRoles">
<list>
<value>ROLE_USER</value>
</list>
</property>
<property name="organizationRoleMap">
<map>
<!-- Example of mapping customer roles to JRS roles -->
<entry>
<key>
<value>ROLE_MY-NESTED-GROUP-NAME</value>
</key>
<!-- JRS role that the <key> external role is mapped to -->
<value>ROLE_USER</value>
</entry>
</map>
</property>
</bean>
<!--bean id="externalUserFolderProcessor" class="com.jaspersoft.jasperserver.api.security.externalAuth.processors.ExternalUserFolderProcessor"
parent="abstractExternalProcessor"> <property name="repositoryService" ref="${bean.unsecureRepositoryService}"/>
</bean -->
<!-- ############ JRS Synchronizer ############ -->
Después de hablar con un experto en LDAP, no es posible de esta manera. Una consulta no puede buscar más de un DC u OU.
Sus opciones son:
- Ejecutar más de 1 consulta y analizar el resultado.
- Use un filtro para encontrar los usuarios / objetos deseados basados en un atributo diferente, como un grupo de AD o por nombre.
Es sencillo. Solo cambia el puerto. Use 3268 en lugar de 389. Si su nombre de dominio DOMAIN.LOCAL , en la búsqueda, coloque DC = DOMINIO, DC = LOCAL
Puerto 3268: este puerto se usa para consultas específicamente dirigidas al catálogo global. Las solicitudes LDAP enviadas al puerto 3268 se pueden usar para buscar objetos en todo el bosque. Sin embargo, solo se pueden devolver los atributos marcados para la replicación en el catálogo global.
Puerto 389: este puerto se utiliza para solicitar información desde el controlador de dominio. Las solicitudes LDAP enviadas al puerto 389 se pueden usar para buscar objetos solo dentro del dominio principal del catálogo global. Sin embargo, la aplicación puede obtener todos los atributos de los objetos buscados.
La respuesta es NO, no puedes. ¿Por qué?
Debido a que el estándar LDAP describe una BÚSQUEDA LDAP como tipo de función con 4 parámetros:
- El nodo donde debería comenzar la búsqueda, que es un nombre distintivo (DN)
- Los atributos que quieres que te devuelvan.
- La profundidad de la búsqueda (base, un nivel, subárbol)
- El filtro
Usted está interesado en el filtro. here tiene un resumen (es proporcionado por Microsoft para Active Directory, es de un estándar). El filtro está compuesto, de forma booleana, por expresión del tipo Attribute Operator Value
.
Así que el filtro que das no significa nada.
En el punto de vista teórico, existe ExtensibleMatch que permite construir filtros en la ruta del DN, pero no es compatible con Active Directory.
Por lo que sé, tiene que usar un atributo en AD para hacer la distinción para los usuarios en las dos unidades organizativas.
Puede ser cualquier atributo discriminador existente o, por ejemplo, el atributo denominado OU que se hereda de la clase organiserPerson. puede configurarlo (no es automático y no se mantendrá si mueve a los usuarios) con "personal" para algunos usuarios y "proveedores" para otros y ellos usan el filtro:
(&(objectCategory=person)(|(ou=staff)(ou=vendors)))
No creo que esto sea posible con AD. Lo único que sé de este atributo distinguido es que contiene la pieza de unidad organizativa en la que está intentando buscar, por lo que necesitará un comodín para obtener resultados para los objetos que se encuentran debajo de esas unidades organizativas. Desafortunadamente, el carácter comodín no es compatible con los DN.
Si es posible, realmente me gustaría hacer esto en 2 consultas usando OU = Personal ... y OU = Proveedores ... como los DN base.