Comparison

mod_audit/mod_audit.lua @ 4932:530d116b7f68

mod_audit*: modules for audit logging in prosody These are to be seen as proof-of-concept for now.
author Jonas Schäfer <jonas@wielicki.name>
date Tue, 26 Apr 2022 22:32:44 +0200
child 4933:08dea42a302a
comparison
equal deleted inserted replaced
4931:f4a9e804c457 4932:530d116b7f68
1 module:set_global();
2
3 local time_now = os.time;
4 local st = require "util.stanza";
5
6 local host_wide_user = "@";
7
8 local stores = {};
9
10 local function get_store(self, host)
11 local store = rawget(self, host);
12 if store then
13 return store
14 end
15 local store = module:context(host):open_store("audit", "archive");
16 rawset(self, host, store);
17 return store;
18 end
19
20 setmetatable(stores, { __index = get_store });
21
22
23 local function session_extra(session)
24 local attr = {
25 xmlns = "xmpp:prosody.im/audit",
26 };
27 if session.id then
28 attr.id = session.id;
29 end
30 if session.type then
31 attr.type = session.type;
32 end
33 local stanza = st.stanza("session", attr);
34 if session.ip then
35 stanza:text_tag("remote-ip", session.ip);
36 end
37 return stanza
38 end
39
40 local function audit(host, user, source, event_type, extra)
41 if not host or host == "*" then
42 error("cannot log audit events for global");
43 end
44 local user = user or host_wide_user;
45
46 local attr = {
47 ["source"] = source,
48 ["type"] = event_type,
49 };
50 if user ~= host_wide_user then
51 attr.user = user;
52 end
53 local stanza = st.stanza("audit-event", attr);
54 if extra ~= nil then
55 if extra.session then
56 local child = session_extra(extra.session);
57 if child then
58 stanza:add_child(child);
59 end
60 end
61 if extra.custom then
62 for _, child in extra.custom do
63 if not st.is_stanza(child) then
64 error("all extra.custom items must be stanzas")
65 end
66 stanza:add_child(child);
67 end
68 end
69 end
70
71 local id, err = stores[host]:append(nil, nil, stanza, time_now(), user);
72 if err then
73 module:log("error", "failed to persist audit event: %s", err);
74 return
75 else
76 module:log("debug", "persisted audit event %s as %s", stanza:top_tag(), id);
77 end
78 end
79
80 local module_api = getmetatable(module).__index;
81
82 function module_api:audit(user, event_type, extra)
83 audit(self.host, user, "mod_" .. self:get_name(), event_type, extra);
84 end
85
86 module:hook("audit", audit, 0);