[enh] Metronome regen script

This commit is contained in:
kload 2015-09-29 08:52:34 -04:00
parent 3804873142
commit ec63f336cf
8 changed files with 416 additions and 260 deletions

View file

@ -0,0 +1,59 @@
#!/bin/bash
set -e
force=$1
function safe_copy () {
if [[ "$force" == "True" ]]; then
sudo yunohost service safecopy \
-s metronome \
$1 $2 \
--force
else
sudo yunohost service safecopy \
-s metronome \
$1 $2
fi
}
cd /usr/share/yunohost/templates/metronome
# Copy additional modules
files="ldap.lib.lua
mod_auth_ldap2.lua
mod_legacyauth.lua
mod_storage_ldap.lua
vcard.lib.lua"
for file in $files; do
safe_copy modules/$file /usr/lib/metronome/modules/$file
done
# Copy configuration files
main_domain=$(cat /etc/yunohost/current_host)
cat metronome.cfg.lua.sed \
| sed "s/{{ main_domain }}/$main_domain/g" \
| sudo tee metronome.cfg.lua
safe_copy metronome.cfg.lua /etc/metronome/metronome.cfg.lua
safe_copy metronome.init /etc/init.d/metronome
safe_copy metronome.logrotate /etc/logrotate.d/metronome
need_restart=False
sudo mkdir -p /etc/metronome/conf.d
# Copy a configuration file for each YunoHost domain
for domain in $(sudo yunohost domain list --raw); do
cat domain.cfg.lua.sed \
| sed "s/{{ domain }}/$domain/g" \
| sudo tee $domain.cfg.lua
if [[ $(safe_copy $domain.cfg.lua /etc/metronome/conf.d/$domain.cfg.lua) == "True" ]]; then
need_restart=True
fi
done
# Restart if need be
if [[ "$need_restart" == "True" ]]; then
sudo service metronome restart
else
sudo service metronome reload
fi

View file

@ -0,0 +1,15 @@
VirtualHost "{{ domain }}"
ssl = {
key = "/etc/yunohost/certs/{{ domain }}/key.pem";
certificate = "/etc/yunohost/certs/{{ domain }}/crt.pem";
}
authentication = "ldap2"
ldap = {
hostname = "localhost",
user = {
basedn = "ou=users,dc=yunohost,dc=org",
filter = "(&(objectClass=posixAccount)(mail=*@{{ domain }}))",
usernamefield = "mail",
namefield = "cn",
},
}

View file

