On 2023-01-01 Su 18:31, Andrew Dunstan wrote:
> 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.
>
>

Not so well :-(. This version tries to make the tests totally
independent, as they should be. That's an attempt to get the cfbot to go
green, but I am intending to refactor this code substantially so the
common bits are in a module each test file will load.


cheers


andrew



--
Andrew Dunstan
EDB: https://www.enterprisedb.com
From c2bedfd8a5b326ffb563da49b7b4b4006ddac361 Mon Sep 17 00:00:00 2001
From: Andrew Dunstan <and...@dunslane.net>
Date: Mon, 2 Jan 2023 09:41:06 -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.

Authors: John Naylor and Andrew Dunstan
---
 src/test/ldap/meson.build         |   1 +
 src/test/ldap/t/002_bindpasswd.pl | 223 ++++++++++++++++++++++++++++++
 2 files changed, 224 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..330a2b7dad
--- /dev/null
+++ b/src/test/ldap/t/002_bindpasswd.pl
@@ -0,0 +1,223 @@
+
+# Copyright (c) 2022, PostgreSQL Global Development Group
+
+use strict;
+use warnings;
+use File::Copy;
+use File::Basename;
+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 '/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 '/usr/local/opt/openldap')
+{
+	# typical paths for Homebrew on Intel
+	$slapd           = '/usr/local/opt/openldap/libexec/slapd';
+	$ldap_schema_dir = '/usr/local/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 $tst_name = basename(__FILE__,'.pl');
+my $test_temp = PostgreSQL::Test::Utils::tempdir("ldap-$tst_name");
+
+my $ldap_datadir  = "$test_temp/openldap-data";
+my $slapd_certs   = "$test_temp/slapd-certs";
+my $slapd_conf    = "$test_temp/slapd.conf";
+my $slapd_pidfile = "$test_temp/slapd.pid";
+my $slapd_logfile = "${PostgreSQL::Test::Utils::log_path}/slapd-2.log";
+my $ldap_conf     = "$test_temp/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   = "$test_temp/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 "making $ldap_datadir: $!";
+mkdir $slapd_certs  or die "making $slapd_certs: $!";
+
+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;
+}
+
+append_to_file($ldap_pwfile, $ldap_rootpw);
+chmod 0600, $ldap_pwfile or die;
+
+# 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 "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 = 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

Reply via email to