From 7f7ec524347b6478bcf07b60a191ed15ff0862ec Mon Sep 17 00:00:00 2001 From: Kerstin Humm Date: Wed, 5 Jun 2024 22:39:10 +0200 Subject: [PATCH] nixos/tests/postgresql: add tls client cert test --- nixos/tests/all-tests.nix | 1 + nixos/tests/postgresql-tls-client-cert.nix | 141 +++++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 nixos/tests/postgresql-tls-client-cert.nix diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 98ba04119ea5..53b5ff754ec5 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -754,6 +754,7 @@ in { postgresql = handleTest ./postgresql.nix {}; postgresql-jit = handleTest ./postgresql-jit.nix {}; postgresql-wal-receiver = handleTest ./postgresql-wal-receiver.nix {}; + postgresql-tls-client-cert = handleTest ./postgresql-tls-client-cert.nix {}; powerdns = handleTest ./powerdns.nix {}; powerdns-admin = handleTest ./powerdns-admin.nix {}; power-profiles-daemon = handleTest ./power-profiles-daemon.nix {}; diff --git a/nixos/tests/postgresql-tls-client-cert.nix b/nixos/tests/postgresql-tls-client-cert.nix new file mode 100644 index 000000000000..c1678ed733be --- /dev/null +++ b/nixos/tests/postgresql-tls-client-cert.nix @@ -0,0 +1,141 @@ +{ system ? builtins.currentSystem +, config ? { } +, pkgs ? import ../.. { inherit system config; } +, package ? null +}: + +with import ../lib/testing-python.nix { inherit system pkgs; }; + +let + lib = pkgs.lib; + + # Makes a test for a PostgreSQL package, given by name and looked up from `pkgs`. + makeTestAttribute = name: + { + inherit name; + value = makePostgresqlTlsClientCertTest pkgs."${name}"; + }; + + makePostgresqlTlsClientCertTest = pkg: + let + runWithOpenSSL = file: cmd: pkgs.runCommand file + { + buildInputs = [ pkgs.openssl ]; + } + cmd; + caKey = runWithOpenSSL "ca.key" "openssl ecparam -name prime256v1 -genkey -noout -out $out"; + caCert = runWithOpenSSL + "ca.crt" + '' + openssl req -new -x509 -sha256 -key ${caKey} -out $out -subj "/CN=test.example" -days 36500 + ''; + serverKey = + runWithOpenSSL "server.key" "openssl ecparam -name prime256v1 -genkey -noout -out $out"; + serverKeyPath = "/var/lib/postgresql"; + serverCert = + runWithOpenSSL "server.crt" '' + openssl req -new -sha256 -key ${serverKey} -out server.csr -subj "/CN=db.test.example" + openssl x509 -req -in server.csr -CA ${caCert} -CAkey ${caKey} \ + -CAcreateserial -out $out -days 36500 -sha256 + ''; + clientKey = + runWithOpenSSL "client.key" "openssl ecparam -name prime256v1 -genkey -noout -out $out"; + clientCert = + runWithOpenSSL "client.crt" '' + openssl req -new -sha256 -key ${clientKey} -out client.csr -subj "/CN=test" + openssl x509 -req -in client.csr -CA ${caCert} -CAkey ${caKey} \ + -CAcreateserial -out $out -days 36500 -sha256 + ''; + clientKeyPath = "/root"; + + in + makeTest { + name = "postgresql-tls-client-cert-${pkg.name}"; + meta.maintainers = with lib.maintainers; [ erictapen ]; + + nodes.server = { ... }: { + system.activationScripts = { + keyPlacement.text = '' + mkdir -p '${serverKeyPath}' + cp '${serverKey}' '${serverKeyPath}/server.key' + chown postgres:postgres '${serverKeyPath}/server.key' + chmod 600 '${serverKeyPath}/server.key' + ''; + }; + services.postgresql = { + package = pkg; + enable = true; + enableTCPIP = true; + ensureUsers = [ + { + name = "test"; + ensureDBOwnership = true; + } + ]; + ensureDatabases = [ "test" ]; + settings = { + ssl = "on"; + ssl_ca_file = toString caCert; + ssl_cert_file = toString serverCert; + ssl_key_file = "${serverKeyPath}/server.key"; + }; + authentication = '' + hostssl test test ::/0 cert clientcert=verify-full + ''; + }; + networking = { + interfaces.eth1 = { + ipv6.addresses = [ + { address = "fc00::1"; prefixLength = 120; } + ]; + }; + firewall.allowedTCPPorts = [ 5432 ]; + }; + }; + + nodes.client = { ... }: { + system.activationScripts = { + keyPlacement.text = '' + mkdir -p '${clientKeyPath}' + cp '${clientKey}' '${clientKeyPath}/client.key' + chown root:root '${clientKeyPath}/client.key' + chmod 600 '${clientKeyPath}/client.key' + ''; + }; + environment = { + variables = { + PGHOST = "db.test.example"; + PGPORT = "5432"; + PGDATABASE = "test"; + PGUSER = "test"; + PGSSLMODE = "verify-full"; + PGSSLCERT = clientCert; + PGSSLKEY = "${clientKeyPath}/client.key"; + PGSSLROOTCERT = caCert; + }; + systemPackages = [ pkg ]; + }; + networking = { + interfaces.eth1 = { + ipv6.addresses = [ + { address = "fc00::2"; prefixLength = 120; } + ]; + }; + hosts = { "fc00::1" = [ "db.test.example" ]; }; + }; + }; + + testScript = '' + server.wait_for_unit("multi-user.target") + client.wait_for_unit("multi-user.target") + client.succeed("psql -c \"SELECT 1;\"") + ''; + }; + +in +if package == null then +# all-tests.nix: Maps the generic function over all attributes of PostgreSQL packages + builtins.listToAttrs (map makeTestAttribute (builtins.attrNames (import ../../pkgs/servers/sql/postgresql pkgs))) +else +# Called directly from .tests + makePostgresqlTlsClientCertTest package