@ -1,131 +0,0 @@
-- ** Metronome's config file example **
--
-- The format is exactly equal to Prosody's:
--
-- Lists are written { "like", "this", "one" }
-- Lists can also be of { 1, 2, 3 } numbers, etc.
-- Either commas, or semi-colons; may be used as seperators.
--
-- A table is a list of values, except each value has a name. An
-- example would be:
--
-- ssl = { key = "keyfile.key", certificate = "certificate.crt" }
--
-- Tip: You can check that the syntax of this file is correct when you have finished
-- by running: luac -p metronome.cfg.lua
-- If there are any errors, it will let you know what and where they are, otherwise it
-- will keep quiet.
-- Global settings go in this section
-- This is the list of modules Metronome will load on startup.
-- It looks for mod_modulename.lua in the plugins folder, so make sure that exists too.
pidfile = "/var/run/metronome/metronome.pid"
log = {
info = "/var/log/metronome/metronome.log"; -- Change 'info' to 'debug' for verbose logging
error = "/var/log/metronome/metronome.err";
"*syslog";
}
modules_enabled = {
-- Generally required
"roster"; -- Allow users to have a roster. Recommended ;)
"saslauth"; -- Authentication for clients and servers. Recommended if you want to log in.
"tls"; -- Add support for secure TLS on c2s/s2s connections
"dialback"; -- s2s dialback support
"disco"; -- Service discovery
-- Not essential, but recommended
"private"; -- Private XML storage (for room bookmarks, etc.)
"vcard"; -- Allow users to set vCards
"privacy"; -- Support privacy lists
--"compression"; -- Stream compression (Debian: requires lua-zlib module to work)
-- Nice to have
"legacyauth"; -- Legacy authentication. Only used by some old clients and bots.
"version"; -- Replies to server version requests
"uptime"; -- Report how long server has been running
"time"; -- Let others know the time here on this server
"ping"; -- Replies to XMPP pings with pongs
"pep"; -- Enables users to publish their mood, activity, playing music and more
"register"; -- Allow users to register on this server using a client and change passwords
"adhoc"; -- Support for "ad-hoc commands" that can be executed with an XMPP client
-- Admin interfaces
"admin_adhoc"; -- Allows administration via an XMPP client that supports ad-hoc commands
"admin_telnet"; -- Opens telnet console interface on localhost port 5582
-- Other specific functionality
"bosh"; -- Enable BOSH clients, aka "Jabber over HTTP"
--"httpserver"; -- Serve static files from a directory over HTTP
--"groups"; -- Shared roster support
--"announce"; -- Send announcement to all online users
--"welcome"; -- Welcome users who register accounts
--"watchregistrations"; -- Alert admins of registrations
--"motd"; -- Send a message to users when they log in
"mam"; -- Nice archive management
-- Debian: do not remove this module, or you lose syslog
-- support
"posix"; -- POSIX functionality, sends server to background, enables syslog, etc.
};
-- Discovery items
disco_items = {
{ "muc.yunohost.org" },
{ "vjud.yunohost.org" },
{ "pubsub.yunohost.org" }
};
use_ipv6 = true
c2s_require_encryption = false
s2s_secure = true
-- HTTP ports
http_ports = { 5290 }
https_ports = { 5291 }
-- BOSH configuration (mod_bosh)
bosh_max_inactivity = 30
consider_bosh_secure = true
cross_domain_bosh = true
anonymous_login = false
allow_registration = false
storage = "ldap"
Component "localhost" "http"
modules_enabled = { "bosh" }
Component "muc.yunohost.org" "muc"
name = "YunoHost Chatrooms"
modules_enabled = {
"muc_limits";
"muc_log";
"muc_log_http";
}
muc_event_rate = 0.5
muc_burst_factor = 10
muc_log_http = {
http_port = 5290;
show_join = true;
show_status = false;
theme = "metronome";
}
Component "pubsub.yunohost.org" "pubsub"
name = "YunoHost Publish/Subscribe"
unrestricted_node_creation = true
Component "vjud.yunohost.org" "vjud"
ud_disco_name = "Jappix User Directory"
Include "conf.d/*.cfg.lua"

View file

