diff options
author | Michael Paquier | 2021-04-07 01:16:39 +0000 |
---|---|---|
committer | Michael Paquier | 2021-04-07 01:16:39 +0000 |
commit | 9afffcb833d3c5e59a328a2af674fac7e7334fc1 (patch) | |
tree | 48b3aff83fefc902317e30802abd453d5228a906 /src/test/perl/PostgresNode.pm | |
parent | 8ee9b662daa6d51b54d21ec274f22a218462ad2d (diff) |
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
Diffstat (limited to 'src/test/perl/PostgresNode.pm')
-rw-r--r-- | src/test/perl/PostgresNode.pm | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/src/test/perl/PostgresNode.pm b/src/test/perl/PostgresNode.pm index ec202f1b6e5..598906ad649 100644 --- a/src/test/perl/PostgresNode.pm +++ b/src/test/perl/PostgresNode.pm @@ -1876,6 +1876,18 @@ instead of the default. If this regular expression is set, matches it with the output generated. +=item log_like => [ qr/required message/ ] + +If given, it must be an array reference containing a list of regular +expressions that must match against the server log, using +C<Test::More::like()>. + +=item log_unlike => [ qr/prohibited message/ ] + +If given, it must be an array reference containing a list of regular +expressions that must NOT match against the server log. They will be +passed to C<Test::More::unlike()>. + =back =cut @@ -1895,6 +1907,22 @@ sub connect_ok $sql = "SELECT \$\$connected with $connstr\$\$"; } + my (@log_like, @log_unlike); + if (defined($params{log_like})) + { + @log_like = @{ $params{log_like} }; + } + if (defined($params{log_unlike})) + { + @log_unlike = @{ $params{log_unlike} }; + } + + if (@log_like or @log_unlike) + { + # Don't let previous log entries match for this connection. + truncate $self->logfile, 0; + } + # Never prompt for a password, any callers of this routine should # have set up things properly, and this should not block. my ($ret, $stdout, $stderr) = $self->psql( @@ -1910,6 +1938,19 @@ sub connect_ok { like($stdout, $params{expected_stdout}, "$test_name: matches"); } + if (@log_like or @log_unlike) + { + my $log_contents = TestLib::slurp_file($self->logfile); + + while (my $regex = shift @log_like) + { + like($log_contents, $regex, "$test_name: log matches"); + } + while (my $regex = shift @log_unlike) + { + unlike($log_contents, $regex, "$test_name: log does not match"); + } + } } =pod @@ -1925,6 +1966,12 @@ to fail. If this regular expression is set, matches it with the output generated. +=item log_like => [ qr/required message/ ] + +=item log_unlike => [ qr/prohibited message/ ] + +See C<connect_ok(...)>, above. + =back =cut @@ -1934,6 +1981,22 @@ sub connect_fails local $Test::Builder::Level = $Test::Builder::Level + 1; my ($self, $connstr, $test_name, %params) = @_; + my (@log_like, @log_unlike); + if (defined($params{log_like})) + { + @log_like = @{ $params{log_like} }; + } + if (defined($params{log_unlike})) + { + @log_unlike = @{ $params{log_unlike} }; + } + + if (@log_like or @log_unlike) + { + # Don't let previous log entries match for this connection. + truncate $self->logfile, 0; + } + # Never prompt for a password, any callers of this routine should # have set up things properly, and this should not block. my ($ret, $stdout, $stderr) = $self->psql( @@ -1948,6 +2011,20 @@ sub connect_fails { like($stderr, $params{expected_stderr}, "$test_name: matches"); } + + if (@log_like or @log_unlike) + { + my $log_contents = TestLib::slurp_file($self->logfile); + + while (my $regex = shift @log_like) + { + like($log_contents, $regex, "$test_name: log matches"); + } + while (my $regex = shift @log_unlike) + { + unlike($log_contents, $regex, "$test_name: log does not match"); + } + } } =pod |