nixos/synapse: implement more advanced integration test (#400845)
This commit is contained in:
@@ -821,6 +821,7 @@
|
||||
./services/matrix/mautrix-whatsapp.nix
|
||||
./services/matrix/mjolnir.nix
|
||||
./services/matrix/pantalaimon.nix
|
||||
./services/matrix/rust-federation-tester.nix
|
||||
./services/matrix/synapse-auto-compressor.nix
|
||||
./services/matrix/synapse.nix
|
||||
./services/matrix/tuwunel.nix
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
utils,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
cfg = config.services.rust-federation-tester;
|
||||
|
||||
configFile = "/run/rust-federation-tester/config.yaml";
|
||||
commonServiceConfig = {
|
||||
DynamicUser = true;
|
||||
RuntimeDirectory = "rust-federation-tester";
|
||||
RuntimeDirectoryPreserve = true;
|
||||
StateDirectory = "rust-federation-tester";
|
||||
User = "rust-federation-tester";
|
||||
WorkingDirectory = "%t/rust-federation-tester";
|
||||
|
||||
# Hardening
|
||||
UMask = "0077";
|
||||
CapabilityBoundingSet = [ "" ];
|
||||
DevicePolicy = "closed";
|
||||
PrivateTmp = true;
|
||||
ProtectHome = true;
|
||||
ProtectSystem = "strict";
|
||||
MemoryDenyWriteExecute = true;
|
||||
NoNewPrivileges = true;
|
||||
LockPersonality = true;
|
||||
PrivateDevices = true;
|
||||
PrivateMounts = true;
|
||||
ProcSubset = "pid";
|
||||
ProtectClock = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectProc = "invisible";
|
||||
RemoveIPC = true;
|
||||
RestrictAddressFamilies = [
|
||||
"AF_INET"
|
||||
"AF_INET6"
|
||||
"AF_UNIX"
|
||||
];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = [
|
||||
"@system-service"
|
||||
];
|
||||
};
|
||||
|
||||
secretsInjection = utils.genJqSecretsReplacement {
|
||||
loadCredential = true;
|
||||
} cfg.settings configFile;
|
||||
in
|
||||
{
|
||||
options.services.rust-federation-tester = {
|
||||
enable = lib.mkEnableOption "rust-federation-tester";
|
||||
|
||||
settings = lib.mkOption {
|
||||
type = lib.types.submodule {
|
||||
freeformType = lib.types.json;
|
||||
options = {
|
||||
frontend_url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
example = "federation-tester.example.org";
|
||||
description = ''
|
||||
URL of the service's frontend.
|
||||
'';
|
||||
};
|
||||
|
||||
database_url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "sqlite:///var/lib/rust-federation-tester/db?mode=rwc";
|
||||
example = "postgres://localhost/db?currentSchema=schema";
|
||||
description = ''
|
||||
The database to store accounts and statistics.
|
||||
'';
|
||||
};
|
||||
|
||||
smtp = {
|
||||
enabled = lib.mkEnableOption "mail delivery for configured alerts";
|
||||
};
|
||||
|
||||
listen_addr = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "[::]:8080";
|
||||
example = "unix:/run/rust-federation-tester/rust-federation-tester.sock";
|
||||
description = ''
|
||||
Address the API server should listen on.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
description = ''
|
||||
Settings representing the values in {file}`config.yaml` of the service.
|
||||
|
||||
Refer to [`config.yaml.example`] for supported values.
|
||||
|
||||
[`config.yaml.example`]: https://github.com/MTRNord/rust-federation-tester/blob/main/config.yaml.example
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
systemd.sockets.rust-federation-tester = {
|
||||
description = "Matrix-Federation-Tester in Rust socket";
|
||||
wantedBy = [ "sockets.target" ];
|
||||
listenStreams = [ (lib.removePrefix "unix:" cfg.settings.listen_addr) ];
|
||||
};
|
||||
|
||||
systemd.services.rust-federation-tester-setup = {
|
||||
description = "Matrix-Federation-Tester in Rust";
|
||||
path = [ pkgs.rust-federation-tester ];
|
||||
|
||||
serviceConfig = lib.mkMerge [
|
||||
commonServiceConfig
|
||||
{
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
LoadCredential = secretsInjection.credentials;
|
||||
ExecStart = "${pkgs.writeShellScript "rust-federation-tester-setup" ''
|
||||
${secretsInjection.script}
|
||||
|
||||
migration up
|
||||
''}";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
systemd.services.rust-federation-tester = {
|
||||
description = "Matrix-Federation-Tester in Rust";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
documentation = [ "https://github.com/MTRNord/rust-federation-tester" ];
|
||||
after = [ "rust-federation-tester-setup.service" ];
|
||||
requires = [ "rust-federation-tester-setup.service" ];
|
||||
|
||||
serviceConfig = lib.mkMerge [
|
||||
commonServiceConfig
|
||||
{
|
||||
ExecSearchPath = lib.makeBinPath [ pkgs.rust-federation-tester ];
|
||||
ExecStart = "rust-federation-tester";
|
||||
Restart = "on-failure";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1005,7 +1005,6 @@ in
|
||||
matrix-conduit = runTest ./matrix/conduit.nix;
|
||||
matrix-continuwuity = runTest ./matrix/continuwuity.nix;
|
||||
matrix-synapse = runTest ./matrix/synapse.nix;
|
||||
matrix-synapse-workers = runTest ./matrix/synapse-workers.nix;
|
||||
matrix-tuwunel = runTest ./matrix/tuwunel.nix;
|
||||
matter-server = runTest ./matter-server.nix;
|
||||
matterjs-server = runTest ./matterjs-server.nix;
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
name = "matrix-synapse-workers";
|
||||
meta = {
|
||||
inherit (pkgs.matrix-synapse.meta) maintainers;
|
||||
};
|
||||
|
||||
nodes = {
|
||||
homeserver =
|
||||
{
|
||||
pkgs,
|
||||
nodes,
|
||||
...
|
||||
}:
|
||||
{
|
||||
services.postgresql = {
|
||||
enable = true;
|
||||
initialScript = pkgs.writeText "synapse-init.sql" ''
|
||||
CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD 'synapse';
|
||||
CREATE DATABASE "matrix-synapse" WITH OWNER "matrix-synapse"
|
||||
TEMPLATE template0
|
||||
LC_COLLATE = "C"
|
||||
LC_CTYPE = "C";
|
||||
'';
|
||||
};
|
||||
|
||||
services.matrix-synapse = {
|
||||
enable = true;
|
||||
settings = {
|
||||
database = {
|
||||
name = "psycopg2";
|
||||
args.password = "synapse";
|
||||
};
|
||||
enable_registration = true;
|
||||
enable_registration_without_verification = true;
|
||||
|
||||
federation_sender_instances = [ "federation_sender" ];
|
||||
};
|
||||
configureRedisLocally = true;
|
||||
workers = {
|
||||
"federation_sender" = { };
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
start_all()
|
||||
|
||||
homeserver.wait_for_unit("matrix-synapse.service");
|
||||
homeserver.wait_for_unit("matrix-synapse-worker-federation_sender.service");
|
||||
'';
|
||||
}
|
||||
+328
-136
@@ -1,101 +1,194 @@
|
||||
{ pkgs, ... }:
|
||||
let
|
||||
|
||||
ca_key = mailerCerts.ca.key;
|
||||
ca_pem = mailerCerts.ca.cert;
|
||||
|
||||
bundle =
|
||||
pkgs.runCommand "bundle"
|
||||
aliceName = "alice";
|
||||
alicePassword = "alicealice";
|
||||
aliceEmail = "alice@example.com";
|
||||
|
||||
bobName = "bob";
|
||||
bobPassword = "hunter2";
|
||||
|
||||
mkBundle =
|
||||
domain:
|
||||
pkgs.runCommand "bundle-${domain}"
|
||||
{
|
||||
nativeBuildInputs = [ pkgs.minica ];
|
||||
}
|
||||
''
|
||||
minica -ca-cert ${ca_pem} -ca-key ${ca_key} \
|
||||
-domains localhost
|
||||
install -Dm444 -t $out localhost/{key,cert}.pem
|
||||
-domains ${domain}
|
||||
install -Dm444 -t $out ${domain}/{key,cert}.pem
|
||||
'';
|
||||
|
||||
mailerCerts = import ../common/acme/server/snakeoil-certs.nix;
|
||||
mailerDomain = mailerCerts.domain;
|
||||
registrationSharedSecret = "unsecure123";
|
||||
testUser = "alice";
|
||||
testPassword = "alicealice";
|
||||
testEmail = "alice@example.com";
|
||||
|
||||
listeners = [
|
||||
anonHash = "hunter2hunter2hunter2";
|
||||
anonHashF = pkgs.writeText "hash" anonHash;
|
||||
|
||||
mkHomeserverBase =
|
||||
domain: nodes:
|
||||
let
|
||||
bundle = mkBundle domain;
|
||||
in
|
||||
{ lib, ... }:
|
||||
{
|
||||
port = 8448;
|
||||
bind_addresses = [
|
||||
"127.0.0.1"
|
||||
"::1"
|
||||
security.pki.certificateFiles = [
|
||||
mailerCerts.ca.cert
|
||||
];
|
||||
type = "http";
|
||||
tls = true;
|
||||
x_forwarded = false;
|
||||
resources = [
|
||||
{
|
||||
names = [
|
||||
"client"
|
||||
];
|
||||
compress = true;
|
||||
}
|
||||
{
|
||||
names = [
|
||||
"federation"
|
||||
];
|
||||
compress = false;
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
|
||||
networking = {
|
||||
hostName = lib.head (lib.strings.splitString "." domain);
|
||||
domain = lib.last (lib.strings.splitString "." domain);
|
||||
firewall.allowedTCPPorts = [
|
||||
80
|
||||
443
|
||||
8448
|
||||
];
|
||||
};
|
||||
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
virtualHosts."${domain}" = {
|
||||
sslCertificate = "${bundle}/cert.pem";
|
||||
sslCertificateKey = "${bundle}/key.pem";
|
||||
addSSL = true;
|
||||
locations."/.well-known/matrix/server".extraConfig = ''
|
||||
default_type application/json;
|
||||
return 200 '${
|
||||
builtins.toJSON {
|
||||
"m.server" = "${domain}:8448";
|
||||
}
|
||||
}';
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mkSynapseConfig =
|
||||
domain: primaryIP:
|
||||
let
|
||||
bundle = mkBundle domain;
|
||||
in
|
||||
{
|
||||
enable = true;
|
||||
settings = {
|
||||
# We're in a test environment with local machines, so
|
||||
# we actually _want_ to use RFC1918 addresses.
|
||||
ip_range_blacklist = [ ];
|
||||
|
||||
trusted_key_servers = [
|
||||
{ server_name = "hs1.test"; }
|
||||
{ server_name = "hs2.test"; }
|
||||
];
|
||||
|
||||
registration_shared_secret = registrationSharedSecret;
|
||||
public_baseurl = "https://${domain}";
|
||||
tls_certificate_path = "${bundle}/cert.pem";
|
||||
tls_private_key_path = "${bundle}/key.pem";
|
||||
listeners = [
|
||||
# Using a local listener, otherwise matrix-synapse-register_new_matrix_user will
|
||||
# fail because it'll try to connect to the first bind address, but via TLS resulting
|
||||
# in a signature verification failure.
|
||||
{
|
||||
port = 8008;
|
||||
type = "http";
|
||||
tls = false;
|
||||
resources = [
|
||||
{
|
||||
names = [ "client" ];
|
||||
compress = true;
|
||||
}
|
||||
];
|
||||
bind_addresses = [ "::1" ];
|
||||
}
|
||||
{
|
||||
port = 8448;
|
||||
bind_addresses = [
|
||||
primaryIP
|
||||
];
|
||||
type = "http";
|
||||
tls = true;
|
||||
x_forwarded = false;
|
||||
resources = [
|
||||
{
|
||||
names = [
|
||||
"client"
|
||||
];
|
||||
compress = true;
|
||||
}
|
||||
{
|
||||
names = [
|
||||
"federation"
|
||||
];
|
||||
compress = false;
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
|
||||
name = "matrix-synapse";
|
||||
meta = {
|
||||
inherit (pkgs.matrix-synapse.meta) maintainers;
|
||||
};
|
||||
|
||||
nodes = {
|
||||
# Since 0.33.0, matrix-synapse doesn't allow underscores in server names
|
||||
serverpostgres =
|
||||
synapse-with-workers =
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
pkgs,
|
||||
nodes,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
mailserverIP = nodes.mailserver.networking.primaryIPAddress;
|
||||
in
|
||||
{
|
||||
services.matrix-synapse = {
|
||||
enable = true;
|
||||
settings = {
|
||||
inherit listeners;
|
||||
database = {
|
||||
name = "psycopg2";
|
||||
args.password = "synapse";
|
||||
imports = [
|
||||
(mkHomeserverBase "hs1.test" nodes)
|
||||
];
|
||||
|
||||
services.matrix-synapse = lib.mkMerge [
|
||||
(mkSynapseConfig "hs1.test" config.networking.primaryIPAddress)
|
||||
{
|
||||
settings = {
|
||||
server_name = "hs1.test";
|
||||
email = {
|
||||
smtp_host = mailerDomain;
|
||||
smtp_port = 25;
|
||||
require_transport_security = true;
|
||||
notif_from = "matrix <matrix@${mailerDomain}>";
|
||||
app_name = "Matrix";
|
||||
};
|
||||
listeners = [
|
||||
{
|
||||
path = "/run/matrix-synapse/main_replication.sock";
|
||||
type = "http";
|
||||
resources = [
|
||||
{
|
||||
names = [ "replication" ];
|
||||
compress = false;
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
database = {
|
||||
name = "psycopg2";
|
||||
args.password = "synapse";
|
||||
};
|
||||
federation_sender_instances = [ "federation_sender" ];
|
||||
};
|
||||
redis = {
|
||||
enabled = true;
|
||||
host = "localhost";
|
||||
port = config.services.redis.servers.matrix-synapse.port;
|
||||
configureRedisLocally = true;
|
||||
workers = {
|
||||
"federation_sender" = { };
|
||||
};
|
||||
tls_certificate_path = "${bundle}/cert.pem";
|
||||
tls_private_key_path = "${bundle}/key.pem";
|
||||
registration_shared_secret = registrationSharedSecret;
|
||||
public_baseurl = "https://example.com";
|
||||
email = {
|
||||
smtp_host = mailerDomain;
|
||||
smtp_port = 25;
|
||||
require_transport_security = true;
|
||||
notif_from = "matrix <matrix@${mailerDomain}>";
|
||||
app_name = "Matrix";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
services.postgresql = {
|
||||
enable = true;
|
||||
|
||||
@@ -113,20 +206,6 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
services.redis.servers.matrix-synapse = {
|
||||
enable = true;
|
||||
port = 6380;
|
||||
};
|
||||
|
||||
networking.extraHosts = ''
|
||||
${mailserverIP} ${mailerDomain}
|
||||
'';
|
||||
|
||||
security.pki.certificateFiles = [
|
||||
mailerCerts.ca.cert
|
||||
ca_pem
|
||||
];
|
||||
|
||||
environment.systemPackages =
|
||||
let
|
||||
sendTestMailStarttls = pkgs.writeScriptBin "send-testmail-starttls" ''
|
||||
@@ -140,7 +219,7 @@ in
|
||||
smtp.ehlo()
|
||||
smtp.starttls(context=ctx)
|
||||
smtp.ehlo()
|
||||
smtp.sendmail('matrix@${mailerDomain}', '${testEmail}', 'Subject: Test STARTTLS\n\nTest data.')
|
||||
smtp.sendmail('matrix@${mailerDomain}', '${aliceEmail}', 'Subject: Test STARTTLS\n\nTest data.')
|
||||
smtp.quit()
|
||||
'';
|
||||
|
||||
@@ -149,16 +228,14 @@ in
|
||||
# adding the email through the API is quite complicated as it involves more than one step and some
|
||||
# client-side calculation
|
||||
insertEmailForAlice = pkgs.writeText "alice-email.sql" ''
|
||||
INSERT INTO user_threepids (user_id, medium, address, validated_at, added_at) VALUES ('${testUser}@serverpostgres', 'email', '${testEmail}', '1629149927271', '1629149927270');
|
||||
INSERT INTO user_threepids (user_id, medium, address, validated_at, added_at) VALUES ('${aliceName}@serverpostgres', 'email', '${aliceEmail}', '1629149927271', '1629149927270');
|
||||
'';
|
||||
in
|
||||
pkgs.writeScriptBin "obtain-token-and-register-email" ''
|
||||
#!${pkgs.runtimeShell}
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
set -o nounset
|
||||
set -euxo pipefail
|
||||
su postgres -c "psql -d matrix-synapse -f ${insertEmailForAlice}"
|
||||
curl --fail -XPOST 'https://localhost:8448/_matrix/client/r0/account/password/email/requestToken' -d '{"email":"${testEmail}","client_secret":"foobar","send_attempt":1}' -v
|
||||
curl --fail -XPOST 'https://hs1.test:8448/_matrix/client/r0/account/password/email/requestToken' -d '{"email":"${aliceEmail}","client_secret":"foobar","send_attempt":1}' -v
|
||||
'';
|
||||
in
|
||||
[
|
||||
@@ -168,74 +245,189 @@ in
|
||||
];
|
||||
};
|
||||
|
||||
# test mail delivery
|
||||
mailserver = args: {
|
||||
security.pki.certificateFiles = [
|
||||
mailerCerts.ca.cert
|
||||
];
|
||||
mailserver =
|
||||
{ lib, ... }:
|
||||
{
|
||||
security.pki.certificateFiles = [
|
||||
mailerCerts.ca.cert
|
||||
];
|
||||
|
||||
networking.firewall.enable = false;
|
||||
networking = {
|
||||
hostName = lib.head (lib.strings.splitString "." mailerDomain);
|
||||
domain = lib.last (lib.strings.splitString "." mailerDomain);
|
||||
firewall.enable = false;
|
||||
};
|
||||
|
||||
services.postfix = {
|
||||
enable = true;
|
||||
enableSubmission = true;
|
||||
services.postfix = {
|
||||
enable = true;
|
||||
enableSubmission = true;
|
||||
|
||||
# blackhole transport
|
||||
transport = "example.com discard:silently";
|
||||
# blackhole transport
|
||||
transport = "example.com discard:silently";
|
||||
|
||||
settings.main = {
|
||||
myhostname = "${mailerDomain}";
|
||||
# open relay for subnet
|
||||
mynetworks_style = "subnet";
|
||||
debug_peer_level = "10";
|
||||
smtpd_relay_restrictions = [
|
||||
"permit_mynetworks"
|
||||
"reject_unauth_destination"
|
||||
];
|
||||
settings.main = {
|
||||
myhostname = "${mailerDomain}";
|
||||
# open relay for subnet
|
||||
mynetworks_style = "subnet";
|
||||
debug_peer_level = "10";
|
||||
smtpd_relay_restrictions = [
|
||||
"permit_mynetworks"
|
||||
"reject_unauth_destination"
|
||||
];
|
||||
|
||||
# disable obsolete protocols, something old versions of twisted are still using
|
||||
smtpd_tls_protocols = "TLSv1.3, TLSv1.2, !TLSv1.1, !TLSv1, !SSLv2, !SSLv3";
|
||||
smtpd_tls_mandatory_protocols = "TLSv1.3, TLSv1.2, !TLSv1.1, !TLSv1, !SSLv2, !SSLv3";
|
||||
smtpd_tls_chain_files = [
|
||||
"${mailerCerts.${mailerDomain}.key}"
|
||||
"${mailerCerts.${mailerDomain}.cert}"
|
||||
];
|
||||
# disable obsolete protocols, something old versions of twisted are still using
|
||||
smtpd_tls_protocols = "TLSv1.3, TLSv1.2, !TLSv1.1, !TLSv1, !SSLv2, !SSLv3";
|
||||
smtpd_tls_mandatory_protocols = "TLSv1.3, TLSv1.2, !TLSv1.1, !TLSv1, !SSLv2, !SSLv3";
|
||||
smtpd_tls_chain_files = [
|
||||
"${mailerCerts.${mailerDomain}.key}"
|
||||
"${mailerCerts.${mailerDomain}.cert}"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
serversqlite = args: {
|
||||
services.matrix-synapse = {
|
||||
enable = true;
|
||||
settings = {
|
||||
inherit listeners;
|
||||
database.name = "sqlite3";
|
||||
tls_certificate_path = "${bundle}/cert.pem";
|
||||
tls_private_key_path = "${bundle}/key.pem";
|
||||
synapse-minimal =
|
||||
{
|
||||
nodes,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
{
|
||||
imports = [
|
||||
(mkHomeserverBase "hs2.test" nodes)
|
||||
];
|
||||
|
||||
services.matrix-synapse = lib.mkMerge [
|
||||
(mkSynapseConfig "hs2.test" config.networking.primaryIPAddress)
|
||||
{
|
||||
settings = {
|
||||
database.name = "sqlite3";
|
||||
server_name = "hs2.test";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
client =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
environment.systemPackages = [
|
||||
# `pkgs.olm` is cached on c.n.o, even if this test isn't built due
|
||||
# to it being allow-listed in `pkgs/top-level/release.nix`.
|
||||
(import pkgs.path {
|
||||
config = pkgs.config // {
|
||||
permittedInsecurePackages = [ "olm-3.2.16" ];
|
||||
};
|
||||
}).matrix-commander
|
||||
pkgs.jq
|
||||
];
|
||||
|
||||
security.pki.certificateFiles = [ mailerCerts.ca.cert ];
|
||||
|
||||
users.users = {
|
||||
alice.isNormalUser = true;
|
||||
bob.isNormalUser = true;
|
||||
};
|
||||
|
||||
networking.useNetworkd = true;
|
||||
services.rust-federation-tester = {
|
||||
enable = true;
|
||||
settings = {
|
||||
listen_addr = "unix:/run/rust-federation-tester/rust-federation-tester.sock";
|
||||
frontend_url = "http://localhost:8080";
|
||||
database_url = "sqlite:///var/lib/rust-federation-tester/db?mode=rwc";
|
||||
magic_token_secret = "foobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobar";
|
||||
statistics = {
|
||||
enabled = true;
|
||||
prometheus_enabled = true;
|
||||
anonymization_salt._secret = "${anonHashF}";
|
||||
raw_retention_days = 30;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
import json
|
||||
from pprint import pprint
|
||||
|
||||
start_all()
|
||||
mailserver.wait_for_unit("postfix.service")
|
||||
serverpostgres.succeed("send-testmail-starttls")
|
||||
serverpostgres.wait_for_unit("matrix-synapse.service")
|
||||
serverpostgres.wait_until_succeeds(
|
||||
"curl --fail -L --cacert ${ca_pem} https://localhost:8448/"
|
||||
)
|
||||
serverpostgres.wait_until_succeeds(
|
||||
|
||||
synapse_with_workers.wait_for_unit("multi-user.target")
|
||||
synapse_minimal.wait_for_unit("multi-user.target")
|
||||
mailserver.wait_for_unit("multi-user.target")
|
||||
|
||||
synapse_with_workers.wait_until_succeeds(
|
||||
"journalctl -u matrix-synapse.service | grep -q 'Connected to redis'"
|
||||
)
|
||||
serverpostgres.require_unit_state("postgresql.target")
|
||||
serverpostgres.succeed("REQUESTS_CA_BUNDLE=${ca_pem} register_new_matrix_user -u ${testUser} -p ${testPassword} -a -k ${registrationSharedSecret} https://localhost:8448/")
|
||||
serverpostgres.succeed("obtain-token-and-register-email")
|
||||
serversqlite.wait_for_unit("matrix-synapse.service")
|
||||
serversqlite.wait_until_succeeds(
|
||||
"curl --fail -L --cacert ${ca_pem} https://localhost:8448/"
|
||||
)
|
||||
serversqlite.succeed("[ -e /var/lib/matrix-synapse/homeserver.db ]")
|
||||
'';
|
||||
synapse_with_workers.wait_for_unit("matrix-synapse-worker-federation_sender.service");
|
||||
|
||||
with subtest("register user with email confirmation"):
|
||||
synapse_with_workers.succeed("send-testmail-starttls")
|
||||
synapse_with_workers.succeed("REQUESTS_CA_BUNDLE=${mailerCerts.ca.cert} register_new_matrix_user -u ${aliceName} -p ${alicePassword} -a -k ${registrationSharedSecret} https://hs1.test:8448/")
|
||||
synapse_with_workers.succeed("obtain-token-and-register-email")
|
||||
|
||||
with subtest("matrix-synapse-register_new_matrix_user"):
|
||||
synapse_minimal.succeed("matrix-synapse-register_new_matrix_user -u ${bobName} -p ${bobPassword} --no-admin")
|
||||
synapse_minimal.succeed("[ -e /var/lib/matrix-synapse/homeserver.db ]")
|
||||
|
||||
with subtest("Federation tester"):
|
||||
expected_anonymization_hashes = {
|
||||
"hs1.test": "0558582846d6e2d90612900d449871dfcbf9878ba78de4a8469d8aba2d9c037b",
|
||||
"hs2.test": "d3d88c2033c03b74ec1e086e15c0251514de060de5e51cb381e896f892a5b0cd",
|
||||
}
|
||||
|
||||
# /metrics are cached for up to 30 seconds
|
||||
for n, domain in enumerate(["hs2.test", "hs1.test"], start=3):
|
||||
result = json.loads(
|
||||
client.succeed(
|
||||
f"curl --fail --unix-socket /run/rust-federation-tester/rust-federation-tester.sock 'http://localhost:8080/api/federation/report?server_name={domain}&stats_opt_in=true'"
|
||||
)
|
||||
)
|
||||
pprint(result)
|
||||
t.assertTrue(result["FederationOK"])
|
||||
t.assertTrue(result["ConnectionReports"][f"192.168.1.{n}:8448"]["Checks"]["AllChecksOK"])
|
||||
t.assertEqual(f"{domain}:8448", result["WellKnownResult"][f"192.168.1.{n}:443"]["m.server"])
|
||||
|
||||
client.sleep(30)
|
||||
# /metrics are cached for up to 30 seconds
|
||||
for domain in ["hs2.test", "hs1.test"]:
|
||||
metrics = client.succeed("curl --unix-socket /run/rust-federation-tester/rust-federation-tester.sock http://localhost:8080/metrics --fail")
|
||||
t.assertRegex(
|
||||
metrics,
|
||||
f'federation_request_total\\{{server=\\"{expected_anonymization_hashes[domain]}\\",result=\\"success\\",[^}}]+\\}} 1'
|
||||
)
|
||||
|
||||
def run_as_alice(cmd):
|
||||
return client.succeed(f"sudo -u alice matrix-commander -c /home/alice/credentials.json -s /home/alice/matrix {cmd}")
|
||||
|
||||
def run_as_bob(cmd):
|
||||
return client.succeed(f"sudo -u bob matrix-commander -c /home/bob/credentials.json -s /home/bob/matrix {cmd}")
|
||||
|
||||
with subtest("Login"):
|
||||
run_as_alice("--login password --homeserver https://hs1.test:8448 --user-login @${aliceName}:hs1.test --password ${alicePassword} --device commander --room-default '#welcome:hs1.test'")
|
||||
run_as_bob("--login password --homeserver https://hs2.test:8448 --user-login @${bobName}:hs2.test --password ${bobPassword} --device commander --room-default '#welcome:hs1.test'")
|
||||
|
||||
with subtest("Create/Invite/Join"):
|
||||
run_as_alice("--room-create '#welcome:hs1.test'")
|
||||
|
||||
run_as_alice("--room-invite '#welcome:hs1.test' -u @${bobName}:hs2.test")
|
||||
run_as_bob("--listen once --room-invites 'list+join'")
|
||||
|
||||
with subtest("Send/receive messages"):
|
||||
senders = {
|
||||
"alice": ("hs1", run_as_alice),
|
||||
"bob": ("hs2", run_as_bob),
|
||||
}
|
||||
|
||||
for name, (hs, fn) in senders.items():
|
||||
fn(f"-m 'hello, I am {name}'")
|
||||
for _, run in senders.values():
|
||||
msg_data = json.loads(run("--listen once --listen-self --output json"))
|
||||
pprint(msg_data)
|
||||
t.assertEqual(msg_data["source"]["content"]["body"], f"hello, I am {name}")
|
||||
t.assertEqual(msg_data["source"]["sender"], f"@{name}:{hs}.test")
|
||||
'';
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ python3Packages.buildPythonApplication rec {
|
||||
'';
|
||||
|
||||
passthru = {
|
||||
tests = { inherit (nixosTests) matrix-synapse matrix-synapse-workers; };
|
||||
tests = { inherit (nixosTests) matrix-synapse; };
|
||||
plugins = python3Packages.callPackage ./plugins { };
|
||||
inherit (python3Packages) python;
|
||||
updateScript = nix-update-script { };
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
{
|
||||
rustPlatform,
|
||||
fetchFromGitHub,
|
||||
lib,
|
||||
nixosTests,
|
||||
cacert,
|
||||
}:
|
||||
|
||||
rustPlatform.buildRustPackage (finalAttrs: {
|
||||
pname = "rust-federation-tester";
|
||||
version = "0.5.2";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "MTRNord";
|
||||
repo = "rust-federation-tester";
|
||||
rev = "v${finalAttrs.version}";
|
||||
hash = "sha256-KHRG+5AeK7h7k7LoTtcIjGmPYlVcV2ZwpJN8iDsBfHg=";
|
||||
};
|
||||
|
||||
__structuredAttrs = true;
|
||||
strictDeps = true;
|
||||
|
||||
cargoHash = "sha256-nTcE8eqQO0CFdeH0jjT6m1fd4qhG7e/CDpdZHkBq9f8=";
|
||||
cargoTestFlags = finalAttrs.cargoBuildFlags;
|
||||
cargoBuildFlags = [
|
||||
"-p"
|
||||
"rust-federation-tester"
|
||||
"-p"
|
||||
"migration"
|
||||
];
|
||||
|
||||
nativeCheckInputs = [ cacert ];
|
||||
|
||||
checkFlags = map (test: "--skip=${test}") [
|
||||
# Tests depending on network access
|
||||
"test_generate_json_report_ipv4_only_server"
|
||||
"test_generate_json_report_known_bad_servers"
|
||||
"test_generate_json_report_known_good_servers"
|
||||
"test_generate_json_report_valid_domain"
|
||||
"test_generate_json_report_with_port"
|
||||
"test_lookup_server_well_known_valid"
|
||||
"test_matrix_fed_srv_resolution_4msc4040"
|
||||
"test_matrix_srv_resolution_4s"
|
||||
"test_step2_explicit_port"
|
||||
"test_step3b_wellknown_explicit_port"
|
||||
"test_step3c_wellknown_matrix_fed_srv"
|
||||
"test_step3c_wellknown_matrix_srv"
|
||||
"test_step3d_wellknown_default_port"
|
||||
"test_step6_wellknown_fails_default_port"
|
||||
"test_generate_report"
|
||||
"test_concurrent_requests"
|
||||
];
|
||||
|
||||
passthru.tests = {
|
||||
inherit (nixosTests) matrix-synapse;
|
||||
};
|
||||
|
||||
meta = {
|
||||
description = "Matrix-Federation-Tester in Rust";
|
||||
homepage = "https://connectivity-tester.mtrnord.blog/";
|
||||
license = lib.licenses.agpl3Only;
|
||||
maintainers = with lib.maintainers; [ ma27 ];
|
||||
platforms = lib.platforms.linux;
|
||||
mainProgram = "rust-federation-tester";
|
||||
};
|
||||
})
|
||||
Reference in New Issue
Block a user