Git Product home page Git Product logo

nginx-ldap-auth's Introduction

PLEASE note that this project is not designed or hardened for production. It is intended as a model for such connector daemons

The nginx-ldap-auth project

This project provides a reference model implementation of a method for authenticating users on behalf of servers proxied by NGINX or NGINX Plus.

Note:

For ease of reading, this document refers to NGINX Plus, but it also applies to open source NGINX. The prerequisite ngx_http_auth_request_module module is included both in NGINX Plus packages and prebuilt open source NGINX binaries.

Description:

The nginx-ldap-auth software is a reference model implementation of a method for authenticating users who request protected resources from servers proxied by NGINX Plus. It includes a daemon (ldap-auth) that communicates with an authentication server, and a sample daemon that stands in for an actual back-end server during testing, by generating an authentication cookie based on the user’s credentials. The daemons are written in Python for use with a Lightweight Directory Access Protocol (LDAP) authentication server (OpenLDAP or Microsoft Windows Active Directory 2003 and 2012).

The ldap-auth daemon, which mediates between NGINX Plus and the LDAP server, is intended to serve as a model for "connector" daemons written in other languages, for different authentication systems, or both. NGINX, Inc. Professional Services is available to assist with such adaptations.

NGINX LDAP Architecture

For a step-by-step description of the authentication process in the reference implementation, see How Authentication Works in the Reference Implementation in NGINX Plus and NGINX Can Authenticate Application Users.

Installation and Configuration

The NGINX Plus configuration file that is provided with the reference implementation configures all components other than the LDAP server (that is, NGINX Plus, the client, the ldap-auth daemon, and the back-end daemon) to run on the same host, which is adequate for testing purposes. The LDAP server can also run on that host during testing.

In an actual deployment, the back-end application and authentication server typically each run on a separate host, with NGINX Plus on a third host. The ldap-auth daemon does not consume many resources in most situations, so it can run on the NGINX Plus host or another host of your choice.

To install and configure the reference implementation, perform the following steps.

  1. Create a clone of the GitHub repository (nginx-ldap-auth).

  2. If NGINX Plus is not already running, install it according to the instructions for your operating system.

  3. If an LDAP authentication server is not already running, install and configure one. By default the ldap-auth daemon communicates with OpenLDAP, but can be configured to work with Active Directory.

    If you are using the LDAP server only to test the reference implementation, you can use the OpenLDAP server Docker image that is available on GitHub, or you can set up a server in a virtual environment using instructions such as How To Install and Configure a Basic LDAP Server on an Ubuntu 12.04 VPS.

  4. On the host where the ldap-auth daemon is to run, install the following additional software. We recommend using the versions that are distributed with the operating system, instead of downloading the software from an open source repository.

    • Python versions 2 and 3 are supported.
    • The Python LDAP module, python-ldap (created by the python-ldap.org open source project).
  5. Copy the following files from your repository clone to the indicated hosts:

    • nginx-ldap-auth.conf – NGINX Plus configuration file, which contains the minimal set of directives for testing the reference implementation. Install on the NGINX Plus host (in the /etc/nginx/conf.d directory if using the conventional configuration scheme). To avoid configuration conflicts, remember to move or rename any default configuration files installed with NGINX Plus.

    • nginx-ldap-auth-daemon.py – Python code for the ldap-auth daemon. Install on the host of your choice.

      Alternatively, use provided Dockerfile to build Docker image:

      docker build -t nginx-ldap-auth-daemon .
      docker run nginx-ldap-auth-daemon
      

      If you desire to use a container with Python3, you can supply an appropriate build argument:

      docker build -t nginx-ldap-auth-daemon --build-arg PYTHON_VERSION=3 .
      
    • nginx-ldap-auth-daemon-ctl.sh – Sample shell script for starting and stopping the daemon. Install on the same host as the ldap-auth daemon.

    • backend-sample-app.py – Python code for the daemon that during testing stands in for a real back-end application server. Install on the host of your choice.

  6. Modify the NGINX Plus configuration file as described in Required Modifications to the NGINX Plus Configuration File below. For information about customizing your deployment, see Customization below. We recommend running the nginx -t command after making your changes to verify that the file is syntactically valid.

  7. Start NGINX Plus. If it is already running, run the following command to reload the configuration file:

    root# nginx -s reload
  8. Run the following commands to start the ldap-auth daemon and the back-end daemon.

    root# nginx-ldap-auth-daemon-ctl.sh start
    root# python backend-sample-app.py
    
  9. To test the reference implementation, use a web browser to access http://nginx-server-address:8081. Verify that the browser presents a login form. After you fill out the form and submit it, verify that the server returns the expected response to valid credentials. The sample back-end daemon returns this:

Hello, world! Requested URL: URL

Required Modifications to the NGINX Plus Configuration File

Modify the nginx-ldap-auth.conf file, by changing values as appropriate for your deployment for the terms shown in bold font in the following configuration.

For detailed instructions, see Configuring the Reference Implementation in the NGINX Plus and NGINX Can Authenticate Application Users blog post. The nginx-ldap-auth.conf file includes detailed instructions (in comments not shown here) for setting the proxy-set-header directives; for information about other directives, see the NGINX reference documentation.

