Using meta database backend to combine active directory db and openldap local db

J B*_*oyd 5 openldap active-directory

I am trying to use the openldap meta back end to accomplish the following in a single query:

  1. query the local openldap database for the account. (I control this resource and only a few accounts will be stored here.)

  2. if the account is not found locally, then next query active directory (where I have no ability to create accounts)

The user will only be found in one or the other, but not both.

I have tried to follow numerous tutorials to accomplish this, but none have matched my exact scenario and I have been unable to tweak any of them into working order.

For testing I have created a simple LDIF backend to allow anonymous binds:

    database   ldif
    suffix     "ou=local,dc=proxy,dc=ldap"
    directory  "/var/lib/ldap/"
Run Code Online (Sandbox Code Playgroud)

My meta is configured as follows:

    database             meta
    suffix               "dc=example,dc=com"

    uri                  "ldaps://ad.my.edu/ou=org-1,dc=example,dc=com"
    suffixmassage        "dc=org-1,dc=example,dc=com" "ou=axxxx,dc=sxxxx,dc=xxx,dc=xx,dc=xxx"
    idassert-authzFrom   "dn:*"
    idassert-bind        bindmethod=simple
                 binddn="cn=XXXX,ou=it,ou=services,ou=axxxx,dc=sxxxx,dc=nxx,dc=xx,dc=xxx"
                 credentials="XXXX"
                 mode=none

    overlay              rwm
    rwm-map              attribute uid sAMAccountName
    rwm-map              objectClass posixAccount person

    uri                  "ldap://127.0.0.1/ou=org-2,dc=example,dc=com"
    suffixmassage        "ou=org-2,dc=example,dc=com" "ou=local,dc=proxy,dc=ldap"
Run Code Online (Sandbox Code Playgroud)

Here is the result of my search fromthe command line:

    ldapsearch -x -H 'ldap://127.0.0.1' -b dc=example,dc=com -s sub '(sAMAccountNAme=xxxxxx*)' -LLL

    slapd[1949]: conn=1014 op=2 UNBIND
    slapd[1949]: conn=1014 fd=9 closed
    slapd[1949]: conn=1015 fd=9 ACCEPT from IP=127.0.0.1:59624 (IP=127.0.0.1:389)
    slapd[1949]: conn=1015 op=0 BIND dn="" method=128
    slapd[1949]: conn=1015 op=0 RESULT tag=97 err=0 text=
    slapd[1949]: conn=1015 op=1 SRCH base="dc=example,dc=com" scope=2 deref=0 filter="(?sAMAccountName=xxxxxxxx*)"
    slapd[1949]: conn=1015 op=1 meta_search_dobind_init[0]: retrying URI="ldaps://ad.my.edu" DN="cn=xxxx,ou=it,ou=services,ou=axxxx,dc=sxxxx,dc=nxx,dc=xx,dc=xxx"
    slapd[1949]: conn=1002 op=9 SRCH base="ou=local,dc=proxy,dc=ldap" scope=2 deref=0 filter="(?sAMAccountName=xxxxxxx*)"
    slapd[1949]: conn=1002 op=9 SEARCH RESULT tag=101 err=32 nentries=0 text=
    slapd[1949]: conn=1015 op=1 meta_back_search[1] match="" err=32 (No such object) text="".
    slapd[1949]: conn=1015 op=1 SEARCH RESULT tag=101 err=32 nentries=0 text=
    ldapsearch[2054]: DIGEST-MD5 common mech free
    slapd[1949]: conn=1015 op=2 UNBIND
    slapd[1949]: conn=1015 fd=9 closed
Run Code Online (Sandbox Code Playgroud)

I have made some progress. I can now retrieve the user information from Active Directory if it is not found locally, but can't then rebind-as-user to finish authentication.

