560 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Perl
		
	
	
	
			
		
		
	
	
			560 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Perl
		
	
	
	
| #!/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 /ref1 {
 | |
|             auth_request /auth-ref1;
 | |
| 
 | |
|             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";
 | |
|         }
 | |
| 
 | |
|         location = /auth-ref1 {
 | |
|             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;
 | |
|         }
 | |
| 
 | |
|     }
 | |
| }
 | |
| 
 | |
| 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("slapd2.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/slapd2.pid
 | |
| argsfile $d/slapd2.args
 | |
| logfile $d/slapd2.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 "ou=Users, dc=test,dc=local"
 | |
| rootdn "cn=root, ou=Users, dc=test,dc=local"
 | |
| rootpw secret
 | |
| directory $d/openldap2-data
 | |
| index objectClass eq
 | |
| 
 | |
| TLSCipherSuite HIGH:MEDIUM:+SSLv2
 | |
| TLSCACertificateFile $d/localhost.crt
 | |
| TLSCertificateFile $d/localhost.crt
 | |
| TLSCertificateKeyFile $d/localhost.key
 | |
| 
 | |
| # our upstream
 | |
| referral   ldap://127.0.0.1:%%PORT_8083%%/
 | |
| 
 | |
| 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
 | |
| 
 | |
| dn: ou=more,ou=Users,dc=test,dc=local
 | |
| objectClass: referral
 | |
| objectClass: extensibleObject
 | |
| dc: subtree
 | |
| ref: ldap://127.0.0.1:%%PORT_8085%%/ou=more,ou=Users,dc=test,dc=local
 | |
| 
 | |
| EOF
 | |
| 
 | |
| 
 | |
| $t->write_file_expand("initial2.ldif", <<'EOF');
 | |
| dn: ou=Users, dc=test,dc=local
 | |
| ou: Users
 | |
| description: All people in organisation
 | |
| objectclass: organizationalunit
 | |
| 
 | |
| dn: ou=more,ou=Users,dc=test,dc=local
 | |
| dc: test
 | |
| description: BlaBlaBla
 | |
| objectClass: dcObject
 | |
| objectClass: organizationalUnit
 | |
| 
 | |
| dn: cn=user4, ou=more, ou=Users,dc=test,dc=local
 | |
| objectclass: inetOrgPerson
 | |
| cn: User number one
 | |
| sn: u4
 | |
| uid: user4
 | |
| userpassword: user4secret
 | |
| mail: user4@example.com
 | |
| description: user4
 | |
| 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");
 | |
| mkdir("$d/openldap2-data");
 | |
| 
 | |
| my $p3 = port(8083);
 | |
| my $p4 = port(8084);
 | |
| my $p5 = port(8085);
 | |
| 
 | |
| # 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->run_daemon($SLAPD, '-d', '0', '-f', "$d/slapd2.conf",
 | |
| 		'-h', "ldap://127.0.0.1:$p5");
 | |
| 
 | |
| $t->waitforsocket("127.0.0.1:$p3") or die "Can't start slapd";
 | |
| $t->waitforsocket("127.0.0.1:$p5") or die "Can't start slapd2";
 | |
| 
 | |
| 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";
 | |
| 
 | |
| system("ldapadd -H ldap://127.0.0.1:$p5 -x -D \"cn=root,ou=Users,dc=test,dc=local\""
 | |
|        . " -f $d/initial2.ldif -w secret >> $d/ldif2.log 2>&1") == 0
 | |
| 		or die "Can't import initial2 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(21);
 | |
| 
 | |
| $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');
 | |
| 
 | |
| # LDAP referrals
 | |
| 
 | |
| # user can be found, but bind happens on 1st server, instead of the found
 | |
| # the behaviour may change with different servers
 | |
| like(http_get_auth('/ref1', 'user4', 'user4secret'), qr!LOGIN PAGE!,
 | |
| 	'server2 user via referral on server1');
 | |
| 
 | |
| # unknown user on referred server, result is empty dn
 | |
| like(http_get_auth('/ref1', 'userx', 'blah'), qr!LOGIN PAGE!,
 | |
| 	'unknown user with referral on server1');
 | |
| 
 | |
| 
 | |
| ###############################################################################
 | |
| 
 | |
| 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
 | |
| }
 |