Синтаксис корневого запроса LDAP для поиска более одного определенного подразделения

Мне нужно выполнить один запрос LDAP, который будет выполнять поиск в двух конкретных организационных единицах (OU) в корневом запросе, однако я с этим не согласен. Я пробовал следующие запросы ниже, и ни один из них не был успешным:

(|(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))

Мой вопрос Можно ли запросить более одного подразделения в одном запросе? Предполагая, что это правильный синтаксис для этого типа выражения в корневом запросе LDAP.

6 ответов

Решение

Вы можете!!! Вкратце используйте это как строку подключения:

ldap://<host>:3268/DC=<my>,DC=<domain>?cn

вместе с вашим поисковым фильтром, например

(&(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>))))

Это будет искать в так называемом Глобальном каталоге, который был доступен в нашей среде.

Вместо известных / распространенных других версий (или их комбинаций), которые НЕ работали в нашей среде с несколькими подразделениями:

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)

(Я разработчик, а не гуру AD/LDAP:) Черт, я искал это решение везде почти 2 дня и почти сдался, привыкнув к мысли, что мне, возможно, придется реализовать этот, очевидно, очень распространенный сценарий вручную (с Jasperserver/Spring Security(/Tomcat)). (Так что это будет напоминанием, если у кого-то еще или у меня снова возникнет эта проблема в будущем:O))

Вот некоторые другие связанные темы, которые я нашел во время моего исследования, которые были в основном мало полезны:

