1import ./make-test-python.nix ({ pkgs, ... } : let
2
3
4 runWithOpenSSL = file: cmd: pkgs.runCommand file {
5 buildInputs = [ pkgs.openssl ];
6 } cmd;
7
8
9 ca_key = runWithOpenSSL "ca-key.pem" "openssl genrsa -out $out 2048";
10 ca_pem = runWithOpenSSL "ca.pem" ''
11 openssl req \
12 -x509 -new -nodes -key ${ca_key} \
13 -days 10000 -out $out -subj "/CN=snakeoil-ca"
14 '';
15 key = runWithOpenSSL "matrix_key.pem" "openssl genrsa -out $out 2048";
16 csr = runWithOpenSSL "matrix.csr" ''
17 openssl req \
18 -new -key ${key} \
19 -out $out -subj "/CN=localhost" \
20 '';
21 cert = runWithOpenSSL "matrix_cert.pem" ''
22 openssl x509 \
23 -req -in ${csr} \
24 -CA ${ca_pem} -CAkey ${ca_key} \
25 -CAcreateserial -out $out \
26 -days 365
27 '';
28
29
30 mailerCerts = import ./common/acme/server/snakeoil-certs.nix;
31 mailerDomain = mailerCerts.domain;
32 registrationSharedSecret = "unsecure123";
33 testUser = "alice";
34 testPassword = "alicealice";
35 testEmail = "alice@example.com";
36in {
37
38 name = "matrix-synapse";
39 meta = with pkgs.lib; {
40 maintainers = teams.matrix.members;
41 };
42
43 nodes = {
44 # Since 0.33.0, matrix-synapse doesn't allow underscores in server names
45 serverpostgres = { pkgs, nodes, ... }: let
46 mailserverIP = nodes.mailserver.config.networking.primaryIPAddress;
47 in
48 {
49 services.matrix-synapse = {
50 enable = true;
51 database_type = "psycopg2";
52 tls_certificate_path = "${cert}";
53 tls_private_key_path = "${key}";
54 database_args = {
55 password = "synapse";
56 };
57 registration_shared_secret = registrationSharedSecret;
58 public_baseurl = "https://example.com";
59 extraConfig = ''
60 email:
61 smtp_host: "${mailerDomain}"
62 smtp_port: 25
63 require_transport_security: true
64 notif_from: "matrix <matrix@${mailerDomain}>"
65 app_name: "Matrix"
66 '';
67 };
68 services.postgresql = {
69 enable = true;
70
71 # The database name and user are configured by the following options:
72 # - services.matrix-synapse.database_name
73 # - services.matrix-synapse.database_user
74 #
75 # The values used here represent the default values of the module.
76 initialScript = pkgs.writeText "synapse-init.sql" ''
77 CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD 'synapse';
78 CREATE DATABASE "matrix-synapse" WITH OWNER "matrix-synapse"
79 TEMPLATE template0
80 LC_COLLATE = "C"
81 LC_CTYPE = "C";
82 '';
83 };
84
85 networking.extraHosts = ''
86 ${mailserverIP} ${mailerDomain}
87 '';
88
89 security.pki.certificateFiles = [
90 mailerCerts.ca.cert ca_pem
91 ];
92
93 environment.systemPackages = let
94 sendTestMailStarttls = pkgs.writeScriptBin "send-testmail-starttls" ''
95 #!${pkgs.python3.interpreter}
96 import smtplib
97 import ssl
98
99 ctx = ssl.create_default_context()
100
101 with smtplib.SMTP('${mailerDomain}') as smtp:
102 smtp.ehlo()
103 smtp.starttls(context=ctx)
104 smtp.ehlo()
105 smtp.sendmail('matrix@${mailerDomain}', '${testEmail}', 'Subject: Test STARTTLS\n\nTest data.')
106 smtp.quit()
107 '';
108
109 obtainTokenAndRegisterEmail = let
110 # adding the email through the API is quite complicated as it involves more than one step and some
111 # client-side calculation
112 insertEmailForAlice = pkgs.writeText "alice-email.sql" ''
113 INSERT INTO user_threepids (user_id, medium, address, validated_at, added_at) VALUES ('${testUser}@serverpostgres', 'email', '${testEmail}', '1629149927271', '1629149927270');
114 '';
115 in
116 pkgs.writeScriptBin "obtain-token-and-register-email" ''
117 #!${pkgs.runtimeShell}
118 set -o errexit
119 set -o pipefail
120 set -o nounset
121 su postgres -c "psql -d matrix-synapse -f ${insertEmailForAlice}"
122 curl --fail -XPOST 'https://localhost:8448/_matrix/client/r0/account/password/email/requestToken' -d '{"email":"${testEmail}","client_secret":"foobar","send_attempt":1}' -v
123 '';
124 in [ sendTestMailStarttls pkgs.matrix-synapse obtainTokenAndRegisterEmail ];
125 };
126
127 # test mail delivery
128 mailserver = args: let
129 in
130 {
131 security.pki.certificateFiles = [
132 mailerCerts.ca.cert
133 ];
134
135 networking.firewall.enable = false;
136
137 services.postfix = {
138 enable = true;
139 hostname = "${mailerDomain}";
140 # open relay for subnet
141 networksStyle = "subnet";
142 enableSubmission = true;
143 tlsTrustedAuthorities = "${mailerCerts.ca.cert}";
144 sslCert = "${mailerCerts.${mailerDomain}.cert}";
145 sslKey = "${mailerCerts.${mailerDomain}.key}";
146
147 # blackhole transport
148 transport = "example.com discard:silently";
149
150 config = {
151 debug_peer_level = "10";
152 smtpd_relay_restrictions = [
153 "permit_mynetworks" "reject_unauth_destination"
154 ];
155
156 # disable obsolete protocols, something old versions of twisted are still using
157 smtpd_tls_protocols = "TLSv1.3, TLSv1.2, !TLSv1.1, !TLSv1, !SSLv2, !SSLv3";
158 smtp_tls_protocols = "TLSv1.3, TLSv1.2, !TLSv1.1, !TLSv1, !SSLv2, !SSLv3";
159 smtpd_tls_mandatory_protocols = "TLSv1.3, TLSv1.2, !TLSv1.1, !TLSv1, !SSLv2, !SSLv3";
160 smtp_tls_mandatory_protocols = "TLSv1.3, TLSv1.2, !TLSv1.1, !TLSv1, !SSLv2, !SSLv3";
161 };
162 };
163 };
164
165 serversqlite = args: {
166 services.matrix-synapse = {
167 enable = true;
168 database_type = "sqlite3";
169 tls_certificate_path = "${cert}";
170 tls_private_key_path = "${key}";
171 };
172 };
173 };
174
175 testScript = ''
176 start_all()
177 mailserver.wait_for_unit("postfix.service")
178 serverpostgres.succeed("send-testmail-starttls")
179 serverpostgres.wait_for_unit("matrix-synapse.service")
180 serverpostgres.wait_until_succeeds(
181 "curl --fail -L --cacert ${ca_pem} https://localhost:8448/"
182 )
183 serverpostgres.require_unit_state("postgresql.service")
184 serverpostgres.succeed("register_new_matrix_user -u ${testUser} -p ${testPassword} -a -k ${registrationSharedSecret} ")
185 serverpostgres.succeed("obtain-token-and-register-email")
186 serversqlite.wait_for_unit("matrix-synapse.service")
187 serversqlite.wait_until_succeeds(
188 "curl --fail -L --cacert ${ca_pem} https://localhost:8448/"
189 )
190 serversqlite.succeed("[ -e /var/lib/matrix-synapse/homeserver.db ]")
191 '';
192
193})