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