И здесь я предоставлю нашу анонимную конфигурацию Tomcat LDAP на случай, если она окажется полезной (/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="(&amp;(member={0})(&amp;(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>(&amp;(sAMAccountName={0})(&amp;((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 ############ -->

Ответ НЕТ, ты не можешь. Зачем?

Поскольку стандарт LDAP описывает LDAP-SEARCH как вид функции с 4 параметрами:

  1. Узел, с которого должен начаться поиск, который является отличительным именем (DN)
  2. Атрибуты, которые вы хотите вернуть
  3. Глубина поиска (база, одноуровневая, поддерево)
  4. Фильтр

Вы заинтересованы в фильтре. Здесь у вас есть сводка (предоставлена ​​Microsoft для Active Directory, стандартная). Фильтр логическим образом состоит из выражения типа Attribute Operator Value,

Так что фильтр, который вы даете, ничего не значит.

С теоретической точки зрения существует ExtensibleMatch, который позволяет создавать фильтры buildind для пути DN, но он не поддерживается Active Directory.

Насколько я знаю, вы должны использовать атрибут в AD, чтобы различать пользователей в двух подразделениях.

Это может быть любой существующий атрибут дискриминатора или, например, атрибут с именем OU, который наследуется от organizationalPerson учебный класс. Вы можете установить его (он не является автоматическим и не будет поддерживаться, если вы перемещаете пользователей) с помощью "персонала" для одних пользователей и "поставщиков" для других, и они используют фильтр:

(&(objectCategory=person)(|(ou=staff)(ou=vendors)))

Это просто. Просто поменяй порт. Используйте 3268 вместо 389. Если ваше доменное имя DOMAIN.LOCAL, в поиске введите DC=DOMAIN,DC=LOCAL

Порт 3268: этот порт используется для запросов, специально предназначенных для глобального каталога. Запросы LDAP, отправленные на порт 3268, можно использовать для поиска объектов во всем лесу. Однако могут быть возвращены только атрибуты, помеченные для репликации в глобальный каталог.

Порт 389: Этот порт используется для запроса информации от контроллера домена. Запросы LDAP, отправленные на порт 389, могут использоваться для поиска объектов только в домашнем домене глобального каталога. Однако приложение может получить все атрибуты искомых объектов.

Поговорив с экспертом LDAP, это невозможно. Один запрос не может искать более одного DC или OU.

Ваши варианты:

  1. Запустите более 1 запроса и проанализируйте результат.
  2. Используйте фильтр, чтобы найти нужных пользователей / объекты на основе другого атрибута, такого как группа AD или по имени.

Я не думаю, что это возможно с AD. Единственное, что я знаю, - это отличительный атрибут, содержащий часть OU, в которой вы пытаетесь выполнить поиск, поэтому вам понадобится подстановочный знак, чтобы получить результаты для объектов в этих OU. К сожалению, подстановочный знак не поддерживается в DN.

Если это вообще возможно, я бы действительно посмотрел на это в двух запросах, используя OU=Staff... и OU=Vendors... в качестве базовых DN.

tl;dr - Использовать синтаксис

В принципе, ваш случай сложен, потому что значения OU не отображаются в выводе пользователя - значения OU являются частью DN.

Например, результат поиска здесь:

      [root@pg data]# ldapsearch -H "ldap://ldap-service" -D "cn=admin,dc=example,dc=org" -w admin -b"DC=example,DC=org" cn=testuser2 
# extended LDIF
#
# LDAPv3
# base <DC=example,DC=org> with scope subtree
# filter: cn=testuser2
# requesting: ALL
#

# testuser2, AU, IIQ, example.org
dn: cn=testuser2,ou=AU,ou=IIQ,dc=example,dc=org
cn: testuser2
displayName: pgtest
gidNumber: 500
givenName: testuser2
homeDirectory: /home/testuser2
loginShell: /bin/sh
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: top
userPassword:: e01ENX1GMnFxVVpDTjh4VVJveGg5bkJBcGF3PT0=
sn: testuser2
uidNumber: 1012
uid: testuser2

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1

Здесь нет ou: линии, потому что OU принадлежит dn:линия. Итак, если вы возьмете ou к поиску, вы увидите, что это requesting: ou вместо requesting: ALL, но атрибуты не перечислены:

      [root@pg data]# ldapsearch -H "ldap://ldap-service" -D "cn=admin,dc=example,dc=org" -w admin -b"DC=example,DC=org" cn=testuser2 ou
# extended LDIF
#
# LDAPv3
# base <DC=example,DC=org> with scope subtree
# filter: cn=testuser2
# requesting: ou 
#

# testuser2, AU, IIQ, example.org
dn: cn=testuser2,ou=AU,ou=IIQ,dc=example,dc=org

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1

Поиск в OU даст вам результаты, но это только объекты OU, а не сами пользователи:

      [root@pg data]# ldapsearch -H "ldap://ldap-service" -D "cn=admin,dc=example,dc=org" -w admin -b"DC=example,DC=org" "(|(OU=IN)(OU=AU))"
# extended LDIF
#
# LDAPv3
# base <DC=example,DC=org> with scope subtree
# filter: (|(OU=IN)(OU=AU))
# requesting: ALL
#

# IN, example.org
dn: ou=IN,dc=example,dc=org
ou: IN
objectClass: organizationalUnit
objectClass: top

# AU, example.org
dn: ou=AU,dc=example,dc=org
ou: AU
objectClass: organizationalUnit
objectClass: top

# IN, IIQ, example.org
dn: ou=IN,ou=IIQ,dc=example,dc=org
objectClass: organizationalUnit
objectClass: top
ou: IN

# AU, IIQ, example.org
dn: ou=AU,ou=IIQ,dc=example,dc=org
ou: AU
objectClass: organizationalUnit
objectClass: top

# search result
search: 2
result: 0 Success

# numResponses: 5
# numEntries: 4

Тем не мение, ldapsearch позволяет извлекать части DN с помощью ou:dn:=<val> синтаксис:

      [root@pg data]# ldapsearch -H "ldap://ldap-service" -D "cn=admin,dc=example,dc=org" -w admin -b"DC=example,DC=org" "(&(displayname=pgtest)(|(ou:dn:=IN)(ou:dn:=AU)))" cn displayname
# extended LDIF
#
# LDAPv3
# base <DC=example,DC=org> with scope subtree
# filter: (&(displayname=pgtest)(|(ou:dn:=IN)(ou:dn:=AU)))
# requesting: cn displayname 
#

# testuser3, AU, example.org
dn: cn=testuser3,ou=AU,dc=example,dc=org
cn: testuser3
displayName: pgtest

# testuser4, IN, example.org
dn: cn=testuser4,ou=IN,dc=example,dc=org
cn: testuser4
displayName: pgtest

# testuser2, AU, IIQ, example.org
dn: cn=testuser2,ou=AU,ou=IIQ,dc=example,dc=org
cn: testuser2
displayName: pgtest

# testuser1, IN, IIQ, example.org
dn: cn=testuser1,ou=IN,ou=IIQ,dc=example,dc=org
cn: testuser1
displayName: pgtest

# testuser14, IN, example.org
dn: cn=testuser14,ou=IN,dc=example,dc=org
cn: testuser14
displayName: pgtest

# search result
search: 2
result: 0 Success

# numResponses: 6
# numEntries: 5
Другие вопросы по тегам