Added test suite.
The testsuite depends on nginx test suite, and requires an OpenLDAP server installed.
This commit is contained in:
parent
850f5ea5ca
commit
57fb98b528
|
|
@ -0,0 +1,22 @@
|
|||
Test suite is available at http://hg.nginx.org/nginx-tests.
|
||||
Check the http://hg.nginx.org/nginx-tests/file/tip/README file
|
||||
for instructions on how to use it.
|
||||
|
||||
Additionally, the test requires a working installation
|
||||
of OpenLDAP server and utilities (http://www.openldap.org/),
|
||||
and python's coverage tool (https://coverage.readthedocs.io)
|
||||
|
||||
copy ldap-auth.t into testsuite, setup environment variables:
|
||||
|
||||
$ export TEST_LDAP_DAEMON=/usr/lib64/openldap/slapd
|
||||
$ export TEST_LDAP_AUTH_DAEMON=/path/to/nginx-ldap-auth-daemon.py
|
||||
$ prove 'ldap-auth.t'
|
||||
|
||||
to get coverage report:
|
||||
|
||||
$ export TEST_NGINX_LEAVE=1
|
||||
$ prove 'ldap-auth.t'
|
||||
$ cd /tmp/nginx-test-xxxx
|
||||
$ coverage2 html
|
||||
|
||||
report is now generated in htmlcov/
|
||||
|
|
@ -0,0 +1,444 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
# (C) Nginx, Inc.
|
||||
|
||||
# Test for nginx-ldap-auth daemon with OpenLDAP.
|
||||
|
||||
###############################################################################
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
use Test::More;
|
||||
|
||||
use MIME::Base64;
|
||||
|
||||
BEGIN { use FindBin; chdir($FindBin::Bin); }
|
||||
|
||||
use lib 'lib';
|
||||
use Test::Nginx;
|
||||
|
||||
###############################################################################
|
||||
|
||||
select STDERR; $| = 1;
|
||||
select STDOUT; $| = 1;
|
||||
|
||||
my $t = Test::Nginx->new()->has(qw/http proxy rewrite auth_request/)
|
||||
->write_file_expand('nginx.conf', <<'EOF');
|
||||
|
||||
%%TEST_GLOBALS%%
|
||||
|
||||
events { }
|
||||
|
||||
daemon off;
|
||||
|
||||
http {
|
||||
|
||||
%%TEST_GLOBALS_HTTP%%
|
||||
|
||||
#proxy_cache_path cache/ keys_zone=auth_cache:10m;
|
||||
|
||||
server {
|
||||
listen 127.0.0.1:8082;
|
||||
|
||||
location / {
|
||||
return 200 "ACCESS GRANTED\n";
|
||||
}
|
||||
|
||||
location /login {
|
||||
return 200 "LOGIN PAGE\n";
|
||||
}
|
||||
}
|
||||
|
||||
upstream backend {
|
||||
server 127.0.0.1:8082;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 127.0.0.1:8080;
|
||||
|
||||
location / {
|
||||
auth_request /auth-proxy;
|
||||
|
||||
error_page 401 =200 /login;
|
||||
|
||||
proxy_pass http://backend/;
|
||||
}
|
||||
|
||||
location /ssl {
|
||||
auth_request /auth-proxy-ssl;
|
||||
|
||||
error_page 401 =200 /login;
|
||||
|
||||
proxy_pass http://backend/;
|
||||
}
|
||||
|
||||
location /starttls {
|
||||
auth_request /auth-proxy-starttls;
|
||||
|
||||
error_page 401 =200 /login;
|
||||
|
||||
proxy_pass http://backend/;
|
||||
}
|
||||
|
||||
location /nodn {
|
||||
auth_request /auth-nodn;
|
||||
|
||||
error_page 401 =200 /login;
|
||||
|
||||
proxy_pass http://backend/;
|
||||
}
|
||||
|
||||
location /nourl {
|
||||
auth_request /auth-nourl;
|
||||
|
||||
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://127.0.0.1:8083";
|
||||
proxy_set_header X-Ldap-BaseDN "ou=Users,dc=test,dc=local";
|
||||
proxy_set_header X-Ldap-BindDN "cn=root,dc=test,dc=local";
|
||||
proxy_set_header X-Ldap-BindPass "secret";
|
||||
|
||||
proxy_set_header X-CookieName "nginxauth";
|
||||
proxy_set_header Cookie nginxauth=$cookie_nginxauth;
|
||||
|
||||
#proxy_set_header X-Ldap-Starttls "true";
|
||||
|
||||
#proxy_set_header X-Ldap-Template "(sAMAccountName=%(username)s)";
|
||||
#proxy_set_header X-Ldap-DisableReferrals "true";
|
||||
|
||||
#proxy_set_header X-Ldap-Template "(cn=%(username)s)";
|
||||
#proxy_set_header X-Ldap-Realm "Restricted";
|
||||
}
|
||||
|
||||
location = /auth-proxy-ssl {
|
||||
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 "ldaps://127.0.0.1:8084";
|
||||
proxy_set_header X-Ldap-BaseDN "ou=Users,dc=test,dc=local";
|
||||
proxy_set_header X-Ldap-BindDN "cn=root,dc=test,dc=local";
|
||||
proxy_set_header X-Ldap-BindPass "secret";
|
||||
|
||||
proxy_set_header X-CookieName "nginxauth";
|
||||
proxy_set_header Cookie nginxauth=$cookie_nginxauth;
|
||||
|
||||
#proxy_set_header X-Ldap-Starttls "true";
|
||||
}
|
||||
|
||||
location = /auth-proxy-starttls {
|
||||
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://127.0.0.1:8083";
|
||||
proxy_set_header X-Ldap-BaseDN "ou=Users,dc=test,dc=local";
|
||||
proxy_set_header X-Ldap-BindDN "cn=root,dc=test,dc=local";
|
||||
proxy_set_header X-Ldap-BindPass "secret";
|
||||
|
||||
proxy_set_header X-CookieName "nginxauth";
|
||||
proxy_set_header Cookie nginxauth=$cookie_nginxauth;
|
||||
|
||||
proxy_set_header X-Ldap-Starttls "true";
|
||||
}
|
||||
|
||||
location = /auth-nodn {
|
||||
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://127.0.0.1:8083";
|
||||
proxy_set_header X-Ldap-BindDN "cn=root,dc=test,dc=local";
|
||||
proxy_set_header X-Ldap-BindPass "secret";
|
||||
}
|
||||
|
||||
location = /auth-nourl {
|
||||
internal;
|
||||
|
||||
proxy_pass http://127.0.0.1:8888;
|
||||
|
||||
proxy_pass_request_body off;
|
||||
proxy_set_header Content-Length "";
|
||||
|
||||
proxy_set_header X-Ldap-BaseDN "ou=Users,dc=test,dc=local";
|
||||
proxy_set_header X-Ldap-BindDN "cn=root,dc=test,dc=local";
|
||||
proxy_set_header X-Ldap-BindPass "secret";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EOF
|
||||
|
||||
my $d = $t->testdir();
|
||||
|
||||
$t->write_file('openssl.conf', <<EOF);
|
||||
[ req ]
|
||||
default_bits = 1024
|
||||
encrypt_key = no
|
||||
distinguished_name = req_distinguished_name
|
||||
[ req_distinguished_name ]
|
||||
EOF
|
||||
|
||||
foreach my $name ('localhost') {
|
||||
system('openssl req -x509 -new '
|
||||
. "-config $d/openssl.conf -subj /CN=$name/ "
|
||||
. "-out $d/$name.crt -keyout $d/$name.key "
|
||||
. ">>$d/openssl.out 2>&1") == 0
|
||||
or die "Can't create certificate for $name: $!\n";
|
||||
}
|
||||
|
||||
$t->write_file_expand("slapd.conf", <<"EOF");
|
||||
include /etc/openldap/schema/core.schema
|
||||
include /etc/openldap/schema/cosine.schema
|
||||
include /etc/openldap/schema/inetorgperson.schema
|
||||
include /etc/openldap/schema/nis.schema
|
||||
include /etc/openldap/schema/misc.schema
|
||||
|
||||
pidfile $d/slapd.pid
|
||||
argsfile $d/slapd.args
|
||||
logfile $d/slapd.log
|
||||
|
||||
loglevel 256 64
|
||||
|
||||
access to dn.base="" by * read
|
||||
access to dn.base="cn=Subschema" by * read
|
||||
access to *
|
||||
by self write
|
||||
by users read
|
||||
by anonymous read
|
||||
|
||||
database hdb
|
||||
suffix "dc=test,dc=local"
|
||||
rootdn "cn=root,dc=test,dc=local"
|
||||
rootpw secret
|
||||
directory $d/openldap-data
|
||||
index objectClass eq
|
||||
|
||||
TLSCipherSuite HIGH:MEDIUM:+SSLv2
|
||||
TLSCACertificateFile $d/localhost.crt
|
||||
TLSCertificateFile $d/localhost.crt
|
||||
TLSCertificateKeyFile $d/localhost.key
|
||||
|
||||
EOF
|
||||
|
||||
|
||||
$t->write_file_expand("initial.ldif", <<'EOF');
|
||||
dn: dc=test,dc=local
|
||||
dc: test
|
||||
description: BlaBlaBla
|
||||
objectClass: dcObject
|
||||
objectClass: organization
|
||||
o: Example, Inc.
|
||||
|
||||
dn: ou=Users, dc=test,dc=local
|
||||
ou: Users
|
||||
description: All people in organisation
|
||||
objectclass: organizationalunit
|
||||
|
||||
dn: cn=user1,ou=Users,dc=test,dc=local
|
||||
objectclass: inetOrgPerson
|
||||
cn: User number one
|
||||
sn: u1
|
||||
uid: user1
|
||||
userpassword: user1secret
|
||||
mail: user1@example.com
|
||||
description: user1
|
||||
ou: Users
|
||||
|
||||
dn: cn=user2,ou=Users,dc=test,dc=local
|
||||
objectclass: inetOrgPerson
|
||||
cn: User number one
|
||||
sn: u2
|
||||
uid: user2
|
||||
userpassword: user2secret
|
||||
mail: user2@example.com
|
||||
description: user2
|
||||
ou: Users
|
||||
|
||||
dn: cn=user3,ou=Users,dc=test,dc=local
|
||||
objectclass: inetOrgPerson
|
||||
cn: User number one
|
||||
sn: u3
|
||||
uid: user3
|
||||
userpassword: user3secret
|
||||
mail: user3@example.com
|
||||
description: user3
|
||||
ou: Users
|
||||
|
||||
EOF
|
||||
|
||||
# -u ldap -g ldap
|
||||
my $SLAPD = defined $ENV{TEST_LDAP_DAEMON} ? $ENV{TEST_LDAP_DAEMON}
|
||||
: '/usr/lib64/openldap/slapd';
|
||||
|
||||
my $AUTHD = defined $ENV{TEST_LDAP_AUTH_DAEMON} ? $ENV{TEST_LDAP_AUTH_DAEMON}
|
||||
: 'nginx-ldap-auth-daemon.py';
|
||||
|
||||
$t->has_daemon($SLAPD);
|
||||
$t->has_daemon($AUTHD);
|
||||
|
||||
mkdir("$d/openldap-data");
|
||||
|
||||
my $p3 = port(8083);
|
||||
my $p4 = port(8084);
|
||||
|
||||
# change '0' to '1' or more to get debug from slapd
|
||||
$t->run_daemon($SLAPD, '-d', '0', '-f', "$d/slapd.conf",
|
||||
'-h', "ldap://127.0.0.1:$p3 ldaps://127.0.0.1:$p4");
|
||||
|
||||
$t->waitforsocket("127.0.0.1:$p3") or die "Can't start slapd";
|
||||
|
||||
|
||||
system("ldapadd -H ldap://127.0.0.1:$p3 -x -D \"cn=root,dc=test,dc=local\""
|
||||
. " -f $d/initial.ldif -w secret >> $d/ldif.log 2>&1") == 0
|
||||
or die "Can't import initial LDIF\n";
|
||||
|
||||
|
||||
$t->write_file_expand("auth_daemon.sh", <<"EOF");
|
||||
AUTHBIN=\$(realpath $AUTHD)
|
||||
cd $d
|
||||
exec coverage2 run \$AUTHBIN --host 127.0.0.1 \\
|
||||
-p %%PORT_8888%% >$d/nginx-ldap-auth-dameon.stdlog 2>&1
|
||||
EOF
|
||||
|
||||
$t->run_daemon('/bin/sh', "$d/auth_daemon.sh");
|
||||
$t->waitforsocket('127.0.0.1:' . port(8888))
|
||||
or die "Can't start auth daemon";
|
||||
|
||||
$t->plan(19);
|
||||
|
||||
$t->run();
|
||||
|
||||
###############################################################################
|
||||
|
||||
like(http_get_auth('/', 'user1', 'user1secret'), qr!ACCESS GRANTED!,
|
||||
'proper user with proper pass');
|
||||
like(http_get_auth('/', 'user1', 'randompass'), qr!LOGIN PAGE!,
|
||||
'proper user with incorrect pass');
|
||||
like(http_get_auth('/', 'user111', 'user1secret'), qr!LOGIN PAGE!,
|
||||
'similar user with user1 pass');
|
||||
like(http_get_auth('/', 'randomuser', 'randompass'), qr!LOGIN PAGE!,
|
||||
'random user with random pass');
|
||||
like(http_get_auth('/', 'user2', 'user2secret'), qr!ACCESS GRANTED!,
|
||||
'user2 with proper pass');
|
||||
like(http_get_auth('/', 'user3', 'user3secret'), qr!ACCESS GRANTED!,
|
||||
'user3 with proper pass');
|
||||
like(http_get_auth('/', '', ''), qr!LOGIN PAGE!, 'empty user no password');
|
||||
like(http_get('/'), qr!LOGIN PAGE!, 'no auth header');
|
||||
|
||||
like(http_get_cookie('/', 'user1', 'user1secret'), qr!ACCESS GRANTED!,
|
||||
'proper user with proper pass cookie');
|
||||
like(http_get_cookie('/', 'user1', 'randompasz'), qr!LOGIN PAGE!,
|
||||
'proper user with incorrect pass cookie');
|
||||
like(http_get_cookie('/', 'randomuser', 'randompass'), qr!LOGIN PAGE!,
|
||||
'random user with random pass cookie');
|
||||
like(http_get_cookie('/', 'user2', 'user2secret'), qr!ACCESS GRANTED!,
|
||||
'user2 with proper pass cookie');
|
||||
like(http_get_cookie('/', 'user3', 'user3secret'), qr!ACCESS GRANTED!,
|
||||
'user3 with proper pass cookie');
|
||||
|
||||
like(http_get_auth_broken_base64('/', 'user3', 'user3secret'), qr!LOGIN PAGE!,
|
||||
'user3 with proper pass broken base64');
|
||||
like(http_get_cookie_broken_base64('/', 'user3', 'user3secret'), qr!LOGIN PAGE!,
|
||||
'user3 with proper pass broken cookie');
|
||||
|
||||
like(http_get_auth('/ssl', 'user1', 'user1secret'), qr!ACCESS GRANTED!,
|
||||
'proper user with proper pass with ssl');
|
||||
|
||||
like(http_get_auth('/starttls', 'user1', 'user1secret'), qr!ACCESS GRANTED!,
|
||||
'proper user with proper pass with starttls');
|
||||
|
||||
# dn is not set, no default, daemon error => 502
|
||||
like(http_get_auth('/nodn', 'user1', 'user1secret'), qr!Internal Server Error!,
|
||||
'dn must be set');
|
||||
|
||||
# url is not set, default is used, which is not accessible => login page
|
||||
like(http_get_auth('/nourl', 'user1', 'user1secret'), qr!LOGIN PAGE!,
|
||||
'url must be set');
|
||||
|
||||
###############################################################################
|
||||
|
||||
sub http_get_auth {
|
||||
my ($url, $user, $password) = @_;
|
||||
|
||||
my $auth = encode_base64($user . ':' . $password, '');
|
||||
|
||||
return http(<<EOF);
|
||||
GET $url HTTP/1.0
|
||||
Host: localhost
|
||||
Authorization: Basic $auth
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# do not encode auth with base64, send plain
|
||||
sub http_get_auth_broken_base64 {
|
||||
my ($url, $user, $password) = @_;
|
||||
|
||||
my $auth = $user . ':' . $password;
|
||||
|
||||
return http(<<EOF);
|
||||
GET $url HTTP/1.0
|
||||
Host: localhost
|
||||
Authorization: Basic $auth
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
|
||||
sub http_get_cookie {
|
||||
my ($url, $user, $password) = @_;
|
||||
|
||||
my $auth = encode_base64($user . ':' . $password, '');
|
||||
|
||||
return http(<<EOF);
|
||||
GET $url HTTP/1.0
|
||||
Host: localhost
|
||||
Cookie: nginxauth=$auth
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
sub http_get_cookie_broken_base64 {
|
||||
my ($url, $user, $password) = @_;
|
||||
|
||||
my $auth = $user . ':' . $password;
|
||||
|
||||
return http(<<EOF);
|
||||
GET $url HTTP/1.0
|
||||
Host: localhost
|
||||
Cookie: nginxauth=$auth
|
||||
|
||||
EOF
|
||||
}
|
||||
Loading…
Reference in New Issue