On 2023-01-01 Su 14:02, Thomas Munro wrote: > On Mon, Jan 2, 2023 at 3:04 AM Andrew Dunstan <and...@dunslane.net> wrote: >> On 2022-12-19 Mo 11:16, Andrew Dunstan wrote: >>> There is currently no test for the use of ldapbindpasswd in the >>> pg_hba.conf file. This patch, mostly the work of John Naylor, remedies that. >>> >>> >> This currently has failures on the cfbot for meson builds on FBSD13 and >> Debian Bullseye, but it's not at all clear why. In both cases it fails >> where the ldap server is started. > I think it's failing when using meson. I guess it fails to fail on > macOS only because you need to add a new path for Homebrew/ARM like > commit 14d63dd2, so it's skipping (it'd be nice if we didn't need > another copy of all that logic). Trying locally... it looks like > slapd is failing silently, and with some tracing I can see it's > sending an error message to my syslog daemon, which logged: > > 2023-01-02T07:50:20.853019+13:00 x1 slapd[153599]: main: TLS init def > ctx failed: -1 > > Ah, it looks like this test is relying on "slapd-certs", which doesn't exist: > > tmunro@x1:~/projects/postgresql/build$ ls testrun/ldap/001_auth/data/ > ldap.conf ldappassword openldap-data portlock slapd-certs slapd.conf > tmunro@x1:~/projects/postgresql/build$ ls testrun/ldap/002_bindpasswd/data/ > portlock slapd.conf > > I didn't look closely, but apparently there is something wrong in the > part that copies certs from the ssl test? Not sure why it works for > autoconf...
Let's see how we fare with this patch. cheers andrew -- Andrew Dunstan EDB: https://www.enterprisedb.com
From dace23df29efb43aa5e4bddc99098203c0e5ed00 Mon Sep 17 00:00:00 2001 From: Andrew Dunstan <and...@dunslane.net> Date: Sun, 1 Jan 2023 18:27:30 -0500 Subject: [PATCH] Add a test for ldapbindpasswd The existing LDAP tests don't cover the use of ldapbindpasswd in pg_hba.conf, so remedy that. Author: John Naylor --- src/test/ldap/meson.build | 1 + src/test/ldap/t/002_bindpasswd.pl | 207 ++++++++++++++++++++++++++++++ 2 files changed, 208 insertions(+) create mode 100644 src/test/ldap/t/002_bindpasswd.pl diff --git a/src/test/ldap/meson.build b/src/test/ldap/meson.build index 90d88138e7..7628a9c7c6 100644 --- a/src/test/ldap/meson.build +++ b/src/test/ldap/meson.build @@ -7,6 +7,7 @@ tests += { 'tap': { 'tests': [ 't/001_auth.pl', + 't/002_bindpasswd.pl', ], 'env': { 'with_ldap': ldap.found() ? 'yes' : 'no', diff --git a/src/test/ldap/t/002_bindpasswd.pl b/src/test/ldap/t/002_bindpasswd.pl new file mode 100644 index 0000000000..8296864209 --- /dev/null +++ b/src/test/ldap/t/002_bindpasswd.pl @@ -0,0 +1,207 @@ + +# Copyright (c) 2022, PostgreSQL Global Development Group + +use strict; +use warnings; +use File::Copy; +use PostgreSQL::Test::Utils; +use PostgreSQL::Test::Cluster; +use Test::More; + + +my ($slapd, $ldap_bin_dir, $ldap_schema_dir); + +$ldap_bin_dir = undef; # usually in PATH + +if ($ENV{with_ldap} ne 'yes') +{ + plan skip_all => 'LDAP not supported by this build'; +} +elsif ($ENV{PG_TEST_EXTRA} !~ /\bldap\b/) +{ + plan skip_all => 'Potentially unsafe test LDAP not enabled in PG_TEST_EXTRA'; +} +elsif ($^O eq 'darwin' && -d '/usr/local/opt/openldap') +{ + # typical paths for Homebrew + $slapd = '/usr/local/opt/openldap/libexec/slapd'; + $ldap_schema_dir = '/usr/local/etc/openldap/schema'; +} +elsif ($^O eq 'darwin' && -d '/opt/homebrew/opt/openldap') +{ + # typical paths for Homebrew on ARM + $slapd = '/opt/homebrew/opt/openldap/libexec/slapd'; + $ldap_schema_dir = '/opt/homebrew/etc/openldap/schema'; +} +elsif ($^O eq 'darwin' && -d '/opt/local/etc/openldap') +{ + # typical paths for MacPorts + $slapd = '/opt/local/libexec/slapd'; + $ldap_schema_dir = '/opt/local/etc/openldap/schema'; +} +elsif ($^O eq 'linux') +{ + $slapd = '/usr/sbin/slapd'; + $ldap_schema_dir = '/etc/ldap/schema' if -d '/etc/ldap/schema'; + $ldap_schema_dir = '/etc/openldap/schema' if -d '/etc/openldap/schema'; +} +elsif ($^O eq 'freebsd') +{ + $slapd = '/usr/local/libexec/slapd'; + $ldap_schema_dir = '/usr/local/etc/openldap/schema'; +} +elsif ($^O eq 'openbsd') +{ + $slapd = '/usr/local/libexec/slapd'; + $ldap_schema_dir = '/usr/local/share/examples/openldap/schema'; +} +else +{ + plan skip_all => "ldap tests not supported on $^O or dependencies not installed"; +} + +# 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 = "${PostgreSQL::Test::Utils::tmp_check}/openldap-data"; +my $slapd_certs = "${PostgreSQL::Test::Utils::tmp_check}/slapd-certs"; +my $slapd_conf = "${PostgreSQL::Test::Utils::tmp_check}/slapd.conf"; +my $slapd_pidfile = "${PostgreSQL::Test::Utils::tmp_check}/slapd.pid"; +my $slapd_logfile = "${PostgreSQL::Test::Utils::log_path}/slapd.log"; +my $ldap_conf = "${PostgreSQL::Test::Utils::tmp_check}/ldap.conf"; +my $ldap_server = 'localhost'; +my $ldap_port = PostgreSQL::Test::Cluster::get_free_port(); +my $ldaps_port = PostgreSQL::Test::Cluster::get_free_port(); +my $ldap_url = "ldap://$ldap_server:$ldap_port"; +my $ldaps_url = "ldaps://$ldap_server:$ldaps_port"; +my $ldap_basedn = 'dc=example,dc=net'; +my $ldap_rootdn = 'cn=Manager,dc=example,dc=net'; +my $ldap_rootpw = 'secret'; +my $ldap_pwfile = "${PostgreSQL::Test::Utils::tmp_check}/ldappassword"; + +note "setting up slapd"; + +# need to create new config without anonymous auth +unlink $slapd_conf; + +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 users auth + +database ldif +directory $ldap_datadir + +TLSCACertificateFile $slapd_certs/ca.crt +TLSCertificateFile $slapd_certs/server.crt +TLSCertificateKeyFile $slapd_certs/server.key + +suffix "dc=example,dc=net" +rootdn "$ldap_rootdn" +rootpw $ldap_rootpw}); + +mkdir $ldap_datadir or die; +mkdir $slapd_certs or die; + +copy "../ssl/ssl/server_ca.crt", "$slapd_certs/ca.crt" + || die "copying ca.crt: $!"; +copy "../ssl/ssl/server-cn-only.crt", "$slapd_certs/server.crt" + || die "copying server.crt: $!";; +copy "../ssl/ssl/server-cn-only.key", "$slapd_certs/server.key" + || die "copying server.key: $!";; + +system_or_bail $slapd, '-f', $slapd_conf, '-h', "$ldap_url $ldaps_url"; + +END +{ + kill 'INT', `cat $slapd_pidfile` if -f $slapd_pidfile; +} + +# wait until slapd accepts requests +my $retries = 0; +while (1) +{ + last + if ( + system_log( + "ldapsearch", "-sbase", + "-H", $ldap_url, + "-b", $ldap_basedn, + "-D", $ldap_rootdn, + "-y", $ldap_pwfile, + "-n", "'objectclass=*'") == 0); + die "cannot connect to slapd" if ++$retries >= 300; + note "waiting for slapd to accept requests..."; + Time::HiRes::usleep(1000000); +} + +$ENV{'LDAPURI'} = $ldap_url; +$ENV{'LDAPBINDDN'} = $ldap_rootdn; +$ENV{'LDAPCONF'} = $ldap_conf; + +# use same data as 001 test + +note "setting up PostgreSQL instance"; + +my $node = PostgreSQL::Test::Cluster->new('node'); +$node->init; +$node->append_conf('postgresql.conf', "log_connections = on\n"); +$node->start; + +$node->safe_psql('postgres', 'CREATE USER test0;'); +$node->safe_psql('postgres', 'CREATE USER test1;'); +$node->safe_psql('postgres', 'CREATE USER "te...@example.net";'); + +note "running tests"; + +sub test_access +{ + local $Test::Builder::Level = $Test::Builder::Level + 1; + + my ($node, $role, $expected_res, $test_name, %params) = @_; + my $connstr = "user=$role"; + + if ($expected_res eq 0) + { + $node->connect_ok($connstr, $test_name, %params); + } + else + { + # No checks of the error message, only the status code. + $node->connect_fails($connstr, $test_name, %params); + } +} + +note "use ldapbindpasswd"; + +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" ldapbinddn="$ldap_rootdn" ldapbindpasswd=wrong} +); +$node->restart; + +$ENV{"PGPASSWORD"} = 'secret1'; +test_access($node, 'test1', 2, 'search+bind authentication fails with wrong ldapbindpasswd'); + +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" ldapbinddn="$ldap_rootdn" ldapbindpasswd="$ldap_rootpw"} +); +$node->restart; + +test_access($node, 'test1', 0, 'search+bind authentication succeeds with ldapbindpasswd'); + +done_testing(); -- 2.34.1