about summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
authorSilvan Mosberger <infinisil@icloud.com>2019-04-27 23:36:52 +0200
committerGitHub <noreply@github.com>2019-04-27 23:36:52 +0200
commit77fb90d27ef7162c4e0651ead1157de8a796205d (patch)
treede9b297ec904ce77c8a29056b43ea327eeed5de7 /nixos
parent15010f04369429e582a4e152143f125108837002 (diff)
parent3e32e150cb327e791f2df1e7f0a1589ac885bbd7 (diff)
downloadnixlib-77fb90d27ef7162c4e0651ead1157de8a796205d.tar
nixlib-77fb90d27ef7162c4e0651ead1157de8a796205d.tar.gz
nixlib-77fb90d27ef7162c4e0651ead1157de8a796205d.tar.bz2
nixlib-77fb90d27ef7162c4e0651ead1157de8a796205d.tar.lz
nixlib-77fb90d27ef7162c4e0651ead1157de8a796205d.tar.xz
nixlib-77fb90d27ef7162c4e0651ead1157de8a796205d.tar.zst
nixlib-77fb90d27ef7162c4e0651ead1157de8a796205d.zip
Merge pull request #59731 from ajs124/ejabberd_test
ejabberd: refactor module, add test
Diffstat (limited to 'nixos')
-rw-r--r--nixos/modules/services/networking/ejabberd.nix28
-rw-r--r--nixos/tests/all-tests.nix1
-rw-r--r--nixos/tests/ejabberd.nix262
-rw-r--r--nixos/tests/prosody.nix68
-rw-r--r--nixos/tests/xmpp-sendmessage.nix46
5 files changed, 334 insertions, 71 deletions
diff --git a/nixos/modules/services/networking/ejabberd.nix b/nixos/modules/services/networking/ejabberd.nix
index ef5e2cee6f20..6a38f85c48a2 100644
--- a/nixos/modules/services/networking/ejabberd.nix
+++ b/nixos/modules/services/networking/ejabberd.nix
@@ -11,7 +11,7 @@ let
     ${cfg.ctlConfig}
   '';
 
-  ectl = ''${cfg.package}/bin/ejabberdctl ${if cfg.configFile == null then "" else "--config ${cfg.configFile}"} --ctl-config "${ctlcfg}" --spool "${cfg.spoolDir}" --logs "${cfg.logsDir}"'';
+  ectl = ''${cfg.package}/bin/ejabberdctl ${optionalString (cfg.configFile != null) "--config ${cfg.configFile}"} --ctl-config "${ctlcfg}" --spool "${cfg.spoolDir}" --logs "${cfg.logsDir}"'';
 
   dumps = lib.escapeShellArgs cfg.loadDumps;
 
@@ -111,28 +111,17 @@ in {
       description = "ejabberd server";
       wantedBy = [ "multi-user.target" ];
       after = [ "network.target" ];
-      path = [ pkgs.findutils pkgs.coreutils pkgs.runit ] ++ lib.optional cfg.imagemagick pkgs.imagemagick;
+      path = [ pkgs.findutils pkgs.coreutils ] ++ lib.optional cfg.imagemagick pkgs.imagemagick;
 
       serviceConfig = {
-        ExecStart = ''${ectl} foreground'';
-        # FIXME: runit is used for `chpst` -- can we get rid of this?
-        ExecStop = ''${pkgs.runit}/bin/chpst -u "${cfg.user}:${cfg.group}" ${ectl} stop'';
-        ExecReload = ''${pkgs.runit}/bin/chpst -u "${cfg.user}:${cfg.group}" ${ectl} reload_config'';
         User = cfg.user;
         Group = cfg.group;
-        PermissionsStartOnly = true;
+        ExecStart = "${ectl} foreground";
+        ExecStop = "${ectl} stop";
+        ExecReload = "${ectl} reload_config";
       };
 
       preStart = ''
-        mkdir -p -m750 "${cfg.logsDir}"
-        chown "${cfg.user}:${cfg.group}" "${cfg.logsDir}"
-
-        mkdir -p -m750 "/var/lock/ejabberdctl"
-        chown "${cfg.user}:${cfg.group}" "/var/lock/ejabberdctl"
-
-        mkdir -p -m750 "${cfg.spoolDir}"
-        chown -R "${cfg.user}:${cfg.group}" "${cfg.spoolDir}"
-
         if [ -z "$(ls -A '${cfg.spoolDir}')" ]; then
           touch "${cfg.spoolDir}/.firstRun"
         fi
@@ -149,13 +138,18 @@ in {
           for src in ${dumps}; do
             find "$src" -type f | while read dump; do
               echo "Loading configuration dump at $dump"
-              chpst -u "${cfg.user}:${cfg.group}" ${ectl} load "$dump"
+              ${ectl} load "$dump"
             done
           done
         fi
       '';
     };
 
+    systemd.tmpfiles.rules = [
+      "d '${cfg.logsDir}' 0750 ${cfg.user} ${cfg.group} -"
+      "d '${cfg.spoolDir}' 0700 ${cfg.user} ${cfg.group} -"
+    ];
+
     security.pam.services.ejabberd = {};
 
   };
diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix
index 81dc7beb6021..5639b2668c30 100644
--- a/nixos/tests/all-tests.nix
+++ b/nixos/tests/all-tests.nix
@@ -72,6 +72,7 @@ in
   #ec2-config = (handleTestOn ["x86_64-linux"] ./ec2.nix {}).boot-ec2-config or {};
   ec2-nixops = (handleTestOn ["x86_64-linux"] ./ec2.nix {}).boot-ec2-nixops or {};
   ecryptfs = handleTest ./ecryptfs.nix {};
+  ejabberd = handleTest ./ejabberd.nix {};
   elk = handleTestOn ["x86_64-linux"] ./elk.nix {};
   env = handleTest ./env.nix {};
   etcd = handleTestOn ["x86_64-linux"] ./etcd.nix {};
diff --git a/nixos/tests/ejabberd.nix b/nixos/tests/ejabberd.nix
new file mode 100644
index 000000000000..0691dfe780d2
--- /dev/null
+++ b/nixos/tests/ejabberd.nix
@@ -0,0 +1,262 @@
+import ./make-test.nix ({ pkgs, ... }: {
+  name = "ejabberd";
+  meta = with pkgs.stdenv.lib.maintainers; {
+    maintainers = [ ajs124 ];
+  };
+  nodes = {
+    client = { nodes, pkgs, ... }: {
+      environment.systemPackages = [
+        (pkgs.callPackage ./xmpp-sendmessage.nix { connectTo = nodes.server.config.networking.primaryIPAddress; })
+      ];
+    };
+    server = { config, pkgs, ... }: {
+      networking.extraHosts = ''
+        ${config.networking.primaryIPAddress} example.com
+      '';
+
+      services.ejabberd = {
+        enable = true;
+        configFile = "/etc/ejabberd.yml";
+      };
+
+      environment.etc."ejabberd.yml" = {
+        user = "ejabberd";
+        mode = "0600";
+        text = ''
+          loglevel: 3
+
+          hosts:
+            - "example.com"
+
+          listen:
+            -
+              port: 5222
+              module: ejabberd_c2s
+              zlib: false
+              max_stanza_size: 65536
+              shaper: c2s_shaper
+              access: c2s
+            -
+              port: 5269
+              ip: "::"
+              module: ejabberd_s2s_in
+            -
+              port: 5347
+              ip: "127.0.0.1"
+              module: ejabberd_service
+              access: local
+              shaper_rule: fast
+              ip: "127.0.0.1"
+
+          ## Disabling digest-md5 SASL authentication. digest-md5 requires plain-text
+          ## password storage (see auth_password_format option).
+          disable_sasl_mechanisms: "digest-md5"
+
+          ## Outgoing S2S options
+          ## Preferred address families (which to try first) and connect timeout
+          ## in seconds.
+          outgoing_s2s_families:
+             - ipv4
+             - ipv6
+
+          ## auth_method: Method used to authenticate the users.
+          ## The default method is the internal.
+          ## If you want to use a different method,
+          ## comment this line and enable the correct ones.
+          auth_method: internal
+
+          ## Store the plain passwords or hashed for SCRAM:
+          ## auth_password_format: plain
+          auth_password_format: scram
+
+          ###'  TRAFFIC SHAPERS
+          shaper:
+            # in B/s
+            normal: 1000000
+            fast: 50000000
+
+          ## This option specifies the maximum number of elements in the queue
+          ## of the FSM. Refer to the documentation for details.
+          max_fsm_queue: 1000
+
+          ###'   ACCESS CONTROL LISTS
+          acl:
+            ## The 'admin' ACL grants administrative privileges to XMPP accounts.
+            ## You can put here as many accounts as you want.
+            admin:
+               user:
+                 - "root": "example.com"
+
+            ## Local users: don't modify this.
+            local:
+              user_regexp: ""
+
+            ## Loopback network
+            loopback:
+              ip:
+                - "127.0.0.0/8"
+                - "::1/128"
+                - "::FFFF:127.0.0.1/128"
+
+          ###'  SHAPER RULES
+          shaper_rules:
+            ## Maximum number of simultaneous sessions allowed for a single user:
+            max_user_sessions: 10
+            ## Maximum number of offline messages that users can have:
+            max_user_offline_messages:
+              - 5000: admin
+              - 1024
+            ## For C2S connections, all users except admins use the "normal" shaper
+            c2s_shaper:
+              - none: admin
+              - normal
+            ## All S2S connections use the "fast" shaper
+            s2s_shaper: fast
+
+          ###'  ACCESS RULES
+          access_rules:
+            ## This rule allows access only for local users:
+            local:
+              - allow: local
+            ## Only non-blocked users can use c2s connections:
+            c2s:
+              - deny: blocked
+              - allow
+            ## Only admins can send announcement messages:
+            announce:
+              - allow: admin
+            ## Only admins can use the configuration interface:
+            configure:
+              - allow: admin
+            ## Only accounts of the local ejabberd server can create rooms:
+            muc_create:
+              - allow: local
+            ## Only accounts on the local ejabberd server can create Pubsub nodes:
+            pubsub_createnode:
+              - allow: local
+            ## In-band registration allows registration of any possible username.
+            ## To disable in-band registration, replace 'allow' with 'deny'.
+            register:
+              - allow
+            ## Only allow to register from localhost
+            trusted_network:
+              - allow: loopback
+
+          ## ===============
+          ## API PERMISSIONS
+          ## ===============
+          ##
+          ## This section allows you to define who and using what method
+          ## can execute commands offered by ejabberd.
+          ##
+          ## By default "console commands" section allow executing all commands
+          ## issued using ejabberdctl command, and "admin access" section allows
+          ## users in admin acl that connect from 127.0.0.1 to  execute all
+          ## commands except start and stop with any available access method
+          ## (ejabberdctl, http-api, xmlrpc depending what is enabled on server).
+          ##
+          ## If you remove "console commands" there will be one added by
+          ## default allowing executing all commands, but if you just change
+          ## permissions in it, version from config file will be used instead
+          ## of default one.
+          ##
+          api_permissions:
+            "console commands":
+              from:
+                - ejabberd_ctl
+              who: all
+              what: "*"
+
+          language: "en"
+
+          ###'  MODULES
+          ## Modules enabled in all ejabberd virtual hosts.
+          modules:
+            mod_adhoc: {}
+            mod_announce: # recommends mod_adhoc
+              access: announce
+            mod_blocking: {} # requires mod_privacy
+            mod_caps: {}
+            mod_carboncopy: {}
+            mod_client_state: {}
+            mod_configure: {} # requires mod_adhoc
+            ## mod_delegation: {} # for xep0356
+            mod_echo: {}
+            #mod_irc:
+            #  host: "irc.@HOST@"
+            #  default_encoding: "utf-8"
+            ## mod_bosh: {}
+            ## mod_http_fileserver:
+            ##   docroot: "/var/www"
+            ##   accesslog: "/var/log/ejabberd/access.log"
+            #mod_http_upload:
+            #  thumbnail: false # otherwise needs the identify command from ImageMagick installed
+            #  put_url: "https://@HOST@:5444"
+            ##   # docroot: "@HOME@/upload"
+            #mod_http_upload_quota:
+            #  max_days: 14
+            mod_last: {}
+            ## XEP-0313: Message Archive Management
+            ## You might want to setup a SQL backend for MAM because the mnesia database is
+            ## limited to 2GB which might be exceeded on large servers
+            mod_mam: {}
+            mod_muc:
+              host: "muc.@HOST@"
+              access:
+                - allow
+              access_admin:
+                - allow: admin
+              access_create: muc_create
+              access_persistent: muc_create
+            mod_muc_admin: {}
+            mod_muc_log: {}
+            mod_offline:
+              access_max_user_messages: max_user_offline_messages
+            mod_ping: {}
+            ## mod_pres_counter:
+            ##   count: 5
+            ##   interval: 60
+            mod_privacy: {}
+            mod_private: {}
+            mod_roster:
+                versioning: true
+            mod_shared_roster: {}
+            mod_stats: {}
+            mod_time: {}
+            mod_vcard:
+              search: false
+            mod_vcard_xupdate: {}
+            ## Convert all avatars posted by Android clients from WebP to JPEG
+            mod_avatar: {}
+            #  convert:
+            #    webp: jpeg
+            mod_version: {}
+            mod_stream_mgmt: {}
+            ##   The module for S2S dialback (XEP-0220). Please note that you cannot
+            ##   rely solely on dialback if you want to federate with other servers,
+            ##   because a lot of servers have dialback disabled and instead rely on
+            ##   PKIX authentication. Make sure you have proper certificates installed
+            ##   and check your accessibility at https://check.messaging.one/
+            mod_s2s_dialback: {}
+            mod_pubsub:
+              plugins:
+                - "pep"
+            mod_push: {}
+        '';
+      };
+
+      networking.firewall.enable = false;
+    };
+  };
+
+  testScript = { nodes, ... }: ''
+    $server->waitForUnit('ejabberd.service');
+    $server->succeed('su ejabberd -s $(which ejabberdctl) status|grep started') =~ /ejabberd is running/;
+    $server->succeed('su ejabberd -s $(which ejabberdctl) register azurediamond example.com hunter2');
+    $server->succeed('su ejabberd -s $(which ejabberdctl) register cthon98 example.com nothunter2');
+    $server->fail('su ejabberd -s $(which ejabberdctl) register asdf wrong.domain');
+    $client->succeed('send-message');
+    $server->succeed('su ejabberd -s $(which ejabberdctl) unregister cthon98 example.com');
+    $server->succeed('su ejabberd -s $(which ejabberdctl) unregister azurediamond example.com');
+  '';
+})
diff --git a/nixos/tests/prosody.nix b/nixos/tests/prosody.nix
index 61ae5bb38ed9..a39bae7898dc 100644
--- a/nixos/tests/prosody.nix
+++ b/nixos/tests/prosody.nix
@@ -9,70 +9,30 @@ import ./make-test.nix {
       extraConfig = ''
         storage = "sql"
       '';
+      virtualHosts.test = {
+        domain = "example.com";
+        enabled = true;
+      };
     };