http {
  ...
  proxy_cache_path cache/ keys_zone=auth_cache:10m;

  upstream backend {
        server 127.0.0.1:9000;
  }

  server {
      listen 127.0.0.1:8081;

      location = /auth-proxy {
         proxy_pass http://127.0.0.1:8888;
         proxy_pass_request_body off;
         proxy_pass_request_headers off;
         proxy_set_header Content-Length "";
         proxy_cache auth_cache; # Must match the name in the proxy_cache_path directive above
         proxy_cache_valid 200 10m;

         # URL and port for connecting to the LDAP server
         proxy_set_header X-Ldap-URL "ldap://example.com";

         # Negotiate a TLS-enabled (STARTTLS) connection before sending credentials
         proxy_set_header X-Ldap-Starttls "true";

         # Base DN
         proxy_set_header X-Ldap-BaseDN "cn=Users,dc=test,dc=local";

         # Bind DN
         proxy_set_header X-Ldap-BindDN "cn=root,dc=test,dc=local";

         # Bind password
         proxy_set_header X-Ldap-BindPass "secret";
      }
   }
}

If the authentication server runs Active Directory rather than OpenLDAP, uncomment the following directive as shown:

proxy_set_header X-Ldap-Template "(sAMAccountName=%(username)s)";

In addition, the X-Ldap-Template header can be used to create complex LDAP searches. The code in ldap-auth-daemon creates a search filter that is based on this template header. By default, template is empty, and does not make any effect on LDAP search. However, you may decide for instance to authenticate only users from a specific user group (see LDAP documentation for more information regarding filters).

Suppose, your web resource should only be available for users from group1 group. In such a case you can define X-Ldap-Template template as follows:

proxy_set_header X-Ldap-Template "(&(cn=%(username)s)(memberOf=cn=group1,cn=Users,dc=example,dc=com))";

The search filters can be combined from less complex filters using boolean operations and can be rather complex.

The reference implementation uses cookie-based authentication. If you are using HTTP basic authentication instead, comment out the following directives, and enable the Authorization header as shown:

#proxy_set_header X-CookieName "nginxauth";
#proxy_set_header Cookie nginxauth=$cookie_nginxauth;
proxy_set_header Authorization $http_authorization;

Customization

Caching

The nginx-ldap-auth.conf file enables caching of both data and credentials. To disable caching, comment out the four proxy_cache* directives as shown:

http {
  ...
  #proxy_cache_path cache/ keys_zone=auth_cache:10m;
  ...
  server {
    ...
    location = /auth-proxy {
      #proxy_cache auth_cache;
      # note that cookie is added to cache key
      #proxy_cache_key "$http_authorization$cookie_nginxauth";
      #proxy_cache_valid 200 10m;
     }
   }
}

Optional LDAP Parameters

If you want to change the value for the template parameter that the ldap-auth daemon passes to the OpenLDAP server by default, uncomment the following directive as shown, and change the value:

proxy_set_header X-Ldap-Template "(cn=%(username)s)";

If you want to change the realm name from the default value (Restricted), uncomment and change the following directive:

proxy_set_header X-Ldap-Realm "Restricted";

Authentication Server

To modify the ldap-auth daemon to communicate with a different (non-LDAP) type of authentication server, write a new authentication-handler class to replace LDAPAuthHandler in the nginx-ldap-auth-daemon.py script.

Compatibility

The auth daemon was tested against default configurations of the following LDAP servers:

  • OpenLDAP
  • Microsoft Windows Server Active Directory 2003
  • Microsoft Windows Server Active Directory 2012

Limitations

The back-end daemon uses Base64 encoding on the username and password in the cookie. Base64 is a very weak form of scrambling, rendering the credentials vulnerable to extraction and misuse. We strongly recommend using a more sophisticated algorithm in your actual back-end application.

License

The reference implementation is subject to the same 2-clause BSD license as the open source NGINX software.

nginx-ldap-auth's People

Contributors

alexjfisher avatar arfyfr avatar arozyev avatar cmur2 avatar dd-han avatar dwmcallister avatar faisal-memon avatar lcrilly avatar lesinigo avatar lpby avatar nikolaev-rd avatar oxpa avatar rysiekpl avatar szuro avatar thresheek avatar tippexs avatar tmauro-nginx avatar vl-homutov avatar vlhomutov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nginx-ldap-auth's Issues

Connection reset by peer (nginx-ldap-auth-daemon.py)

When I try to access my protected location / , I get the following error in nginx:

2019/09/18 13:45:48 [error] 6#6: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 192.168.253.1, server: , request: "GET / HTTP/1.1", subrequest: "/auth-proxy", upstream: "http://127.0.0.1:8888/auth-proxy", host: "localhost:3000"
2019/09/18 13:45:48 [error] 6#6: *1 auth request unexpected status: 502 while sending to client, client: 192.168.253.1, server: , request: "GET / HTTP/1.1", host: "localhost:3000"
192.168.253.1 - - [18/Sep/2019:13:45:48 +0000] "GET / HTTP/1.1" 500 579 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.75 Safari/537.36"

When using the following command:

curl -v \
	-H "X-Ldap-URL ldap://my-ldap" \
	-H "X-Ldap-BaseDN ou=User,dc=Domain" \
	-H "X-Ldap-BindDN OU=Groups,OU=User,DC=Domain" \
	-H "X-Ldap-BindPass password" \
	-H "X-Ldap-Template (&(sAMAccountName=%(username)s)" \
	-H "X-Ldap-DisableReferrals true" \
localhost:3001;

I get the response:

