# HG changeset patch # User Matthew Wild # Date 1743695654 -3600 # Node ID 02856974396a6e176a61107208f45881fbe12471 # Parent a5f6943a1abd602b70e99d0dbd3400c7181893c7# Parent 3ee95eb17045de6036107e12882069d750b4049d Merge 13.0->trunk diff -r a5f6943a1abd -r 02856974396a core/certmanager.lua --- a/core/certmanager.lua Thu Apr 03 15:14:07 2025 +0100 +++ b/core/certmanager.lua Thu Apr 03 16:54:14 2025 +0100 @@ -116,11 +116,15 @@ else log("debug", "Skipping expired certificate: %s", full); end + else + log("debug", "Skipping non-certificate (based on contents): %s", full); end f:close(); elseif err then - log("debug", "Failed to open file for indexing: %s", full); + log("debug", "Skipping file due to error: %s", err); end + else + log("debug", "Skipping non-certificate (based on filename): %s", full); end end log("debug", "Certificate index in %s: %q", dir, files_by_name); diff -r a5f6943a1abd -r 02856974396a plugins/mod_admin_shell.lua --- a/plugins/mod_admin_shell.lua Thu Apr 03 15:14:07 2025 +0100 +++ b/plugins/mod_admin_shell.lua Thu Apr 03 16:54:14 2025 +0100 @@ -2401,6 +2401,56 @@ return true, ("%d runners pending"):format(c); end +describe_command [[debug:cert_index([path]) - Show Prosody's view of a directory of certs]] +function def_env.debug:cert_index(path) + local print = self.session.print; + local cm = require "core.certmanager"; + + path = path or module:get_option("certificates", "certs"); + + local sink = logger.add_simple_sink(function (source, level, message) + if source == "certmanager" then + self.session.print(source, level, message); + end + end); + + local index = {}; + cm.index_certs(path, index) + + if not logger.remove_sink(sink) then + module:log("warn", "Unable to remove log sink"); + end + + local c, max_domain = 0, 8; + for domain in pairs(index) do + if #domain > max_domain then + max_domain = #domain; + end + end + + print(""); + + local row = format_table({ + { title = "Domain", width = max_domain }; + { title = "Certificate", width = "100%" }; + { title = "Service", width = 5 }; + }, self.session.width); + print(row()); + + for domain, certs in it.sorted_pairs(index) do + for cert_file, services in it.sorted_pairs(certs) do + for service in it.sorted_pairs(services) do + c = c + 1; + print(row({ domain, cert_file, service })); + end + end + end + + print(""); + + return true, ("Showing %d certificates in %s"):format(c, path); +end + def_env.stats = new_section("Commands to show internal statistics"); local short_units = {