Software /
code /
prosody-modules
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); |