1
0
mirror of https://github.com/postgres/postgres.git synced 2025-09-02 04:21:28 +03:00

Add some information about authenticated identity via log_connections

The "authenticated identity" is the string used by an authentication
method to identify a particular user.  In many common cases, this is the
same as the PostgreSQL username, but for some third-party authentication
methods, the identifier in use may be shortened or otherwise translated
(e.g. through pg_ident user mappings) before the server stores it.

To help administrators see who has actually interacted with the system,
this commit adds the capability to store the original identity when
authentication succeeds within the backend's Port, and generates a log
entry when log_connections is enabled.  The log entries generated look
something like this (where a local user named "foouser" is connecting to
the database as the database user called "admin"):

  LOG:  connection received: host=[local]
  LOG:  connection authenticated: identity="foouser" method=peer (/data/pg_hba.conf:88)
  LOG:  connection authorized: user=admin database=postgres application_name=psql

Port->authn_id is set according to the authentication method:

  bsd: the PostgreSQL username (aka the local username)
  cert: the client's Subject DN
  gss: the user principal
  ident: the remote username
  ldap: the final bind DN
  pam: the PostgreSQL username (aka PAM username)
  password (and all pw-challenge methods): the PostgreSQL username
  peer: the peer's pw_name
  radius: the PostgreSQL username (aka the RADIUS username)
  sspi: either the down-level (SAM-compatible) logon name, if
        compat_realm=1, or the User Principal Name if compat_realm=0

The trust auth method does not set an authenticated identity.  Neither
does clientcert=verify-full.

Port->authn_id could be used for other purposes, like a superuser-only
extra column in pg_stat_activity, but this is left as future work.

PostgresNode::connect_{ok,fails}() have been modified to let tests check
the backend log files for required or prohibited patterns, using the
new log_like and log_unlike parameters.  This uses a method based on a
truncation of the existing server log file, like issues_sql_like().
Tests are added to the ldap, kerberos, authentication and SSL test
suites.

Author: Jacob Champion
Reviewed-by: Stephen Frost, Magnus Hagander, Tom Lane, Michael Paquier
Discussion: https://postgr.es/m/c55788dd1773c521c862e8e0dddb367df51222be.camel@vmware.com
This commit is contained in:
Michael Paquier
2021-04-07 10:16:39 +09:00
parent 8ee9b662da
commit 9afffcb833
11 changed files with 416 additions and 74 deletions

View File

@@ -17,7 +17,7 @@ if (!$use_unix_sockets)
}
else
{
plan tests => 13;
plan tests => 23;
}
@@ -35,15 +35,12 @@ sub reset_pg_hba
return;
}
# Test access for a single role, useful to wrap all tests into one.
# Test access for a single role, useful to wrap all tests into one. Extra
# named parameters are passed to connect_ok/fails as-is.
sub test_role
{
my $node = shift;
my $role = shift;
my $method = shift;
my $expected_res = shift;
my ($node, $role, $method, $expected_res, %params) = @_;
my $status_string = 'failed';
$status_string = 'success' if ($expected_res eq 0);
my $connstr = "user=$role";
@@ -52,18 +49,19 @@ sub test_role
if ($expected_res eq 0)
{
$node->connect_ok($connstr, $testname);
$node->connect_ok($connstr, $testname, %params);
}
else
{
# No checks of the error message, only the status code.
$node->connect_fails($connstr, $testname);
$node->connect_fails($connstr, $testname, %params);
}
}
# Initialize primary node
my $node = get_new_node('primary');
$node->init;
$node->append_conf('postgresql.conf', "log_connections = on\n");
$node->start;
# Create 3 roles with different password methods for each one. The same
@@ -76,26 +74,51 @@ $node->safe_psql('postgres',
);
$ENV{"PGPASSWORD"} = 'pass';
# For "trust" method, all users should be able to connect.
# For "trust" method, all users should be able to connect. These users are not
# considered to be authenticated.
reset_pg_hba($node, 'trust');
test_role($node, 'scram_role', 'trust', 0);
test_role($node, 'md5_role', 'trust', 0);
test_role($node, 'scram_role', 'trust', 0,
log_unlike => [qr/connection authenticated:/]);
test_role($node, 'md5_role', 'trust', 0,
log_unlike => [qr/connection authenticated:/]);
# For plain "password" method, all users should also be able to connect.
reset_pg_hba($node, 'password');
test_role($node, 'scram_role', 'password', 0);
test_role($node, 'md5_role', 'password', 0);
test_role($node, 'scram_role', 'password', 0,
log_like =>
[qr/connection authenticated: identity="scram_role" method=password/]);
test_role($node, 'md5_role', 'password', 0,
log_like =>
[qr/connection authenticated: identity="md5_role" method=password/]);
# For "scram-sha-256" method, user "scram_role" should be able to connect.
reset_pg_hba($node, 'scram-sha-256');
test_role($node, 'scram_role', 'scram-sha-256', 0);
test_role($node, 'md5_role', 'scram-sha-256', 2);
test_role(
$node,
'scram_role',
'scram-sha-256',
0,
log_like => [
qr/connection authenticated: identity="scram_role" method=scram-sha-256/
]);
test_role($node, 'md5_role', 'scram-sha-256', 2,
log_unlike => [qr/connection authenticated:/]);
# Test that bad passwords are rejected.
$ENV{"PGPASSWORD"} = 'badpass';
test_role($node, 'scram_role', 'scram-sha-256', 2,
log_unlike => [qr/connection authenticated:/]);
$ENV{"PGPASSWORD"} = 'pass';
# For "md5" method, all users should be able to connect (SCRAM
# authentication will be performed for the user with a SCRAM secret.)
reset_pg_hba($node, 'md5');
test_role($node, 'scram_role', 'md5', 0);
test_role($node, 'md5_role', 'md5', 0);
test_role($node, 'scram_role', 'md5', 0,
log_like =>
[qr/connection authenticated: identity="scram_role" method=md5/]);
test_role($node, 'md5_role', 'md5', 0,
log_like =>
[qr/connection authenticated: identity="md5_role" method=md5/]);
# Tests for channel binding without SSL.
# Using the password authentication method; channel binding can't work