From 533560de5ba1d245a150433de9f4212721443379 Mon Sep 17 00:00:00 2001 From: elseym Date: Wed, 7 Oct 2020 11:27:05 +0200 Subject: [PATCH] nixos/murmur: add option `environmentFile` for injecting secrets Secrets are injected from the environment into the rendered configuration before each startup using envsubst. The test now makes use of this feature for the server password. --- nixos/modules/services/networking/murmur.nix | 46 +++++++++++++++++--- nixos/tests/mumble.nix | 22 +++++++--- 2 files changed, 58 insertions(+), 10 deletions(-) diff --git a/nixos/modules/services/networking/murmur.nix b/nixos/modules/services/networking/murmur.nix index 3054ae1b201..b384f436861 100644 --- a/nixos/modules/services/networking/murmur.nix +++ b/nixos/modules/services/networking/murmur.nix @@ -241,6 +241,34 @@ in default = ""; description = "Extra configuration to put into murmur.ini."; }; + + environmentFile = mkOption { + type = types.nullOr types.path; + default = null; + example = "/var/lib/murmur/murmurd.env"; + description = '' + Environment file as defined in + systemd.exec5 + . + + Secrets may be passed to the service without adding them to the world-readable + Nix store, by specifying placeholder variables as the option value in Nix and + setting these variables accordingly in the environment file. + + + # snippet of murmur-related config + services.murmur.password = "$MURMURD_PASSWORD"; + + + + # content of the environment file + MURMURD_PASSWORD=verysecretpassword + + + Note that this file needs to be available on the host on which + murmur is running. + ''; + }; }; }; @@ -256,14 +284,22 @@ in description = "Murmur Chat Service"; wantedBy = [ "multi-user.target" ]; after = [ "network-online.target "]; + preStart = '' + ${pkgs.envsubst}/bin/envsubst \ + -o /run/murmur/murmurd.ini \ + -i ${configFile} + ''; serviceConfig = { # murmurd doesn't fork when logging to the console. - Type = if forking then "forking" else "simple"; - PIDFile = mkIf forking "/run/murmur/murmurd.pid"; - RuntimeDirectory = mkIf forking "murmur"; - User = "murmur"; - ExecStart = "${pkgs.murmur}/bin/murmurd -ini ${configFile}"; + Type = if forking then "forking" else "simple"; + PIDFile = mkIf forking "/run/murmur/murmurd.pid"; + EnvironmentFile = mkIf (cfg.environmentFile != null) cfg.environmentFile; + ExecStart = "${pkgs.murmur}/bin/murmurd -ini /run/murmur/murmurd.ini"; + Restart = "always"; + RuntimeDirectory = "murmur"; + RuntimeDirectoryMode = "0700"; + User = "murmur"; }; }; }; diff --git a/nixos/tests/mumble.nix b/nixos/tests/mumble.nix index e9b6d14c6a1..cb3e0ec42fc 100644 --- a/nixos/tests/mumble.nix +++ b/nixos/tests/mumble.nix @@ -5,6 +5,12 @@ let imports = [ ./common/x11.nix ]; environment.systemPackages = [ pkgs.mumble ]; }; + + # outside of tests, this file should obviously not come from the nix store + envFile = pkgs.writeText "nixos-test-mumble-murmurd.env" '' + MURMURD_PASSWORD=testpassword + ''; + in { name = "mumble"; @@ -14,8 +20,10 @@ in nodes = { server = { config, ... }: { - services.murmur.enable = true; + services.murmur.enable = true; services.murmur.registerName = "NixOS tests"; + services.murmur.password = "$MURMURD_PASSWORD"; + services.murmur.environmentFile = envFile; networking.firewall.allowedTCPPorts = [ config.services.murmur.port ]; }; @@ -30,8 +38,8 @@ in client1.wait_for_x() client2.wait_for_x() - client1.execute("mumble mumble://client1\@server/test &") - client2.execute("mumble mumble://client2\@server/test &") + client1.execute("mumble mumble://client1:testpassword\@server/test &") + client2.execute("mumble mumble://client2:testpassword\@server/test &") # cancel client audio configuration client1.wait_for_window(r"Audio Tuning Wizard") @@ -63,8 +71,12 @@ in client2.send_chars("y") # Find clients in logs - server.wait_until_succeeds("journalctl -eu murmur -o cat | grep -q client1") - server.wait_until_succeeds("journalctl -eu murmur -o cat | grep -q client2") + server.wait_until_succeeds( + "journalctl -eu murmur -o cat | grep -q 'client1.\+Authenticated'" + ) + server.wait_until_succeeds( + "journalctl -eu murmur -o cat | grep -q 'client2.\+Authenticated'" + ) server.sleep(5) # wait to get screenshot client1.screenshot("screen1")