Merge branch 'master' into staging-next

This commit is contained in:
Vladimír Čunát
2021-05-14 22:27:34 +02:00
64 changed files with 1924 additions and 1438 deletions
+1
View File
@@ -91,6 +91,7 @@ in
custom-ca = handleTest ./custom-ca.nix {};
croc = handleTest ./croc.nix {};
deluge = handleTest ./deluge.nix {};
dendrite = handleTest ./dendrite.nix {};
dhparams = handleTest ./dhparams.nix {};
discourse = handleTest ./discourse.nix {};
dnscrypt-proxy2 = handleTestOn ["x86_64-linux"] ./dnscrypt-proxy2.nix {};
+99
View File
@@ -0,0 +1,99 @@
import ./make-test-python.nix (
{ pkgs, ... }:
let
homeserverUrl = "http://homeserver:8008";
private_key = pkgs.runCommand "matrix_key.pem" {
buildInputs = [ pkgs.dendrite ];
} "generate-keys --private-key $out";
in
{
name = "dendrite";
meta = with pkgs.lib; {
maintainers = teams.matrix.members;
};
nodes = {
homeserver = { pkgs, ... }: {
services.dendrite = {
enable = true;
settings = {
global.server_name = "test-dendrite-server.com";
global.private_key = private_key;
client_api.registration_disabled = false;
};
};
networking.firewall.allowedTCPPorts = [ 8008 ];
};
client = { pkgs, ... }: {
environment.systemPackages = [
(
pkgs.writers.writePython3Bin "do_test"
{ libraries = [ pkgs.python3Packages.matrix-nio ]; } ''
import asyncio
from nio import AsyncClient
async def main() -> None:
# Connect to dendrite
client = AsyncClient("http://homeserver:8008", "alice")
# Register as user alice
response = await client.register("alice", "my-secret-password")
# Log in as user alice
response = await client.login("my-secret-password")
# Create a new room
response = await client.room_create(federate=False)
room_id = response.room_id
# Join the room
response = await client.join(room_id)
# Send a message to the room
response = await client.room_send(
room_id=room_id,
message_type="m.room.message",
content={
"msgtype": "m.text",
"body": "Hello world!"
}
)
# Sync responses
response = await client.sync(timeout=30000)
# Check the message was received by dendrite
last_message = response.rooms.join[room_id].timeline.events[-1].body
assert last_message == "Hello world!"
# Leave the room
response = await client.room_leave(room_id)
# Close the client
await client.close()
asyncio.get_event_loop().run_until_complete(main())
''
)
];
};
};
testScript = ''
start_all()
with subtest("start the homeserver"):
homeserver.wait_for_unit("dendrite.service")
homeserver.wait_for_open_port(8008)
with subtest("ensure messages can be exchanged"):
client.succeed("do_test")
'';
}
)
+51
View File
@@ -326,6 +326,57 @@ let
'';
};
kea = {
exporterConfig = {
enable = true;
controlSocketPaths = [
"/run/kea/kea-dhcp6.sock"
];
};
metricProvider = {
users.users.kea = {
isSystemUser = true;
};
users.groups.kea = {};
systemd.services.prometheus-kea-exporter.after = [ "kea-dhcp6.service" ];
systemd.services.kea-dhcp6 = let
configFile = pkgs.writeText "kea-dhcp6.conf" (builtins.toJSON {
Dhcp6 = {
"control-socket" = {
"socket-type" = "unix";
"socket-name" = "/run/kea/kea-dhcp6.sock";
};
};
});
in
{
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
DynamicUser = false;
User = "kea";
Group = "kea";
ExecStart = "${pkgs.kea}/bin/kea-dhcp6 -c ${configFile}";
StateDirectory = "kea";
RuntimeDirectory = "kea";
UMask = "0007";
};
};
};
exporterTest = ''
wait_for_unit("kea-dhcp6.service")
wait_for_file("/run/kea/kea-dhcp6.sock")
wait_for_unit("prometheus-kea-exporter.service")
wait_for_open_port(9547)
succeed(
"curl --fail localhost:9547/metrics | grep 'packets_received_total'"
)
'';
};
knot = {
exporterConfig = {
enable = true;
+77 -122
View File
@@ -1,140 +1,95 @@
import ./make-test-python.nix ({ lib, pkgs, ... }:
let
user = "someuser";
password = "some_password";
port = builtins.toString 5232;
port = "5232";
filesystem_folder = "/data/radicale";
common = { pkgs, ... }: {
cli = "${pkgs.calendar-cli}/bin/calendar-cli --caldav-user ${user} --caldav-pass ${password}";
in {
name = "radicale3";
meta.maintainers = with lib.maintainers; [ dotlambda ];
machine = { pkgs, ... }: {
services.radicale = {
enable = true;
config = ''
[auth]
type = htpasswd
htpasswd_filename = /etc/radicale/htpasswd
htpasswd_encryption = bcrypt
[storage]
filesystem_folder = /tmp/collections
'';
settings = {
auth = {
type = "htpasswd";
htpasswd_filename = "/etc/radicale/users";
htpasswd_encryption = "bcrypt";
};
storage = {
inherit filesystem_folder;
hook = "git add -A && (git diff --cached --quiet || git commit -m 'Changes by '%(user)s)";
};
logging.level = "info";
};
rights = {
principal = {
user = ".+";
collection = "{user}";
permissions = "RW";
};
calendars = {
user = ".+";
collection = "{user}/[^/]+";
permissions = "rw";
};
};
};
systemd.services.radicale.path = [ pkgs.git ];
environment.systemPackages = [ pkgs.git ];
systemd.tmpfiles.rules = [ "d ${filesystem_folder} 0750 radicale radicale -" ];
# WARNING: DON'T DO THIS IN PRODUCTION!
# This puts unhashed secrets directly into the Nix store for ease of testing.
environment.etc."radicale/htpasswd".source = pkgs.runCommand "htpasswd" {} ''
environment.etc."radicale/users".source = pkgs.runCommand "htpasswd" {} ''
${pkgs.apacheHttpd}/bin/htpasswd -bcB "$out" ${user} ${password}
'';
};
testScript = ''
machine.wait_for_unit("radicale.service")
machine.wait_for_open_port(${port})
in
machine.succeed("sudo -u radicale git -C ${filesystem_folder} init")
machine.succeed(
"sudo -u radicale git -C ${filesystem_folder} config --local user.email radicale@example.com"
)
machine.succeed(
"sudo -u radicale git -C ${filesystem_folder} config --local user.name radicale"
)
import ./make-test-python.nix ({ lib, ... }@args: {
name = "radicale";
meta.maintainers = with lib.maintainers; [ aneeshusa infinisil ];
with subtest("Test calendar and event creation"):
machine.succeed(
"${cli} --caldav-url http://localhost:${port}/${user} calendar create cal"
)
machine.succeed("test -d ${filesystem_folder}/collection-root/${user}/cal")
machine.succeed('test -z "$(ls ${filesystem_folder}/collection-root/${user}/cal)"')
machine.succeed(
"${cli} --caldav-url http://localhost:${port}/${user}/cal calendar add 2021-04-23 testevent"
)
machine.succeed('test -n "$(ls ${filesystem_folder}/collection-root/${user}/cal)"')
(status, stdout) = machine.execute(
"sudo -u radicale git -C ${filesystem_folder} log --format=oneline | wc -l"
)
assert status == 0, "git log failed"
assert stdout == "3\n", "there should be exactly 3 commits"
nodes = rec {
radicale = radicale1; # Make the test script read more nicely
radicale1 = lib.recursiveUpdate (common args) {
nixpkgs.overlays = [
(self: super: {
radicale1 = super.radicale1.overrideAttrs (oldAttrs: {
propagatedBuildInputs = with self.pythonPackages;
(oldAttrs.propagatedBuildInputs or []) ++ [ passlib ];
});
})
];
system.stateVersion = "17.03";
};
radicale1_export = lib.recursiveUpdate radicale1 {
services.radicale.extraArgs = [
"--export-storage" "/tmp/collections-new"
];
system.stateVersion = "17.03";
};
radicale2_verify = lib.recursiveUpdate radicale2 {
services.radicale.extraArgs = [ "--debug" "--verify-storage" ];
system.stateVersion = "17.09";
};
radicale2 = lib.recursiveUpdate (common args) {
system.stateVersion = "17.09";
};
radicale3 = lib.recursiveUpdate (common args) {
system.stateVersion = "20.09";
};
};
with subtest("Test rights file"):
machine.fail(
"${cli} --caldav-url http://localhost:${port}/${user} calendar create sub/cal"
)
machine.fail(
"${cli} --caldav-url http://localhost:${port}/otheruser calendar create cal"
)
# This tests whether the web interface is accessible to an authenticated user
testScript = { nodes }: let
switchToConfig = nodeName: let
newSystem = nodes.${nodeName}.config.system.build.toplevel;
in "${newSystem}/bin/switch-to-configuration test";
in ''
with subtest("Check Radicale 1 functionality"):
radicale.succeed(
"${switchToConfig "radicale1"} >&2"
)
radicale.wait_for_unit("radicale.service")
radicale.wait_for_open_port(${port})
radicale.succeed(
"curl --fail http://${user}:${password}@localhost:${port}/someuser/calendar.ics/"
)
with subtest("Test web interface"):
machine.succeed("curl --fail http://${user}:${password}@localhost:${port}/.web/")
with subtest("Export data in Radicale 2 format"):
radicale.succeed("systemctl stop radicale")
radicale.succeed("ls -al /tmp/collections")
radicale.fail("ls -al /tmp/collections-new")
with subtest("Radicale exits immediately after exporting storage"):
radicale.succeed(
"${switchToConfig "radicale1_export"} >&2"
)
radicale.wait_until_fails("systemctl status radicale")
radicale.succeed("ls -al /tmp/collections")
radicale.succeed("ls -al /tmp/collections-new")
with subtest("Verify data in Radicale 2 format"):
radicale.succeed("rm -r /tmp/collections/${user}")
radicale.succeed("mv /tmp/collections-new/collection-root /tmp/collections")
radicale.succeed(
"${switchToConfig "radicale2_verify"} >&2"
)
radicale.wait_until_fails("systemctl status radicale")
(retcode, logs) = radicale.execute("journalctl -u radicale -n 10")
assert (
retcode == 0 and "Verifying storage" in logs
), "Radicale 2 didn't verify storage"
assert (
"failed" not in logs and "exception" not in logs
), "storage verification failed"
with subtest("Check Radicale 2 functionality"):
radicale.succeed(
"${switchToConfig "radicale2"} >&2"
)
radicale.wait_for_unit("radicale.service")
radicale.wait_for_open_port(${port})
(retcode, output) = radicale.execute(
"curl --fail http://${user}:${password}@localhost:${port}/someuser/calendar.ics/"
)
assert (
retcode == 0 and "VCALENDAR" in output
), "Could not read calendar from Radicale 2"
radicale.succeed("curl --fail http://${user}:${password}@localhost:${port}/.web/")
with subtest("Check Radicale 3 functionality"):
radicale.succeed(
"${switchToConfig "radicale3"} >&2"
)
radicale.wait_for_unit("radicale.service")
radicale.wait_for_open_port(${port})
(retcode, output) = radicale.execute(
"curl --fail http://${user}:${password}@localhost:${port}/someuser/calendar.ics/"
)
assert (
retcode == 0 and "VCALENDAR" in output
), "Could not read calendar from Radicale 3"
radicale.succeed("curl --fail http://${user}:${password}@localhost:${port}/.web/")
'';
with subtest("Test security"):
output = machine.succeed("systemd-analyze security radicale.service")
machine.log(output)
assert output[-9:-1] == "SAFE :-}"
'';
})
+14
View File
@@ -38,6 +38,9 @@ import ./make-test-python.nix ({ pkgs, lib, ...} :
programs.sway.enable = true;
# To test pinentry via gpg-agent:
programs.gnupg.agent.enable = true;
virtualisation.memorySize = 1024;
# Need to switch to a different VGA card / GPU driver than the default one (std) so that Sway can launch:
virtualisation.qemu.options = [ "-vga virtio" ];
@@ -80,6 +83,17 @@ import ./make-test-python.nix ({ pkgs, lib, ...} :
machine.send_key("alt-shift-q")
machine.wait_until_fails("pgrep alacritty")
# Test gpg-agent starting pinentry-gnome3 via D-Bus (tests if
# $WAYLAND_DISPLAY is correctly imported into the D-Bus user env):
machine.succeed(
"su - alice -c 'swaymsg -- exec gpg --no-tty --yes --quick-generate-key test'"
)
machine.wait_until_succeeds("pgrep --exact gpg")
machine.wait_for_text("Passphrase")
machine.screenshot("gpg_pinentry")
machine.send_key("alt-shift-q")
machine.wait_until_fails("pgrep --exact gpg")
# Test swaynag:
machine.send_key("alt-shift-e")
machine.wait_for_text("You pressed the exit shortcut.")