1import ../make-test-python.nix (
2 { pkgs, ... }:
3 let
4 # Set up SSL certs for Synapse to be happy.
5 runWithOpenSSL =
6 file: cmd:
7 pkgs.runCommand file {
8 buildInputs = [ pkgs.openssl ];
9 } cmd;
10
11 ca_key = runWithOpenSSL "ca-key.pem" "openssl genrsa -out $out 2048";
12 ca_pem = runWithOpenSSL "ca.pem" ''
13 openssl req \
14 -x509 -new -nodes -key ${ca_key} \
15 -days 10000 -out $out -subj "/CN=snakeoil-ca"
16 '';
17 key = runWithOpenSSL "matrix_key.pem" "openssl genrsa -out $out 2048";
18 csr = runWithOpenSSL "matrix.csr" ''
19 openssl req \
20 -new -key ${key} \
21 -out $out -subj "/CN=localhost" \
22 '';
23 cert = runWithOpenSSL "matrix_cert.pem" ''
24 openssl x509 \
25 -req -in ${csr} \
26 -CA ${ca_pem} -CAkey ${ca_key} \
27 -CAcreateserial -out $out \
28 -days 365
29 '';
30 in
31 {
32 name = "mjolnir";
33 meta = {
34 inherit (pkgs.mjolnir.meta) maintainers;
35 };
36
37 nodes = {
38 homeserver =
39 { pkgs, ... }:
40 {
41 services.matrix-synapse = {
42 enable = true;
43 settings = {
44 database.name = "sqlite3";
45 tls_certificate_path = "${cert}";
46 tls_private_key_path = "${key}";
47 enable_registration = true;
48 enable_registration_without_verification = true;
49 registration_shared_secret = "supersecret-registration";
50
51 listeners = [
52 {
53 # The default but tls=false
54 bind_addresses = [
55 "0.0.0.0"
56 ];
57 port = 8448;
58 resources = [
59 {
60 compress = true;
61 names = [ "client" ];
62 }
63 {
64 compress = false;
65 names = [ "federation" ];
66 }
67 ];
68 tls = false;
69 type = "http";
70 x_forwarded = false;
71 }
72 ];
73 };
74 };
75
76 networking.firewall.allowedTCPPorts = [ 8448 ];
77
78 environment.systemPackages = [
79 (pkgs.writeShellScriptBin "register_mjolnir_user" ''
80 exec ${pkgs.matrix-synapse}/bin/register_new_matrix_user \
81 -u mjolnir \
82 -p mjolnir-password \
83 --admin \
84 --shared-secret supersecret-registration \
85 http://localhost:8448
86 '')
87 (pkgs.writeShellScriptBin "register_moderator_user" ''
88 exec ${pkgs.matrix-synapse}/bin/register_new_matrix_user \
89 -u moderator \
90 -p moderator-password \
91 --no-admin \
92 --shared-secret supersecret-registration \
93 http://localhost:8448
94 '')
95 ];
96 };
97
98 mjolnir =
99 { pkgs, ... }:
100 {
101 services.mjolnir = {
102 enable = true;
103 homeserverUrl = "http://homeserver:8448";
104 pantalaimon = {
105 enable = true;
106 username = "mjolnir";
107 passwordFile = pkgs.writeText "password.txt" "mjolnir-password";
108 # otherwise mjolnir tries to connect to ::1, which is not listened by pantalaimon
109 options.listenAddress = "127.0.0.1";
110 };
111 managementRoom = "#moderators:homeserver";
112 };
113 };
114
115 client =
116 { pkgs, ... }:
117 {
118 environment.systemPackages = [
119 (pkgs.writers.writePython3Bin "create_management_room_and_invite_mjolnir"
120 {
121 libraries = with pkgs.python3Packages; [
122 (matrix-nio.override { withOlm = true; })
123 ];
124 }
125 ''
126 import asyncio
127
128 from nio import (
129 AsyncClient,
130 EnableEncryptionBuilder
131 )
132
133
134 async def main() -> None:
135 client = AsyncClient("http://homeserver:8448", "moderator")
136
137 await client.login("moderator-password")
138
139 room = await client.room_create(
140 name="Moderators",
141 alias="moderators",
142 initial_state=[EnableEncryptionBuilder().as_dict()],
143 )
144
145 await client.join(room.room_id)
146 await client.room_invite(room.room_id, "@mjolnir:homeserver")
147
148 asyncio.run(main())
149 ''
150 )
151 ];
152 };
153 };
154
155 testScript = ''
156 with subtest("start homeserver"):
157 homeserver.start()
158
159 homeserver.wait_for_unit("matrix-synapse.service")
160 homeserver.wait_until_succeeds("curl --fail -L http://localhost:8448/")
161
162 with subtest("register users"):
163 # register mjolnir user
164 homeserver.succeed("register_mjolnir_user")
165 # register moderator user
166 homeserver.succeed("register_moderator_user")
167
168 with subtest("start mjolnir"):
169 mjolnir.start()
170
171 # wait for pantalaimon to be ready
172 mjolnir.wait_for_unit("pantalaimon-mjolnir.service")
173 mjolnir.wait_for_unit("mjolnir.service")
174
175 mjolnir.wait_until_succeeds("curl --fail -L http://localhost:8009/")
176
177 with subtest("ensure mjolnir can be invited to the management room"):
178 client.start()
179
180 client.wait_until_succeeds("curl --fail -L http://homeserver:8448/")
181
182 client.succeed("create_management_room_and_invite_mjolnir")
183
184 mjolnir.wait_for_console_text("Startup complete. Now monitoring rooms")
185 '';
186 }
187)