I receive a "Proxy operation retry failed" error:

    slapd[22555]: conn=1000 fd=8 ACCEPT from IP=127.0.0.1:35848 (IP=127.0.0.1:389)
    slapd[22555]: conn=1001 fd=9 ACCEPT from IP=127.0.0.1:35850 (IP=127.0.0.1:389)
    slapd[22555]: conn=1000 op=0 BIND dn="cn=xxxx,ou=local" method=128
    slapd[22555]: conn=1000 op=0 BIND dn="cn=xxxx,ou=local" mech=SIMPLE ssf=0
    slapd[22555]: conn=1000 op=0 RESULT tag=97 err=0 text=
    slapd[22555]: conn=1000 op=1 SRCH base="dc=example,dc=com" scope=2 deref=0 filter="(uid=xxxxxx)"
    slapd[22555]: conn=1002 fd=11 ACCEPT from IP=127.0.0.1:35852 (IP=127.0.0.1:389)
    slapd[22555]: conn=1002 op=0 BIND dn="cn=xxxx,ou=local" method=128
    slapd[22555]: conn=1002 op=0 BIND dn="cn=xxxx,ou=local" mech=SIMPLE ssf=0
    slapd[22555]: conn=1002 op=0 RESULT tag=97 err=0 text=
    slapd[22555]: conn=1003 fd=13 ACCEPT from IP=127.0.0.1:35854 (IP=127.0.0.1:389)
    slapd[22555]: conn=1003 op=0 BIND dn="cn=xxxx,ou=local" method=128
    slapd[22555]: conn=1003 op=0 BIND dn="cn=xxxx,ou=local" mech=SIMPLE ssf=0
    slapd[22555]: conn=1003 op=0 RESULT tag=97 err=0 text=
    slapd[22555]: conn=1002 op=1 SRCH base="ou=xxxx,dc=sxxxx,dc=nxx,dc=xx,dc=xxx" scope=2 deref=0 filter="(uid=xxxxxx)"
    slapd[22555]: conn=1003 op=1 SRCH base="ou=local" scope=2 deref=0 filter="(uid=xxxxxx)"
    slapd[22555]: conn=1003 op=1 SEARCH RESULT tag=101 err=32 nentries=0 text=
    slapd[22555]: conn=1000 op=1 meta_back_search[1] match="" err=32 (No such object) text="".
    slapd[22555]: conn=1002 op=1 SEARCH RESULT tag=101 err=0 nentries=1 text=
    slapd[22555]: conn=1000 op=1 SEARCH RESULT tag=101 err=0 nentries=1 text=
    slapd[22555]: conn=1001 op=0 BIND dn="cn=xxxxxx,ou=xxxx,dc=a,dc=example,dc=com" method=128
    slapd[22555]: conn=1004 fd=16 ACCEPT from IP=127.0.0.1:35858 (IP=127.0.0.1:389)
    slapd[22555]: conn=1004 op=0 BIND dn="cn=xxxxxx,ou=General,ou=xxxx,dc=sxxxx,dc=nxx,dc=xx,dc=xxx" method=128
    slapd[22555]: conn=1004 op=0 ldap_back_retry: retrying URI="ldaps://active.directory" DN=""
    slapd[22555]: conn=1004 op=0 RESULT tag=97 err=52 text=Proxy operation retry failed
    slapd[22555]: conn=1004 op=1 UNBIND
    slapd[22555]: conn=1001 op=0 RESULT tag=97 err=52 text=
    slapd[22555]: conn=1004 fd=16 closed
Run Code Online (Sandbox Code Playgroud)

Here is my revised meta configuration:

    database meta
    suffix dc=example,dc=com
    # The last rwm-map line maps all other attributes to nothing.
    overlay rwm
    rwm-map attribute uid sAMAccountname
    rwm-map attribute *
    #rwm-map objectclass posixGroup group
    #rwm-map objectclass posixAccount person
    #rwm-map objectclass memberUid member

    ##
    uri "ldap://127.0.0.1/dc=a,dc=example,dc=com"
    suffixmassage "dc=a,dc=example,dc=com" "ou=xxxx,dc=sxxxx,dc=nxx,dc=xx,dc=xxx"
    rebind-as-user true
    idassert-bind
      bindmethod=simple
      binddn="cn=XXXX,ou=local"
      credentials=XXXX
      mode=none
    idassert-authzFrom "dn.regex:.*"

    ##
    uri "ldap://127.0.0.1/dc=b,dc=example,dc=com"
    suffixmassage "dc=b,dc=example,dc=com" "ou=local"
    rebind-as-user true
    idassert-bind
      bindmethod=simple
      binddn="cn=XXXX,ou=local"
      credentials=XXXX
      mode=none
    idassert-authzFrom "dn.regex:.*"

    ##
    database ldap
    uri ldaps://active.directory
    suffix ou=xxxx,dc=sxxxx,dc=nxx,dc=xx,dc=xxx
    rebind-as-user true
    idassert-bind
      bindmethod=simple
      binddn="cn=XXXX,ou=xxxx,ou=sxxxx,ou=axxxx,dc=sxxxx,dc=nxx,dc=xx,dc=xxx"
      credentials=XXXX
      tls_reqcert=allow
      tls_cacert=/etc/letsencrypt/live/xxxx/fullchain.pem
      tls_cert=/etc/letsencrypt/live/xxxx/cert.pem
      tls_key=/etc/letsencrypt/live/xxxx/privkey.pem
      mode=none
    idassert-authzFrom "dn.regex:.*"
