From 8b780cfdd2f3e970357951026fa993603fdcd3a0 Mon Sep 17 00:00:00 2001 From: Kamil Figiela Date: Tue, 23 Feb 2021 16:20:24 +0000 Subject: [PATCH 1/2] Check if domain is whitelisted before cert renewal --- README.md | 10 +++++++--- lib/resty/acme/autossl.lua | 21 ++++++++++++++++----- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index a0475ba..2246e83 100644 --- a/README.md +++ b/README.md @@ -148,7 +148,7 @@ domain_whitelist = { "domain1.com", "domain2.com", "domain3.com" }, To match a pattern in your domain name, for example all subdomains under `example.com`, use: ```lua -domain_whitelist_callback = function(domain) +domain_whitelist_callback = function(domain, source) return ngx.re.match(domain, [[\.example\.com$]], "jo") end ``` @@ -158,7 +158,7 @@ It's possible to use cosocket API here. Do note that this will increase the SSL latency. ```lua -domain_whitelist_callback = function(domain) +domain_whitelist_callback = function(domain, source) -- send HTTP request local http = require("resty.http") local res, err = httpc:request_uri("http://example.com") @@ -169,6 +169,10 @@ domain_whitelist_callback = function(domain) end}), ``` +`domain_whitelist_callback` function is provided request source as a second argument, +which can be either `server` (on incoming HTTP request) or `update_cert` +(when certificate is generated or renewed). This allows to use cached +values on hot path (`server`) while fetching fresh data on `update_cert`. ## tls-alpn-01 challenge @@ -300,7 +304,7 @@ All normal https traffic listens on `unix:/tmp/nginx-default.sock`. ``` [stream server unix:/tmp/nginx-tls-alpn.sock ssl] - Y / + Y / [stream server 443] --- ALPN is acme-tls ? N \ [http server unix:/tmp/nginx-default.sock ssl] diff --git a/lib/resty/acme/autossl.lua b/lib/resty/acme/autossl.lua index 12b0f72..410da94 100644 --- a/lib/resty/acme/autossl.lua +++ b/lib/resty/acme/autossl.lua @@ -209,6 +209,10 @@ function AUTOSSL.update_cert(data) AUTOSSL.client_initialized = true end + if not AUTOSSL.is_domain_whitelisted(data.domain, 'update_cert') then + return "cert update is not allowed for domain " .. data.domain + end + -- Note that we lock regardless of key types -- Let's encrypt tends to have a (undocumented?) behaviour that if -- you submit an order with different CSR while the previous order is still pending @@ -260,7 +264,7 @@ function AUTOSSL.check_renew() }) if err then - log(ngx_ERR, "failed to renew certificate for domain ", domain) + log(ngx_ERR, "failed to renew certificate for domain ", domain, " error: ", err) else log(ngx_INFO, "successfully renewed ", deserialized.type, " cert for domain ", domain) end @@ -380,6 +384,16 @@ function AUTOSSL.serve_tls_alpn_challenge() AUTOSSL.client:serve_tls_alpn_challenge() end +-- source = server | update_cert +function AUTOSSL.is_domain_whitelisted(domain, source) + if domain_whitelist_callback then + return domain_whitelist_callback(domain, source) + elseif domain_whitelist then + return domain_whitelist[domain] + else + return true + end +end function AUTOSSL.ssl_certificate() local domain, err = ssl.server_name() @@ -391,10 +405,7 @@ function AUTOSSL.ssl_certificate() domain = string.lower(domain) - if domain_whitelist_callback and not domain_whitelist_callback(domain) then - log(ngx_INFO, "domain ", domain, " does not pass whitelist_callback, skipping") - return - elseif domain_whitelist and not domain_whitelist[domain] then + if not AUTOSSL.is_domain_whitelisted(domain, 'server') then log(ngx_INFO, "domain ", domain, " not in whitelist, skipping") return end From 6b98ac0f3abe2075fc77095e742649ef93fb05b4 Mon Sep 17 00:00:00 2001 From: Kamil Figiela Date: Mon, 15 Mar 2021 11:45:28 +0000 Subject: [PATCH 2/2] Use bool value --- README.md | 10 ++++------ lib/resty/acme/autossl.lua | 9 ++++----- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 2246e83..dd6b3b6 100644 --- a/README.md +++ b/README.md @@ -148,7 +148,7 @@ domain_whitelist = { "domain1.com", "domain2.com", "domain3.com" }, To match a pattern in your domain name, for example all subdomains under `example.com`, use: ```lua -domain_whitelist_callback = function(domain, source) +domain_whitelist_callback = function(domain, is_new_cert_needed) return ngx.re.match(domain, [[\.example\.com$]], "jo") end ``` @@ -158,7 +158,7 @@ It's possible to use cosocket API here. Do note that this will increase the SSL latency. ```lua -domain_whitelist_callback = function(domain, source) +domain_whitelist_callback = function(domain, is_new_cert_needed) -- send HTTP request local http = require("resty.http") local res, err = httpc:request_uri("http://example.com") @@ -169,10 +169,8 @@ domain_whitelist_callback = function(domain, source) end}), ``` -`domain_whitelist_callback` function is provided request source as a second argument, -which can be either `server` (on incoming HTTP request) or `update_cert` -(when certificate is generated or renewed). This allows to use cached -values on hot path (`server`) while fetching fresh data on `update_cert`. +`domain_whitelist_callback` function is provided with a second argument, +which indicates whether the certificate is about to be served on incoming HTTP request (false) or new certificate is about to be requested (true). This allows to use cached values on hot path (serving requests) while fetching fresh data from storage for new certificates. One may also implement different logic, e.g. do extra checks before requesting new cert. ## tls-alpn-01 challenge diff --git a/lib/resty/acme/autossl.lua b/lib/resty/acme/autossl.lua index 410da94..12ecefc 100644 --- a/lib/resty/acme/autossl.lua +++ b/lib/resty/acme/autossl.lua @@ -209,7 +209,7 @@ function AUTOSSL.update_cert(data) AUTOSSL.client_initialized = true end - if not AUTOSSL.is_domain_whitelisted(data.domain, 'update_cert') then + if not AUTOSSL.is_domain_whitelisted(data.domain, true) then return "cert update is not allowed for domain " .. data.domain end @@ -384,10 +384,9 @@ function AUTOSSL.serve_tls_alpn_challenge() AUTOSSL.client:serve_tls_alpn_challenge() end --- source = server | update_cert -function AUTOSSL.is_domain_whitelisted(domain, source) +function AUTOSSL.is_domain_whitelisted(domain, is_new_cert_needed) if domain_whitelist_callback then - return domain_whitelist_callback(domain, source) + return domain_whitelist_callback(domain, is_new_cert_needed) elseif domain_whitelist then return domain_whitelist[domain] else @@ -405,7 +404,7 @@ function AUTOSSL.ssl_certificate() domain = string.lower(domain) - if not AUTOSSL.is_domain_whitelisted(domain, 'server') then + if not AUTOSSL.is_domain_whitelisted(domain, false) then log(ngx_INFO, "domain ", domain, " not in whitelist, skipping") return end