-    environment.systemPackages = let
-      sendMessage = pkgs.writeScriptBin "send-message" ''
-        #!/usr/bin/env python3
-        # Based on the sleekxmpp send_client example, look there for more details:
-        # https://github.com/fritzy/SleekXMPP/blob/develop/examples/send_client.py
-        import sleekxmpp
-
-        class SendMsgBot(sleekxmpp.ClientXMPP):
-            """
-            A basic SleekXMPP bot that will log in, send a message,
-            and then log out.
-            """
-            def __init__(self, jid, password, recipient, message):
-                sleekxmpp.ClientXMPP.__init__(self, jid, password)
-
-                self.recipient = recipient
-                self.msg = message
-
-                self.add_event_handler("session_start", self.start, threaded=True)
-
-            def start(self, event):
-                self.send_presence()
-                self.get_roster()
-
-                self.send_message(mto=self.recipient,
-                                  mbody=self.msg,
-                                  mtype='chat')
-
-                self.disconnect(wait=True)
-
-
-        if __name__ == '__main__':
-            xmpp = SendMsgBot("test1@localhost", "test1", "test2@localhost", "Hello World!")
-            xmpp.register_plugin('xep_0030') # Service Discovery
-            xmpp.register_plugin('xep_0199') # XMPP Ping
-
-            # TODO: verify certificate
-            # If you want to verify the SSL certificates offered by a server:
-            # xmpp.ca_certs = "path/to/ca/cert"
-
-            if xmpp.connect(('localhost', 5222)):
-                xmpp.process(block=True)
-            else:
-                print("Unable to connect.")
-                sys.exit(1)
-      '';
-    in [ (pkgs.python3.withPackages (ps: [ ps.sleekxmpp ])) sendMessage ];
+    environment.systemPackages = [
+      (pkgs.callPackage ./xmpp-sendmessage.nix {})
+    ];
   };
 
   testScript = ''
     $machine->waitForUnit('prosody.service');
     $machine->succeed('prosodyctl status') =~ /Prosody is running/;
 
