|
| 1 | + |
| 2 | +# Copyright (c) 2021-2022, PostgreSQL Global Development Group |
| 3 | + |
| 4 | +# Tests for peer authentication and user name map. |
| 5 | +# The test is skipped if the platform does not support peer authentication. |
| 6 | + |
| 7 | +use strict; |
| 8 | +use warnings; |
| 9 | +use PostgreSQL::Test::Cluster; |
| 10 | +use PostgreSQL::Test::Utils; |
| 11 | +use Test::More; |
| 12 | + |
| 13 | +# Delete pg_hba.conf from the given node, add a new entry to it |
| 14 | +# and then execute a reload to refresh it. |
| 15 | +subreset_pg_hba |
| 16 | +{ |
| 17 | +my$node =shift; |
| 18 | +my$hba_method =shift; |
| 19 | + |
| 20 | +unlink($node->data_dir .'/pg_hba.conf'); |
| 21 | +$node->append_conf('pg_hba.conf',"local all all$hba_method"); |
| 22 | +$node->reload; |
| 23 | +return; |
| 24 | +} |
| 25 | + |
| 26 | +# Test access for a single role, useful to wrap all tests into one. |
| 27 | +subtest_role |
| 28 | +{ |
| 29 | +local$Test::Builder::Level =$Test::Builder::Level + 1; |
| 30 | + |
| 31 | +my ($node,$role,$method,$expected_res,%params) =@_; |
| 32 | +my$status_string ='failed'; |
| 33 | +$status_string ='success'if ($expected_reseq 0); |
| 34 | + |
| 35 | +my$connstr ="user=$role"; |
| 36 | +my$testname = |
| 37 | +"authentication$status_string for method$method, role$role"; |
| 38 | + |
| 39 | +if ($expected_reseq 0) |
| 40 | +{ |
| 41 | +$node->connect_ok($connstr,$testname,%params); |
| 42 | +} |
| 43 | +else |
| 44 | +{ |
| 45 | +# No checks of the error message, only the status code. |
| 46 | +$node->connect_fails($connstr,$testname,%params); |
| 47 | +} |
| 48 | +} |
| 49 | + |
| 50 | +# Find $pattern in log file of $node. |
| 51 | +subfind_in_log |
| 52 | +{ |
| 53 | +my ($node,$offset,$pattern) =@_; |
| 54 | + |
| 55 | +my$log = PostgreSQL::Test::Utils::slurp_file($node->logfile,$offset); |
| 56 | +return 0if (length($log) <= 0); |
| 57 | + |
| 58 | +return$log =~m/$pattern/; |
| 59 | +} |
| 60 | + |
| 61 | +my$node = PostgreSQL::Test::Cluster->new('node'); |
| 62 | +$node->init; |
| 63 | +$node->append_conf('postgresql.conf',"log_connections = on\n"); |
| 64 | +$node->start; |
| 65 | + |
| 66 | +# Set pg_hba.conf with the peer authentication. |
| 67 | +reset_pg_hba($node,'peer'); |
| 68 | + |
| 69 | +# Check if peer authentication is supported on this platform. |
| 70 | +my$log_offset =-s$node->logfile; |
| 71 | +$node->psql('postgres'); |
| 72 | +if (find_in_log( |
| 73 | +$node,$log_offset, |
| 74 | +qr/peer authentication is not supported on this platform/)) |
| 75 | +{ |
| 76 | +planskip_all=>'peer authentication is not supported on this platform'; |
| 77 | +} |
| 78 | + |
| 79 | +# Add a database role, to use for the user name map. |
| 80 | +$node->safe_psql('postgres',qq{CREATE ROLE testmapuser LOGIN}); |
| 81 | + |
| 82 | +# Extract as well the system user for the user name map. |
| 83 | +my$system_user = |
| 84 | +$node->safe_psql('postgres', |
| 85 | +q(select (string_to_array(SYSTEM_USER, ':'))[2])); |
| 86 | + |
| 87 | +# Tests without the user name map. |
| 88 | +# Failure as connection is attempted with a database role not mapping |
| 89 | +# to an authorized system user. |
| 90 | +test_role($node,qq{testmapuser},'peer', 2, |
| 91 | +log_like=> [qr/Peer authentication failed for user "testmapuser"/]); |
| 92 | + |
| 93 | +# Tests with a user name map. |
| 94 | +$node->append_conf('pg_ident.conf',qq{mypeermap$system_user testmapuser}); |
| 95 | +reset_pg_hba($node,'peer map=mypeermap'); |
| 96 | + |
| 97 | +# Success as the database role matches with the system user in the map. |
| 98 | +test_role($node,qq{testmapuser},'peer', 0, |
| 99 | +log_like=> |
| 100 | + [qr/connection authenticated: identity="$system_user" method=peer/]); |
| 101 | + |
| 102 | +done_testing(); |