Merge pull request #59731 from ajs124/ejabberd_test
ejabberd: refactor module, add test
This commit is contained in:
commit
77fb90d27e
@ -197,6 +197,11 @@
|
||||
github = "aij";
|
||||
name = "Ivan Jager";
|
||||
};
|
||||
ajs124 = {
|
||||
email = "nix@ajs124.de";
|
||||
github = "ajs124";
|
||||
name = "Andreas Schrägle";
|
||||
};
|
||||
ajgrf = {
|
||||
email = "a@ajgrf.com";
|
||||
github = "ajgrf";
|
||||
|
@ -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 = {};
|
||||
|
||||
};
|
||||
|
@ -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 {};
|
||||
|
262
nixos/tests/ejabberd.nix
Normal file
262
nixos/tests/ejabberd.nix
Normal file
@ -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');
|
||||
'';
|
||||
})
|
@ -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');
|
||||
'';
|
||||
}
|
||||
|
46
nixos/tests/xmpp-sendmessage.nix
Normal file
46
nixos/tests/xmpp-sendmessage.nix
Normal file
@ -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)
|
||||
''
|
Loading…
Reference in New Issue
Block a user