mirror of
https://github.com/postgres/postgres.git
synced 2025-04-24 10:47:04 +03:00
Add LDAP authentication test suite
Like the SSL test suite, this will not be run by default. Reviewed-by: Thomas Munro <thomas.munro@enterprisedb.com>
This commit is contained in:
parent
71aa4801a8
commit
f0e60ee4bc
@ -15,9 +15,10 @@ include $(top_builddir)/src/Makefile.global
|
||||
SUBDIRS = perl regress isolation modules authentication recovery subscription
|
||||
|
||||
# We don't build or execute examples/, locale/, or thread/ by default,
|
||||
# but we do want "make clean" etc to recurse into them. Likewise for ssl/,
|
||||
# because the SSL test suite is not secure to run on a multi-user system.
|
||||
ALWAYS_SUBDIRS = examples locale thread ssl
|
||||
# but we do want "make clean" etc to recurse into them. Likewise for
|
||||
# ldap/ and ssl/, because these test suites are not secure to run on a
|
||||
# multi-user system.
|
||||
ALWAYS_SUBDIRS = examples ldap locale thread ssl
|
||||
|
||||
# We want to recurse to all subdirs for all standard targets, except that
|
||||
# installcheck and install should not recurse into the subdirectory "modules".
|
||||
|
2
src/test/ldap/.gitignore
vendored
Normal file
2
src/test/ldap/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
# Generated by test suite
|
||||
/tmp_check/
|
20
src/test/ldap/Makefile
Normal file
20
src/test/ldap/Makefile
Normal file
@ -0,0 +1,20 @@
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Makefile for src/test/ldap
|
||||
#
|
||||
# Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
|
||||
# Portions Copyright (c) 1994, Regents of the University of California
|
||||
#
|
||||
# src/test/ldap/Makefile
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
subdir = src/test/ldap
|
||||
top_builddir = ../../..
|
||||
include $(top_builddir)/src/Makefile.global
|
||||
|
||||
check:
|
||||
$(prove_check)
|
||||
|
||||
clean distclean maintainer-clean:
|
||||
rm -rf tmp_check
|
20
src/test/ldap/README
Normal file
20
src/test/ldap/README
Normal file
@ -0,0 +1,20 @@
|
||||
src/test/ldap/README
|
||||
|
||||
Tests for LDAP functionality
|
||||
============================
|
||||
|
||||
This directory contains a test suite for LDAP functionality. This
|
||||
requires a full OpenLDAP installation, including server and client
|
||||
tools, and is therefore kept separate and not run by default. You
|
||||
might need to adjust some paths in the test file to have it find
|
||||
OpenLDAP in a place that hadn't been thought of yet.
|
||||
|
||||
Also, this test suite creates an LDAP server that listens for TCP/IP
|
||||
connections on localhost without any real access control, so it is not
|
||||
safe to run this on a system where there might be untrusted local
|
||||
users.
|
||||
|
||||
Running the tests
|
||||
=================
|
||||
|
||||
make check
|
32
src/test/ldap/authdata.ldif
Normal file
32
src/test/ldap/authdata.ldif
Normal file
@ -0,0 +1,32 @@
|
||||
dn: dc=example,dc=net
|
||||
objectClass: top
|
||||
objectClass: dcObject
|
||||
objectClass: organization
|
||||
dc: example
|
||||
o: ExampleCo
|
||||
|
||||
dn: uid=test1,dc=example,dc=net
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: posixAccount
|
||||
uid: test1
|
||||
sn: Lastname
|
||||
givenName: Firstname
|
||||
cn: First Test User
|
||||
displayName: First Test User
|
||||
uidNumber: 101
|
||||
gidNumber: 100
|
||||
homeDirectory: /home/test1
|
||||
mail: test1@example.net
|
||||
|
||||
dn: uid=test2,dc=example,dc=net
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: posixAccount
|
||||
uid: test2
|
||||
sn: Lastname
|
||||
givenName: Firstname
|
||||
cn: Second Test User
|
||||
displayName: Second Test User
|
||||
uidNumber: 102
|
||||
gidNumber: 100
|
||||
homeDirectory: /home/test2
|
||||
mail: test2@example.net
|
177
src/test/ldap/t/001_auth.pl
Normal file
177
src/test/ldap/t/001_auth.pl
Normal file
@ -0,0 +1,177 @@
|
||||
use strict;
|
||||
use warnings;
|
||||
use TestLib;
|
||||
use PostgresNode;
|
||||
use Test::More tests => 14;
|
||||
|
||||
my ($slapd, $ldap_bin_dir, $ldap_schema_dir);
|
||||
|
||||
$ldap_bin_dir = undef; # usually in PATH
|
||||
|
||||
if ($^O eq 'darwin')
|
||||
{
|
||||
$slapd = '/usr/local/opt/openldap/libexec/slapd';
|
||||
$ldap_schema_dir = '/usr/local/etc/openldap/schema';
|
||||
}
|
||||
elsif ($^O eq 'linux')
|
||||
{
|
||||
$slapd = '/usr/sbin/slapd';
|
||||
$ldap_schema_dir = '/etc/ldap/schema' if -f '/etc/ldap/schema';
|
||||
$ldap_schema_dir = '/etc/openldap/schema' if -f '/etc/openldap/schema';
|
||||
}
|
||||
elsif ($^O eq 'freebsd')
|
||||
{
|
||||
$slapd = '/usr/local/libexec/slapd';
|
||||
$ldap_schema_dir = '/usr/local/etc/openldap/schema';
|
||||
}
|
||||
|
||||
# make your own edits here
|
||||
#$slapd = '';
|
||||
#$ldap_bin_dir = '';
|
||||
#$ldap_schema_dir = '';
|
||||
|
||||
$ENV{PATH} = "$ldap_bin_dir:$ENV{PATH}" if $ldap_bin_dir;
|
||||
|
||||
my $ldap_datadir = "${TestLib::tmp_check}/openldap-data";
|
||||
my $slapd_conf = "${TestLib::tmp_check}/slapd.conf";
|
||||
my $slapd_pidfile = "${TestLib::tmp_check}/slapd.pid";
|
||||
my $slapd_logfile = "${TestLib::tmp_check}/slapd.log";
|
||||
my $ldap_conf = "${TestLib::tmp_check}/ldap.conf";
|
||||
my $ldap_server = 'localhost';
|
||||
my $ldap_port = int(rand() * 16384) + 49152;
|
||||
my $ldap_url = "ldap://$ldap_server:$ldap_port";
|
||||
my $ldap_basedn = 'dc=example,dc=net';
|
||||
my $ldap_rootdn = 'cn=Manager,dc=example,dc=net';
|
||||
my $ldap_rootpw = 'secret';
|
||||
my $ldap_pwfile = "${TestLib::tmp_check}/ldappassword";
|
||||
|
||||
note "setting up slapd";
|
||||
|
||||
append_to_file($slapd_conf,
|
||||
qq{include $ldap_schema_dir/core.schema
|
||||
include $ldap_schema_dir/cosine.schema
|
||||
include $ldap_schema_dir/nis.schema
|
||||
include $ldap_schema_dir/inetorgperson.schema
|
||||
|
||||
pidfile $slapd_pidfile
|
||||
logfile $slapd_logfile
|
||||
|
||||
access to *
|
||||
by * read
|
||||
by anonymous auth
|
||||
|
||||
database ldif
|
||||
directory $ldap_datadir
|
||||
|
||||
suffix "dc=example,dc=net"
|
||||
rootdn "$ldap_rootdn"
|
||||
rootpw $ldap_rootpw});
|
||||
|
||||
mkdir $ldap_datadir or die;
|
||||
|
||||
system_or_bail $slapd, '-f', $slapd_conf, '-h', $ldap_url;
|
||||
|
||||
END
|
||||
{
|
||||
kill 'INT', `cat $slapd_pidfile` if -f $slapd_pidfile;
|
||||
}
|
||||
|
||||
append_to_file($ldap_pwfile, $ldap_rootpw);
|
||||
chmod 0600, $ldap_pwfile or die;
|
||||
|
||||
$ENV{'LDAPURI'} = $ldap_url;
|
||||
$ENV{'LDAPBINDDN'} = $ldap_rootdn;
|
||||
|
||||
note "loading LDAP data";
|
||||
|
||||
system_or_bail 'ldapadd', '-x', '-y', $ldap_pwfile, '-f', 'authdata.ldif';
|
||||
system_or_bail 'ldappasswd', '-x', '-y', $ldap_pwfile, '-s', 'secret1', 'uid=test1,dc=example,dc=net';
|
||||
system_or_bail 'ldappasswd', '-x', '-y', $ldap_pwfile, '-s', 'secret2', 'uid=test2,dc=example,dc=net';
|
||||
|
||||
note "setting up PostgreSQL instance";
|
||||
|
||||
my $node = get_new_node('node');
|
||||
$node->init;
|
||||
$node->start;
|
||||
|
||||
$node->safe_psql('postgres', 'CREATE USER test0;');
|
||||
$node->safe_psql('postgres', 'CREATE USER test1;');
|
||||
$node->safe_psql('postgres', 'CREATE USER "test2@example.net";');
|
||||
|
||||
note "running tests";
|
||||
|
||||
sub test_access
|
||||
{
|
||||
my ($node, $role, $expected_res, $test_name) = @_;
|
||||
|
||||
my $res = $node->psql('postgres', 'SELECT 1', extra_params => [ '-U', $role ]);
|
||||
is($res, $expected_res, $test_name);
|
||||
}
|
||||
|
||||
note "simple bind";
|
||||
|
||||
unlink($node->data_dir . '/pg_hba.conf');
|
||||
$node->append_conf('pg_hba.conf', qq{local all all ldap ldapserver=$ldap_server ldapport=$ldap_port ldapprefix="uid=" ldapsuffix=",dc=example,dc=net"});
|
||||
$node->reload;
|
||||
|
||||
$ENV{"PGPASSWORD"} = 'wrong';
|
||||
test_access($node, 'test0', 2, 'simple bind authentication fails if user not found in LDAP');
|
||||
test_access($node, 'test1', 2, 'simple bind authentication fails with wrong password');
|
||||
$ENV{"PGPASSWORD"} = 'secret1';
|
||||
test_access($node, 'test1', 0, 'simple bind authentication succeeds');
|
||||
|
||||
note "search+bind";
|
||||
|
||||
unlink($node->data_dir . '/pg_hba.conf');
|
||||
$node->append_conf('pg_hba.conf', qq{local all all ldap ldapserver=$ldap_server ldapport=$ldap_port ldapbasedn="$ldap_basedn"});
|
||||
$node->reload;
|
||||
|
||||
$ENV{"PGPASSWORD"} = 'wrong';
|
||||
test_access($node, 'test0', 2, 'search+bind authentication fails if user not found in LDAP');
|
||||
test_access($node, 'test1', 2, 'search+bind authentication fails with wrong password');
|
||||
$ENV{"PGPASSWORD"} = 'secret1';
|
||||
test_access($node, 'test1', 0, 'search+bind authentication succeeds');
|
||||
|
||||
note "LDAP URLs";
|
||||
|
||||
unlink($node->data_dir . '/pg_hba.conf');
|
||||
$node->append_conf('pg_hba.conf', qq{local all all ldap ldapurl="$ldap_url/$ldap_basedn?uid?sub"});
|
||||
$node->reload;
|
||||
|
||||
$ENV{"PGPASSWORD"} = 'wrong';
|
||||
test_access($node, 'test0', 2, 'search+bind with LDAP URL authentication fails if user not found in LDAP');
|
||||
test_access($node, 'test1', 2, 'search+bind with LDAP URL authentication fails with wrong password');
|
||||
$ENV{"PGPASSWORD"} = 'secret1';
|
||||
test_access($node, 'test1', 0, 'search+bind with LDAP URL authentication succeeds');
|
||||
|
||||
note "search filters";
|
||||
|
||||
unlink($node->data_dir . '/pg_hba.conf');
|
||||
$node->append_conf('pg_hba.conf', qq{local all all ldap ldapserver=$ldap_server ldapport=$ldap_port ldapbasedn="$ldap_basedn" ldapsearchfilter="(|(uid=\$username)(mail=\$username))"});
|
||||
$node->reload;
|
||||
|
||||
$ENV{"PGPASSWORD"} = 'secret1';
|
||||
test_access($node, 'test1', 0, 'search filter finds by uid');
|
||||
$ENV{"PGPASSWORD"} = 'secret2';
|
||||
test_access($node, 'test2@example.net', 0, 'search filter finds by mail');
|
||||
|
||||
note "search filters in LDAP URLs";
|
||||
|
||||
unlink($node->data_dir . '/pg_hba.conf');
|
||||
$node->append_conf('pg_hba.conf', qq{local all all ldap ldapurl="$ldap_url/$ldap_basedn??sub?(|(uid=\$username)(mail=\$username))"});
|
||||
$node->reload;
|
||||
|
||||
$ENV{"PGPASSWORD"} = 'secret1';
|
||||
test_access($node, 'test1', 0, 'search filter finds by uid');
|
||||
$ENV{"PGPASSWORD"} = 'secret2';
|
||||
test_access($node, 'test2@example.net', 0, 'search filter finds by mail');
|
||||
|
||||
# This is not documented: You can combine ldapurl and other ldap*
|
||||
# settings. ldapurl is always parsed first, then the other settings
|
||||
# override. It might be useful in a case like this.
|
||||
unlink($node->data_dir . '/pg_hba.conf');
|
||||
$node->append_conf('pg_hba.conf', qq{local all all ldap ldapurl="$ldap_url/$ldap_basedn??sub" ldapsearchfilter="(|(uid=\$username)(mail=\$username))"});
|
||||
$node->reload;
|
||||
|
||||
$ENV{"PGPASSWORD"} = 'secret1';
|
||||
test_access($node, 'test1', 0, 'combined LDAP URL and search filter');
|
Loading…
x
Reference in New Issue
Block a user