2021-05-07 16:56:14 +02:00
|
|
|
|
2023-01-02 21:00:37 +01:00
|
|
|
# Copyright (c) 2021-2023, PostgreSQL Global Development Group
|
2021-05-07 16:56:14 +02:00
|
|
|
|
2019-04-20 03:22:22 +02:00
|
|
|
# Sets up a KDC and then runs a variety of tests to make sure that the
|
|
|
|
# GSSAPI/Kerberos authentication and encryption are working properly,
|
|
|
|
# that the options in pg_hba.conf and pg_ident.conf are handled correctly,
|
Introduce SYSTEM_USER
SYSTEM_USER is a reserved keyword of the SQL specification that,
roughly described, is aimed at reporting some information about the
system user who has connected to the database server. It may include
implementation-specific information about the means by the user
connected, like an authentication method.
This commit implements SYSTEM_USER as of auth_method:identity, where
"auth_method" is a keyword about the authentication method used to log
into the server (like peer, md5, scram-sha-256, gss, etc.) and
"identity" is the authentication identity as introduced by 9afffcb (peer
sets authn to the OS user name, gss to the user principal, etc.). This
format has been suggested by Tom Lane.
Note that thanks to d951052, SYSTEM_USER is available to parallel
workers.
Bump catalog version.
Author: Bertrand Drouvot
Reviewed-by: Jacob Champion, Joe Conway, Álvaro Herrera, Michael Paquier
Discussion: https://postgr.es/m/7e692b8c-0b11-45db-1cad-3afc5b57409f@amazon.com
2022-09-29 08:05:40 +02:00
|
|
|
# that the server-side pg_stat_gssapi view reports what we expect to
|
|
|
|
# see for each test and that SYSTEM_USER returns what we expect to see.
|
2019-04-20 03:22:22 +02:00
|
|
|
#
|
|
|
|
# Since this requires setting up a full KDC, it doesn't make much sense
|
|
|
|
# to have multiple test scripts (since they'd have to also create their
|
|
|
|
# own KDC and that could cause race conditions or other problems)- so
|
|
|
|
# just add whatever other tests are needed to here.
|
|
|
|
#
|
|
|
|
# See the README for additional information.
|
|
|
|
|
2018-03-05 20:42:11 +01:00
|
|
|
use strict;
|
|
|
|
use warnings;
|
2021-10-24 16:28:19 +02:00
|
|
|
use PostgreSQL::Test::Utils;
|
|
|
|
use PostgreSQL::Test::Cluster;
|
2018-03-05 20:42:11 +01:00
|
|
|
use Test::More;
|
2020-12-02 20:41:53 +01:00
|
|
|
use Time::HiRes qw(usleep);
|
2018-03-05 20:42:11 +01:00
|
|
|
|
2022-02-11 20:54:44 +01:00
|
|
|
if ($ENV{with_gssapi} ne 'yes')
|
2018-03-05 20:42:11 +01:00
|
|
|
{
|
|
|
|
plan skip_all => 'GSSAPI/Kerberos not supported by this build';
|
|
|
|
}
|
2022-09-20 20:09:30 +02:00
|
|
|
elsif ($ENV{PG_TEST_EXTRA} !~ /\bkerberos\b/)
|
|
|
|
{
|
|
|
|
plan skip_all => 'Potentially unsafe test GSSAPI/Kerberos not enabled in PG_TEST_EXTRA';
|
|
|
|
}
|
2018-03-05 20:42:11 +01:00
|
|
|
|
|
|
|
my ($krb5_bin_dir, $krb5_sbin_dir);
|
|
|
|
|
2022-12-31 22:45:18 +01:00
|
|
|
if ($^O eq 'darwin' && -d "/opt/homebrew" )
|
2018-03-05 20:42:11 +01:00
|
|
|
{
|
2022-12-31 22:45:18 +01:00
|
|
|
# typical paths for Homebrew on ARM
|
|
|
|
$krb5_bin_dir = '/opt/homebrew/opt/krb5/bin';
|
|
|
|
$krb5_sbin_dir = '/opt/homebrew/opt/krb5/sbin';
|
|
|
|
}
|
|
|
|
elsif ($^O eq 'darwin')
|
|
|
|
{
|
|
|
|
# typical paths for Homebrew on Intel
|
2018-03-05 20:42:11 +01:00
|
|
|
$krb5_bin_dir = '/usr/local/opt/krb5/bin';
|
|
|
|
$krb5_sbin_dir = '/usr/local/opt/krb5/sbin';
|
|
|
|
}
|
|
|
|
elsif ($^O eq 'freebsd')
|
|
|
|
{
|
|
|
|
$krb5_bin_dir = '/usr/local/bin';
|
|
|
|
$krb5_sbin_dir = '/usr/local/sbin';
|
|
|
|
}
|
|
|
|
elsif ($^O eq 'linux')
|
|
|
|
{
|
|
|
|
$krb5_sbin_dir = '/usr/sbin';
|
|
|
|
}
|
|
|
|
|
|
|
|
my $krb5_config = 'krb5-config';
|
|
|
|
my $kinit = 'kinit';
|
|
|
|
my $kdb5_util = 'kdb5_util';
|
|
|
|
my $kadmin_local = 'kadmin.local';
|
|
|
|
my $krb5kdc = 'krb5kdc';
|
|
|
|
|
|
|
|
if ($krb5_bin_dir && -d $krb5_bin_dir)
|
|
|
|
{
|
|
|
|
$krb5_config = $krb5_bin_dir . '/' . $krb5_config;
|
|
|
|
$kinit = $krb5_bin_dir . '/' . $kinit;
|
|
|
|
}
|
|
|
|
if ($krb5_sbin_dir && -d $krb5_sbin_dir)
|
|
|
|
{
|
|
|
|
$kdb5_util = $krb5_sbin_dir . '/' . $kdb5_util;
|
|
|
|
$kadmin_local = $krb5_sbin_dir . '/' . $kadmin_local;
|
|
|
|
$krb5kdc = $krb5_sbin_dir . '/' . $krb5kdc;
|
|
|
|
}
|
|
|
|
|
2018-08-04 05:53:25 +02:00
|
|
|
my $host = 'auth-test-localhost.postgresql.example.com';
|
|
|
|
my $hostaddr = '127.0.0.1';
|
2019-04-20 03:22:22 +02:00
|
|
|
my $realm = 'EXAMPLE.COM';
|
2018-03-05 20:42:11 +01:00
|
|
|
|
2021-10-24 16:28:19 +02:00
|
|
|
my $krb5_conf = "${PostgreSQL::Test::Utils::tmp_check}/krb5.conf";
|
|
|
|
my $kdc_conf = "${PostgreSQL::Test::Utils::tmp_check}/kdc.conf";
|
|
|
|
my $krb5_cache = "${PostgreSQL::Test::Utils::tmp_check}/krb5cc";
|
|
|
|
my $krb5_log = "${PostgreSQL::Test::Utils::log_path}/krb5libs.log";
|
|
|
|
my $kdc_log = "${PostgreSQL::Test::Utils::log_path}/krb5kdc.log";
|
|
|
|
my $kdc_port = PostgreSQL::Test::Cluster::get_free_port();
|
|
|
|
my $kdc_datadir = "${PostgreSQL::Test::Utils::tmp_check}/krb5kdc";
|
|
|
|
my $kdc_pidfile = "${PostgreSQL::Test::Utils::tmp_check}/krb5kdc.pid";
|
|
|
|
my $keytab = "${PostgreSQL::Test::Utils::tmp_check}/krb5.keytab";
|
2018-03-05 20:42:11 +01:00
|
|
|
|
2020-12-02 20:41:53 +01:00
|
|
|
my $dbname = 'postgres';
|
|
|
|
my $username = 'test1';
|
|
|
|
my $application = '001_auth.pl';
|
|
|
|
|
2018-03-05 20:42:11 +01:00
|
|
|
note "setting up Kerberos";
|
|
|
|
|
|
|
|
my ($stdout, $krb5_version);
|
|
|
|
run_log [ $krb5_config, '--version' ], '>', \$stdout
|
|
|
|
or BAIL_OUT("could not execute krb5-config");
|
|
|
|
BAIL_OUT("Heimdal is not supported") if $stdout =~ m/heimdal/;
|
|
|
|
$stdout =~ m/Kerberos 5 release ([0-9]+\.[0-9]+)/
|
|
|
|
or BAIL_OUT("could not get Kerberos version");
|
|
|
|
$krb5_version = $1;
|
|
|
|
|
2023-03-09 16:32:49 +01:00
|
|
|
# Build the krb5.conf to use.
|
|
|
|
#
|
|
|
|
# Explicitly specify the default (test) realm and the KDC for
|
|
|
|
# that realm to avoid the Kerberos library trying to look up
|
|
|
|
# that information in DNS, and also because we're using a
|
|
|
|
# non-standard KDC port.
|
|
|
|
#
|
|
|
|
# Reverse DNS is explicitly disabled to avoid any issue with a
|
|
|
|
# captive portal or other cases where the reverse DNS succeeds
|
|
|
|
# and the Kerberos library uses that as the canonical name of
|
|
|
|
# the host and then tries to acquire a cross-realm ticket.
|
2018-03-05 20:42:11 +01:00
|
|
|
append_to_file(
|
|
|
|
$krb5_conf,
|
|
|
|
qq![logging]
|
|
|
|
default = FILE:$krb5_log
|
|
|
|
kdc = FILE:$kdc_log
|
|
|
|
|
|
|
|
[libdefaults]
|
|
|
|
default_realm = $realm
|
2023-03-09 16:32:49 +01:00
|
|
|
rdns = false
|
2018-03-05 20:42:11 +01:00
|
|
|
|
|
|
|
[realms]
|
|
|
|
$realm = {
|
2018-08-04 05:53:25 +02:00
|
|
|
kdc = $hostaddr:$kdc_port
|
2018-03-05 20:42:11 +01:00
|
|
|
}!);
|
|
|
|
|
|
|
|
append_to_file(
|
|
|
|
$kdc_conf,
|
|
|
|
qq![kdcdefaults]
|
|
|
|
!);
|
2018-04-25 20:00:19 +02:00
|
|
|
|
2018-03-05 20:42:11 +01:00
|
|
|
# For new-enough versions of krb5, use the _listen settings rather
|
|
|
|
# than the _ports settings so that we can bind to localhost only.
|
|
|
|
if ($krb5_version >= 1.15)
|
|
|
|
{
|
|
|
|
append_to_file(
|
|
|
|
$kdc_conf,
|
2018-08-04 05:53:25 +02:00
|
|
|
qq!kdc_listen = $hostaddr:$kdc_port
|
|
|
|
kdc_tcp_listen = $hostaddr:$kdc_port
|
2018-03-05 20:42:11 +01:00
|
|
|
!);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
append_to_file(
|
|
|
|
$kdc_conf,
|
|
|
|
qq!kdc_ports = $kdc_port
|
|
|
|
kdc_tcp_ports = $kdc_port
|
|
|
|
!);
|
|
|
|
}
|
|
|
|
append_to_file(
|
|
|
|
$kdc_conf,
|
|
|
|
qq!
|
|
|
|
[realms]
|
|
|
|
$realm = {
|
|
|
|
database_name = $kdc_datadir/principal
|
|
|
|
admin_keytab = FILE:$kdc_datadir/kadm5.keytab
|
|
|
|
acl_file = $kdc_datadir/kadm5.acl
|
|
|
|
key_stash_file = $kdc_datadir/_k5.$realm
|
|
|
|
}!);
|
|
|
|
|
|
|
|
mkdir $kdc_datadir or die;
|
|
|
|
|
2021-01-25 20:53:13 +01:00
|
|
|
# Ensure that we use test's config and cache files, not global ones.
|
2018-03-05 20:42:11 +01:00
|
|
|
$ENV{'KRB5_CONFIG'} = $krb5_conf;
|
|
|
|
$ENV{'KRB5_KDC_PROFILE'} = $kdc_conf;
|
2021-01-25 20:53:13 +01:00
|
|
|
$ENV{'KRB5CCNAME'} = $krb5_cache;
|
2018-03-05 20:42:11 +01:00
|
|
|
|
2018-08-04 05:53:25 +02:00
|
|
|
my $service_principal = "$ENV{with_krb_srvnam}/$host";
|
2018-03-05 20:42:11 +01:00
|
|
|
|
|
|
|
system_or_bail $kdb5_util, 'create', '-s', '-P', 'secret0';
|
|
|
|
|
|
|
|
my $test1_password = 'secret1';
|
|
|
|
system_or_bail $kadmin_local, '-q', "addprinc -pw $test1_password test1";
|
|
|
|
|
|
|
|
system_or_bail $kadmin_local, '-q', "addprinc -randkey $service_principal";
|
|
|
|
system_or_bail $kadmin_local, '-q', "ktadd -k $keytab $service_principal";
|
|
|
|
|
|
|
|
system_or_bail $krb5kdc, '-P', $kdc_pidfile;
|
|
|
|
|
|
|
|
END
|
|
|
|
{
|
|
|
|
kill 'INT', `cat $kdc_pidfile` if -f $kdc_pidfile;
|
|
|
|
}
|
|
|
|
|
|
|
|
note "setting up PostgreSQL instance";
|
|
|
|
|
2021-10-24 16:28:19 +02:00
|
|
|
my $node = PostgreSQL::Test::Cluster->new('node');
|
2018-03-05 20:42:11 +01:00
|
|
|
$node->init;
|
2020-12-25 03:37:46 +01:00
|
|
|
$node->append_conf(
|
|
|
|
'postgresql.conf', qq{
|
|
|
|
listen_addresses = '$hostaddr'
|
|
|
|
krb_server_keyfile = '$keytab'
|
|
|
|
log_connections = on
|
|
|
|
lc_messages = 'C'
|
|
|
|
});
|
2018-03-05 20:42:11 +01:00
|
|
|
$node->start;
|
|
|
|
|
|
|
|
$node->safe_psql('postgres', 'CREATE USER test1;');
|
|
|
|
|
Introduce SYSTEM_USER
SYSTEM_USER is a reserved keyword of the SQL specification that,
roughly described, is aimed at reporting some information about the
system user who has connected to the database server. It may include
implementation-specific information about the means by the user
connected, like an authentication method.
This commit implements SYSTEM_USER as of auth_method:identity, where
"auth_method" is a keyword about the authentication method used to log
into the server (like peer, md5, scram-sha-256, gss, etc.) and
"identity" is the authentication identity as introduced by 9afffcb (peer
sets authn to the OS user name, gss to the user principal, etc.). This
format has been suggested by Tom Lane.
Note that thanks to d951052, SYSTEM_USER is available to parallel
workers.
Bump catalog version.
Author: Bertrand Drouvot
Reviewed-by: Jacob Champion, Joe Conway, Álvaro Herrera, Michael Paquier
Discussion: https://postgr.es/m/7e692b8c-0b11-45db-1cad-3afc5b57409f@amazon.com
2022-09-29 08:05:40 +02:00
|
|
|
# Set up a table for SYSTEM_USER parallel worker testing.
|
|
|
|
$node->safe_psql('postgres',
|
|
|
|
"CREATE TABLE ids (id) AS SELECT 'gss:test1\@$realm' FROM generate_series(1, 10);"
|
|
|
|
);
|
|
|
|
|
|
|
|
$node->safe_psql('postgres', 'GRANT SELECT ON ids TO public;');
|
|
|
|
|
2018-03-05 20:42:11 +01:00
|
|
|
note "running tests";
|
|
|
|
|
2020-01-11 23:14:08 +01:00
|
|
|
# Test connection success or failure, and if success, that query returns true.
|
2018-03-05 20:42:11 +01:00
|
|
|
sub test_access
|
|
|
|
{
|
2021-09-23 22:49:20 +02:00
|
|
|
local $Test::Builder::Level = $Test::Builder::Level + 1;
|
|
|
|
|
2021-04-05 03:13:57 +02:00
|
|
|
my ($node, $role, $query, $expected_res, $gssencmode, $test_name,
|
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
2021-04-07 03:16:39 +02:00
|
|
|
@expect_log_msgs)
|
2021-04-05 03:13:57 +02:00
|
|
|
= @_;
|
2018-03-05 20:42:11 +01:00
|
|
|
|
|
|
|
# need to connect over TCP/IP for Kerberos
|
2021-04-05 03:13:57 +02:00
|
|
|
my $connstr = $node->connstr('postgres')
|
|
|
|
. " user=$role host=$host hostaddr=$hostaddr $gssencmode";
|
|
|
|
|
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
2021-04-07 03:16:39 +02:00
|
|
|
my %params = (sql => $query,);
|
|
|
|
|
|
|
|
if (@expect_log_msgs)
|
|
|
|
{
|
|
|
|
# Match every message literally.
|
|
|
|
my @regexes = map { qr/\Q$_\E/ } @expect_log_msgs;
|
|
|
|
|
|
|
|
$params{log_like} = \@regexes;
|
|
|
|
}
|
|
|
|
|
2021-04-05 03:13:57 +02:00
|
|
|
if ($expected_res eq 0)
|
2019-04-20 03:22:22 +02:00
|
|
|
{
|
2021-04-05 03:13:57 +02:00
|
|
|
# The result is assumed to match "true", or "t", here.
|
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
2021-04-07 03:16:39 +02:00
|
|
|
$params{expected_stdout} = qr/^t$/;
|
|
|
|
|
|
|
|
$node->connect_ok($connstr, $test_name, %params);
|
2019-04-20 03:22:22 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
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
2021-04-07 03:16:39 +02:00
|
|
|
$node->connect_fails($connstr, $test_name, %params);
|
2019-04-20 03:22:22 +02:00
|
|
|
}
|
2018-03-05 20:42:11 +01:00
|
|
|
}
|
|
|
|
|
2020-01-11 23:14:08 +01:00
|
|
|
# As above, but test for an arbitrary query result.
|
|
|
|
sub test_query
|
|
|
|
{
|
2021-10-12 04:15:44 +02:00
|
|
|
local $Test::Builder::Level = $Test::Builder::Level + 1;
|
|
|
|
|
2020-01-11 23:14:08 +01:00
|
|
|
my ($node, $role, $query, $expected, $gssencmode, $test_name) = @_;
|
|
|
|
|
|
|
|
# need to connect over TCP/IP for Kerberos
|
2021-04-05 03:13:57 +02:00
|
|
|
my $connstr = $node->connstr('postgres')
|
|
|
|
. " user=$role host=$host hostaddr=$hostaddr $gssencmode";
|
|
|
|
|
2021-04-06 06:23:57 +02:00
|
|
|
$node->connect_ok(
|
|
|
|
$connstr, $test_name,
|
|
|
|
sql => $query,
|
|
|
|
expected_stdout => $expected);
|
2020-01-11 23:14:08 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-03-05 20:42:11 +01:00
|
|
|
unlink($node->data_dir . '/pg_hba.conf');
|
2018-08-04 05:53:25 +02:00
|
|
|
$node->append_conf('pg_hba.conf',
|
|
|
|
qq{host all all $hostaddr/32 gss map=mymap});
|
2018-03-05 20:42:11 +01:00
|
|
|
$node->restart;
|
|
|
|
|
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
2021-04-07 03:16:39 +02:00
|
|
|
test_access($node, 'test1', 'SELECT true', 2, '', 'fails without ticket');
|
2018-03-05 20:42:11 +01:00
|
|
|
|
|
|
|
run_log [ $kinit, 'test1' ], \$test1_password or BAIL_OUT($?);
|
|
|
|
|
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
2021-04-07 03:16:39 +02:00
|
|
|
test_access(
|
|
|
|
$node,
|
|
|
|
'test1',
|
|
|
|
'SELECT true',
|
|
|
|
2,
|
|
|
|
'',
|
|
|
|
'fails without mapping',
|
|
|
|
"connection authenticated: identity=\"test1\@$realm\" method=gss",
|
|
|
|
"no match in usermap \"mymap\" for user \"test1\"");
|
2018-03-05 20:42:11 +01:00
|
|
|
|
|
|
|
$node->append_conf('pg_ident.conf', qq{mymap /^(.*)\@$realm\$ \\1});
|
|
|
|
$node->restart;
|
|
|
|
|
2019-04-20 03:22:22 +02:00
|
|
|
test_access(
|
|
|
|
$node,
|
|
|
|
'test1',
|
|
|
|
'SELECT gss_authenticated AND encrypted from pg_stat_gssapi where pid = pg_backend_pid();',
|
|
|
|
0,
|
|
|
|
'',
|
2020-12-02 20:41:53 +01:00
|
|
|
'succeeds with mapping with default gssencmode and host hba',
|
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
2021-04-07 03:16:39 +02:00
|
|
|
"connection authenticated: identity=\"test1\@$realm\" method=gss",
|
2020-12-02 20:41:53 +01:00
|
|
|
"connection authorized: user=$username database=$dbname application_name=$application GSS (authenticated=yes, encrypted=yes, principal=test1\@$realm)"
|
|
|
|
);
|
|
|
|
|
2019-04-20 03:22:22 +02:00
|
|
|
test_access(
|
|
|
|
$node,
|
2020-12-02 20:41:53 +01:00
|
|
|
'test1',
|
2019-04-20 03:22:22 +02:00
|
|
|
'SELECT gss_authenticated AND encrypted from pg_stat_gssapi where pid = pg_backend_pid();',
|
|
|
|
0,
|
2020-12-02 20:41:53 +01:00
|
|
|
'gssencmode=prefer',
|
|
|
|
'succeeds with GSS-encrypted access preferred with host hba',
|
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
2021-04-07 03:16:39 +02:00
|
|
|
"connection authenticated: identity=\"test1\@$realm\" method=gss",
|
2020-12-02 20:41:53 +01:00
|
|
|
"connection authorized: user=$username database=$dbname application_name=$application GSS (authenticated=yes, encrypted=yes, principal=test1\@$realm)"
|
|
|
|
);
|
2019-04-20 03:22:22 +02:00
|
|
|
test_access(
|
|
|
|
$node,
|
2020-12-02 20:41:53 +01:00
|
|
|
'test1',
|
2019-04-20 03:22:22 +02:00
|
|
|
'SELECT gss_authenticated AND encrypted from pg_stat_gssapi where pid = pg_backend_pid();',
|
|
|
|
0,
|
2020-12-02 20:41:53 +01:00
|
|
|
'gssencmode=require',
|
|
|
|
'succeeds with GSS-encrypted access required with host hba',
|
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
2021-04-07 03:16:39 +02:00
|
|
|
"connection authenticated: identity=\"test1\@$realm\" method=gss",
|
2020-12-02 20:41:53 +01:00
|
|
|
"connection authorized: user=$username database=$dbname application_name=$application GSS (authenticated=yes, encrypted=yes, principal=test1\@$realm)"
|
|
|
|
);
|
2019-04-20 03:22:22 +02:00
|
|
|
|
2020-01-11 23:14:08 +01:00
|
|
|
# Test that we can transport a reasonable amount of data.
|
|
|
|
test_query(
|
|
|
|
$node,
|
2020-12-02 20:41:53 +01:00
|
|
|
'test1',
|
2020-01-11 23:14:08 +01:00
|
|
|
'SELECT * FROM generate_series(1, 100000);',
|
|
|
|
qr/^1\n.*\n1024\n.*\n9999\n.*\n100000$/s,
|
2020-12-02 20:41:53 +01:00
|
|
|
'gssencmode=require',
|
|
|
|
'receiving 100K lines works');
|
2020-01-11 23:14:08 +01:00
|
|
|
|
|
|
|
test_query(
|
|
|
|
$node,
|
2020-12-02 20:41:53 +01:00
|
|
|
'test1',
|
2021-09-10 09:44:01 +02:00
|
|
|
"CREATE TEMP TABLE mytab (f1 int primary key);\n"
|
2020-01-11 23:14:08 +01:00
|
|
|
. "COPY mytab FROM STDIN;\n"
|
|
|
|
. join("\n", (1 .. 100000))
|
|
|
|
. "\n\\.\n"
|
|
|
|
. "SELECT COUNT(*) FROM mytab;",
|
|
|
|
qr/^100000$/s,
|
2020-12-02 20:41:53 +01:00
|
|
|
'gssencmode=require',
|
|
|
|
'sending 100K lines works');
|
2020-01-11 23:14:08 +01:00
|
|
|
|
libpq: Add support for require_auth to control authorized auth methods
The new connection parameter require_auth allows a libpq client to
define a list of comma-separated acceptable authentication types for use
with the server. There is no negotiation: if the server does not
present one of the allowed authentication requests, the connection
attempt done by the client fails.
The following keywords can be defined in the list:
- password, for AUTH_REQ_PASSWORD.
- md5, for AUTH_REQ_MD5.
- gss, for AUTH_REQ_GSS[_CONT].
- sspi, for AUTH_REQ_SSPI and AUTH_REQ_GSS_CONT.
- scram-sha-256, for AUTH_REQ_SASL[_CONT|_FIN].
- creds, for AUTH_REQ_SCM_CREDS (perhaps this should be removed entirely
now).
- none, to control unauthenticated connections.
All the methods that can be defined in the list can be negated, like
"!password", in which case the server must NOT use the listed
authentication type. The special method "none" allows/disallows the use
of unauthenticated connections (but it does not govern transport-level
authentication via TLS or GSSAPI).
Internally, the patch logic is tied to check_expected_areq(), that was
used for channel_binding, ensuring that an incoming request is
compatible with conn->require_auth. It also introduces a new flag,
conn->client_finished_auth, which is set by various authentication
routines when the client side of the handshake is finished. This
signals to check_expected_areq() that an AUTH_REQ_OK from the server is
expected, and allows the client to complain if the server bypasses
authentication entirely, with for example the reception of a too-early
AUTH_REQ_OK message.
Regression tests are added in authentication TAP tests for all the
keywords supported (except "creds", because it is around only for
compatibility reasons). A new TAP script has been added for SSPI, as
there was no script dedicated to it yet. It relies on SSPI being the
default authentication method on Windows, as set by pg_regress.
Author: Jacob Champion
Reviewed-by: Peter Eisentraut, David G. Johnston, Michael Paquier
Discussion: https://postgr.es/m/9e5a8ccddb8355ea9fa4b75a1e3a9edc88a70cd3.camel@vmware.com
2023-03-14 06:00:05 +01:00
|
|
|
# require_auth=gss succeeds if required.
|
|
|
|
$node->connect_ok(
|
|
|
|
$node->connstr('postgres')
|
|
|
|
. " user=test1 host=$host hostaddr=$hostaddr gssencmode=disable require_auth=gss",
|
|
|
|
"GSS authentication requested, works with non-encyrpted GSS");
|
|
|
|
$node->connect_ok(
|
|
|
|
$node->connstr('postgres')
|
|
|
|
. " user=test1 host=$host hostaddr=$hostaddr gssencmode=require require_auth=gss",
|
|
|
|
"GSS authentication requested, works with encrypted GSS auth");
|
|
|
|
|
|
|
|
# require_auth=sspi fails if required.
|
|
|
|
$node->connect_fails(
|
|
|
|
$node->connstr('postgres')
|
|
|
|
. " user=test1 host=$host hostaddr=$hostaddr gssencmode=disable require_auth=sspi",
|
|
|
|
"SSPI authentication requested, fails with non-encrypted GSS",
|
|
|
|
expected_stderr =>
|
|
|
|
qr/auth method "sspi" requirement failed: server requested GSSAPI authentication/
|
|
|
|
);
|
|
|
|
$node->connect_fails(
|
|
|
|
$node->connstr('postgres')
|
|
|
|
. " user=test1 host=$host hostaddr=$hostaddr gssencmode=require require_auth=sspi",
|
|
|
|
"SSPI authentication requested, fails with encrypted GSS",
|
|
|
|
expected_stderr =>
|
|
|
|
qr/auth method "sspi" requirement failed: server did not complete authentication/
|
|
|
|
);
|
|
|
|
|
Introduce SYSTEM_USER
SYSTEM_USER is a reserved keyword of the SQL specification that,
roughly described, is aimed at reporting some information about the
system user who has connected to the database server. It may include
implementation-specific information about the means by the user
connected, like an authentication method.
This commit implements SYSTEM_USER as of auth_method:identity, where
"auth_method" is a keyword about the authentication method used to log
into the server (like peer, md5, scram-sha-256, gss, etc.) and
"identity" is the authentication identity as introduced by 9afffcb (peer
sets authn to the OS user name, gss to the user principal, etc.). This
format has been suggested by Tom Lane.
Note that thanks to d951052, SYSTEM_USER is available to parallel
workers.
Bump catalog version.
Author: Bertrand Drouvot
Reviewed-by: Jacob Champion, Joe Conway, Álvaro Herrera, Michael Paquier
Discussion: https://postgr.es/m/7e692b8c-0b11-45db-1cad-3afc5b57409f@amazon.com
2022-09-29 08:05:40 +02:00
|
|
|
# Test that SYSTEM_USER works.
|
|
|
|
test_query($node, 'test1', 'SELECT SYSTEM_USER;',
|
|
|
|
qr/^gss:test1\@$realm$/s, 'gssencmode=require', 'testing system_user');
|
|
|
|
|
|
|
|
# Test that SYSTEM_USER works with parallel workers.
|
|
|
|
test_query(
|
|
|
|
$node,
|
|
|
|
'test1', qq(
|
|
|
|
SET min_parallel_table_scan_size TO 0;
|
|
|
|
SET parallel_setup_cost TO 0;
|
|
|
|
SET parallel_tuple_cost TO 0;
|
|
|
|
SET max_parallel_workers_per_gather TO 2;
|
|
|
|
SELECT bool_and(SYSTEM_USER = id) FROM ids;),
|
|
|
|
qr/^t$/s,
|
|
|
|
'gssencmode=require',
|
|
|
|
'testing system_user with parallel workers');
|
|
|
|
|
2019-04-20 03:22:22 +02:00
|
|
|
unlink($node->data_dir . '/pg_hba.conf');
|
|
|
|
$node->append_conf('pg_hba.conf',
|
|
|
|
qq{hostgssenc all all $hostaddr/32 gss map=mymap});
|
|
|
|
$node->restart;
|
|
|
|
|
|
|
|
test_access(
|
|
|
|
$node,
|
2020-12-02 20:41:53 +01:00
|
|
|
'test1',
|
2019-04-20 03:22:22 +02:00
|
|
|
'SELECT gss_authenticated AND encrypted from pg_stat_gssapi where pid = pg_backend_pid();',
|
|
|
|
0,
|
2020-12-02 20:41:53 +01:00
|
|
|
'gssencmode=prefer',
|
|
|
|
'succeeds with GSS-encrypted access preferred and hostgssenc hba',
|
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
2021-04-07 03:16:39 +02:00
|
|
|
"connection authenticated: identity=\"test1\@$realm\" method=gss",
|
2020-12-02 20:41:53 +01:00
|
|
|
"connection authorized: user=$username database=$dbname application_name=$application GSS (authenticated=yes, encrypted=yes, principal=test1\@$realm)"
|
|
|
|
);
|
2019-04-20 03:22:22 +02:00
|
|
|
test_access(
|
|
|
|
$node,
|
2020-12-02 20:41:53 +01:00
|
|
|
'test1',
|
2019-04-20 03:22:22 +02:00
|
|
|
'SELECT gss_authenticated AND encrypted from pg_stat_gssapi where pid = pg_backend_pid();',
|
|
|
|
0,
|
2020-12-02 20:41:53 +01:00
|
|
|
'gssencmode=require',
|
|
|
|
'succeeds with GSS-encrypted access required and hostgssenc hba',
|
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
2021-04-07 03:16:39 +02:00
|
|
|
"connection authenticated: identity=\"test1\@$realm\" method=gss",
|
2020-12-02 20:41:53 +01:00
|
|
|
"connection authorized: user=$username database=$dbname application_name=$application GSS (authenticated=yes, encrypted=yes, principal=test1\@$realm)"
|
|
|
|
);
|
|
|
|
test_access($node, 'test1', 'SELECT true', 2, 'gssencmode=disable',
|
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
2021-04-07 03:16:39 +02:00
|
|
|
'fails with GSS encryption disabled and hostgssenc hba');
|
2019-04-20 03:22:22 +02:00
|
|
|
|
libpq: Add support for require_auth to control authorized auth methods
The new connection parameter require_auth allows a libpq client to
define a list of comma-separated acceptable authentication types for use
with the server. There is no negotiation: if the server does not
present one of the allowed authentication requests, the connection
attempt done by the client fails.
The following keywords can be defined in the list:
- password, for AUTH_REQ_PASSWORD.
- md5, for AUTH_REQ_MD5.
- gss, for AUTH_REQ_GSS[_CONT].
- sspi, for AUTH_REQ_SSPI and AUTH_REQ_GSS_CONT.
- scram-sha-256, for AUTH_REQ_SASL[_CONT|_FIN].
- creds, for AUTH_REQ_SCM_CREDS (perhaps this should be removed entirely
now).
- none, to control unauthenticated connections.
All the methods that can be defined in the list can be negated, like
"!password", in which case the server must NOT use the listed
authentication type. The special method "none" allows/disallows the use
of unauthenticated connections (but it does not govern transport-level
authentication via TLS or GSSAPI).
Internally, the patch logic is tied to check_expected_areq(), that was
used for channel_binding, ensuring that an incoming request is
compatible with conn->require_auth. It also introduces a new flag,
conn->client_finished_auth, which is set by various authentication
routines when the client side of the handshake is finished. This
signals to check_expected_areq() that an AUTH_REQ_OK from the server is
expected, and allows the client to complain if the server bypasses
authentication entirely, with for example the reception of a too-early
AUTH_REQ_OK message.
Regression tests are added in authentication TAP tests for all the
keywords supported (except "creds", because it is around only for
compatibility reasons). A new TAP script has been added for SSPI, as
there was no script dedicated to it yet. It relies on SSPI being the
default authentication method on Windows, as set by pg_regress.
Author: Jacob Champion
Reviewed-by: Peter Eisentraut, David G. Johnston, Michael Paquier
Discussion: https://postgr.es/m/9e5a8ccddb8355ea9fa4b75a1e3a9edc88a70cd3.camel@vmware.com
2023-03-14 06:00:05 +01:00
|
|
|
# require_auth=gss succeeds if required.
|
|
|
|
$node->connect_ok(
|
|
|
|
$node->connstr('postgres')
|
|
|
|
. " user=test1 host=$host hostaddr=$hostaddr gssencmode=require require_auth=gss",
|
|
|
|
"GSS authentication requested, works with GSS encryption");
|
|
|
|
$node->connect_ok(
|
|
|
|
$node->connstr('postgres')
|
|
|
|
. " user=test1 host=$host hostaddr=$hostaddr gssencmode=require require_auth=gss,scram-sha-256",
|
|
|
|
"multiple authentication types requested, works with GSS encryption");
|
|
|
|
|
2019-04-20 03:22:22 +02:00
|
|
|
unlink($node->data_dir . '/pg_hba.conf');
|
|
|
|
$node->append_conf('pg_hba.conf',
|
|
|
|
qq{hostnogssenc all all $hostaddr/32 gss map=mymap});
|
|
|
|
$node->restart;
|
|
|
|
|
|
|
|
test_access(
|
|
|
|
$node,
|
2020-12-02 20:41:53 +01:00
|
|
|
'test1',
|
2019-04-20 03:22:22 +02:00
|
|
|
'SELECT gss_authenticated and not encrypted from pg_stat_gssapi where pid = pg_backend_pid();',
|
|
|
|
0,
|
2020-12-02 20:41:53 +01:00
|
|
|
'gssencmode=prefer',
|
|
|
|
'succeeds with GSS-encrypted access preferred and hostnogssenc hba, but no encryption',
|
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
2021-04-07 03:16:39 +02:00
|
|
|
"connection authenticated: identity=\"test1\@$realm\" method=gss",
|
2020-12-02 20:41:53 +01:00
|
|
|
"connection authorized: user=$username database=$dbname application_name=$application GSS (authenticated=yes, encrypted=no, principal=test1\@$realm)"
|
2019-04-20 03:22:22 +02:00
|
|
|
);
|
2020-12-02 20:41:53 +01:00
|
|
|
test_access($node, 'test1', 'SELECT true', 2, 'gssencmode=require',
|
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
2021-04-07 03:16:39 +02:00
|
|
|
'fails with GSS-encrypted access required and hostnogssenc hba');
|
2019-04-20 03:22:22 +02:00
|
|
|
test_access(
|
|
|
|
$node,
|
2020-12-02 20:41:53 +01:00
|
|
|
'test1',
|
2019-04-20 03:22:22 +02:00
|
|
|
'SELECT gss_authenticated and not encrypted from pg_stat_gssapi where pid = pg_backend_pid();',
|
|
|
|
0,
|
2020-12-02 20:41:53 +01:00
|
|
|
'gssencmode=disable',
|
|
|
|
'succeeds with GSS encryption disabled and hostnogssenc hba',
|
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
2021-04-07 03:16:39 +02:00
|
|
|
"connection authenticated: identity=\"test1\@$realm\" method=gss",
|
2020-12-02 20:41:53 +01:00
|
|
|
"connection authorized: user=$username database=$dbname application_name=$application GSS (authenticated=yes, encrypted=no, principal=test1\@$realm)"
|
|
|
|
);
|
2018-03-05 20:42:11 +01:00
|
|
|
|
|
|
|
truncate($node->data_dir . '/pg_ident.conf', 0);
|
|
|
|
unlink($node->data_dir . '/pg_hba.conf');
|
|
|
|
$node->append_conf('pg_hba.conf',
|
2018-08-04 05:53:25 +02:00
|
|
|
qq{host all all $hostaddr/32 gss include_realm=0});
|
2018-03-05 20:42:11 +01:00
|
|
|
$node->restart;
|
|
|
|
|
2019-04-20 03:22:22 +02:00
|
|
|
test_access(
|
|
|
|
$node,
|
|
|
|
'test1',
|
|
|
|
'SELECT gss_authenticated AND encrypted from pg_stat_gssapi where pid = pg_backend_pid();',
|
|
|
|
0,
|
|
|
|
'',
|
2020-12-02 20:41:53 +01:00
|
|
|
'succeeds with include_realm=0 and defaults',
|
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
2021-04-07 03:16:39 +02:00
|
|
|
"connection authenticated: identity=\"test1\@$realm\" method=gss",
|
2020-12-02 20:41:53 +01:00
|
|
|
"connection authorized: user=$username database=$dbname application_name=$application GSS (authenticated=yes, encrypted=yes, principal=test1\@$realm)"
|
|
|
|
);
|
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
2021-04-07 03:16:39 +02:00
|
|
|
|
|
|
|
# Reset pg_hba.conf, and cause a usermap failure with an authentication
|
|
|
|
# that has passed.
|
|
|
|
unlink($node->data_dir . '/pg_hba.conf');
|
|
|
|
$node->append_conf('pg_hba.conf',
|
|
|
|
qq{host all all $hostaddr/32 gss include_realm=0 krb_realm=EXAMPLE.ORG});
|
|
|
|
$node->restart;
|
|
|
|
|
|
|
|
test_access(
|
|
|
|
$node,
|
|
|
|
'test1',
|
|
|
|
'SELECT true',
|
|
|
|
2,
|
|
|
|
'',
|
|
|
|
'fails with wrong krb_realm, but still authenticates',
|
|
|
|
"connection authenticated: identity=\"test1\@$realm\" method=gss");
|
2022-02-11 20:54:44 +01:00
|
|
|
|
|
|
|
done_testing();
|