-    # set password to 'test' (it's asked twice)
-    $machine->succeed('yes test1 | prosodyctl adduser test1@localhost');
+    # set password to 'nothunter2' (it's asked twice)
+    $machine->succeed('yes nothunter2 | prosodyctl adduser cthon98@example.com');
     # set password to 'y'
-    $machine->succeed('yes | prosodyctl adduser test2@localhost');
-    # correct password to 'test2'
-    $machine->succeed('yes test2 | prosodyctl passwd test2@localhost');
+    $machine->succeed('yes | prosodyctl adduser azurediamond@example.com');
+    # correct password to 'hunter2'
+    $machine->succeed('yes hunter2 | prosodyctl passwd azurediamond@example.com');
 
     $machine->succeed("send-message");
 
-    $machine->succeed('prosodyctl deluser test1@localhost');
-    $machine->succeed('prosodyctl deluser test2@localhost');
+    $machine->succeed('prosodyctl deluser cthon98@example.com');
+    $machine->succeed('prosodyctl deluser azurediamond@example.com');
   '';
 }
diff --git a/nixos/tests/xmpp-sendmessage.nix b/nixos/tests/xmpp-sendmessage.nix
new file mode 100644
index 000000000000..2a075a018134
--- /dev/null
+++ b/nixos/tests/xmpp-sendmessage.nix
@@ -0,0 +1,46 @@
+{ writeScriptBin, python3, connectTo ? "localhost" }:
+writeScriptBin "send-message" ''
+  #!${(python3.withPackages (ps: [ ps.sleekxmpp ])).interpreter}
+  # Based on the sleekxmpp send_client example, look there for more details:
+  # https://github.com/fritzy/SleekXMPP/blob/develop/examples/send_client.py
+  import sleekxmpp
+
+  class SendMsgBot(sleekxmpp.ClientXMPP):
+      """
+      A basic SleekXMPP bot that will log in, send a message,
+      and then log out.
+      """
+      def __init__(self, jid, password, recipient, message):
+          sleekxmpp.ClientXMPP.__init__(self, jid, password)
+
+          self.recipient = recipient
+          self.msg = message
+
+          self.add_event_handler("session_start", self.start, threaded=True)
+
+      def start(self, event):
+          self.send_presence()
+          self.get_roster()
+
+          self.send_message(mto=self.recipient,
+                            mbody=self.msg,
+                            mtype='chat')
+
+          self.disconnect(wait=True)
+
+
+  if __name__ == '__main__':
+      xmpp = SendMsgBot("cthon98@example.com", "nothunter2", "azurediamond@example.com", "hey, if you type in your pw, it will show as stars")
+      xmpp.register_plugin('xep_0030') # Service Discovery
+      xmpp.register_plugin('xep_0199') # XMPP Ping
+
+      # TODO: verify certificate
+      # If you want to verify the SSL certificates offered by a server:
+      # xmpp.ca_certs = "path/to/ca/cert"
+
+      if xmpp.connect(('${connectTo}', 5222)):
+          xmpp.process(block=True)
+      else:
+          print("Unable to connect.")
+          sys.exit(1)
+''