From f60eb3f2827db292edf71bb7296fbdf5958ace3d Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Mon, 3 Oct 2022 16:42:25 +0900 Subject: [PATCH] Add authentication TAP test for peer authentication This commit introduces an authentication test for the peer method, as of a set of scenarios with and without a user name map. The script is automatically skipped if peer is not supported in the environment where this test is run, checking this behavior by attempting a connection first on a cluster up and running. Author: Bertrand Drouvot Discussion: https://postgr.es/m/aa60994b-1c66-ca7a-dab9-9a200dbac3d2@amazon.com --- src/test/authentication/meson.build | 1 + src/test/authentication/t/003_peer.pl | 102 ++++++++++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 src/test/authentication/t/003_peer.pl diff --git a/src/test/authentication/meson.build b/src/test/authentication/meson.build index 2374028cbd..c2b48c43c9 100644 --- a/src/test/authentication/meson.build +++ b/src/test/authentication/meson.build @@ -6,6 +6,7 @@ tests += { 'tests': [ 't/001_password.pl', 't/002_saslprep.pl', + 't/003_peer.pl', ], }, } diff --git a/src/test/authentication/t/003_peer.pl b/src/test/authentication/t/003_peer.pl new file mode 100644 index 0000000000..fc951dea06 --- /dev/null +++ b/src/test/authentication/t/003_peer.pl @@ -0,0 +1,102 @@ + +# Copyright (c) 2021-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'); + $node->append_conf('pg_hba.conf', "local all all $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, %params) = @_; + 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, %params); + } + else + { + # No checks of the error message, only the status code. + $node->connect_fails($connstr, $testname, %params); + } +} + +# Find $pattern in log file of $node. +sub find_in_log +{ + my ($node, $offset, $pattern) = @_; + + my $log = PostgreSQL::Test::Utils::slurp_file($node->logfile, $offset); + return 0 if (length($log) <= 0); + + return $log =~ m/$pattern/; +} + +my $node = PostgreSQL::Test::Cluster->new('node'); +$node->init; +$node->append_conf('postgresql.conf', "log_connections = on\n"); +$node->start; + +# Set pg_hba.conf with the peer authentication. +reset_pg_hba($node, 'peer'); + +# Check if peer authentication is supported on this platform. +my $log_offset = -s $node->logfile; +$node->psql('postgres'); +if (find_in_log( + $node, $log_offset, + qr/peer authentication is not supported on this platform/)) +{ + plan skip_all => 'peer authentication is not supported on this platform'; +} + +# Add a database role, to use for the user name map. +$node->safe_psql('postgres', qq{CREATE ROLE testmapuser LOGIN}); + +# Extract as well the system user for the user name map. +my $system_user = + $node->safe_psql('postgres', + q(select (string_to_array(SYSTEM_USER, ':'))[2])); + +# Tests without the user name map. +# Failure as connection is attempted with a database role not mapping +# to an authorized system user. +test_role($node, qq{testmapuser}, 'peer', 2, + log_like => [qr/Peer authentication failed for user "testmapuser"/]); + +# Tests with a user name map. +$node->append_conf('pg_ident.conf', qq{mypeermap $system_user testmapuser}); +reset_pg_hba($node, 'peer map=mypeermap'); + +# Success as the database role matches with the system user in the map. +test_role($node, qq{testmapuser}, 'peer', 0, + log_like => + [qr/connection authenticated: identity="$system_user" method=peer/]); + +done_testing();