3
3
[ ![ Build Status] ( https://app.travis-ci.com/elonen/ldap_authz_proxy.svg?branch=master )] ( https://app.travis-ci.com/elonen/ldap_authz_proxy )
4
4
[ ![ Release] ( https://img.shields.io/github/v/release/elonen/ldap_authz_proxy?include_prereleases )] ( )
5
5
6
- Authorize Nginx users against LDAP, optionally returning attributes.
6
+ Secure any HTTP resource (static site, a web app, ...) with LDAP / Active Directory.
7
+ That is, trasparently authorize Nginx users against LDAP, optionally returning attributes.
7
8
8
- Once a user has been authenticated by some other means (e.g. Kerberos, Basic auth, Token, ...),
9
+ Once a user has been authenticated by some other means (e.g. OIDC, Kerberos, Basic auth, Token, ...),
9
10
this server can be used to authorize them to access some resource.
10
11
11
12
If one LDAP/Active Directory query is not enough, the program can perform sub-queries to
@@ -116,7 +117,7 @@ Corresponding **Nginx** configuration block would look roughly like this -- assu
116
117
}
117
118
```
118
119
119
- (See a more complete example below.)
120
+ (See more complete examples below.)
120
121
121
122
## Cache
122
123
@@ -139,11 +140,12 @@ was served from cache, and `0` if it was a fresh query.
139
140
The server is written in Rust and can be manually built with ` cargo build --release ` .
140
141
Resulting binary is ` target/release/ldap_authz_proxy ` .
141
142
142
- If you want Debian packages, see below.
143
+ If you want Debian packages instead (recommended) , see below.
143
144
144
145
## Running
145
146
146
- The server can be run with ` ldap_authz_proxy <configfile> ` . Additional
147
+ The recommended way to run the server is through a process manager (e.g. systemd),
148
+ but it can also be run manually like this: ` ldap_authz_proxy <configfile> ` . Additional
147
149
options are available (` --help ` ):
148
150
149
151
```
@@ -182,8 +184,8 @@ Options:
182
184
-v --version Show version.
183
185
```
184
186
185
- The executable stays in foreground, so it's recommended to run it
186
- with a process manager such as ` systemd ` or ` supervisord ` . Example
187
+ The executable stays in foreground, which is why it's recommended to use a
188
+ process manager such as ` systemd ` or ` supervisord ` . Example
187
189
` systemd ` service file is included in ` debian/service ` .
188
190
189
191
## Security
@@ -218,7 +220,7 @@ This is the recommended way to install this on Debian systems.
218
220
## Testing
219
221
220
222
Use ` ./run-tests.sh ` to execute test suite. It requires ` docker compose `
221
- and ` curl ` . The script performs an end-to-end integratiot test with a
223
+ and ` curl ` . The script performs an end-to-end integration test with a
222
224
real Active Directory server and an Nginx reverse proxy.
223
225
224
226
It spins up necessary containers, sets up example users, and then performs
@@ -246,7 +248,7 @@ server {
246
248
server_name www.example.com;
247
249
248
250
249
- satisfy all; # Require 2 auths: auth_gss (Kerberos) for authn and auth_request (LDAP proxy ) for authz
251
+ satisfy all; # Require 2 auths: auth_gss (Kerberos) for authn and auth_request (ldap_authz_proxy ) for authz
250
252
251
253
auth_gss on;
252
254
auth_gss_keytab /etc/krb5.keytab;
@@ -293,6 +295,102 @@ The VM running Nginx (and ldap_authz_proxy) was joined to AD domain like this:
293
295
Script(s) for building Nginx Kerberos (SPNEGO) module for Debian:
294
296
https://github.com/elonen/debian-nginx-spnego
295
297
298
+
299
+ ### OpenID Connect (OIDC, e.g. Okta)
300
+
301
+ This example uses [ Vouch Proxy] ( https://github.com/vouch/vouch-proxy ) to authenticate against
302
+ an OIDC ID provider (e.g. Okta), and then ldap_authz_proxy to authorize. Again, both authn and authz
303
+ happen transparently on Nginx level; the application itself doesn't know anything about LDAP, OIDC or auth tokens.
304
+
305
+ This configuration is a bit more complex than the previous ones, because it needs to
306
+ perform two ` auth_request ` calls: one for OIDC authentication and another for LDAP authorization.
307
+ Nginx doesn't allow multiple ` auth_request ` calls in the same location, so we need to
308
+ authenticate first, then proxy to another location that performs the authorization and finally
309
+ serves the actual application.
310
+
311
+ (This doesn't cover Vouch Proxy setup, see other docmentation for that.)
312
+
313
+ ``` nginx
314
+ # Phase 1: Authenticate and proxy to Phase 2
315
+ server {
316
+ listen 443 ssl;
317
+ ssl_certificate /etc/ssl/private/example.com.fullchain.pem;
318
+ ssl_certificate_key /etc/ssl/private/example.com.privkey.pem;
319
+
320
+ server_name my-app.example.com;
321
+
322
+ error_page 401 = @error401;
323
+ location @error401 {
324
+ return 302 https://vouch.example.com/login?url=https://$http_host$request_uri;
325
+ }
326
+
327
+ location = /authn {
328
+ internal;
329
+
330
+ proxy_pass https://vouch.example.com/validate;
331
+ proxy_pass_request_body off;
332
+ proxy_set_header Cookie $http_cookie;
333
+ proxy_set_header Content-Length "";
334
+
335
+ # If Vouch Proxy JWT validation returns 401, the error_page above will redirect to login page
336
+ }
337
+
338
+ location = / {
339
+ # Authn against Vouch Proxy and store results in variables:
340
+
341
+ auth_request /authn;
342
+ auth_request_set $authn_jwt $upstream_http_x_vouch_jwt;
343
+ auth_request_set $authn_user $upstream_http_x_vouch_user;
344
+
345
+ # Pass authenticated username to phase 2:
346
+
347
+ proxy_pass http://127.0.0.1:8000;
348
+ proxy_set_header X-Authn-User $authn_user;
349
+ }
350
+ }
351
+
352
+ # Phase 2: Authorize and serve the application
353
+ server {
354
+ listen 127.0.0.1:8000;
355
+
356
+ location = /authz {
357
+ internal;
358
+ proxy_pass http://127.0.0.1:10567/ldap_authz_example_app;
359
+ proxy_pass_request_body off;
360
+ proxy_set_header Content-Length "";
361
+ proxy_set_header X-Ldap-Authz-Username $http_x_authn_user;
362
+ }
363
+
364
+ location / {
365
+ # Authz against ldap_authz_proxy.
366
+ # Note that we already set X-Ldap-Authz-Username in phase 1, from where
367
+ # ldap_authz_proxy reads it.
368
+
369
+ auth_request /authz;
370
+ auth_request_set $ldap_displayname $upstream_http_x_ldap_res_displayname;
371
+ auth_request_set $ldap_groups $upstream_http_x_ldap_res_pdugroups;
372
+
373
+
374
+ # Example app: PHP script that gets, in headers, username from Vouch,
375
+ # and display name + groups from ldap_authz_proxy.
376
+ #
377
+ # You could replace this with another proxy_pass to a different app,
378
+ # or even just serve your top secret static files.
379
+
380
+ root /var/www/my-app;
381
+ index index.php;
382
+ try_files $uri $uri/ =404;
383
+ location ~ \.php$ {
384
+ include snippets/fastcgi-php.conf;
385
+ fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
386
+ fastcgi_param X_REMOTE_USER_ID $http_x_authn_user;
387
+ fastcgi_param X_USER_GROUPS $ldap_groups;
388
+ fastcgi_param X_DISPLAY_NAME $ldap_displayname;
389
+ }
390
+ }
391
+ }
392
+ ```
393
+
296
394
## Config option details
297
395
298
396
Configuration options (generated by ` ldap_authz_proxy --help-config ` ):
@@ -431,7 +529,7 @@ Config options:
431
529
Probably the easiest way to develop this is to spin up the LDAP server
432
530
in Docker and then run program locally:
433
531
434
- ``` bash
532
+ ``` bash
435
533
# Start test LDAP server
436
534
cd test
437
535
docker compose up --detach
0 commit comments