Hi hackers,

During the work in [1] we created a new TAP test to test the SYSTEM_USER behavior with peer authentication.

It turns out that there is currently no TAP test for the peer authentication, so we think (thanks Michael for the suggestion [2]) that it's better to split the work in [1] between "pure" SYSTEM_USER related work and the "pure" peer authentication TAP test work.

That's the reason of this new thread, please find attached a patch to add a new TAP test for the peer authentication.

[1]: https://www.postgresql.org/message-id/flat/7e692b8c-0b11-45db-1cad-3afc5b57409f%40amazon.com

[2]: https://www.postgresql.org/message-id/YwgboqQUV1%2BY/k6z%40paquier.xyz

Regards,

--
Bertrand Drouvot
Amazon Web Services: https://aws.amazon.com
diff --git a/src/test/authentication/t/003_peer.pl 
b/src/test/authentication/t/003_peer.pl
new file mode 100644
index 0000000000..006c4405a5
--- /dev/null
+++ b/src/test/authentication/t/003_peer.pl
@@ -0,0 +1,140 @@
+
+# Copyright (c) 2022, PostgreSQL Global Development Group
+
+# Tests for peer authentication and user name map.
+# The test is skipped if the platform does not support peer authentication.
+
+use strict;
+use warnings;
+use PostgreSQL::Test::Cluster;
+use PostgreSQL::Test::Utils;
+use Test::More;
+
+# Delete pg_hba.conf from the given node, add a new entry to it
+# and then execute a reload to refresh it.
+sub reset_pg_hba
+{
+       my $node       = shift;
+       my $hba_method = shift;
+
+       unlink($node->data_dir . '/pg_hba.conf');
+       # just for testing purposes, use a continuation line.
+       $node->append_conf('pg_hba.conf', "local all all\\\n $hba_method");
+       $node->reload;
+       return;
+}
+
+# Test access for a single role, useful to wrap all tests into one.
+sub test_role
+{
+  local $Test::Builder::Level = $Test::Builder::Level + 1;
+
+  my ($node, $role, $method, $expected_res) = @_;
+  my $status_string = 'failed';
+  $status_string = 'success' if ($expected_res eq 0);
+
+  my $connstr = "user=$role";
+  my $testname =
+    "authentication $status_string for method $method, role $role";
+
+  if ($expected_res eq 0)
+  {
+    $node->connect_ok($connstr, $testname);
+  }
+  else
+  {
+      # No checks of the error message, only the status code.
+      $node->connect_fails($connstr, $testname);
+  }
+}
+
+# return the size of logfile of $node in bytes.
+sub get_log_size
+{
+  my ($node) = @_;
+
+  return (stat $node->logfile)[7];
+}
+
+# find $pat in logfile of $node after $off-th byte.
+sub find_in_log
+{
+  my ($node, $pat, $off) = @_;
+
+  $off = 0 unless defined $off;
+  my $log = PostgreSQL::Test::Utils::slurp_file($node->logfile);
+  return 0 if (length($log) <= $off);
+
+  $log = substr($log, $off);
+
+  return $log =~ m/$pat/;
+}
+
+# Initialize primary node.
+my $node = PostgreSQL::Test::Cluster->new('primary');
+$node->init;
+$node->append_conf('postgresql.conf', "log_connections = on\n");
+$node->start;
+
+# Get the session_user to define the user name map test.
+my $session_user =
+  $node->safe_psql('postgres', 'select session_user');
+
+# Create a new user for the user name map test.
+$node->safe_psql('postgres',
+  qq{CREATE USER testmap$session_user});
+
+# Set pg_hba.conf with the peer authentication.
+reset_pg_hba($node, 'peer');
+
+# Check that peer authentication is supported on this platform.
+my $logstart = get_log_size($node);
+
+$node->psql('postgres', undef, connstr  => "user=$session_user");
+
+# If not supported, then skip the rest of the test.
+if (find_in_log($node, qr/peer authentication is not supported on this 
platform/, $logstart))
+{
+    plan skip_all => 'peer authentication is not supported on this platform';
+}
+
+# It's supported so let's test peer authentication.
+# This connection should succeed.
+$logstart = get_log_size($node);
+test_role($node, $session_user, 'peer', 0);
+
+ok( find_in_log(
+      $node,
+      qr/connection authenticated: identity="$session_user" method=peer/, 
$logstart),
+      "logfile: connection authenticated for method peer and identity 
$session_user");
+
+# This connection should failed.
+$logstart = get_log_size($node);
+test_role($node, qq{testmap$session_user}, 'peer', 2);
+
+ok( find_in_log(
+      $node,
+      qr/Peer authentication failed for user "testmap$session_user"/, 
$logstart),
+      "logfile: Peer authentication failed for user testmap$session_user");
+
+# Define a user name map.
+$node->append_conf('pg_ident.conf', qq{mypeermap $session_user 
testmap$session_user});
+
+# Set pg_hba.conf with the peer authentication and the user name map.
+reset_pg_hba($node, 'peer map=mypeermap');
+
+# This connection should now succeed.
+$logstart = get_log_size($node);
+test_role($node, qq{testmap$session_user}, 'peer', 0);
+
+ok( find_in_log(
+      $node,
+      qr/connection authenticated: identity="$session_user" method=peer/, 
$logstart),
+      "logfile: connection authenticated for method peer and identity 
$session_user");
+
+ok( find_in_log(
+      $node,
+      qr/connection authorized: user=testmap$session_user/, $logstart),
+      "logfile: connection authorized for user testmap$session_user");
+
+done_testing();
\ No newline at end of file

Reply via email to