diff options
Diffstat (limited to 'src/test/ssl/t/SSLServer.pm')
-rw-r--r-- | src/test/ssl/t/SSLServer.pm | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/src/test/ssl/t/SSLServer.pm b/src/test/ssl/t/SSLServer.pm new file mode 100644 index 00000000000..6781fa04991 --- /dev/null +++ b/src/test/ssl/t/SSLServer.pm @@ -0,0 +1,120 @@ +# This module sets up a test server, for the SSL regression tests. +# +# The server is configured as follows: +# +# - SSL enabled, with the server certificate specified by argument to +# switch_server_cert function. +# - ssl/root+client_ca.crt as the CA root for validating client certs. +# - reject non-SSL connections +# - a database called trustdb that lets anyone in +# - another database called certdb that uses certificate authentication, ie. +# the client must present a valid certificate signed by the client CA +# - two users, called ssltestuser and anotheruser. +# +# The server is configured to only accept connections from localhost. If you +# want to run the client from another host, you'll have to configure that +# manually. +package SSLServer; + +use strict; +use warnings; +use TestLib; +use File::Basename; +use File::Copy; +use Test::More; + +use Exporter 'import'; +our @EXPORT = qw( + configure_test_server_for_ssl switch_server_cert +); + +# Copy a set of files, taking into account wildcards +sub copy_files +{ + my $orig = shift; + my $dest = shift; + + my @orig_files = glob $orig; + foreach my $orig_file (@orig_files) + { + my $base_file = basename($orig_file); + copy($orig_file, "$dest/$base_file") + or die "Could not copy $orig_file to $dest"; + } +} + +sub configure_test_server_for_ssl +{ + my $tempdir = $_[0]; + my $serverhost = $_[1]; + + # Create test users and databases + psql 'postgres', "CREATE USER ssltestuser"; + psql 'postgres', "CREATE USER anotheruser"; + psql 'postgres', "CREATE DATABASE trustdb"; + psql 'postgres', "CREATE DATABASE certdb"; + + # enable logging etc. + open CONF, ">>$tempdir/pgdata/postgresql.conf"; + print CONF "fsync=off\n"; + print CONF "log_connections=on\n"; + print CONF "log_hostname=on\n"; + print CONF "listen_addresses='$serverhost'\n"; + print CONF "log_statement=all\n"; + + # enable SSL and set up server key + print CONF "include 'sslconfig.conf'"; + + close CONF; + +# Copy all server certificates and keys, and client root cert, to the data dir + copy_files("ssl/server-*.crt", "$tempdir/pgdata"); + copy_files("ssl/server-*.key", "$tempdir/pgdata"); + chmod(0600, glob "$tempdir/pgdata/server-*.key") or die $!; + copy_files("ssl/root+client_ca.crt", "$tempdir/pgdata"); + copy_files("ssl/root_ca.crt", "$tempdir/pgdata"); + copy_files("ssl/root+client.crl", "$tempdir/pgdata"); + + # Only accept SSL connections from localhost. Our tests don't depend on this + # but seems best to keep it as narrow as possible for security reasons. + # + # When connecting to certdb, also check the client certificate. + open HBA, ">$tempdir/pgdata/pg_hba.conf"; + print HBA +"# TYPE DATABASE USER ADDRESS METHOD\n"; + print HBA +"hostssl trustdb ssltestuser 127.0.0.1/32 trust\n"; + print HBA +"hostssl trustdb ssltestuser ::1/128 trust\n"; + print HBA +"hostssl certdb ssltestuser 127.0.0.1/32 cert\n"; + print HBA +"hostssl certdb ssltestuser ::1/128 cert\n"; + close HBA; +} + +# Change the configuration to use given server cert file, and restart +# the server so that the configuration takes effect. +sub switch_server_cert +{ + my $tempdir = $_[0]; + my $certfile = $_[1]; + my $cafile = $_[2] || "root+client_ca"; + + diag "Restarting server with certfile \"$certfile\" and cafile \"$cafile\"..."; + + open SSLCONF, ">$tempdir/pgdata/sslconfig.conf"; + print SSLCONF "ssl=on\n"; + print SSLCONF "ssl_ca_file='$cafile.crt'\n"; + print SSLCONF "ssl_cert_file='$certfile.crt'\n"; + print SSLCONF "ssl_key_file='$certfile.key'\n"; + print SSLCONF "ssl_crl_file='root+client.crl'\n"; + close SSLCONF; + + # Stop and restart server to reload the new config. We cannot use + # restart_test_server() because that overrides listen_addresses to only all + # Unix domain socket connections. + + system_or_bail 'pg_ctl', 'stop', '-D', "$tempdir/pgdata"; + system_or_bail 'pg_ctl', 'start', '-D', "$tempdir/pgdata", '-w'; +} |