@ -0,0 +1,193 @@
-- ** Metronome's config file example **
--
-- The format is exactly equal to Prosody's:
--
-- Lists are written { "like", "this", "one" }
-- Lists can also be of { 1, 2, 3 } numbers, etc.
-- Either commas, or semi-colons; may be used as seperators.
--
-- A table is a list of values, except each value has a name. An
-- example would be:
--
-- ssl = { key = "keyfile.key", certificate = "certificate.crt" }
--
-- Tip: You can check that the syntax of this file is correct when you have finished
-- by running: luac -p metronome.cfg.lua
-- If there are any errors, it will let you know what and where they are, otherwise it
-- will keep quiet.
---------- Server-wide settings ----------
-- Settings in this section apply to the whole server and are the default settings
-- for any virtual hosts
-- Server PID
pidfile = "/var/run/metronome/metronome.pid"
-- HTTP server
http_ports = { 5290 }
http_interfaces = { "127.0.0.1", "::1" }
--https_ports = { 5291 }
--https_interfaces = { "127.0.0.1", "::1" }
-- Enable IPv6
use_ipv6 = true
-- This is the list of modules Metronome will load on startup.
-- It looks for mod_modulename.lua in the plugins folder, so make sure that exists too.
modules_enabled = {
-- Generally required
"roster"; -- Allow users to have a roster. Recommended ;)
"saslauth"; -- Authentication for clients and servers. Recommended if you want to log in.
"tls"; -- Add support for secure TLS on c2s/s2s connections
"dialback"; -- s2s dialback support
"disco"; -- Service discovery
--"discoitems"; -- Service discovery items
--"extdisco"; -- External Service Discovery
-- Not essential, but recommended
"private"; -- Private XML storage (for room bookmarks, etc.)
"vcard"; -- Allow users to set vCards
"privacy"; -- Support privacy lists
-- These are commented by default as they have a performance impact
--"compression"; -- Stream compression (Debian: requires lua-zlib module to work)
-- Nice to have
"version"; -- Replies to server version requests
"uptime"; -- Report how long server has been running
"time"; -- Let others know the time here on this server
"ping"; -- Replies to XMPP pings with pongs
"pep"; -- Enables users to publish their mood, activity, playing music and more
"message_carbons"; -- Allow clients to keep in sync with messages send on other resources
"register"; -- Allow users to register on this server using a client and change passwords
"adhoc"; -- Support for "ad-hoc commands" that can be executed with an XMPP client
-- Admin interfaces
"admin_adhoc"; -- Allows administration via an XMPP client that supports ad-hoc commands
"admin_telnet"; -- Opens telnet console interface on localhost port 5582
-- HTTP modules
"bosh"; -- Enable BOSH clients, aka "Jabber over HTTP"
--"websockets"; -- Enable WebSocket clients
--"http_files"; -- Serve static files from a directory over HTTP
-- Other specific functionality
-- "bidi"; -- Bidirectional Streams for S2S connections
-- "stream_management"; -- Stream Management support
--"groups"; -- Shared roster support
--"announce"; -- Send announcement to all online users
--"welcome"; -- Welcome users who register accounts
--"watchregistrations"; -- Alert admins of registrations
--"motd"; -- Send a message to users when they log in
"mam"; -- Nice archive management
--"legacyauth"; -- Legacy authentication. Only used by some old clients and bots.
"offline"; -- Store offline messages
"c2s"; -- Handle client connections
"s2s"; -- Handle server-to-server connections
-- Debian: do not remove this module, or you lose syslog
-- support
"posix"; -- POSIX functionality, sends server to background, enables syslog, etc.
};
-- Discovery items
disco_items = {
{ "muc.{{ main_domain }}" },
{ "pubsub.{{ main_domain }}" },
{ "vjud.{{ main_domain }}" }
};
-- BOSH configuration (mod_bosh)
bosh_max_inactivity = 30
consider_bosh_secure = true
cross_domain_bosh = true
-- Disable account creation by default, for security
allow_registration = false
-- SSL/TLS configuration
ssl = {
options = {
"no_sslv2",
"no_sslv3",
"no_ticket",
"no_compression",
"cipher_server_preference"
};
}
-- Force clients to use encrypted connections? This option will
-- prevent clients from authenticating unless they are using encryption.
c2s_require_encryption = true
-- Force servers to use encrypted connections? This option will
-- prevent servers from connecting unless they are using encryption.
s2s_require_encryption = true
-- Allow servers to use an unauthenticated encryption channel
s2s_allow_encryption = true
allow_unencrypted_plain_auth = false;
s2s_secure = true
s2s_secure_auth = false
--anonymous_login = false
-- Use LDAP storage backend for all stores
storage = "ldap"
-- Logging configuration
log = {
info = "/var/log/metronome/metronome.log"; -- Change 'info' to 'debug' for verbose logging
error = "/var/log/metronome/metronome.err";
-- "*syslog"; -- Uncomment this for logging to syslog
-- "*console"; -- Log to the console, useful for debugging with daemonize=false
}
------ Components ------
-- You can specify components to add hosts that provide special services,
-- like multi-user conferences, and transports.
---Set up a local BOSH service
Component "localhost" "http"
modules_enabled = { "bosh" }
---Set up a MUC (multi-user chat) room server
Component "muc.{{ main_domain }}" "muc"
name = "YunoHost Chatrooms"
modules_enabled = {
"muc_limits";
"muc_log";
"muc_log_http";
}
muc_event_rate = 0.5
muc_burst_factor = 10
muc_log_http_config = {
url_base = "logs";
theme = "metronome";
}
---Set up a PubSub server
Component "pubsub.{{ main_domain }}" "pubsub"
name = "YunoHost Publish/Subscribe"
unrestricted_node_creation = true -- Anyone can create a PubSub node (from any server)
---Set up a VJUD service
Component "vjud.{{ main_domain }}" "vjud"
ud_disco_name = "Jappix User Directory"
----------- Virtual hosts -----------
-- You need to add a VirtualHost entry for each domain you wish Metronome to serve.
-- Settings under each VirtualHost entry apply *only* to that host.
Include "conf.d/*.cfg.lua"

View file

