Skip to content

Commit 23412ce

Browse files
committed
Merge branch 'Cargo-delete-dehydrated-cert-files-failures'
2 parents f66bb61 + aa018af commit 23412ce

File tree

3 files changed

+69
-49
lines changed

3 files changed

+69
-49
lines changed

lib/resty/auto-ssl/servers/hook.lua

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
local parse_openssl_time = require "resty.auto-ssl.utils.parse_openssl_time"
2-
local shell_blocking = require "shell-games"
32

43
-- This server provides an internal-only API for the dehydrated bash hook
54
-- script to call. This allows for storing the tokens or certificates in the
@@ -54,14 +53,6 @@ return function(auto_ssl_instance)
5453
ngx.log(ngx.ERR, "auto-ssl: failed to set cert: ", err)
5554
return ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
5655
end
57-
-- remove the extra copy of the certificate files in dehydrated's cert directory
58-
assert(string.find(params["domain"], "/") == nil)
59-
assert(string.find(params["domain"], "%.%.") == nil)
60-
local dir = auto_ssl_instance:get("dir") .. "/letsencrypt/certs/" .. params["domain"]
61-
local _, rm_err = shell_blocking.capture_combined({ "rm", "-rf", dir })
62-
if rm_err then
63-
ngx.log(ngx.ERR, "auto-ssl: failed to cleanup certs: ", rm_err)
64-
end
6556
else
6657
ngx.log(ngx.ERR, "auto-ssl: unknown request to hook server: ", path)
6758
return ngx.exit(ngx.HTTP_NOT_FOUND)

lib/resty/auto-ssl/ssl_providers/lets_encrypt.lua

