Refactor TAP test authentication/001_password.pl

The test is changed to test for connection strings rather than specific
roles, and the reset logic of pg_hba.conf is extended so as the database
and user name entries can be directly specified.  This is aimed at being
used as a base for more test scenarios of pg_hba.conf and authentication
paths.

Author: Bertrand Drouvot, Michael Paquier
Discussion: https://postgr.es/m/Yz0xO0emJ+mxtj2a@paquier.xyz
This commit is contained in:
Michael Paquier 2022-10-06 09:40:16 +09:00
parent d8df67bb1a
commit 051b096b8d
1 changed files with 31 additions and 29 deletions

View File

@ -24,28 +24,30 @@ if (!$use_unix_sockets)
sub reset_pg_hba sub reset_pg_hba
{ {
my $node = shift; my $node = shift;
my $database = shift;
my $role = shift;
my $hba_method = shift; my $hba_method = shift;
unlink($node->data_dir . '/pg_hba.conf'); unlink($node->data_dir . '/pg_hba.conf');
# just for testing purposes, use a continuation line # just for testing purposes, use a continuation line
$node->append_conf('pg_hba.conf', "local all all\\\n $hba_method"); $node->append_conf('pg_hba.conf',
"local $database $role\\\n $hba_method");
$node->reload; $node->reload;
return; return;
} }
# Test access for a single role, useful to wrap all tests into one. Extra # Test access for a connection string, useful to wrap all tests into one.
# named parameters are passed to connect_ok/fails as-is. # Extra named parameters are passed to connect_ok/fails as-is.
sub test_role sub test_conn
{ {
local $Test::Builder::Level = $Test::Builder::Level + 1; local $Test::Builder::Level = $Test::Builder::Level + 1;
my ($node, $role, $method, $expected_res, %params) = @_; my ($node, $connstr, $method, $expected_res, %params) = @_;
my $status_string = 'failed'; my $status_string = 'failed';
$status_string = 'success' if ($expected_res eq 0); $status_string = 'success' if ($expected_res eq 0);
my $connstr = "user=$role";
my $testname = my $testname =
"authentication $status_string for method $method, role $role"; "authentication $status_string for method $method, connstr $connstr";
if ($expected_res eq 0) if ($expected_res eq 0)
{ {
@ -81,10 +83,10 @@ $ENV{"PGPASSWORD"} = 'pass';
# For "trust" method, all users should be able to connect. These users are not # For "trust" method, all users should be able to connect. These users are not
# considered to be authenticated. # considered to be authenticated.
reset_pg_hba($node, 'trust'); reset_pg_hba($node, 'all', 'all', 'trust');
test_role($node, 'scram_role', 'trust', 0, test_conn($node, 'user=scram_role', 'trust', 0,
log_unlike => [qr/connection authenticated:/]); log_unlike => [qr/connection authenticated:/]);
test_role($node, 'md5_role', 'trust', 0, test_conn($node, 'user=md5_role', 'trust', 0,
log_unlike => [qr/connection authenticated:/]); log_unlike => [qr/connection authenticated:/]);
# SYSTEM_USER is null when not authenticated. # SYSTEM_USER is null when not authenticated.
@ -106,40 +108,40 @@ is($res, 't',
); );
# For plain "password" method, all users should also be able to connect. # For plain "password" method, all users should also be able to connect.
reset_pg_hba($node, 'password'); reset_pg_hba($node, 'all', 'all', 'password');
test_role($node, 'scram_role', 'password', 0, test_conn($node, 'user=scram_role', 'password', 0,
log_like => log_like =>
[qr/connection authenticated: identity="scram_role" method=password/]); [qr/connection authenticated: identity="scram_role" method=password/]);
test_role($node, 'md5_role', 'password', 0, test_conn($node, 'user=md5_role', 'password', 0,
log_like => log_like =>
[qr/connection authenticated: identity="md5_role" method=password/]); [qr/connection authenticated: identity="md5_role" method=password/]);
# For "scram-sha-256" method, user "scram_role" should be able to connect. # For "scram-sha-256" method, user "scram_role" should be able to connect.
reset_pg_hba($node, 'scram-sha-256'); reset_pg_hba($node, 'all', 'all', 'scram-sha-256');
test_role( test_conn(
$node, $node,
'scram_role', 'user=scram_role',
'scram-sha-256', 'scram-sha-256',
0, 0,
log_like => [ log_like => [
qr/connection authenticated: identity="scram_role" method=scram-sha-256/ qr/connection authenticated: identity="scram_role" method=scram-sha-256/
]); ]);
test_role($node, 'md5_role', 'scram-sha-256', 2, test_conn($node, 'user=md5_role', 'scram-sha-256', 2,
log_unlike => [qr/connection authenticated:/]); log_unlike => [qr/connection authenticated:/]);
# Test that bad passwords are rejected. # Test that bad passwords are rejected.
$ENV{"PGPASSWORD"} = 'badpass'; $ENV{"PGPASSWORD"} = 'badpass';
test_role($node, 'scram_role', 'scram-sha-256', 2, test_conn($node, 'user=scram_role', 'scram-sha-256', 2,
log_unlike => [qr/connection authenticated:/]); log_unlike => [qr/connection authenticated:/]);
$ENV{"PGPASSWORD"} = 'pass'; $ENV{"PGPASSWORD"} = 'pass';
# For "md5" method, all users should be able to connect (SCRAM # For "md5" method, all users should be able to connect (SCRAM
# authentication will be performed for the user with a SCRAM secret.) # authentication will be performed for the user with a SCRAM secret.)
reset_pg_hba($node, 'md5'); reset_pg_hba($node, 'all', 'all', 'md5');
test_role($node, 'scram_role', 'md5', 0, test_conn($node, 'user=scram_role', 'md5', 0,
log_like => log_like =>
[qr/connection authenticated: identity="scram_role" method=md5/]); [qr/connection authenticated: identity="scram_role" method=md5/]);
test_role($node, 'md5_role', 'md5', 0, test_conn($node, 'user=md5_role', 'md5', 0,
log_like => log_like =>
[qr/connection authenticated: identity="md5_role" method=md5/]); [qr/connection authenticated: identity="md5_role" method=md5/]);
@ -164,13 +166,13 @@ is($res, 't',
# Tests for channel binding without SSL. # Tests for channel binding without SSL.
# Using the password authentication method; channel binding can't work # Using the password authentication method; channel binding can't work
reset_pg_hba($node, 'password'); reset_pg_hba($node, 'all', 'all', 'password');
$ENV{"PGCHANNELBINDING"} = 'require'; $ENV{"PGCHANNELBINDING"} = 'require';
test_role($node, 'scram_role', 'scram-sha-256', 2); test_conn($node, 'user=scram_role', 'scram-sha-256', 2);
# SSL not in use; channel binding still can't work # SSL not in use; channel binding still can't work
reset_pg_hba($node, 'scram-sha-256'); reset_pg_hba($node, 'all', 'all', 'scram-sha-256');
$ENV{"PGCHANNELBINDING"} = 'require'; $ENV{"PGCHANNELBINDING"} = 'require';
test_role($node, 'scram_role', 'scram-sha-256', 2); test_conn($node, 'user=scram_role', 'scram-sha-256', 2);
# Test .pgpass processing; but use a temp file, don't overwrite the real one! # Test .pgpass processing; but use a temp file, don't overwrite the real one!
my $pgpassfile = "${PostgreSQL::Test::Utils::tmp_check}/pgpass"; my $pgpassfile = "${PostgreSQL::Test::Utils::tmp_check}/pgpass";
@ -187,15 +189,15 @@ append_to_file(
!); !);
chmod 0600, $pgpassfile or die; chmod 0600, $pgpassfile or die;
reset_pg_hba($node, 'password'); reset_pg_hba($node, 'all', 'all', 'password');
test_role($node, 'scram_role', 'password from pgpass', 0); test_conn($node, 'user=scram_role', 'password from pgpass', 0);
test_role($node, 'md5_role', 'password from pgpass', 2); test_conn($node, 'user=md5_role', 'password from pgpass', 2);
append_to_file( append_to_file(
$pgpassfile, qq! $pgpassfile, qq!
*:*:*:md5_role:p\\ass *:*:*:md5_role:p\\ass
!); !);
test_role($node, 'md5_role', 'password from pgpass', 0); test_conn($node, 'user=md5_role', 'password from pgpass', 0);
done_testing(); done_testing();