Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,17 @@ The reference implementation uses cookie-based authentication. If you are using
<strong>#</strong>proxy_set_header Cookie nginxauth=$cookie_nginxauth;
</pre>


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

Expand Down
2 changes: 1 addition & 1 deletion debian/nginx-ldap-auth.init
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
47 changes: 38 additions & 9 deletions nginx-ldap-auth-daemon.py
Original file line number Diff line number Diff line change
Expand Up @@ -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', '')
}
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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"',
Expand All @@ -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)
Expand Down
6 changes: 6 additions & 0 deletions nginx-ldap-auth.conf
Original file line number Diff line number Diff line change
Expand Up @@ -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'.
Expand Down Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions nginx-ldap-auth.default
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion nginx-ldap-auth.service
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down