* Rebuilt URL to: localhost:3001/
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 3001 (#0)
> GET / HTTP/1.1
> Host: localhost:3001
> User-Agent: curl/7.58.0
> Accept: */*
> X-Ldap-URL ldap://my-ldap
> 
* Recv failure: Connection reset by peer
* stopped the pause stream!
* Closing connection 0
curl: (56) Recv failure: Connection reset by peer

Support for SRV lookup of LDAP servers and fallback behaviour

At present you need to specify a X-LDAP-URL pointing to a specific server. If this server is down(or points to a round-robin DNS A record) the connection will be retried indefinitely and leads to a 500 error for the client.

I would like to add two features:

  1. Support for lookup of SRV records in AD-integrated LDAP environments to find a Domain Controller
  2. Retry other servers(or A/AAAA records) if a response is not received within a reasonable timeout period.

I have begun work on a local branch to implement these features, but I would like to open a discussion before creating a Pull Request.

Presently X-LDAP-URL is a required parameter supplying the scheme, server, and port all together. With AD only the domain name is required; server/port are looked-up in DNS SRV records, and the scheme(LDAP or LDAPS) can be inferred from the port(389 or 636). I see two ways to implement this:

  • Add a new X-LDAP-Domain parameter which is mutually exclusive with -URL. This should be relatively simple to implement and is my preference. It should be backwards-compatible with the current config, since the two are exclusive.
  • If X-LDAP-URL does not contain a scheme:// or port://(only a bare domain name, eg example.com) infer that this is Active Directory and perform the necessary SRV lookups. This will require additional complexity to parse the URL, but doesn't need any changes to the parameters.

Please let me know your thoughts, thanks for looking.

Self-signed certificates are not accepted

By default the ldap library does not accept self-signed certificates

To let the library accept and verify even self-signed certificate you need to set the following option:
ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_ALLOW)

Maybe worth creating an option?

New release?

Hi

Would it be possible to have an official new release please? 0.0.3 is from 2016 and there have been quite a few changes/improvements since then.

Many thanks,
Alex

backend-sample-app.py concat issue on Python 3

backend-sample-app.py line 124 attempts to concatinate bytes literals and strings. On line 123 convert enc from a string to bytes literal. I purpose the following fix.
- enc = enc.decode()
+ enc = bytes(enc.decode(), encoding='utf-8')
self.send_header('Set-Cookie', b'nginxauth=' + enc + b'; httponly')

How to use complex query in X-Ldap-Template?

Hello!

I need to check username and group of user.
Try to use this:
proxy_set_header X-Ldap-Template "(&(SAMAccountName=%(username))(memberof=CN=MyGroup,OU=Groups,DC=example,DC=local))"";
but it not works.

How write my query right way?

I extend the group management function,you see

vi nginx-ldap-auth-daemon.py

delete code

        self.log_message('Auth OK for user "%s"' % (ctx['user']))

        # Successfully authenticated user
        self.send_response(200)
        self.end_headers()

add code

        for group in ctx['group'].split(';'):
            GroupInfo = ldap_obj.search(ctx['basedn'], ldap.SCOPE_SUBTREE, 'cn=%s' % group.strip(), None)
            GroupMember = ldap_obj.result(GroupInfo,0)
            try:
                print ldap_dn.lower(),GroupMember[1][0][1]['uniqueMember']
                if ldap_dn.lower() in GroupMember[1][0][1]['uniqueMember']:
                    self.send_response(200)
                    self.end_headers()
                    self.log_message('Auth OK for user "%s"' % (ctx['user']))
                    return
            except IndexError,e:
                pass
        self.send_response(403)
        self.end_headers()
        return

in “'cookiename': ('X-CookieName', args.cookie) ” right add code:

,'group': ('X-Ldap-Group', args.cookie)

#nginx config:
proxy_set_header X-Ldap-Group "group2;group2";

Prevent user from overriding the LDAP connection parameters

Hi,

It might be worth emphasizing in the README.md file that, as the example python daemon accepts both headers and CLI parameters, it is necessary to ensure that a user could not send X-Ldap-* parameters to override the default settings.

Typically, in a scenario where one would run the python daemon passing it against a single LDAP, they might be tempted to use LI parameters and discard the proxy_set_header X-Ldap-URL "ldap://example.com"; line in nginx. In this situation, as far as I understand, any user could send a custom X-Ldap-URL to switch the ldap backend against which to check credentials.

Wouldn't it be safer to write it the example nginx configuration this way instead (both in example conf file and in README)?

http {
  ...
  
  server {
      ...

      location = /auth-proxy {
         proxy_pass http://127.0.0.1:8888;

         # Do not pass request headers to ensure end user cannot override LDAP settings.
         proxy_pass_request_headers off;
         proxy_pass_request_body off;
         proxy_set_header Content-Length "";

         # Pass back the Authorization header (whitelist-like)
         proxy_set_header Authorization $http_authorization;

         # Use any useful X-Ldap-* set_header directives here
         ...  
      }
   }
}

Best

Numbered release

Could you please provide a numbered release tarball to allow packaging in Gentoo Linux? Just something like 0.0.1 will do nicely.

RPM build fails when installing nginx-ldap-auth.logrotate

Trying to build an RPM from the current master I get:

+ install -m644 nginx-ldap-auth.logrotate /root/rpmbuild/BUILDROOT/nginx-ldap-auth-0.0.3-1.el7.centos.x86_64/etc/logrotate.d/nginx-ldap-auth
install: cannot create regular file '/root/rpmbuild/BUILDROOT/nginx-ldap-auth-0.0.3-1.el7.centos.x86_64/etc/logrotate.d/nginx-ldap-auth': No such file or directory
error: Bad exit status from /var/tmp/rpm-tmp.dF42L5 (%install)

Inconsistent error - "In Order to perform this operation a successful bind must be completed"

Hey all,
I've configured nginx and nginx-ldap-auth on an ubuntu server as a means of authenticating the webserver to a windows AD instance. Currently i'm experiencing an issue where login fails intermittently, and I'm getting the following error in the logs.

Both Nginx and the auth daemon are running on the same host, and the windows DC is on the same network.

searching on server "ldaps://*****:636" with base dn "dc=**,dc=**,dc=**,dc=**" with filter "(sAMAccountName=******)

localhost - **** [16/Jan/2020 13:32:05] Error while running search query: {'info': u'000004DC: LdapErr: DSID-0C090A4C, comment: In order to perform this operation a successful bind must be completed on the connection., data 0, v3839', 'desc': u'Operations error'}, server="ldaps://****:636", login="*****"

I've put the configuration including the bind account+password in both the /etc/defaults/nginx-ldap-auth and the /etc/nginx/sites-enabled/mysite file but that hasn't resolved the issue.

This link indicates that simple bind should be enabled on the DC to avoid this issue, although due to the security risks involved i'd rather not enable simple bind. -- UPDATE: i enabled simple bind for testing purposes and this resolved the issue, however due to the deployment environment i'm unable to leave this on as a long term solution.

Any ideas please let me know.

How to get username from the form and pass it through nginx?

Hi, I want to extract username from the login form, and pass it through nginx.
the nginx-ldap-auth-daemon.py, backend-sample-app.py, nginx-ldap-auth-daemon-ctl-rh.sh are default.
nginx.conf:

error_log logs/error.log debug;
events {
worker_connections 10240;
}
http {
    proxy_cache_path cache/  keys_zone=auth_cache:10m;
    upstream backend {
        server 127.0.0.1:9000;
        #server 127.0.0.1:5601;
    }
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    server {
        listen 8081;
        location / {
            auth_request /auth-proxy;
            error_page 401 =200 /login;
            proxy_set_header X-PROXY-USER $username;       //how to get the username in nginx?
            #proxy_pass http://backend/;
            proxy_pass http://localhost:5601;
        }
        location /login {
            proxy_pass http://backend/login;
            proxy_set_header X-Target $request_uri;
        }
        location = /auth-proxy {
            internal;
            proxy_pass http://127.0.0.1:8888;
            proxy_pass_request_body off;
            proxy_set_header Content-Length "";
            proxy_cache auth_cache;
            proxy_cache_valid 200 10m;
            proxy_cache_key "$http_authorization$cookie_nginxauth";
            proxy_set_header X-Ldap-URL      "ldap://localhost:389";
            proxy_set_header X-Ldap-BaseDN   "dc=xinhua,dc=org";
            proxy_set_header X-Ldap-BindDN   "cn=Manager,dc=xinhua,dc=org";
            proxy_set_header X-Ldap-BindPass "xxxxxx";
            proxy_set_header X-CookieName "nginxauth";
            proxy_set_header Cookie nginxauth=$cookie_nginxauth;
        }
    }
}

thank you in advance!

LDAP connection always has user/password pair. For the anonymous access, use 'anonymous' login with empty password, if your server is configured to allow it.

Originally posted by @vl-homutov in #52 (comment)

There is no "anonymous user." The LDAP server supports anonymous bind, which means you don't bind as a user. Most software allows you to supply empty strings for DN and password to do this.
https://ldap.com/the-ldap-bind-operation/

I am only providing this :
url ldap://nsp-openldap-local:389;
binddn ou=people,dc=odc,dc=im;
binddn_passwd ;
require valid_user;

ldap error

Error while binding as search user: {'desc': 'Invalid credentials'}, server="ldap://10.2.150.11:389"

  proxy_set_header X-Ldap-URL      "ldap://10.2.150.11:389";
    proxy_set_header X-Ldap-BaseDN   "ou=People,dc=che,dc=org";
    proxy_set_header X-Ldap-BindDN   "cn=OPITUser,ou=OuterUser,dc=che,dc=org";
    proxy_set_header X-Ldap-BindPass "sercet";
    proxy_set_header X-Ldap-Template "(sAMAccountName=%(username)s)";

New published docker image for backend and ldap-auth daemons

Hi, I'm with linuxserver.io and we are a volunteer group dedicated to creating and maintaining docker images for popular (mostly) open source apps.

We created a new docker image that combines the backend daemon and the ldap-auth daemon contained in this repo. As a docker container, it is extremely easy for a user to deploy, it is sandboxed from the system and all dependencies are satisfied within the image.

We also fixed the one current limitation of weak encryption in the cookies. Instead of base64, we implemented fernet encryption. Since both daemons run inside the same image, we are able to create a new fernet key during container creation or update, which is shared by the two daemons through this script.

Feel free to include a link in the readme of this repo. We are using it as a companion to our letsencrypt/nginx image (source here).

The docker image is hosted on docker hub, it is alpine based and therefore very lean, and it is multi-arch (x86_64, armhf and aarch64). The source is here.

We would also appreciate any feedback.

Thanks

Python 2 Deprecation

When building the container, PIP will warn about Python 2 deprecation:

DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7.

It is probably a good idea to start migrating the script(s) to python3 for future compatibility.

python deprecation countdown

script does not start if $LOG is not set

Trying to run the nginx-ldap-auth-daemon.py script without the $LOG environment variable set (e.g. for testing purposes) results in a not-so-useful sh error:

# /usr/bin/nginx-ldap-auth-daemon
/usr/bin/nginx-ldap-auth-daemon: line 2: $LOG: ambiguous redirect

The shell code at the beginning of the script should be changed to add a default value for $LOG and/or to emit an error message that explicitly says that variable is required.

How to authenticate before sending proxy to smtp server

hello i was working nginx .i want to I was working on nginx webserver .I want to authenticate with user name and password just before it send proxy to smtp server is it possible with this nginx-ldap-auth module could anyone please guide me and provide me an eg.

Undocumented Group Restriction Values

This is in reference to #16

It seems that there are a number of undocumented values that would be nice to have provided in README.md

Namely restriction types like:

auth_ldap_require group 'cn=admins,ou=group,dc=example,dc=com';
auth_ldap_require group 'ou=HR,dc=example,dc=com';
auth_ldap_satisfy all;

setting sertificates in Debian

Please advise! I'm new to LDAP authorization (AD). I've already spent a lot of time, but I cann't figure it out. How cat I install certificates on my Debian system for connection using ldaps.

/etc/nginx/conf.d/ldap.conf

`error_log logs/error.log debug;

proxy_cache_path cache/  keys_zone=auth_cache:10m;

# The back-end daemon listens on port 9000 as implemented
# in backend-sample-app.py.
# Change the IP address if the daemon is not running on the
# same host as NGINX/NGINX Plus.
upstream backend {
    server 127.0.0.1:5601;
}

# NGINX/NGINX Plus listen on port 8081 for requests that require
# authentication. Change the port number as appropriate.
server {
    listen 80;

    # Protected application
    location / {
        auth_request /auth-proxy;


        #proxy_pass http://backend/;
    #proxy_pass http://localhost:5601;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header   X-Real-IP        $remote_addr;
        proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
        proxy_cache_bypass $http_upgrade;

    }

    location = /auth-proxy {
        internal;

        # The ldap-auth daemon listens on port 8888, as set
        # in nginx-ldap-auth-daemon.py.
        # Change the IP address if the daemon is not running on
        # the same host as NGINX/NGINX Plus.
        proxy_pass http://127.0.0.1:8888;

        proxy_pass_request_body off;
        proxy_set_header Content-Length "";
        proxy_cache auth_cache;
        proxy_cache_valid 200 10m;

        # The following directive adds the cookie to the cache key
        #proxy_cache_key "$http_authorization$cookie_nginxauth";i
    proxy_set_header X-Ldap-URL      "ldaps://balanced_ldap.co.company.com:636";
        proxy_set_header X-Ldap-BaseDN   "OU=company,DC=central,DC=co,DC=company,DC=com";
        proxy_set_header X-Ldap-BindDN   "CN=NGINX LDAP,OU=Technical Users,OU=Cv,OU=Branches,OU=company,DC=central,DC=co,DC=company,DC=com";
        proxy_set_header X-Ldap-BindPass "pass";
        proxy_set_header X-Ldap-Template "(userPrincipalName=%(username)s)";

    #proxy_set_header X-Ldap-Starttls "true";           

        # (Required) The following directives set the cookie name and pass
        # it, respectively. They are required for cookie-based
        # authentication. Comment them out if using HTTP basic
        # authentication.
        proxy_set_header X-CookieName "nginxauth";
        proxy_set_header Cookie nginxauth=$cookie_nginxauth;
       
    }
}

`

stdout of nginx-ldap-auth:
localhost - [email protected] [04/May/2018 16:20:19] Error while binding as search user: {'info': '(unknown error code)', 'desc': "Can't contact LDAP server"}, server="ldaps://balanced_ldap.co.company.com:636", login="[email protected]"

multiple groups in OU

Hi, I have group in AD: CN=asterisk_rec,OU=Asterisk,OU=учетные записи и группы,DC=test,DC=int

My work nginx config:

    location /login {
       proxy_pass http://auth-backend/login;
       proxy_set_header X-Target $request_uri;
    }

    location = /auth-proxy {
       internal;
       proxy_pass http://127.0.0.1:8888; # сервер аутентификации

       proxy_pass_request_body off;
       proxy_set_header Content-Length "";
 
       proxy_set_header X-Ldap-URL      "ldap://dc01:389";
       proxy_set_header X-Ldap-DisableReferrals "true";
       proxy_set_header X-Ldap-BaseDN   "DC=test,DC=int"; 
       proxy_set_header X-Ldap-BindDN   "[email protected]";
       proxy_set_header X-Ldap-BindPass "Mdfdfdfdfdfdf";
       proxy_set_header X-CookieName "nginxauth";
       proxy_set_header Cookie nginxauth=$cookie_nginxauth;

       proxy_set_header X-Ldap-Template "(&(sAMAccountName=%(username)s)(memberOf=CN=asterisk_rec,OU=Asterisk,OU=учетные записи и группы,DC=test,DC=int)(objectClass=user))";
     }

It works. But, when i create multiple groups in OU (Asterisk) and subdomains configs in nginx (new server port, root directory and X-Ldap-Template), i can not login in all sites with nginx-ldap-auth. In logs:

localhost - asterisk [24/Jun/2019 15:27:46] searching on server "ldap://dc01:389" with base dn "DC=test,DC=int" with filter "(&(sAMAccountName=asterisk)(objectClass=user)(memberOf=CN=asterisk_rec_sd,OU=Asterisk,OU=учетные записи и группы,DC=test,DC=int))"
localhost - asterisk [24/Jun/2019 15:27:46] note: filter match multiple objects: 3, using first
localhost - asterisk [24/Jun/2019 15:27:46] Error while verifying search query results: matched object has no dn, server="ldap://dc01:389", login="asterisk"
localhost - asterisk [24/Jun/2019 15:27:46] "GET /auth-proxy HTTP/1.0" 401 -

binding as an existing user "None"

Hi,

if len(results) < 1:

Wouldn't it be supposed to check not only the length of the results, but also what's inside?
if len(results) < 1:

The following is the output from the daemon:

results with an existent user

[('CN=my.username,OU=AADDC Users,DC=test01ad,DC=me,DC=net',
  {'objectClass': []}),
 (None,
  ['ldaps://DomainDnsZones.test01ad.me.net/DC=DomainDnsZones,DC=test01ad,DC=me,DC=net']),
 (None,
  ['ldaps://ForestDnsZones.test01ad.me.net/DC=ForestDnsZones,DC=test01ad,DC=me,DC=net']),
 (None,
  ['ldaps://test01ad.me.net/CN=Configuration,DC=test01ad,DC=me,DC=net'])]

results with a non-existent user

[(None,
  ['ldaps://ForestDnsZones.test01ad.me.net/DC=ForestDnsZones,DC=test01ad,DC=me,DC=net']),
 (None,
  ['ldaps://DomainDnsZones.test01ad.me.net/DC=DomainDnsZones,DC=test01ad,DC=me,DC=net']),
 (None,
  ['ldaps://test01ad.me.net/CN=Configuration,DC=test01ad,DC=me,DC=net'])]

Even the latter case, the script falls through and returns 200(Auth OK) which is wrong as the user in question does not exist(in my case in MS Active Directory).

Is communication between nginx and ldap-auth encrypted?

Hello,

I couldn't help but noticing that traffic between nginx and ldap-auth contains the most sensitive info (passwords) but nowhere in the docs I see any reference to whether if the channel is encrypted or not.
I can only assume that it isn't, as I didn't provide certificate...

Anyone knows anything about it? Can I provide a certificate and enforce HTTPS?

Thanks!

Error while initializing LDAP connection: (0, 'Error')

Hello Guys,
This is my configuration. I keep getting this error Error while initializing LDAP connection: (0, 'Error')
Similar LDAP filter works perfectly with other model:
I tried lots of possibilities, but none of them seem to work. I would really appreciate a help here.
https://github.com/kvspb/nginx-auth-ldap

  location / {
        proxy_set_header X-Real-IP  $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://192.168.20.69:8080/main/;
        auth_request /auth-proxy;
               }

        location = /auth-proxy {
          internal;
        proxy_pass http://127.0.0.1:8888;
        proxy_pass_request_body off;
        #proxy_set_header Content-Length "";
        #proxy_cache auth_cache;
        #proxy_cache_valid 200 10m;
        #proxy_set_header X-CookieName "nginxauth";
        #proxy_set_header Cookie nginxauth=$cookie_nginxauth;
        proxy_set_header X-Ldap-URL "ldaps://ldap.jumpcloud.com:636/ou=Users,o=companyid,dc=jumpcloud,dc=com?uid?sub?(objectClass=posixAccount)";
        proxy_set_header X-Ldap-BaseDN "ou=Users,o=password,dc=jumpcloud,dc=com";
        proxy_set_header X-Ldap-BindDN "uid=user-bind,ou=Users,o=companyid,dc=jumpcloud,dc=com";
        proxy_set_header X-Ldap-BindPass "password";
        proxy_set_header X-Ldap-Realm    Restricted;

nginx-ldap on docker - not working

Hi @faisal-memon ,

I am from BNYMellon. We are trying to setup nginx-ldap for our one of our service.

I cloned the project from git repo. Then built an image using the existing docker file and started the nginxldap service.
docker run -d -p 9000:80 -v /null/nginx.conf:/etc/nginx/nginx.conf nginxldap

When i checked the logs it shows - Start listening on 0.0.0.0:8888...
When i enter the username and pwd - it shows 13/Aug/2018 11:30:58] LDAP baseDN is not set! in logs

Attaching my nginx.conf (Which has all the connection details).

Your help is really appreciated.

Thanks,
Vivek

Help with exchange webmail

Hi,

it´s not an issue but will help me a lot.

What are the right parameters to use the modul for exchange webmail (owa)
server address mail.example.net
LDAP request work (with the example.py)
So I must only change the backend options?

Thanks for your help.

Regards

misleading error message if log directory is not accessible

Setting the $LOG variable to a file in a non-existent directory will result in a message telling me that the non-existent log file does not exist:

# rm -rf /var/log/nginx-ldap-auth
# LOG=/var/log/nginx-ldap-auth/daemon.log /usr/bin/nginx-ldap-auth-daemon
/usr/bin/nginx-ldap-auth-daemon: line 2: /var/log/nginx-ldap-auth/daemon.log: No such file or directory

The shell code should possibly try to create the directory and/or emit a more explicit message that warns the user that the log directory cannot be accessed.

(IMHO: better yet to get rid of the /bin/sh stuff and directly use #!/usr/bin/env python2 as per PEP-0394)

proxy_set_header X-Ldap-Template in README.md

IT's indicated that the template X-Ldap-Template could be:
"(&(cn=%(username)s)(memberOf=cn=group1,cn=Users,dc=example,dc=com))";
It's:
"(&(cn=%(username)s)(memberOf=cn=group1,cn=Groups,dc=example,dc=com))";

500 Internal Server Error

Hi, I follow this reference step by step: https://www.nginx.com/blog/nginx-plus-authenticate-users/
But when I use a web browser to access http://localhost:8081.
image
Is there something wrong in my nginx.conf?
nginx.conf:

error_log logs/error.log debug;
worker_processes  4;
worker_rlimit_nofile 65535;
events {
worker_connections 10240;
}
http {
    proxy_cache_path cache/  keys_zone=auth_cache:10m;
    upstream backend {
        server 127.0.0.1:9000;
    }
    server {
        listen 8081;
        location / {
            auth_request /auth-proxy;
            error_page 401 =200 /login;

            proxy_pass http://backend/;
        }
        location /login {
            proxy_pass http://backend/login;
            proxy_set_header X-Target $request_uri;
        }
        location = /auth-proxy {
            internal;
            proxy_pass http://127.0.0.1:8888;
            proxy_pass_request_body off;
            proxy_set_header Content-Length "";
            proxy_cache auth_cache;
            proxy_cache_valid 200 10m;
            proxy_cache_key "$http_authorization$cookie_nginxauth";
            proxy_set_header X-Ldap-URL      "ldap://localhost/dc=xinhua,dc=org?uid?sub?(objectClass=posixAccount)";
            proxy_set_header X-Ldap-BaseDN   "cn=secretary,ou=group,dc=xinhua,dc=org";
            proxy_set_header X-Ldap-BindDN   "cn=Manager,dc=xinhua,dc=org";
            proxy_set_header X-Ldap-BindPass "mypassword";
            proxy_set_header X-CookieName "nginxauth";
            proxy_set_header Cookie nginxauth=$cookie_nginxauth;

        }
    }
}

image

I didn't modified nginx-ldap-auth-daemon-rh-ctl.sh and python backend-sample-app.py.
thank you in advance!

500 error if ldap-auth service unreachable

I've got 500 error if my ldap-auth temporary unreachable.
Can I use basic authentification when ldap-auth unreachable?
Tell me, please, how can this be set in config file.

I will be grateful for any help!

proxy_set_header X-Ldap-Opt-Referals

Hello.

It would be great to be able to specify the OPT_REFERRAL option with the related header.

This is useful in case of:

  1. when updating with git (there is no need to edit the script)
  2. when working with multiple independent LDAP servers

Fails to auth if BaseDN isn't maximally narrow OU

I have a problem that this module seems to generally work, however I can't make it work for all of our users:
Our users (CNs in AD) are located in different OUs and there's no way to specify as BaseDN some common ancestor: if I do so - all users fail to log in.

Reduced case:
In AD:
CN=UserA,OU=X,OU=Users,OU=BranchA,DC=my,DC=corp
CN=UserB,OU=Y,OU=Users,OU=BranchB,DC=my,DC=corp
both are members of the group CN=access-group,OU=special_groups,OU=technical_stuff,DC=my,DC=corp
tech account, used for binding with AD:
CN=ldap_gatekeeper,OU=Service Accounts,DC=my,DC=corp

In nginx vhost config:

  proxy_set_header X-Ldap-URL "ldap://my.corp:389";
  proxy_set_header X-Ldap-BaseDN "DC=my,DC=corp"; # fails to auth both UserA and UserB
  proxy_set_header X-Ldap-BindDN "CN=ldap_gatekeeper,OU=Service Accounts,DC=my,DC=corp";
  proxy_set_header X-Ldap-BindPass "passwordhere";
  proxy_set_header X-Ldap-Template "(&(objectClass=user)(sAMAccountName=%(username)s)(memberOf=CN=access-group,OU=special_groups,OU=technical_stuff,DC=my,DC=corp))"";

It appears as if nginx-ldap-auth doesn't search for users in specified BaseDN recursively.

Log looks like this:

- using username/password from authorization header
UserA searching on server "ldap:/my.corp:389" with base dn "DC=my,DC=corp" with filter "(&(objectClass=user)(sAMAccountName=UserA)(memberOf=CN=access-group,OU=special_groups,OU=technical_stuff,DC=my,DC=corp))"
UserA Error while running search query: {'info': '000004DC: LdapErr: DSID-0C090A7D, comment: In order to perform this operation a successful bind must be completed on the connection., data 0, V3839', 'desc': 'Operations error'}, server="ldap://my.corp:389", login="UserA"
UserA "GET /auth HTTP/1.0" 401 -

When nginx vhost is configured so:

  proxy_set_header X-Ldap-BaseDN "OU=Y,OU=Users,OU=BranchB,DC=my,DC=corp"; # successfully auths UserA, but fails to auth UserB

the log looks like this:

- using username/password from authorization header
UserA searching on server "ldap:/my.corp:389" with base dn "OU=Y,OU=Users,OU=BranchB,DC=my,DC=corp" with filter "(&(objectClass=user)(sAMAccountName=UserA)(memberOf=CN=access-group,OU=special_groups,OU=technical_stuff,DC=my,DC=corp))"
UserA attempting to bind using dn "CN=John Smith,OU=Y,OU=Users,OU=BranchB,DC=my,DC=corp"
UserA Auth OK for user "UserA"
UserA "Get /auth HTTP/1.0" 200 -

Judging by the error's wording it looks like it fails even to bind to LDAP, but mind you, that my nginx vhost conf contains X-Ldap-BindDN and X-Ldap-BindPass headers configured to use a service account.

cookies timeout [feature]

i write cookies timeout code

expiretime = datetime.now() + timedelta(minutes=1)
enc = base64.b64encode(user + ':' + passwd)
self.send_header('Set-Cookie', 'nginxauth=' + enc + '; httponly; Expires=%s' % expiretime.strftime('%d-%b-%y %H:%M:%S'))

but not working, any suggest?

Unable to build docker file

Hey,
I'm encountering an issue while trying to run the build command in the documentation. The system is running on CentOS7 (I believe it's 7.7). I've tried both commands I could find in regards to building this and am facing the same error message. I'm not particularly seasoned in Docker so I'm probably just using an obsolete syntax or something but can't seem to find anything online

docker build -t nginx-ldap-auth-daemon --build-arg PYTHON_VERSION=3 . Sending build context to Docker daemon 210.9 kB Step 1/7 : ARG PYTHON_VERSION=2 Please provide a source image with fromprior to commit

docker build -f Dockerfile.test -t my-tag --build-arg PYTHON_VERSION=3 . Sending build context to Docker daemon 210.9 kB Step 1/17 : ARG PYTHON_VERSION=2 Please provide a source image with fromprior to commit

Lots of errors in logfile when used in conjunction with basic auth

Hi,

when used in conjunction with basic auth (and "satisfy any;"), if authorized via ldap, for every subsequent request an error is logged in /var/log/nginx/error.log:
[..] user "[email protected]" was not found in "/etc/nginx/auth/example.com.pw^@" [..]

(example.org.pw contains the htpasswords for basic auth)

Conversely, for requests after authorization via basic auth an error is logged in /var/log/nginx-ldap-auth/daemon.log:
[..] Error while verifying search query results: no objects found, server="ldap://ad.example.com:3268", login="foo" [..]

At least the latter is only logged once (presumably as long as the authorization result is cached, e.g. every 10 minutes).

So both mechanisms work and can coexist, but whichever one isn't being used logs an error, with basic auth being extremely verbose (an error for every single request).

Is there a way to tell the other mechanism not to log an error?

Please update documentation

Hi, please add to step 8 the information that in case of Red Hat / CentOS the script nginx-ldap-auth-daemon-ctl**-rh**.sh has to be used. Otherwise the error "start-stop-daemon: command not found" will be displayed. Thanks!

Setting X-Ldap-Starttls "true" always gives an error

Hi,

depending on what combination of X-Ldap-URL "ldap(s)://..:" I try, when X-Ldap-Starttls "true" is set I always get an error:

With X-Ldap-URL "ldap://10.1.2.3:3268":
Error while initializing LDAP connection: {'info': '(unknown error code)', 'desc': 'Connect error'}, server="ldap://10.1.2.3:3268", login="[email protected]"

"ldap://10.1.2.3:389";
Error while initializing LDAP connection: {'info': '(unknown error code)', 'desc': 'Connect error'}, server="ldap://10.1.2.3:389", login="[email protected]"

"ldap://..:636":
Error while initializing LDAP connection: {'desc': "Can't contact LDAP server"}, server="ldap://10.1.2.3:636", login="[email protected]"

I guess ldaps shouldn't be mixed with TLS, but for completeness sake:
"ldaps://..:636":
Error while initializing LDAP connection: {'info': '(unknown error code)', 'desc': "Can't contact LDAP server"}, server="ldaps://10.1.2.3:636", login="[email protected]"

"ldaps://..:389" and "ldaps://..:3268":
Error while initializing LDAP connection: {'info': 'Error in the pull function.', 'desc': "Can't contact LDAP server"}, server="ldaps://10.1.2.3:389", login="[email protected]"
Error while initializing LDAP connection: {'info': 'Error in the pull function.', 'desc': "Can't contact LDAP server"}, server="ldaps://10.1.2.3:3268", login="[email protected]"

Also, when commenting out the line with X-Ldap-Starttls "true", even then only ldap://..:3268 seems to work in our setup.

ldapsearch -ZZ -H ldap://..:389 and -H ldaps://..:636 works fine after adding our AD's cert via dpgk-reconfigure ca-certificates (exported base 64 x.509 .crt in /usr/local/share/ca-certificates/), am I correct in assuming this isn't used by nginx-ldap-auth? Am I doing something wrong or is secure transmission not working at this moment?

nginx config parameters used:

internal;
proxy_pass http://127.0.0.1:8888$request_uri;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Ldap-URL "ldap://10.1.2.3:3268";
proxy_set_header X-Ldap-Starttls "true";
proxy_set_header X-Ldap-BaseDN "dc=domain,dc=com";
proxy_set_header X-Ldap-BindDN "[email protected]";
proxy_set_header X-Ldap-BindPass "ldapuserspassword";
proxy_set_header X-CookieName "nginxauth";
proxy_set_header Cookie nginxauth=$cookie_nginxauth;
proxy_set_header X-Ldap-Template "(&(memberOf=CN=AccessGroup,OU=_Unit,OU=_Department,DC=domain,DC=com)(userPrincipalName=%(username)s))";

This is on Debian 9.3 in combination with a Windows 2012R2 AD.

Anonymous supported ?

We wanted to have nginx with anonymous LDAP access, can you please share the example on how the ldap config should be ? We dont provide "Root DN", no manager DN/password, only LDAP server , user search base, user search filter and group search base. To elaborate, just like we have "basic authentication" available with nginx, i need similar approach for nginx with ldap integration. Can any one please share config containing this such examples ?

install from rpm

When i build rpm package via rpmbuild and install it to other host, i got error
Failed to start LDAP authentication helper for Nginx.
ls -la /var/log/nginx-ldap-auth/
total 4
drwxr-x--- 2 root root 6 Apr 9 12:46 .
But after
chown -R nginx-ldap-auth /var/log/nginx-ldap-auth
it starts good.

nginx config failure

I am going through the instructions on a fresh ubuntu 14 vagrant machine. Once the machine is spun up I run:

sudo apt-get update && 
sudo apt-get install -y nginx && 
sudo apt-get install -y python-ldap && 
sudo apt-get install -y git && 

git clone [email protected]:nginxinc/nginx-ldap-auth.git && 
sudo cp nginx-ldap-auth/nginx-ldap-auth.conf /etc/nginx/conf.d/ && 
sudo rm /etc/nginx/sites-enabled/default

per the instructions in the readme.

When I run sudo nginx -t I get the below error and can't proceed.

vagrant@logjam:~$ sudo nginx -t
nginx: [emerg] "error_log" directive is duplicate in /etc/nginx/conf.d/nginx-ldap-auth.conf:1
nginx: configuration file /etc/nginx/nginx.conf test failed

Am I doing something incorrectly?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.