From 55ce75a53e28624da5917c4495692ed8c60f7071 Mon Sep 17 00:00:00 2001 From: Kochetkov Viacheslav Date: Fri, 21 Aug 2020 13:40:28 +0300 Subject: [PATCH] Add X-Ldap-GroupDN for search user in group without memberOf. --- README.md | 11 +++++++++ debian/nginx-ldap-auth.init | 2 +- nginx-ldap-auth-daemon.py | 47 ++++++++++++++++++++++++++++++------- nginx-ldap-auth.conf | 6 +++++ nginx-ldap-auth.default | 1 + nginx-ldap-auth.service | 2 +- 6 files changed, 58 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 531aff9..1100495 100644 --- a/README.md +++ b/README.md @@ -134,6 +134,17 @@ The reference implementation uses cookie-based authentication. If you are using #proxy_set_header Cookie nginxauth=$cookie_nginxauth; + +If you don't have memberOf in ldap and need check user in group by memberUid, set **X-Ldap-GroupDN** + +``` +proxy_set_header X-Ldap-GroupDN "cn=mygroup,ou=Group,dc=test,dc=com"; +``` + +This will check if memberUid=username is in the specified group. + + + ## Customization ### Caching diff --git a/debian/nginx-ldap-auth.init b/debian/nginx-ldap-auth.init index 86082f4..18760a2 100755 --- a/debian/nginx-ldap-auth.init +++ b/debian/nginx-ldap-auth.init @@ -40,7 +40,7 @@ case "$1" in fi SSDOPTS="--quiet --oknodo --background --no-close --make-pidfile --pidfile $PIDFILE --chuid $USER:$GROUP --exec $DAEMON" - DAEMON_ARGS="$URL $BASE $BIND_DN $BIND_PASS $COOKIE $FILTER $REALM" + DAEMON_ARGS="$URL $BASE $BIND_DN $BIND_PASS $COOKIE $FILTER $GROUPDN $REALM" if start-stop-daemon --start $SSDOPTS -- $DAEMON_ARGS > $LOG 2>&1 then diff --git a/nginx-ldap-auth-daemon.py b/nginx-ldap-auth-daemon.py index 388364c..75fcf1d 100755 --- a/nginx-ldap-auth-daemon.py +++ b/nginx-ldap-auth-daemon.py @@ -164,6 +164,7 @@ class LDAPAuthHandler(AuthHandler): 'basedn': ('X-Ldap-BaseDN', None), 'template': ('X-Ldap-Template', '(cn=%(username)s)'), 'binddn': ('X-Ldap-BindDN', ''), + 'groupdn': ('X-Ldap-GroupDN', ''), 'bindpasswd': ('X-Ldap-BindPass', ''), 'cookiename': ('X-CookieName', '') } @@ -226,38 +227,63 @@ def do_GET(self): ctx['action'] = 'binding as search user' ldap_obj.bind_s(ctx['binddn'], ctx['bindpasswd'], ldap.AUTH_SIMPLE) + + # Search memberUid in groupdn if defined + if ctx['groupdn']: + self.log_message('GroupDN defined to {}'.format(ctx['groupdn'])) + + ctx['action'] = 'preparing search filter' + searchfilter = "(memberUid=%s)" % ctx['user'] + + self.log_message(('searching on server "%s" with base dn ' +\ + '"%s" with filter "%s"') % + (ctx['url'], ctx['groupdn'], searchfilter)) + + ctx['action'] = 'running search query in GroupDN' + results = ldap_obj.search_s(ctx['groupdn'], ldap.SCOPE_SUBTREE, + searchfilter, ['objectclass'], 1) + + ctx['action'] = 'verifying search query results for GroupDN' + nres = len(results) + if nres < 1: + self.auth_failed(ctx, 'no memberUid found') + return + + self.log_message("MemberUid found in GroupDN") + + # Search filter ctx['action'] = 'preparing search filter' searchfilter = ctx['template'] % { 'username': ctx['user'] } - + self.log_message(('searching on server "%s" with base dn ' + \ '"%s" with filter "%s"') % (ctx['url'], ctx['basedn'], searchfilter)) - + ctx['action'] = 'running search query' results = ldap_obj.search_s(ctx['basedn'], ldap.SCOPE_SUBTREE, searchfilter, ['objectclass'], 1) - + ctx['action'] = 'verifying search query results' - + nres = len(results) - + if nres < 1: self.auth_failed(ctx, 'no objects found') return - + if nres > 1: self.log_message("note: filter match multiple objects: %d, using first" % nres) - + user_entry = results[0] ldap_dn = user_entry[0] - + if ldap_dn == None: self.auth_failed(ctx, 'matched object has no dn') return self.log_message('attempting to bind using dn "%s"' % (ldap_dn)) - + ctx['action'] = 'binding as an existing user "%s"' % ldap_dn ldap_obj.bind_s(ldap_dn, ctx['pass'], ldap.AUTH_SIMPLE) @@ -313,6 +339,8 @@ def exit_handler(signal, frame): group.add_argument('-f', '--filter', metavar='filter', default='(cn=%(username)s)', help="LDAP filter (Default: cn=%%(username)s)") + group.add_argument('-g', metavar='groupdn', dest="groupdn", default='', + help="LDAP groupDN that must contain the memberUid=username (Default: unset)") # http options: group = parser.add_argument_group(title="HTTP options") group.add_argument('-R', '--realm', metavar='"Restricted Area"', @@ -330,6 +358,7 @@ def exit_handler(signal, frame): 'disable_referrals': ('X-Ldap-DisableReferrals', args.disable_referrals), 'basedn': ('X-Ldap-BaseDN', args.basedn), 'template': ('X-Ldap-Template', args.filter), + 'groupdn': ('X-Ldap-GroupDN', args.groupdn), 'binddn': ('X-Ldap-BindDN', args.binddn), 'bindpasswd': ('X-Ldap-BindPass', args.bindpw), 'cookiename': ('X-CookieName', args.cookie) diff --git a/nginx-ldap-auth.conf b/nginx-ldap-auth.conf index 50dcc10..768cf98 100644 --- a/nginx-ldap-auth.conf +++ b/nginx-ldap-auth.conf @@ -71,6 +71,7 @@ http { # cookiename X-CookieName # realm X-Ldap-Realm # template X-Ldap-Template + # groupdn X-Ldap-GroupDN # (Required) Set the URL and port for connecting to the LDAP server, # by replacing 'example.com'. @@ -116,6 +117,11 @@ http { # nginx-ldap-auth-daemon.py. #proxy_set_header X-Ldap-Template "(cn=%(username)s)"; + # Optional. If you don't have memberOf in ldap + # and need check user in group by memberUid + # proxy_set_header X-Ldap-GroupDN "cn=mygroup,ou=Group,dc=test,dc=com"; + + # (Optional) Set the realm name, by uncommenting the following # directive and replacing 'Restricted' which is the default set # in nginx-ldap-auth-daemon.py. diff --git a/nginx-ldap-auth.default b/nginx-ldap-auth.default index 39dc74f..0cec140 100644 --- a/nginx-ldap-auth.default +++ b/nginx-ldap-auth.default @@ -8,6 +8,7 @@ #BIND_PASS="-w secret" #COOKIE="-c nginxauth" #FILTER="-f (cn=%(username)s)" +#GROUPDN="-g cn=mygroup,ou=Group,dc=test,dc=com" #REALM="-R 'Restricted Area'" # these are used with init scripts only diff --git a/nginx-ldap-auth.service b/nginx-ldap-auth.service index ef9eddf..90403ba 100644 --- a/nginx-ldap-auth.service +++ b/nginx-ldap-auth.service @@ -8,7 +8,7 @@ User=nginx-ldap-auth Group=nginx-ldap-auth WorkingDirectory=/var/run EnvironmentFile=/etc/default/nginx-ldap-auth -ExecStart=/usr/bin/nginx-ldap-auth-daemon $URL $BASE $BIND_DN $BIND_PASS $COOKIE $FILTER $REALM +ExecStart=/usr/bin/nginx-ldap-auth-daemon $URL $BASE $BIND_DN $BIND_PASS $COOKIE $FILTER $GROUPDN $REALM KillMode=process KillSignal=SIGINT Restart=on-failure