diff options
author | Daniel Gustafsson <dgustafsson@postgresql.org> | 2021-11-30 11:19:59 +0100 |
---|---|---|
committer | Daniel Gustafsson <dgustafsson@postgresql.org> | 2021-11-30 11:19:59 +0100 |
commit | ae81776a23f78babc9707e22f95dea15aa2dbcd2 (patch) | |
tree | f6e949d6f966aa6323e3a14d0a1507f71efe6c36 /src/test/ssl/t | |
parent | 879fc1a579cc2e2e1dbb79686668b4de2071ab83 (diff) |
Add TAP tests for contrib/sslinfo
This adds rudimentary coverage of the sslinfo extension into the SSL
test harness. The output is validated by comparing with pg_stat_ssl
to provide some level of test stability should the underlying certs
be slightly altered. A new cert is added to provide an extension to
test against.
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Reviewed-by: Andrew Dunstan <andrew@dunslane.net>
Reviewed-by: Dagfinn Ilmari Mannsåker <ilmari@ilmari.org>
Discussion: https://postgr.es/m/E23F9811-0C77-45DA-912F-D809AB140741@yesql.se
Diffstat (limited to 'src/test/ssl/t')
-rw-r--r-- | src/test/ssl/t/003_sslinfo.pl | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/src/test/ssl/t/003_sslinfo.pl b/src/test/ssl/t/003_sslinfo.pl new file mode 100644 index 00000000000..cf2e8dde0f3 --- /dev/null +++ b/src/test/ssl/t/003_sslinfo.pl @@ -0,0 +1,134 @@ + +# Copyright (c) 2021, PostgreSQL Global Development Group + +use strict; +use warnings; +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Test::More; + +use File::Copy; + +use FindBin; +use lib $FindBin::RealBin; + +use SSLServer; + +if ($ENV{with_ssl} ne 'openssl') +{ + plan skip_all => 'OpenSSL not supported by this build'; +} +else +{ + plan tests => 13; +} + +#### Some configuration + +# This is the hostname used to connect to the server. This cannot be a +# hostname, because the server certificate is always for the domain +# postgresql-ssl-regression.test. +my $SERVERHOSTADDR = '127.0.0.1'; +# This is the pattern to use in pg_hba.conf to match incoming connections. +my $SERVERHOSTCIDR = '127.0.0.1/32'; + +# Allocation of base connection string shared among multiple tests. +my $common_connstr; + +# The client's private key must not be world-readable, so take a copy +# of the key stored in the code tree and update its permissions. +my $client_tmp_key = "${PostgreSQL::Test::Utils::tmp_check}/client_ext.key"; +copy("ssl/client_ext.key", $client_tmp_key) + or die "couldn't copy ssl/client_ext.key to $client_tmp_key for permissions change: $!"; +chmod 0600, $client_tmp_key + or die "failed to change permissions on $client_tmp_key: $!"; + +#### Set up the server. + +note "setting up data directory"; +my $node = PostgreSQL::Test::Cluster->new('primary'); +$node->init; + +# PGHOST is enforced here to set up the node, subsequent connections +# will use a dedicated connection string. +$ENV{PGHOST} = $node->host; +$ENV{PGPORT} = $node->port; +$node->start; + +configure_test_server_for_ssl($node, $SERVERHOSTADDR, $SERVERHOSTCIDR, + 'trust', extensions => [ qw(sslinfo) ]); + +# We aren't using any CRL's in this suite so we can keep using server-revoked +# as server certificate for simple client.crt connection much like how the +# 001 test does. +switch_server_cert($node, 'server-revoked'); + +$common_connstr = + "sslrootcert=ssl/root+server_ca.crt sslmode=require dbname=certdb hostaddr=$SERVERHOSTADDR " . + "user=ssltestuser sslcert=ssl/client_ext.crt sslkey=$client_tmp_key"; + +# Make sure we can connect even though previous test suites have established this +$node->connect_ok( + $common_connstr, + "certificate authorization succeeds with correct client cert in PEM format", +); + +my $result; + +$result = $node->safe_psql("certdb", "SELECT ssl_is_used();", + connstr => $common_connstr); +is($result, 't', "ssl_is_used() for TLS connection"); + +$result = $node->safe_psql("certdb", "SELECT ssl_version();", + connstr => $common_connstr . " ssl_min_protocol_version=TLSv1.2 " . + "ssl_max_protocol_version=TLSv1.2"); +is($result, 'TLSv1.2', "ssl_version() correctly returning TLS protocol"); + +$result = $node->safe_psql("certdb", + "SELECT ssl_cipher() = cipher FROM pg_stat_ssl WHERE pid = pg_backend_pid();", + connstr => $common_connstr); +is($result, 't', "ssl_cipher() compared with pg_stat_ssl"); + +$result = $node->safe_psql("certdb", "SELECT ssl_client_cert_present();", + connstr => $common_connstr); +is($result, 't', "ssl_client_cert_present() for connection with cert"); + +$result = $node->safe_psql("trustdb", "SELECT ssl_client_cert_present();", + connstr => "sslrootcert=ssl/root+server_ca.crt sslmode=require " . + "dbname=trustdb hostaddr=$SERVERHOSTADDR user=ssltestuser"); +is($result, 'f', "ssl_client_cert_present() for connection without cert"); + +$result = $node->safe_psql("certdb", + "SELECT ssl_client_serial() = client_serial FROM pg_stat_ssl WHERE pid = pg_backend_pid();", + connstr => $common_connstr); +is($result, 't', "ssl_client_serial() compared with pg_stat_ssl"); + +# Must not use safe_psql since we expect an error here +$result = $node->psql("certdb", "SELECT ssl_client_dn_field('invalid');", + connstr => $common_connstr); +is($result, '3', "ssl_client_dn_field() for an invalid field"); + +$result = $node->safe_psql("trustdb", "SELECT ssl_client_dn_field('commonName');", + connstr => "sslrootcert=ssl/root+server_ca.crt sslmode=require " . + "dbname=trustdb hostaddr=$SERVERHOSTADDR user=ssltestuser"); +is($result, '', "ssl_client_dn_field() for connection without cert"); + +$result = $node->safe_psql("certdb", + "SELECT '/CN=' || ssl_client_dn_field('commonName') = client_dn FROM pg_stat_ssl WHERE pid = pg_backend_pid();", + connstr => $common_connstr); +is($result, 't', "ssl_client_dn_field() for commonName"); + +$result = $node->safe_psql("certdb", + "SELECT ssl_issuer_dn() = issuer_dn FROM pg_stat_ssl WHERE pid = pg_backend_pid();", + connstr => $common_connstr); +is($result, 't', "ssl_issuer_dn() for connection with cert"); + +$result = $node->safe_psql("certdb", + "SELECT '/CN=' || ssl_issuer_field('commonName') = issuer_dn FROM pg_stat_ssl WHERE pid = pg_backend_pid();", + connstr => $common_connstr); +is($result, 't', "ssl_issuer_field() for commonName"); + +$result = $node->safe_psql("certdb", + "SELECT value, critical FROM ssl_extension_info() WHERE name = 'basicConstraints';", + connstr => $common_connstr); +is($result, 'CA:FALSE|t', 'extract extension from cert'); |