Lines changed: 18 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ function _M.issue_cert(auto_ssl_instance, domain)
3636
"--config", base_dir .. "/letsencrypt/config",
3737
"--hook", lua_root .. "/bin/resty-auto-ssl/letsencrypt_hooks",
3838
})
39+
40+
-- Cleanup dehydrated files after running to prevent temp files from piling
41+
-- up. This always runs, regardless of whether or not dehydrated succeeds (in
42+
-- which case the certs should be installed in storage) or dehydrated fails
43+
-- (in which case these files aren't of much additional use).
44+
_M.cleanup(auto_ssl_instance, domain)
45+
3946
if result["status"] ~= 0 then
4047
ngx.log(ngx.ERR, "auto-ssl: dehydrated failed: ", result["command"], " status: ", result["status"], " out: ", result["output"], " err: ", err)
4148
return nil, "dehydrated failure"
@@ -51,40 +58,6 @@ function _M.issue_cert(auto_ssl_instance, domain)
5158
ngx.log(ngx.ERR, "auto-ssl: error fetching certificate from storage for ", domain, ": ", get_cert_err)
5259
end
5360

54-
-- If dehydrated succeeded, but we still don't have any certs in storage, the
55-
-- issue might be that dehydrated succeeded and has local certs cached, but
56-
-- the initial attempt to deploy them and save them into storage failed (eg,
57-
-- storage was temporarily unavailable). If this occurs, try to manually fire
58-
-- the deploy_cert hook again to populate our storage with dehydrated's local
59-
-- copies.
60-
if not cert or not cert["fullchain_pem"] or not cert["privkey_pem"] then
61-
ngx.log(ngx.WARN, "auto-ssl: dehydrated succeeded, but certs still missing from storage - trying to manually copy - domain: " .. domain)
62-
63-
result, err = shell_execute({
64-
"env",
65-
"HOOK_SECRET=" .. hook_secret,
66-
"HOOK_SERVER_PORT=" .. hook_port,
67-
lua_root .. "/bin/resty-auto-ssl/letsencrypt_hooks",
68-
"deploy_cert",
69-
domain,
70-
base_dir .. "/letsencrypt/certs/" .. domain .. "/privkey.pem",
71-
base_dir .. "/letsencrypt/certs/" .. domain .. "/cert.pem",
72-
base_dir .. "/letsencrypt/certs/" .. domain .. "/fullchain.pem",
73-
base_dir .. "/letsencrypt/certs/" .. domain .. "/chain.pem",
74-
math.floor(ngx.now()),
75-
})
76-
if result["status"] ~= 0 then
77-
ngx.log(ngx.ERR, "auto-ssl: dehydrated manual hook.sh failed: ", result["command"], " status: ", result["status"], " out: ", result["output"], " err: ", err)
78-
return nil, "dehydrated failure"
79-
end
80-
81-
-- Try fetching again.
82-
cert, get_cert_err = storage:get_cert(domain)
83-
if get_cert_err then
84-
ngx.log(ngx.ERR, "auto-ssl: error fetching certificate from storage for ", domain, ": ", get_cert_err)
85-
end
86-
end
87-
8861
-- Return error if things are still unexpectedly missing.
8962
if not cert or not cert["fullchain_pem"] or not cert["privkey_pem"] then
9063
return nil, "dehydrated succeeded, but no certs present"
@@ -93,4 +66,15 @@ function _M.issue_cert(auto_ssl_instance, domain)
9366
return cert
9467
end
9568

69+
function _M.cleanup(auto_ssl_instance, domain)
70+
assert(string.find(domain, "/") == nil)
71+
assert(string.find(domain, "%.%.") == nil)
72+
73+
local dir = auto_ssl_instance:get("dir") .. "/letsencrypt/certs/" .. domain
74+
local _, rm_err = shell_execute({ "rm", "-rf", dir })
75+
if rm_err then
76+
ngx.log(ngx.ERR, "auto-ssl: failed to cleanup certs: ", rm_err)
77+
end
78+
end
79+
9680
return _M

spec/sanity_spec.lua

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,52 @@ describe("sanity", function()
197197
assert.Not.matches("[emerg]", error_log, nil, true)
198198
end)
199199

200+
it("cleans up dehydrated files on certificate registration failure", function()
201+
server.start()
202+
203+
local ls_before_result, ls_before_err = shell_blocking.capture_combined({ "ls", "-1", server.current_test_dir .. "/auto-ssl/letsencrypt" })
204+
assert.equal(nil, ls_before_err)
205+
local expected_ls_before = {
206+
"conf.d",
207+
"config",
208+
"locks",
209+
}
210+
if server.dehydrated_cached_accounts then
211+
table.insert(expected_ls_before, "accounts")
212+
end
213+
table.sort(expected_ls_before)
214+
assert.same(expected_ls_before, pl_utils.split(ls_before_result["output"]))
215+
216+
local httpc = http.new()
217+
local _, connect_err = httpc:connect("127.0.0.1", 9443)
218+
assert.equal(nil, connect_err)
219+
220+
local _, ssl_err = httpc:ssl_handshake(nil, "unresolvable-sdjfklsdjf.example", true)
221+
assert.equal("18: self signed certificate", ssl_err)
222+
223+
local error_log = server.read_error_log()
224+
assert.matches("auto-ssl: issuing new certificate for unresolvable-sdjfklsdjf.example", error_log, nil, true)
225+
assert.matches("auto-ssl: dehydrated failed", error_log, nil, true)
226+
assert.matches("auto-ssl: could not get certificate for unresolvable-sdjfklsdjf.example", error_log, nil, true)
227+
assert.Not.matches("[alert]", error_log, nil, true)
228+
assert.Not.matches("[emerg]", error_log, nil, true)
229+
230+
local ls_result, ls_err = shell_blocking.capture_combined({ "ls", "-1", server.current_test_dir .. "/auto-ssl/letsencrypt" })
231+
assert.equal(nil, ls_err)
232+
assert.same({
233+
"accounts",
234+
"certs",
235+
"chains",
236+
"conf.d",
237+
"config",
238+
"locks",
239+
}, pl_utils.split(ls_result["output"]))
240+
241+
local ls_certs_result, ls_certs_err = shell_blocking.capture_combined({ "ls", "-1", server.current_test_dir .. "/auto-ssl/letsencrypt/certs" })
242+
assert.equal(nil, ls_certs_err)
243+
assert.same({}, pl_utils.split(ls_certs_result["output"]))
244+
end)
245+
200246
it("allows for custom logic to control domain name to handle lack of SNI support", function()
201247
server.start({
202248
auto_ssl_pre_new = [[
@@ -378,7 +424,7 @@ describe("sanity", function()
378424
assert.Not.matches("[emerg]", error_log, nil, true)
379425
end)
380426

381-
it("retains dehydrated temporary files if cert deployment fails", function()
427+
it("deletes dehydrated temporary files if cert deployment fails", function()
382428
server.start()
383429

384430
-- Create a directory where the storage file would normally belong so
@@ -429,9 +475,7 @@ describe("sanity", function()
429475

430476
local ls_certs_result, ls_certs_err = shell_blocking.capture_combined({ "ls", "-1", server.current_test_dir .. "/auto-ssl/letsencrypt/certs" })
431477
assert.equal(nil, ls_certs_err)
432-
assert.same({
433-
server.ngrok_hostname,
434-
}, pl_utils.split(ls_certs_result["output"]))
478+
assert.same({}, pl_utils.split(ls_certs_result["output"]))
435479

436480
assert(dir.rmtree(server.current_test_dir .. "/auto-ssl/storage/file/" .. ngx.escape_uri(server.ngrok_hostname .. ":latest")))
437481

@@ -452,8 +496,9 @@ describe("sanity", function()
452496

453497
local error_log = server.nginx_error_log_tail:read()
454498
assert.matches("auto-ssl: issuing new certificate for", error_log, nil, true)
455-
assert.matches("Checking domain name(s) of existing cert... unchanged.", error_log, nil, true)
456-
assert.matches("auto-ssl: dehydrated succeeded, but certs still missing from storage - trying to manually copy", error_log, nil, true)
499+
assert.Not.matches("[error]", error_log, nil, true)
500+
assert.Not.matches("[alert]", error_log, nil, true)
501+
assert.Not.matches("[emerg]", error_log, nil, true)
457502
end
458503

459504
local error_log = server.read_error_log()

0 commit comments

Comments
 (0)