aboutsummaryrefslogtreecommitdiff
path: root/src/test/ssl/ServerSetup.pm
blob: 1579dc9137a7113e061e6470ab2645990cebeb94 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# 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 authentiction, 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 ServerSetup;

use strict;
use warnings;
use TestLib;
use Test::More;

use Exporter 'import';
our @EXPORT = qw(
  configure_test_server_for_ssl switch_server_cert
);

sub configure_test_server_for_ssl
{
  my $tempdir = $_[0];

  # 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 "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
  system_or_bail "cp ssl/server-*.crt '$tempdir'/pgdata";
  system_or_bail "cp ssl/server-*.key '$tempdir'/pgdata";
  system_or_bail "chmod 0600 '$tempdir'/pgdata/server-*.key";
  system_or_bail "cp ssl/root+client_ca.crt '$tempdir'/pgdata";
  system_or_bail "cp 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];

  diag "Restarting server with certfile \"$certfile\"...";

  open SSLCONF, ">$tempdir/pgdata/sslconfig.conf";
  print SSLCONF "ssl=on\n";
  print SSLCONF "ssl_ca_file='root+client_ca.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', '-s', '-D', "$tempdir/pgdata", '-w';
  system_or_bail 'pg_ctl', 'start', '-s', '-D', "$tempdir/pgdata", '-w', '-l',
        "$tempdir/logfile";
}