Fix all integrations
This commit is contained in:
@@ -41,7 +41,7 @@ up() {
|
||||
-p "${MANTICORE_SPHINX_PORT}:9312" \
|
||||
-v "$MANTICORE_DATA_DIR:/var/lib/manticore" \
|
||||
-v "$MANTICORE_LOG_DIR:/var/log/manticore" \
|
||||
-v "$MANTICORE_CONFIG_FILE:/etc/manticoresearch/manticore.conf:ro" \
|
||||
-v "$MANTICORE_CONFIG_FILE:/etc/manticoresearch/manticore.conf" \
|
||||
docker.io/manticoresearch/manticore:latest >/dev/null
|
||||
echo "Started $MANTICORE_CONTAINER"
|
||||
}
|
||||
|
||||
121
utilities/prosody/modules/mod_privilege.lua
Normal file
121
utilities/prosody/modules/mod_privilege.lua
Normal file
@@ -0,0 +1,121 @@
|
||||
local st = require "prosody.util.stanza";
|
||||
local jid_bare = require "prosody.util.jid".bare;
|
||||
|
||||
local xmlns_privilege = "urn:xmpp:privilege:2";
|
||||
local xmlns_forward = "urn:xmpp:forward:0";
|
||||
local xmlns_carbons = "urn:xmpp:carbons:2";
|
||||
local bare_sessions = prosody.bare_sessions;
|
||||
|
||||
local allowed_component_jid = module:get_option_string("privileged_entity_jid");
|
||||
|
||||
module:log("info", "mod_privilege loaded for host=%s privileged_entity_jid=%s", module.host or "?", allowed_component_jid or "");
|
||||
|
||||
local function iter_sessions(user_sessions)
|
||||
if not user_sessions or not user_sessions.sessions then
|
||||
return function() return nil end;
|
||||
end
|
||||
return pairs(user_sessions.sessions);
|
||||
end
|
||||
|
||||
local function send_privilege_advertisement(session)
|
||||
if not allowed_component_jid or allowed_component_jid == "" then
|
||||
module:log("debug", "Privilege advertisement skipped: no privileged_entity_jid configured");
|
||||
return;
|
||||
end
|
||||
if session.host ~= allowed_component_jid then
|
||||
module:log("debug", "Privilege advertisement skipped: session host %s != %s", session.host or "?", allowed_component_jid);
|
||||
return;
|
||||
end
|
||||
local msg = st.message({
|
||||
from = module.host;
|
||||
to = session.host;
|
||||
type = "normal";
|
||||
});
|
||||
msg:tag("privilege", { xmlns = xmlns_privilege })
|
||||
:tag("perm", { access = "message", type = "outgoing" }):up()
|
||||
:up();
|
||||
session.send(msg);
|
||||
module:log("info", "Advertised outgoing message privilege to %s", session.host);
|
||||
end
|
||||
|
||||
local function unwrap_forwarded_message(stanza)
|
||||
local privilege = stanza:get_child("privilege", xmlns_privilege);
|
||||
if not privilege then
|
||||
return nil;
|
||||
end
|
||||
local forwarded = privilege:get_child("forwarded", xmlns_forward);
|
||||
if not forwarded then
|
||||
return nil;
|
||||
end
|
||||
for _, tag in ipairs(forwarded.tags or {}) do
|
||||
if tag.name == "message" then
|
||||
return tag;
|
||||
end
|
||||
end
|
||||
return nil;
|
||||
end
|
||||
|
||||
local function is_carbon_delivery(inner)
|
||||
if not inner then
|
||||
return false;
|
||||
end
|
||||
return inner:get_child("sent", xmlns_carbons) ~= nil
|
||||
or inner:get_child("received", xmlns_carbons) ~= nil;
|
||||
end
|
||||
|
||||
local function deliver_carbon_to_user_sessions(bare_jid, inner)
|
||||
local user_sessions = bare_sessions[bare_jid];
|
||||
if not user_sessions then
|
||||
module:log("debug", "Privilege carbon skipped for offline user %s", bare_jid);
|
||||
return true;
|
||||
end
|
||||
local delivered = false;
|
||||
for _, session in iter_sessions(user_sessions) do
|
||||
if session.full_jid and session.send then
|
||||
local copy = st.clone(inner);
|
||||
copy.attr.to = session.full_jid;
|
||||
session.send(copy);
|
||||
delivered = true;
|
||||
end
|
||||
end
|
||||
module:log("debug", "Privilege carbon delivered user=%s delivered=%s", bare_jid, tostring(delivered));
|
||||
return true;
|
||||
end
|
||||
|
||||
local function handle_privileged_carbon(event)
|
||||
local origin, stanza = event.origin, event.stanza;
|
||||
if not origin or origin.type ~= "component" then
|
||||
return nil;
|
||||
end
|
||||
if allowed_component_jid and allowed_component_jid ~= "" and origin.host ~= allowed_component_jid then
|
||||
module:log("debug", "Ignoring privileged message from unexpected component %s", origin.host or "?");
|
||||
return nil;
|
||||
end
|
||||
|
||||
local inner = unwrap_forwarded_message(stanza);
|
||||
if not is_carbon_delivery(inner) then
|
||||
module:log("debug", "Ignoring privileged message without carbon payload from %s", origin.host or "?");
|
||||
return nil;
|
||||
end
|
||||
|
||||
local bare_to = jid_bare(inner.attr.to);
|
||||
local bare_from = jid_bare(inner.attr.from);
|
||||
if not bare_to or bare_to == "" or bare_to ~= bare_from then
|
||||
module:log("warn", "Rejected malformed privileged carbon from %s", origin.host or "?");
|
||||
return true;
|
||||
end
|
||||
if bare_to:match("@(.+)$") ~= module.host then
|
||||
module:log("debug", "Ignoring privileged carbon for remote host %s", bare_to);
|
||||
return nil;
|
||||
end
|
||||
|
||||
return deliver_carbon_to_user_sessions(bare_to, inner);
|
||||
end
|
||||
|
||||
module:hook_global("component-authenticated", function(event)
|
||||
module:log("info", "component-authenticated for %s", event.session and event.session.host or "?");
|
||||
send_privilege_advertisement(event.session);
|
||||
end);
|
||||
|
||||
module:hook("pre-message/host", handle_privileged_carbon, 10);
|
||||
module:hook("message/host", handle_privileged_carbon, 10);
|
||||
138
utilities/prosody/modules/mod_privileged_carbons.lua
Normal file
138
utilities/prosody/modules/mod_privileged_carbons.lua
Normal file
@@ -0,0 +1,138 @@
|
||||
local st = require "prosody.util.stanza";
|
||||
local jid_bare = require "prosody.util.jid".bare;
|
||||
|
||||
local xmlns_privilege = "urn:xmpp:privilege:2";
|
||||
local xmlns_forward = "urn:xmpp:forward:0";
|
||||
local xmlns_carbons = "urn:xmpp:carbons:2";
|
||||
local bare_sessions = prosody.bare_sessions;
|
||||
|
||||
local allowed_component_jid = module:get_option_string("privileged_entity_jid");
|
||||
|
||||
module:log("info", "mod_privileged_carbons loaded for host=%s privileged_entity_jid=%s", module.host or "?", allowed_component_jid or "");
|
||||
|
||||
local function iter_sessions(user_sessions)
|
||||
if not user_sessions or not user_sessions.sessions then
|
||||
return function() return nil end;
|
||||
end
|
||||
return pairs(user_sessions.sessions);
|
||||
end
|
||||
|
||||
local function unwrap_forwarded_message(stanza)
|
||||
local privilege = stanza:get_child("privilege", xmlns_privilege);
|
||||
if not privilege then
|
||||
return nil;
|
||||
end
|
||||
local forwarded = privilege:get_child("forwarded", xmlns_forward);
|
||||
if not forwarded then
|
||||
return nil;
|
||||
end
|
||||
for _, tag in ipairs(forwarded.tags or {}) do
|
||||
if tag.name == "message" then
|
||||
return tag;
|
||||
end
|
||||
end
|
||||
return nil;
|
||||
end
|
||||
|
||||
local function is_carbon_delivery(inner)
|
||||
if not inner then
|
||||
return false;
|
||||
end
|
||||
return inner:get_child("sent", xmlns_carbons) ~= nil
|
||||
or inner:get_child("received", xmlns_carbons) ~= nil;
|
||||
end
|
||||
|
||||
local function build_sent_carbon(inner, user_bare)
|
||||
local function rebuild_stanza(node)
|
||||
if type(node) ~= "table" or not node.name then
|
||||
return node;
|
||||
end
|
||||
local attr = {};
|
||||
for k, v in pairs(node.attr or {}) do
|
||||
attr[k] = v;
|
||||
end
|
||||
local rebuilt = st.stanza(node.name, attr);
|
||||
for _, child in ipairs(node) do
|
||||
if type(child) == "table" and child.name then
|
||||
rebuilt:add_direct_child(rebuild_stanza(child));
|
||||
elseif type(child) == "string" then
|
||||
rebuilt:add_direct_child(child);
|
||||
end
|
||||
end
|
||||
return rebuilt;
|
||||
end
|
||||
local copy = rebuild_stanza(inner);
|
||||
local function normalize_client_ns(node)
|
||||
if not node then
|
||||
return;
|
||||
end
|
||||
if node.attr then
|
||||
if node.attr.xmlns == nil or node.attr.xmlns == "jabber:component:accept" then
|
||||
node.attr.xmlns = "jabber:client";
|
||||
end
|
||||
end
|
||||
if node.tags then
|
||||
for _, child in ipairs(node.tags) do
|
||||
normalize_client_ns(child);
|
||||
end
|
||||
end
|
||||
end
|
||||
normalize_client_ns(copy);
|
||||
return st.message({ from = user_bare, type = inner.attr.type or "chat", xmlns = "jabber:client" })
|
||||
:tag("sent", { xmlns = xmlns_carbons })
|
||||
:tag("forwarded", { xmlns = xmlns_forward })
|
||||
:add_child(copy):reset();
|
||||
end
|
||||
|
||||
local function deliver_carbon_to_user_sessions(bare_jid, inner)
|
||||
local user_sessions = bare_sessions[bare_jid];
|
||||
if not user_sessions then
|
||||
module:log("debug", "Privileged carbon skipped for offline user %s", bare_jid);
|
||||
return true;
|
||||
end
|
||||
local carbon = build_sent_carbon(inner, bare_jid);
|
||||
local delivered = false;
|
||||
for _, session in iter_sessions(user_sessions) do
|
||||
if session.full_jid and session.send then
|
||||
local copy = st.clone(carbon);
|
||||
copy.attr.xmlns = "jabber:client";
|
||||
copy.attr.to = session.full_jid;
|
||||
session.rawsend(tostring(copy));
|
||||
delivered = true;
|
||||
end
|
||||
end
|
||||
module:log("info", "Privileged carbon delivered user=%s delivered=%s", bare_jid, tostring(delivered));
|
||||
return true;
|
||||
end
|
||||
|
||||
local function handle_privileged_carbon(event)
|
||||
local origin, stanza = event.origin, event.stanza;
|
||||
if not origin or origin.type ~= "component" then
|
||||
return nil;
|
||||
end
|
||||
if allowed_component_jid and allowed_component_jid ~= "" and origin.host ~= allowed_component_jid then
|
||||
module:log("debug", "Ignoring privileged message from unexpected component %s", origin.host or "?");
|
||||
return nil;
|
||||
end
|
||||
|
||||
local inner = unwrap_forwarded_message(stanza);
|
||||
if not inner then
|
||||
module:log("debug", "Ignoring privileged message without forwarded payload from %s", origin.host or "?");
|
||||
return nil;
|
||||
end
|
||||
|
||||
local bare_from = jid_bare(inner.attr.from);
|
||||
if not bare_from or bare_from == "" then
|
||||
module:log("warn", "Rejected malformed privileged carbon from %s", origin.host or "?");
|
||||
return true;
|
||||
end
|
||||
if bare_from:match("@(.+)$") ~= module.host then
|
||||
module:log("debug", "Ignoring privileged carbon for remote host %s", bare_from);
|
||||
return nil;
|
||||
end
|
||||
|
||||
return deliver_carbon_to_user_sessions(bare_from, inner);
|
||||
end
|
||||
|
||||
module:hook("pre-message/host", handle_privileged_carbon, 10);
|
||||
module:hook("message/host", handle_privileged_carbon, 10);
|
||||
@@ -1,5 +1,7 @@
|
||||
local env = os.getenv
|
||||
local xmpp_secret = env("XMPP_SECRET") or ""
|
||||
local xmpp_user_domain = env("XMPP_USER_DOMAIN") or "example.com"
|
||||
local xmpp_upload_base_url = env("XMPP_UPLOAD_BASE_URL") or "https://share.example.com/file_share"
|
||||
|
||||
if xmpp_secret == "" then
|
||||
error("XMPP_SECRET is required for Prosody component authentication")
|
||||
@@ -19,6 +21,7 @@ modules_enabled = {
|
||||
"saslauth";
|
||||
"tls";
|
||||
"blocklist";
|
||||
"privileged_carbons";
|
||||
"carbons";
|
||||
"dialback";
|
||||
"limits";
|
||||
@@ -34,6 +37,7 @@ modules_enabled = {
|
||||
"admin_adhoc";
|
||||
"announce";
|
||||
"http";
|
||||
"http_file_share";
|
||||
}
|
||||
|
||||
s2s_secure_auth = true
|
||||
@@ -66,7 +70,10 @@ http_external_url = "https://share.example.com/"
|
||||
|
||||
VirtualHost "example.com"
|
||||
authentication = "gia"
|
||||
http_host = "share.example.com"
|
||||
external_auth_command = "/code/utilities/prosody/auth_django.sh"
|
||||
privileged_entity_jid = env("XMPP_JID") or "jews.example.com"
|
||||
http_file_share_size_limit = 104857600
|
||||
ssl = {
|
||||
key = "/etc/prosody/certs/cert.pem";
|
||||
certificate = "/etc/prosody/certs/cert.pem";
|
||||
|
||||
85
utilities/signal/Containerfile
Normal file
85
utilities/signal/Containerfile
Normal file
@@ -0,0 +1,85 @@
|
||||
# Custom signal-cli-rest-api image with signal-cli 0.14.1
|
||||
#
|
||||
# signal-cli 0.14.1 ships pre-built as two standalone binaries:
|
||||
# signal-cli-<VER>-Linux-client.tar.gz → single file "signal-cli-client" (JVM)
|
||||
# signal-cli-<VER>-Linux-native.tar.gz → single file "signal-cli" (native/GraalVM)
|
||||
#
|
||||
# We pull the REST API Go binaries from the upstream bbernhard image and
|
||||
# layer in the 0.14.1 native binary.
|
||||
|
||||
ARG SIGNAL_CLI_VERSION=0.14.1
|
||||
ARG BBERNHARD_TAG=latest
|
||||
|
||||
# ── Stage 1: REST API binaries from upstream ───────────────────────────────
|
||||
FROM docker.io/bbernhard/signal-cli-rest-api:${BBERNHARD_TAG} AS restapi
|
||||
|
||||
# ── Stage 2: runtime image ─────────────────────────────────────────────────
|
||||
FROM ubuntu:noble
|
||||
|
||||
ARG SIGNAL_CLI_VERSION
|
||||
|
||||
ENV GIN_MODE=release
|
||||
ENV PORT=8080
|
||||
ENV SIGNAL_CLI_CONFIG_DIR=/home/.local/share/signal-cli
|
||||
ENV SIGNAL_CLI_UID=1000
|
||||
ENV SIGNAL_CLI_GID=1000
|
||||
ENV SIGNAL_CLI_CHOWN_ON_STARTUP=true
|
||||
ENV SIGNAL_CLI_REST_API_PLUGIN_SHARED_OBJ_DIR=/usr/bin/
|
||||
ENV LANG=en_US.UTF-8
|
||||
|
||||
# Runtime deps (openjdk-21 for JVM fallback, supervisor for json-rpc mode)
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
util-linux supervisor openjdk-21-jre wget curl locales \
|
||||
&& sed -i 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen \
|
||||
&& dpkg-reconfigure --frontend=noninteractive locales \
|
||||
&& update-locale LANG=en_US.UTF-8 \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Copy REST API binaries from upstream image
|
||||
COPY --from=restapi /usr/bin/signal-cli-rest-api /usr/bin/signal-cli-rest-api
|
||||
COPY --from=restapi /usr/bin/jsonrpc2-helper /usr/bin/jsonrpc2-helper
|
||||
COPY --from=restapi /usr/bin/signal-cli-rest-api_plugin_loader.so /usr/bin/signal-cli-rest-api_plugin_loader.so
|
||||
COPY --from=restapi /entrypoint.sh /entrypoint.sh
|
||||
COPY --from=restapi /etc/supervisor /etc/supervisor
|
||||
|
||||
# Download signal-cli 0.14.1 binaries.
|
||||
# The tarballs each contain a single file (no subdirectory).
|
||||
# native tarball → file named "signal-cli"
|
||||
# client tarball → file named "signal-cli-client"
|
||||
RUN mkdir -p /opt/signal-cli-${SIGNAL_CLI_VERSION}/bin \
|
||||
\
|
||||
# Native binary (GraalVM compiled, no JVM needed)
|
||||
&& wget -q "https://github.com/AsamK/signal-cli/releases/download/v${SIGNAL_CLI_VERSION}/signal-cli-${SIGNAL_CLI_VERSION}-Linux-native.tar.gz" \
|
||||
-O /opt/signal-cli-native.tar.gz \
|
||||
&& tar xzf /opt/signal-cli-native.tar.gz -C /opt/signal-cli-${SIGNAL_CLI_VERSION}/bin/ \
|
||||
&& mv /opt/signal-cli-${SIGNAL_CLI_VERSION}/bin/signal-cli \
|
||||
/opt/signal-cli-${SIGNAL_CLI_VERSION}/bin/signal-cli-native \
|
||||
&& chmod +x /opt/signal-cli-${SIGNAL_CLI_VERSION}/bin/signal-cli-native \
|
||||
&& rm /opt/signal-cli-native.tar.gz \
|
||||
\
|
||||
# JVM client (used when MODE != native, and as "signal-cli" wrapper)
|
||||
&& wget -q "https://github.com/AsamK/signal-cli/releases/download/v${SIGNAL_CLI_VERSION}/signal-cli-${SIGNAL_CLI_VERSION}-Linux-client.tar.gz" \
|
||||
-O /opt/signal-cli-client.tar.gz \
|
||||
&& tar xzf /opt/signal-cli-client.tar.gz -C /opt/signal-cli-${SIGNAL_CLI_VERSION}/bin/ \
|
||||
&& mv /opt/signal-cli-${SIGNAL_CLI_VERSION}/bin/signal-cli-client \
|
||||
/opt/signal-cli-${SIGNAL_CLI_VERSION}/bin/signal-cli \
|
||||
&& chmod +x /opt/signal-cli-${SIGNAL_CLI_VERSION}/bin/signal-cli \
|
||||
&& rm /opt/signal-cli-client.tar.gz \
|
||||
\
|
||||
# Symlinks to /usr/bin (expected by signal-cli-rest-api)
|
||||
&& ln -sf /opt/signal-cli-${SIGNAL_CLI_VERSION}/bin/signal-cli /usr/bin/signal-cli \
|
||||
&& ln -sf /opt/signal-cli-${SIGNAL_CLI_VERSION}/bin/signal-cli-native /usr/bin/signal-cli-native
|
||||
|
||||
# User + directories (mirror upstream; remove default ubuntu user first)
|
||||
RUN userdel ubuntu -r 2>/dev/null || true \
|
||||
&& groupadd -g 1000 signal-api \
|
||||
&& useradd --no-log-init -M -d /home -s /bin/bash -u 1000 -g 1000 signal-api \
|
||||
&& mkdir -p /home/.local/share/signal-cli /signal-cli-config
|
||||
|
||||
EXPOSE ${PORT}
|
||||
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
|
||||
HEALTHCHECK --interval=20s --timeout=10s --retries=3 \
|
||||
CMD curl -f http://localhost:${PORT}/v1/health || exit 1
|
||||
Reference in New Issue
Block a user