function loadaliasesfromfile() local env = { alias = {} } local f,err = loadfile("/etc/powerdns/updatepolicy.aliases", "t", env) if f then f() -- run the loaded code in the prepared env for safety reasons pdnslog("Successfully loaded alias config", pdns.loglevels.Debug) else pdnslog("Failed to load alias config: "..err, pdns.loglevels.Warning) end return env.alias end function getacmedomains(domain) -- Add domain as the first entry to the list local domains = {[0] = "_acme-challenge."..domain} local counter = 1 -- Load additional alias domains from config file local aliases = loadaliasesfromfile() if aliases[domain] ~= nil then for _,alias in pairs(aliases[domain]) do domains[counter] = "_acme-challenge."..alias counter = counter + 1 end end -- Return all challenge domains return domains end function updatepolicy(input) -- Check for valid TSIG key or fail local key = input:getTsigName() local keyname = nil if key == nil or not pcall(function() keyname = key:toString() end) or keyname == "" then -- fail on no key (and work around the possible odd exception with pcall) pdnslog("No TSIG key found. Update rejected.", pdns.loglevels.Error) return false end -- Process ACME keys local pos,_,domain = string.find(keyname, "^acme%-(.+)") if pos ~= nil then for _,acmedomain in pairs(getacmedomains(domain)) do pdnslog("Validating against "..acmedomain, pdns.loglevels.Debug) if input:getQType() == pdns.TXT and input:getQName():toString():lower() == acmedomain:lower() then -- valid acme key with matching domain matches name and TXT pdnslog("ACME TSIG '"..keyname.."' key found and request matches domain or known aliases. Update permitted.") return true end end -- acme key and no valid match pdnslog("ACME TSIG '"..keyname.."' key found but request does not match domain or known aliases. Update rejected.", pdns.loglevels.Error) return false end -- Process other keys with the normal default policy result pdnslog("TSIG Key '"..keyname.."' found. Update permitted.") return true end