@ -2,8 +2,8 @@
### BEGIN INIT INFO ### BEGIN INIT INFO
# Provides: metronome # Provides: metronome
# Required-Start: $network $local_fs $remote_fs # Required-Start: $network $local_fs $remote_fs $syslog
# Required-Stop: $remote_fs # Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5 # Default-Start: 2 3 4 5
# Default-Stop: 0 1 6 # Default-Stop: 0 1 6
# Short-Description: Metronome XMPP Server # Short-Description: Metronome XMPP Server
@ -13,10 +13,11 @@ set -e
# /etc/init.d/metronome: start and stop Metronome XMPP server # /etc/init.d/metronome: start and stop Metronome XMPP server
NAME=metronome
USER=metronome
DAEMON=/usr/bin/metronome DAEMON=/usr/bin/metronome
PIDPATH=/var/run/metronome PIDPATH=/var/run/metronome
PIDFILE="$PIDPATH"/metronome.pid PIDFILE="$PIDPATH"/metronome.pid
RUNTIME=/usr/bin/lua5.1
NICE= NICE=
MAXFDS= MAXFDS=
@ -25,77 +26,94 @@ IOSCHED=
test -x "$DAEMON" || exit 0 test -x "$DAEMON" || exit 0
. /lib/lsb/init-functions
if [ -f /etc/default/metronome ] ; then if [ -f /etc/default/metronome ] ; then
. /etc/default/metronome . /etc/default/metronome
fi fi
if [ ! -d "$PIDPATH" ]; then
mkdir "$PIDPATH";
chown metronome:adm "$PIDPATH";
fi
# Check that user 'metronome' exists
check_user() {
if ! getent passwd metronome >/dev/null; then
exit 1;
fi
}
start_opts() { start_opts() {
test -z "$NICE" || echo -n " --nicelevel $NICE" test -z "$NICE" || echo -n " --nicelevel $NICE"
test -z "$CPUSCHED" || echo -n " --procsched $CPUSCHED" test -z "$CPUSCHED" || echo -n " --procsched $CPUSCHED"
test -z "$IOSCHED" || echo -n " --iosched $IOSCHED" test -z "$IOSCHED" || echo -n " --iosched $IOSCHED"
} }
. /lib/lsb/init-functions start_metronome () {
mkdir -p `dirname $PIDFILE`
chown metronome:adm `dirname $PIDFILE`
if start-stop-daemon --start --quiet --pidfile "$PIDFILE" \
--chuid "$USER" --oknodo --user "$USER" --name lua5.1 \
$(start_opts) --startas "$DAEMON";
then
return 0
else
return 1
fi
}
test -z "$MAXFDS" || ulimit -n "$MAXFDS" stop_metronome () {
if start-stop-daemon --stop --quiet --retry 30 \
--oknodo --pidfile "$PIDFILE" --user "$USER" --name lua5.1;
then
return 0
else
return 1
fi
}
signal_metronome () {
if start-stop-daemon --stop --quiet --pidfile "$PIDFILE" \
--user "$USER" --name lua5.1 --oknodo --signal $1;
then
return 0
else
return 1
fi
}
case "$1" in case "$1" in
start) start)
check_user log_daemon_msg "Starting Metronome XMPP Server" "metronome"
log_daemon_msg "Starting Metronome XMPP Server" "metronome" if start_metronome; then
log_end_msg 0;
if start-stop-daemon --start --quiet --oknodo --pidfile "$PIDFILE" --chuid metronome $(start_opts) --exec "$RUNTIME" -- "$DAEMON"; then else
log_end_msg 0 log_end_msg 1;
else fi
log_end_msg 1 ;;
fi
;;
stop) stop)
log_daemon_msg "Stopping Metronome XMPP Server" "metronome" log_daemon_msg "Stopping Metronome XMPP Server" "metronome"
if start-stop-daemon --stop --retry 30 --quiet --oknodo --pidfile "$PIDFILE"; then if stop_metronome; then
log_end_msg 0 log_end_msg 0;
else else
log_end_msg 1 log_end_msg 1;
fi fi
;; ;;
force-reload|restart) force-reload|restart)
log_daemon_msg "Restarting Metronome XMPP Server" "metronome" log_daemon_msg "Restarting Metronome XMPP Server" "metronome"
start-stop-daemon --stop --quiet --oknodo --retry 30 --pidfile "$PIDFILE" stop_metronome
check_user log_end_msg if start_metronome; then
log_end_msg 0;
if start-stop-daemon --start --quiet --oknodo --pidfile "$PIDFILE" --chuid metronome $(start_opts) --exec "$RUNTIME" -- "$DAEMON"; then else
log_end_msg 0 log_end_msg 1;
else fi
log_end_msg 1 ;;
fi
;;
reload) reload)
log_daemon_msg "Reloading Metronome XMPP Server" "metronome" log_daemon_msg "Reloading Metronome XMPP Server" "metronome"
if start-stop-daemon --stop --quiet --pidfile "$PIDFILE" --signal 1; then if signal_metronome 1; then
log_end_msg 0 log_end_msg 0;
else else
log_end_msg 1 log_end_msg 1;
fi fi
;;
status)
status_of_proc -p $PIDFILE $DAEMON $NAME
;; ;;
*) *)
log_action_msg "Usage: /etc/init.d/metronome {start|stop|restart|reload}" log_action_msg "Usage: /etc/init.d/metronome {start|stop|restart|reload|status}"
exit 1 exit 1
esac esac
exit 0 exit 0