Run Code Online (Sandbox Code Playgroud)

J B*_*oyd 3

我已经搜索这个解决方案大约一个月了,在看到与我的问题直接相关的 openldap 线程中的示例配置后,终于在 slapd 手册页中偶然发现了答案。

我的解决方案的关键是 ldap 后端的 idasert-bind 标志部分。我添加了

flags=override
Run Code Online (Sandbox Code Playgroud)

来自 slapd 手册页:

标志可以是

覆盖、[非]规定性、代理授权-[非]关键

当使用覆盖标志时,即使数据库正在对客户端的身份进行授权,即在与提供的身份绑定并因此对其进行身份验证之后,代理也会使用配置的身份和身份验证方法执行身份断言。

最终工作后端 LDAP 配置:

database meta
suffix dc=example,dc=com

##
uri "ldaps://127.0.0.1/dc=a,dc=example,dc=com"
suffixmassage "dc=a,dc=example,dc=com" "ou=local"
rebind-as-user yes
idassert-bind 
   bindmethod=simple 
   binddn="cn=admin,ou=local" 
   credentials=XXXXXXXX 
   starttls=yes 
   tls_reqcert=allow 
   tls_cacert=/etc/letsencrypt/live/my.site.com/fullchain.pem 
   tls_cert=/etc/letsencrypt/live/my.site.com/cert.pem 
   tls_key=/etc/letsencrypt/live/my.site.com/privkey.pem 
   mode=none
idassert-authzFrom "dn.regex:.*"

##
uri "ldaps://127.0.0.1/dc=b,dc=example,dc=com"
suffixmassage "dc=b,dc=example,dc=com" "ou=axxxx,dc=sxxxx,dc=nxx,dc=xx,dc=xxx"
rebind-as-user yes
idassert-bind 
   bindmethod=simple 
   binddn="cn=admin,ou=local" 
   credentials=XXXXXXXX 
   starttls=yes 
   tls_reqcert=allow 
   tls_cacert=/etc/letsencrypt/live/my.site.com/fullchain.pem 
   tls_cert=/etc/letsencrypt/live/my.site.com/cert.pem 
   tls_key=/etc/letsencrypt/live/my.site.com/privkey.pem mode=none
   mode=none
idassert-authzFrom "dn.regex:.*"

##
database ldap
uri ldaps://ldaps.my.site.com/
suffix "OU=AXXXX,DC=sxxxx,DC=nxx,DC=xx,DC=xxx"
rebind-as-user yes
chase-referrals yes
readonly yes
idassert-bind
   bindmethod=simple
   binddn="CN=IXXXX,OU=IX,OU=SXXXX,OU=AXXXX,DC=sxxxx,DC=nxx,DC=xx,DC=xxx"
   credentials=XXXXXXXX
   flags=override
   mode=none
idassert-authzFrom "dn.regex:.*"

# The last rwm-map line maps all other attributes to nothing.
overlay rwm
rwm-map attribute uid sAMAccountname
rwm-map attribute cn cn
rwm-map attribute sn sn
rwm-map attribute givenName givenName
rwm-map attribute employeeID employeeID
rwm-map attribute employeeNumber employeeNumber
rwm-map attribute uidNumber uidNumber
rwm-map attribute gidNumber gidNumber
rwm-map attribute mail mail
rwm-map attribute departmentNumber departmentNumber
rwm-map attribute department department
rwm-map attribute home extensionAttribute12
rwm-map attribute *
Run Code Online (Sandbox Code Playgroud)