Mercurial > prosody-modules
view mod_checkcerts/mod_checkcerts.lua @ 5571:ca3c2d11823c
mod_pubsub_feeds: Track latest timestamp seen in feeds instead of last poll
This should ensure that an entry that has a publish timestmap after the
previously oldest post, but before the time of the last poll check, is
published to the node.
Previously if an entry would be skipped if it was published at 13:00
with a timestamp of 12:30, where the last poll was at 12:45.
For feeds that lack a timestamp, it now looks for the first post that is
not published, assuming that the feed is in reverse chronological order,
then iterates back up from there.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Sun, 25 Jun 2023 16:27:55 +0200 |
parents | c8ccaac78f64 |
children |
line wrap: on
line source
local config = require "core.configmanager"; local ssl = require"ssl"; local datetime_parse = require"util.datetime".parse; local load_cert = ssl.loadcertificate; local st = require"util.stanza" -- These are in days. local nag_time = module:get_option_number("checkcerts_notify", 7) * 86400; if not load_cert then module:log("error", "This version of LuaSec (%s) does not support certificate checking", ssl._VERSION); return end local pat = "^([JFMAONSD][ceupao][glptbvyncr]) ?(%d%d?) (%d%d):(%d%d):(%d%d) (%d%d%d%d) GMT$"; local months = {Jan=1,Feb=2,Mar=3,Apr=4,May=5,Jun=6,Jul=7,Aug=8,Sep=9,Oct=10,Nov=11,Dec=12}; local function parse_x509_datetime(s) local month, day, hour, min, sec, year = s:match(pat); month = months[month]; return datetime_parse(("%04d-%02d-%02dT%02d:%02d:%02dZ"):format(year, month, day, hour, min, sec)); end local timeunits = {"minute",60,"hour",3600,"day",86400,"week",604800,"month",2629746,"year",31556952,}; local function humantime(timediff) local ret = {}; for i=#timeunits,2,-2 do if timeunits[i] < timediff then local n = math.floor(timediff / timeunits[i]); if n > 0 and #ret < 2 then ret[#ret+1] = ("%d %s%s"):format(n, timeunits[i-1], n ~= 1 and "s" or ""); timediff = timediff - n*timeunits[i]; end end end return table.concat(ret, " and ") end local function check_certs_validity() local now = os.time(); -- First, let's find out what certificate this host uses. local ssl_config = config.rawget(module.host, "ssl"); if not ssl_config or not ssl_config.certificate then ssl_config = config.get(module.host:match("%.(.*)"), "ssl"); end if not ssl_config or not ssl_config.certificate then ssl_config = config.get("*", "ssl"); end if not ssl_config or not ssl_config.certificate then module:log("warn", "Could not find a certificate to check"); return; end local certfile = ssl_config.certificate; local fh, ferr = io.open(certfile); -- Load the file. if not fh then module:log("warn", "Could not open certificate %s", ferr); return; end local cert, lerr = load_cert(fh:read("*a")); -- And parse fh:close(); if not cert then module:log("warn", "Could not parse certificate %s: %s", certfile, lerr or ""); return; end local expires_at = parse_x509_datetime(cert:notafter()); local expires_in = os.difftime(expires_at, now); local fmt = "Certificate %s expires in %s" local nag_admin = expires_in < nag_time; local log_warn = expires_in < nag_time * 2; local timediff = expires_in; if expires_in < 0 then fmt = "Certificate %s expired %s ago"; timediff = -timediff; end timediff = humantime(timediff); module:log(log_warn and "warn" or "info", fmt, certfile, timediff); if nag_admin then local body = fmt:format("for host ".. module.host, timediff); for admin in module:get_option_inherited_set("admins", {}) do module:send(st.message({ from = module.host, to = admin, type = "chat" }, body)); end end return math.max(86400, expires_in / 3); end module:add_timer(1, check_certs_validity);