Mercurial > 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 |
| parents | |
| children | 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); |