View file

@ -1,11 +1,11 @@
/var/log/metronome/metronome.log /var/log/metronome/metronome.err { /var/log/metronome/metronome.log /var/log/metronome/metronome.err {
daily daily
rotate 14 rotate 14
compress compress
create 640 metronome adm create 640 metronome adm
postrotate postrotate
/etc/init.d/metronome reload > /dev/null /etc/init.d/metronome reload > /dev/null
endscript endscript
sharedscripts sharedscripts
missingok missingok
} }

View file

@ -12,8 +12,8 @@ local st = require "util.stanza";
local t_concat = table.concat; local t_concat = table.concat;
local secure_auth_only = module:get_option("c2s_require_encryption") local secure_auth_only = module:get_option("c2s_require_encryption")
or module:get_option("require_encryption") or module:get_option("require_encryption")
or not(module:get_option("allow_unencrypted_plain_auth")); or not(module:get_option("allow_unencrypted_plain_auth"));
local sessionmanager = require "core.sessionmanager"; local sessionmanager = require "core.sessionmanager";
local usermanager = require "core.usermanager"; local usermanager = require "core.usermanager";
@ -22,66 +22,66 @@ local resourceprep = require "util.encodings".stringprep.resourceprep;
module:add_feature("jabber:iq:auth"); module:add_feature("jabber:iq:auth");
module:hook("stream-features", function(event) module:hook("stream-features", function(event)
local origin, features = event.origin, event.features; local origin, features = event.origin, event.features;
if secure_auth_only and not origin.secure then if secure_auth_only and not origin.secure then
-- Sorry, not offering to insecure streams! -- Sorry, not offering to insecure streams!
return; return;
elseif not origin.username then elseif not origin.username then
features:tag("auth", {xmlns='http://jabber.org/features/iq-auth'}):up(); features:tag("auth", {xmlns='http://jabber.org/features/iq-auth'}):up();
end end
end); end);
module:hook("stanza/iq/jabber:iq:auth:query", function(event) module:hook("stanza/iq/jabber:iq:auth:query", function(event)
local session, stanza = event.origin, event.stanza; local session, stanza = event.origin, event.stanza;
if session.type ~= "c2s_unauthed" then if session.type ~= "c2s_unauthed" then
(session.sends2s or session.send)(st.error_reply(stanza, "cancel", "service-unavailable", "Legacy authentication is only allowed for unauthenticated client connections.")); (session.sends2s or session.send)(st.error_reply(stanza, "cancel", "service-unavailable", "Legacy authentication is only allowed for unauthenticated client connections."));
return true; return true;
end end
if secure_auth_only and not session.secure then if secure_auth_only and not session.secure then
session.send(st.error_reply(stanza, "modify", "not-acceptable", "Encryption (SSL or TLS) is required to connect to this server")); session.send(st.error_reply(stanza, "modify", "not-acceptable", "Encryption (SSL or TLS) is required to connect to this server"));
return true; return true;
end end
local username = stanza.tags[1]:child_with_name("username"); local username = stanza.tags[1]:child_with_name("username");
local password = stanza.tags[1]:child_with_name("password"); local password = stanza.tags[1]:child_with_name("password");
local resource = stanza.tags[1]:child_with_name("resource"); local resource = stanza.tags[1]:child_with_name("resource");
if not (username and password and resource) then if not (username and password and resource) then
local reply = st.reply(stanza); local reply = st.reply(stanza);
session.send(reply:query("jabber:iq:auth") session.send(reply:query("jabber:iq:auth")
:tag("username"):up() :tag("username"):up()
:tag("password"):up() :tag("password"):up()
:tag("resource"):up()); :tag("resource"):up());
else else
username, password, resource = t_concat(username), t_concat(password), t_concat(resource); username, password, resource = t_concat(username), t_concat(password), t_concat(resource);
username = nodeprep(username); username = nodeprep(username);
resource = resourceprep(resource) resource = resourceprep(resource)
if not (username and resource) then if not (username and resource) then
session.send(st.error_reply(stanza, "modify", "bad-request")); session.send(st.error_reply(stanza, "modify", "bad-request"));
return true; return true;
end end
if usermanager.test_password(username, session.host, password) then if usermanager.test_password(username, session.host, password) then
-- Authentication successful! -- Authentication successful!
local success, err = sessionmanager.make_authenticated(session, username); local success, err = sessionmanager.make_authenticated(session, username);
if success then if success then
local err_type, err_msg; local err_type, err_msg;
success, err_type, err, err_msg = sessionmanager.bind_resource(session, resource); success, err_type, err, err_msg = sessionmanager.bind_resource(session, resource);
if not success then if not success then
session.send(st.error_reply(stanza, err_type, err, err_msg)); session.send(st.error_reply(stanza, err_type, err, err_msg));
session.username, session.type = nil, "c2s_unauthed"; -- FIXME should this be placed in sessionmanager? session.username, session.type = nil, "c2s_unauthed"; -- FIXME should this be placed in sessionmanager?
return true; return true;
elseif resource ~= session.resource then -- server changed resource, not supported by legacy auth elseif resource ~= session.resource then -- server changed resource, not supported by legacy auth
session.send(st.error_reply(stanza, "cancel", "conflict", "The requested resource could not be assigned to this session.")); session.send(st.error_reply(stanza, "cancel", "conflict", "The requested resource could not be assigned to this session."));
session:close(); -- FIXME undo resource bind and auth instead of closing the session? session:close(); -- FIXME undo resource bind and auth instead of closing the session?
return true; return true;
end end
end end
session.send(st.reply(stanza)); session.send(st.reply(stanza));
else else
session.send(st.error_reply(stanza, "auth", "not-authorized")); session.send(st.error_reply(stanza, "auth", "not-authorized"));
end end
end end
return true; return true;
end); end);

