diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..2b6e914 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,5 @@ +nginx-ldap-auth (0.0.3-1) UNRELEASED; urgency=low + + * Initial release + + -- Ippolitov Igor Wed, 02 Nov 2016 14:32:15 +0300 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..f11c82a --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +9 \ No newline at end of file diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..c4212e2 --- /dev/null +++ b/debian/control @@ -0,0 +1,14 @@ +Source: nginx-ldap-auth +Maintainer: Ippolitov Igor +Section: misc +Priority: optional +Standards-Version: 3.9.7 +Build-Depends: debhelper (>= 9), dh-systemd, python, dh-python, dh-exec + +Package: nginx-ldap-auth +Architecture: all +Depends: systemd, python(>=2.6), python-ldap, python-argparse +Description: a reference implementation of an authentication helper for Nginx + This is a reference implementation of an authentication helper for Nginx. + It listens for incoming requests and uses parameters from headers + to bind to a remote LDAP directory and try authenticating a person. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..e69de29 diff --git a/debian/nginx-ldap-auth.init b/debian/nginx-ldap-auth.init new file mode 100755 index 0000000..5450b96 --- /dev/null +++ b/debian/nginx-ldap-auth.init @@ -0,0 +1,80 @@ +#! /bin/sh +### BEGIN INIT INFO +# Provides: nginx-ldap-auth +# Required-Start: $syslog $remote_fs +# Required-Stop: $syslog $remote_fs +# Should-Start: $local_fs +# Should-Stop: $local_fs +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: nginx-ldap-auth - nginx helper for LDAP authentication +# Description: nginx-ldap-auth - nginx helper for LDAP authentication +### END INIT INFO + + +DAEMON=/usr/bin/nginx-ldap-auth-daemon +NAME=nginx-ldap-auth + +test -x $DAEMON || exit 0 + +if [ -r /etc/default/$NAME ] +then + . /etc/default/$NAME +fi + +. /lib/lsb/init-functions + +set -e + +case "$1" in + start) + echo -n "Starting $DESC: " + mkdir -p $RUNDIR + touch $PIDFILE + chown $USER:$GROUP $RUNDIR $PIDFILE + chmod 755 $RUNDIR + + if [ -n "$ULIMIT" ] + then + ulimit -n $ULIMIT + 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" + + if start-stop-daemon --start $SSDOPTS -- $DAEMON_ARGS &>$LOG + then + echo "$NAME." + else + echo "failed" + fi + ;; + stop) + echo -n "Stopping $DESC: " + + + if start-stop-daemon --stop --retry forever/TERM/1 --quiet --oknodo --remove-pidfile --pidfile $PIDFILE --exec $DAEMON + then + echo "$NAME." + else + echo "failed" + fi + sleep 1 + ;; + + restart|force-reload) + ${0} stop + ${0} start + ;; + + status) + status_of_proc -p ${PIDFILE} ${DAEMON} ${NAME} + ;; + + *) + echo "Usage: /etc/init.d/$NAME {start|stop|restart|force-reload|status}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/debian/nginx-ldap-auth.install b/debian/nginx-ldap-auth.install new file mode 100755 index 0000000..644aaeb --- /dev/null +++ b/debian/nginx-ldap-auth.install @@ -0,0 +1,3 @@ +#!/usr/bin/dh-exec +nginx-ldap-auth-daemon.py => usr/bin/nginx-ldap-auth-daemon +nginx-ldap-auth.default => etc/default/nginx-ldap-auth diff --git a/debian/nginx-ldap-auth.logrotate b/debian/nginx-ldap-auth.logrotate new file mode 100644 index 0000000..133f426 --- /dev/null +++ b/debian/nginx-ldap-auth.logrotate @@ -0,0 +1,8 @@ +/var/log/nginx-ldap-auth/combined.log { + daily + missingok + rotate 7 + compress + notifempty + copytruncate +} diff --git a/debian/nginx-ldap-auth.postinst b/debian/nginx-ldap-auth.postinst new file mode 100644 index 0000000..c7ab8b7 --- /dev/null +++ b/debian/nginx-ldap-auth.postinst @@ -0,0 +1,12 @@ +#!/bin/sh + +set -e + +getent group nginx-ldap-auth > /dev/null || groupadd -r nginx-ldap-auth +getent passwd nginx-ldap-auth > /dev/null || \ + useradd -r -d /var/run -g nginx-ldap-auth \ + -s /sbin/nologin -c "Nginx auth helper" nginx-ldap-auth + +install -d -m755 -o nginx-ldap-auth -g nginx-ldap-auth /var/log/nginx-ldap-auth + +#DEBHELPER# diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..aba6b25 --- /dev/null +++ b/debian/rules @@ -0,0 +1,3 @@ +#!/usr/bin/make -f +%: + dh $@ --with python2 --with systemd diff --git a/nginx-ldap-auth-daemon.py b/nginx-ldap-auth-daemon.py index b35bc89..a7f7aa3 100755 --- a/nginx-ldap-auth-daemon.py +++ b/nginx-ldap-auth-daemon.py @@ -4,10 +4,10 @@ # Copyright (C) 2014-2015 Nginx, Inc. -import sys, os, signal, base64, ldap, Cookie +import sys, os, signal, base64, ldap, Cookie, argparse from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler -Listen = ('localhost', 8888) +#Listen = ('localhost', 8888) #Listen = "/tmp/auth.sock" # Also uncomment lines in 'Requests are # processed with UNIX sockets' section below @@ -142,10 +142,8 @@ class AuthHandler(BaseHTTPRequestHandler): # Verify username/password against LDAP server class LDAPAuthHandler(AuthHandler): - # Parameters to put into self.ctx from the HTTP header of auth request - def get_params(self): - return { + params = { # parameter header default 'realm': ('X-Ldap-Realm', 'Restricted'), 'url': ('X-Ldap-URL', None), @@ -156,6 +154,13 @@ class LDAPAuthHandler(AuthHandler): 'cookiename': ('X-CookieName', '') } + @classmethod + def set_params(cls, params): + cls.params = params + + def get_params(self): + return self.params + # GET handler for the authentication request def do_GET(self): @@ -175,6 +180,15 @@ class LDAPAuthHandler(AuthHandler): return try: + # check that uri and baseDn are set + # either from cli or a request + if not ctx['url']: + self.log_message('LDAP URL is not set!') + return + if not ctx['basedn']: + self.log_message('LDAP baseDN is not set!') + return + ctx['action'] = 'initializing LDAP connection' ldap_obj = ldap.initialize(ctx['url']); @@ -228,6 +242,48 @@ def exit_handler(signal, frame): sys.exit(0) if __name__ == '__main__': + parser = argparse.ArgumentParser( + description="""Simple Nginx LDAP authentication helper.""") + # Group for listen options: + group = parser.add_argument_group("Listen options") + group.add_argument('--host', metavar="hostname", + default="localhost", help="host to bind (Default: localhost)") + group.add_argument('-p', '--port', metavar="port", type=int, + default=8888, help="port to bind (Default: 8888)") + # ldap options: + group = parser.add_argument_group(title="LDAP options") + group.add_argument('-u', '--url', metavar="URL", + default="ldap://localhost:389", + help=("LDAP URI to query (Default: ldap://localhost:389)")) + group.add_argument('-b', metavar="baseDn", dest="basedn", default='', + help="LDAP base dn (Default: unset)") + group.add_argument('-D', metavar="bindDn", dest="binddn", default='', + help="LDAP bind DN (Default: anonymous)") + group.add_argument('-w', metavar="passwd", dest="bindpw", default='', + help="LDAP password for the bind DN (Default: unset)") + group.add_argument('-f', '--filter', metavar='filter', + default='(cn=%(username)s)', + help="LDAP filter (Default: cn=%%(username)s)") + # http options: + group = parser.add_argument_group(title="HTTP options") + group.add_argument('-R', '--realm', metavar='"Restricted Area"', + default="Resticted", help='HTTP auth realm (Default: "Restricted")') + group.add_argument('-c', '--cookie', metavar="cookiename", + default="", help="HTTP cookie name to set in (Default: unset)") + + args = parser.parse_args() + global Listen + Listen = (args.host, args.port) + auth_params = { + 'realm': ('X-Ldap-Realm', args.realm), + 'url': ('X-Ldap-URL', args.url), + 'basedn': ('X-Ldap-BaseDN', args.basedn), + 'template': ('X-Ldap-Template', args.filter), + 'binddn': ('X-Ldap-BindDN', args.binddn), + 'bindpasswd': ('X-Ldap-BindPass', args.bindpw), + 'cookiename': ('X-CookieName', args.cookie) + } + LDAPAuthHandler.set_params(auth_params) server = AuthHTTPServer(Listen, LDAPAuthHandler) signal.signal(signal.SIGINT, exit_handler) server.serve_forever() diff --git a/nginx-ldap-auth.default b/nginx-ldap-auth.default new file mode 100644 index 0000000..94d1ff5 --- /dev/null +++ b/nginx-ldap-auth.default @@ -0,0 +1,18 @@ +# +# these are used with systemd too +# so please keep options names inside variables +# +#URL="--url ldap://example.com:389" +#BASE="-b dc=nodomain" +#BIND_DN="-d cn=admin,dc=nodomain" +#BIND_PASS="-w secret" +#COOKIE="-c nginxauth" +#FILTER="-f (cn=%(username)s)" +#REALM="-R 'Restricted Area'" + +# these are used with init scripts only +LOG=/var/log/nginx-ldap-auth/daemon.log +RUNDIR=/var/run/nginx-ldap-auth/ +PIDFILE=/var/run/nginx-ldap-auth/nginx-ldap-auth.pid +USER=nginx-ldap-auth +GROUP=nginx-ldap-auth diff --git a/nginx-ldap-auth.service b/nginx-ldap-auth.service index 04bd838..0e95325 100644 --- a/nginx-ldap-auth.service +++ b/nginx-ldap-auth.service @@ -4,11 +4,11 @@ After=network.target network-online.target [Service] Type=simple -User=nobody -Group=nobody +User=nginx-ldap-auth +Group=nginx-ldap-auth WorkingDirectory=/var/run -PIDFile=/run/nginx-ldap-auth/nginx-ldap-auth.pid -ExecStart=/usr/bin/nginx-ldap-auth-daemon +EnvFile=/etc/default/nginx-ldap-auth +ExecStart=/usr/bin/nginx-ldap-auth-daemon $URL $BASE $BIND_DN $BIND_PASS $COOKIE $FILTER $REALM KillMode=process KillSignal=SIGINT Restart=on-failure diff --git a/rpm/nginx-ldap-auth.spec b/rpm/nginx-ldap-auth.spec index 65a2279..f86f203 100644 --- a/rpm/nginx-ldap-auth.spec +++ b/rpm/nginx-ldap-auth.spec @@ -11,6 +11,7 @@ Source0: nginx-ldap-auth-release-%{version}.tar.gz BuildRequires: systemd Requires: systemd Requires: python-ldap +Requires: python-argparse %description Reference implementation of method for authenticating users on behalf of @@ -20,17 +21,26 @@ servers proxied by NGINX or NGINX Plus. %setup -q %install +ls mkdir -p %buildroot%_bindir install -m755 nginx-ldap-auth-daemon.py %buildroot%_bindir/nginx-ldap-auth-daemon mkdir -p %buildroot%_unitdir -install -m644 nginx-ldap-auth.service %buildroot%_unitdir/ +install -m644 %name.service %buildroot%_unitdir/ +install -d -m755 %buildroot/etc/default +install -m644 %name.default %buildroot/etc/default/%name %files %doc README.md nginx-ldap-auth.conf backend-sample-app.py LICENSE +/etc/default/%name %_bindir/nginx-ldap-auth-daemon -%_unitdir/nginx-ldap-auth.service +%_unitdir/%name.service + %post +getent group nginx-ldap-auth > /dev/null || groupadd -r nginx-ldap-auth +getent passwd nginx-ldap-auth > /dev/null || \ + useradd -r -d /var/lib/nginx -g nginx-ldap-auth \ + -s /sbin/nologin -c "Nginx auth helper" nginx-ldap-auth /usr/bin/systemctl preset nginx-ldap-auth.service %preun