mirror of https://github.com/postgres/postgres
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.sepull/73/head
parent
879fc1a579
commit
ae81776a23
@ -0,0 +1,16 @@ |
||||
# An OpenSSL format CSR config file for creating a client certificate. |
||||
# |
||||
# The certificate is for user "ssltestuser" and intends to test client |
||||
# certificate with extensions. |
||||
|
||||
[ req ] |
||||
distinguished_name = req_distinguished_name |
||||
req_extensions = client_ext |
||||
prompt = no |
||||
|
||||
[ req_distinguished_name ] |
||||
CN = ssltestuser |
||||
|
||||
[ client_ext ] |
||||
basicConstraints = critical,CA:false |
||||
extendedKeyUsage = clientAuth |
@ -0,0 +1,21 @@ |
||||
-----BEGIN CERTIFICATE----- |
||||
MIIDezCCAmOgAwIBAgIIICEREAQyQQAwDQYJKoZIhvcNAQELBQAwQjFAMD4GA1UE |
||||
Aww3VGVzdCBDQSBmb3IgUG9zdGdyZVNRTCBTU0wgcmVncmVzc2lvbiB0ZXN0IGNs |
||||
aWVudCBjZXJ0czAeFw0yMTExMTAwMzMyNDFaFw00OTAzMjgwMzMyNDFaMBYxFDAS |
||||
BgNVBAMMC3NzbHRlc3R1c2VyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC |
||||
AQEArCHikkEQLFITbn3ZfO8X2RW3fELeaImgy8W4Pkkc4LxdHCWjdCML/vtE/ZVu |
||||
Op74qrQQWT0HKXFVUiZLbjAgV2PONS6VFHhc3sTFxuTaBnVdY+K98hoFnXskINt/ |
||||
wgwUhRcRZuKPcZvEHiqF6e3g3lQa99l1nVKPGPLOCvVhSgoV0Gwgxok0t7s25BCV |
||||
ZmpMAwSTxpeviLF0e2MsttuyClQ4nuD92EHZX3BuG0WNPLxiwikV96uMffpMRGsx |
||||
uiAHzD5ykYM7/b3eU0bjfi0J0qcfTSeytqFuRCNEukJpmtUmyYGqsFJ7HN7ejCY7 |
||||
ObAlBn8h+4bgwBRaeZDZLTMaYQIDAQABo4GgMIGdMAwGA1UdEwEB/wQCMAAwEwYD |
||||
VR0lBAwwCgYIKwYBBQUHAwIwHQYDVR0OBBYEFPPv1n7k1Vd9BBC4eoGWPZwVz2Lx |
||||
MFkGA1UdIwRSMFChRKRCMEAxPjA8BgNVBAMMNVRlc3Qgcm9vdCBDQSBmb3IgUG9z |
||||
dGdyZVNRTCBTU0wgcmVncmVzc2lvbiB0ZXN0IHN1aXRlggggIQMDFBIHATANBgkq |
||||
hkiG9w0BAQsFAAOCAQEAtqIeTmUhtHyCt5k2yx88F0dKshYq4Z+LQI+agyZ1fRE6 |
||||
Ux5p+SBGbzvc+NcUvc7yGG6w2G/nTVnGwSHN9NtQa2T2XbHJysJ/dwCfmRsachKz |
||||
4kCp0zAHEDrEmZua0sy5BLwwVCk5WNBR0lZ35WmIEuRA+5G/2lCywtrb9W4YnbAM |
||||
nH7BtZE8qPbK4OicB40I2NXz6KhG3755oKN03VC1IaX9JFQxf37ac7jVK5bsjfaF |
||||
0xCAeuDN6wDiVHZj6q1GhhmNLzaF5zmU2e/cI1nTI5tfGKnygavlZIz2VvAlcypt |
||||
YZdMDy69VbTWUa57UPCspghgvm5M2/Hjmz50CXGMvw== |
||||
-----END CERTIFICATE----- |
@ -0,0 +1,28 @@ |
||||
-----BEGIN PRIVATE KEY----- |
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCsIeKSQRAsUhNu |
||||
fdl87xfZFbd8Qt5oiaDLxbg+SRzgvF0cJaN0Iwv++0T9lW46nviqtBBZPQcpcVVS |
||||
JktuMCBXY841LpUUeFzexMXG5NoGdV1j4r3yGgWdeyQg23/CDBSFFxFm4o9xm8Qe |
||||
KoXp7eDeVBr32XWdUo8Y8s4K9WFKChXQbCDGiTS3uzbkEJVmakwDBJPGl6+IsXR7 |
||||
Yyy227IKVDie4P3YQdlfcG4bRY08vGLCKRX3q4x9+kxEazG6IAfMPnKRgzv9vd5T |
||||
RuN+LQnSpx9NJ7K2oW5EI0S6Qmma1SbJgaqwUnsc3t6MJjs5sCUGfyH7huDAFFp5 |
||||
kNktMxphAgMBAAECggEAQlVWkmUHXgUNHvXZo8chyhMP4A+G1QNAl3Zs73fObJ66 |
||||
RPgOOtmsrEjZh92XmnibvHDiofkeMu7NYfiG9gIO3I6GL0Fxyu8tXt22l9SmXnnJ |
||||
EQ6Wg19azZrgS9c6ryVnnPhMSPlDLRVJaRSbAZCdqSABOoUvSX7AzWz4UQnJwbVp |
||||
c9Le7DbXcD4IIhi+D2o6k46oGTm+P8kEAbw73tN7NmxBudwMhvGup3HlDNypbwPJ |
||||
0aWR+nxZbaAVnmYiENX7L68R9rweqDES8AgV030L4YF022C8TAuBLeCjuEQucdp4 |
||||
+ZcNUzAF2G1NN/VUpjBKK08+Pu0C0vV+fDrKWK+QnwKBgQC74THLylX/+7TJC24U |
||||
LXu/z5BjkejUr4GLHTZG9edGgaoSiKikXdseCI/RiDVXvtQ7kstFYflOZ+XGuc4l |
||||
GVAN52uRqg7uXw0R8F8bKpal08j4Rhe4rXKvH5h9hSeozOlxq7jrQ2xk96Guu3k7 |
||||
ujqkkVoPX+dnwUVN6elWrMIUpwKBgQDqiwqaKk7Pmkqc5et4WKvKFLKYuTU/qOO6 |
||||
fVEqGlgbLGNf+DVgKcTl5AVyhqtedh1hin0ij/dDHoYOmynmbe/zguSxF7kYUxdJ |
||||
STwWpQt/ccaWMfqgrjxXpWsPc1fRWgmACAaum04GXmBeZ4z0rVT4blwAVddgoLL8 |
||||
q4lrSNbRtwKBgQClv4jnyaxPNecLCmtln66xzFMMlJe8ssztRqswtRYA7Ll2ultV |
||||
DnwVpeYDK1AsBe1EVT/BCSshEaXzyM3lisxGR+htTIL5pp9oORAeblcTGqEM7wFU |
||||
aqhneM9VxRf04jn8j0uHOicxeAmKllfg6m1768NxFuGWdjpG/1pcnfJmtwKBgAF8 |
||||
Nen6AJvB710E+7O8ZAIYlXTwH00y5ZZFuuDYX9x0MIDoEnZ0bUHDauFpxuYHO3Jl |
||||
rRst7DPpmpG3G9HQumdBWe9hJhPoWsplA1NlYihBcS98S4j+8XTgoEftxA2YU10T |
||||
L++lHh5eNKAEadkWy+Xy1PRPltiOy/NbprgeMvYLAoGAKpt7DHcK8B0JdOnEzTuz |
||||
7mT6xRt2C9IASCiv92Fx1BPiPy4l9ukT4CJza/wpSpH3xyeB37afe0kQyU8lDrCF |
||||
iMU3RNTzTftwqO8GgtgntgW8ZKe9fuqzm9VLMQFyL+zdqEfGG6ROS8ipYLx9pn6x |
||||
FHc3UsmLmK0hfCr9B4Yo+C0= |
||||
-----END PRIVATE KEY----- |
@ -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'); |
Loading…
Reference in new issue