View file

@ -397,7 +397,10 @@ def _get_diff(string, filename):
with open(filename, 'r') as f: with open(filename, 'r') as f:
file_lines = f.readlines() file_lines = f.readlines()
new_lines = string.splitlines(1) string = string + '\n'
new_lines = string.splitlines(True)
while '\n' == file_lines[-1]:
del file_lines[-1]
return difflib.unified_diff(file_lines, new_lines) return difflib.unified_diff(file_lines, new_lines)
except IOError: return [] except IOError: return []
@ -543,14 +546,13 @@ def service_safecopy(service, new_conf_file, conf_file, force=False):
if force or previous_hash == current_hash: if force or previous_hash == current_hash:
with open(conf_file, 'w') as f: f.write(new_conf) with open(conf_file, 'w') as f: f.write(new_conf)
new_hash = _hash(conf_file) new_hash = _hash(conf_file)
if current_hash != new_hash: if previous_hash != new_hash:
regenerated = True regenerated = True
elif len(diff) == 0: elif len(diff) == 0:
new_hash = _hash(conf_file) new_hash = _hash(conf_file)
else: else:
new_hash = previous_hash new_hash = previous_hash
if os.isatty(1) and \ if (len(previous_hash) == 32 or previous_hash[-32:] != current_hash):
(len(previous_hash) == 32 or previous_hash[-32:] != current_hash):
msignals.display( msignals.display(
m18n.n('service_configuration_conflict', conf_file), m18n.n('service_configuration_conflict', conf_file),
'warning' 'warning'