|
| 1 | +local cjson = require "cjson.safe" |
| 2 | +local file = require "pl.file" |
| 3 | +local http = require "resty.http" |
| 4 | +local server = require "spec.support.server" |
| 5 | +local shell_blocking = require "shell-games" |
| 6 | + |
| 7 | +describe("expiry", function() |
| 8 | + before_each(server.stop) |
| 9 | + after_each(server.stop) |
| 10 | + |
| 11 | + it("stores the expiry date on issuance", function() |
| 12 | + server.start() |
| 13 | + |
| 14 | + local httpc = http.new() |
| 15 | + local _, connect_err = httpc:connect("127.0.0.1", 9443) |
| 16 | + assert.equal(nil, connect_err) |
| 17 | + |
| 18 | + local _, ssl_err = httpc:ssl_handshake(nil, server.ngrok_hostname, true) |
| 19 | + assert.equal(nil, ssl_err) |
| 20 | + |
| 21 | + local res, request_err = httpc:request({ path = "/foo" }) |
| 22 | + assert.equal(nil, request_err) |
| 23 | + assert.equal(200, res.status) |
| 24 | + |
| 25 | + local body, body_err = res:read_body() |
| 26 | + assert.equal(nil, body_err) |
| 27 | + assert.equal("foo", body) |
| 28 | + |
| 29 | + local error_log = server.nginx_error_log_tail:read() |
| 30 | + assert.matches("issuing new certificate for " .. server.ngrok_hostname, error_log, nil, true) |
| 31 | + assert.Not.matches("auto-ssl: checking certificate renewals for " .. server.ngrok_hostname, error_log, nil, true) |
| 32 | + assert.Not.matches("failed to get the expiry date", error_log, nil, true) |
| 33 | + |
| 34 | + local cert_path = server.current_test_dir .. "/auto-ssl/storage/file/" .. ngx.escape_uri(server.ngrok_hostname .. ":latest") |
| 35 | + local content = assert(file.read(cert_path)) |
| 36 | + assert.string(content) |
| 37 | + local data = assert(cjson.decode(content)) |
| 38 | + assert.number(data["expiry"]) |
| 39 | + assert(data["expiry"] > 0, data["expiry"] .. " is not greater than 0") |
| 40 | + end) |
| 41 | + |
| 42 | + it("fills in missing expiry dates in storage from certificate expiration on renewal", function() |
| 43 | + server.start({ |
| 44 | + auto_ssl_pre_new = [[ |
| 45 | + options["renew_check_interval"] = 1 |
| 46 | + ]], |
| 47 | + }) |
| 48 | + |
| 49 | + local httpc = http.new() |
| 50 | + local _, connect_err = httpc:connect("127.0.0.1", 9443) |
| 51 | + assert.equal(nil, connect_err) |
| 52 | + |
| 53 | + local _, ssl_err = httpc:ssl_handshake(nil, server.ngrok_hostname, true) |
| 54 | + assert.equal(nil, ssl_err) |
| 55 | + |
| 56 | + local res, request_err = httpc:request({ path = "/foo" }) |
| 57 | + assert.equal(nil, request_err) |
| 58 | + assert.equal(200, res.status) |
| 59 | + |
| 60 | + local body, body_err = res:read_body() |
| 61 | + assert.equal(nil, body_err) |
| 62 | + assert.equal("foo", body) |
| 63 | + |
| 64 | + local error_log = server.nginx_error_log_tail:read() |
| 65 | + assert.matches("issuing new certificate for", error_log, nil, true) |
| 66 | + |
| 67 | + local cert_path = server.current_test_dir .. "/auto-ssl/storage/file/" .. ngx.escape_uri(server.ngrok_hostname .. ":latest") |
| 68 | + local content = assert(file.read(cert_path)) |
| 69 | + assert.string(content) |
| 70 | + local data = assert(cjson.decode(content)) |
| 71 | + local original_expiry = data["expiry"] |
| 72 | + assert.number(data["expiry"]) |
| 73 | + |
| 74 | + -- Unset the expiration time. |
| 75 | + data["expiry"] = nil |
| 76 | + assert.Nil(data["expiry"]) |
| 77 | + |
| 78 | + assert(file.write(cert_path, assert(cjson.encode(data)))) |
| 79 | + |
| 80 | + -- Wait for scheduled renewals to happen. |
| 81 | + ngx.sleep(3) |
| 82 | + |
| 83 | + error_log = server.nginx_error_log_tail:read() |
| 84 | + assert.matches("auto-ssl: checking certificate renewals for " .. server.ngrok_hostname, error_log, nil, true) |
| 85 | + assert.matches("auto-ssl: setting expiration date of " .. server.ngrok_hostname, error_log, nil, true) |
| 86 | + assert.matches("auto-ssl: expiry date is more than 30 days out, skipping renewal: " .. server.ngrok_hostname, error_log, nil, true) |
| 87 | + |
| 88 | + content = assert(file.read(cert_path)) |
| 89 | + assert.string(content) |
| 90 | + data = assert(cjson.decode(content)) |
| 91 | + assert.number(data["expiry"]) |
| 92 | + assert.equal(original_expiry, data["expiry"]) |
| 93 | + |
| 94 | + error_log = server.read_error_log() |
| 95 | + assert.Not.matches("[warn]", error_log, nil, true) |
| 96 | + assert.Not.matches("[error]", error_log, nil, true) |
| 97 | + assert.Not.matches("[alert]", error_log, nil, true) |
| 98 | + assert.Not.matches("[emerg]", error_log, nil, true) |
| 99 | + end) |
| 100 | + |
| 101 | + it("removes cert if expiration has expired and renewal fails", function() |
| 102 | + server.start({ |
| 103 | + auto_ssl_pre_new = [[ |
| 104 | + options["renew_check_interval"] = 1 |
| 105 | + ]], |
| 106 | + }) |
| 107 | + |
| 108 | + local httpc = http.new() |
| 109 | + local _, connect_err = httpc:connect("127.0.0.1", 9443) |
| 110 | + assert.equal(nil, connect_err) |
| 111 | + |
| 112 | + local _, ssl_err = httpc:ssl_handshake(nil, server.ngrok_hostname, true) |
| 113 | + assert.equal(nil, ssl_err) |
| 114 | + |
| 115 | + local res, request_err = httpc:request({ path = "/foo" }) |
| 116 | + assert.equal(nil, request_err) |
| 117 | + assert.equal(200, res.status) |
| 118 | + |
| 119 | + local body, body_err = res:read_body() |
| 120 | + assert.equal(nil, body_err) |
| 121 | + assert.equal("foo", body) |
| 122 | + |
| 123 | + local error_log = server.nginx_error_log_tail:read() |
| 124 | + assert.matches("issuing new certificate for", error_log, nil, true) |
| 125 | + |
| 126 | + local cert_path = server.current_test_dir .. "/auto-ssl/storage/file/" .. ngx.escape_uri(server.ngrok_hostname .. ":latest") |
| 127 | + local content = assert(file.read(cert_path)) |
| 128 | + assert.string(content) |
| 129 | + local data = assert(cjson.decode(content)) |
| 130 | + assert.number(data["expiry"]) |
| 131 | + |
| 132 | + -- Set the expiration time to some time in the past. |
| 133 | + data["expiry"] = 1000 |
| 134 | + |
| 135 | + assert(file.write(cert_path, assert(cjson.encode(data)))) |
| 136 | + |
| 137 | + -- Wait for scheduled renewals to happen. |
| 138 | + ngx.sleep(3) |
| 139 | + |
| 140 | + error_log = server.nginx_error_log_tail:read() |
| 141 | + assert.matches("auto-ssl: checking certificate renewals for " .. server.ngrok_hostname, error_log, nil, true) |
| 142 | + assert.matches("Skipping renew!", error_log, nil, true) |
| 143 | + |
| 144 | + -- Since this cert renewal is still valid, it should still remain despite |
| 145 | + -- being marked as expired. |
| 146 | + content = assert(file.read(cert_path)) |
| 147 | + assert.string(content) |
| 148 | + data = assert(cjson.decode(content)) |
| 149 | + assert.number(data["expiry"]) |
| 150 | + |
| 151 | + -- Copy the cert to an unresolvable domain to verify that failed renewals |
| 152 | + -- will be removed. |
| 153 | + local unresolvable_cert_path = server.current_test_dir .. "/auto-ssl/storage/file/" .. ngx.escape_uri("unresolvable-sdjfklsdjf.example:latest") |
| 154 | + local _, cp_err = shell_blocking.capture_combined({ "cp", "-p", cert_path, unresolvable_cert_path }) |
| 155 | + assert.equal(nil, cp_err) |
| 156 | + |
| 157 | + -- Wait for scheduled renewals to happen. |
| 158 | + ngx.sleep(5) |
| 159 | + |
| 160 | + error_log = server.nginx_error_log_tail:read() |
| 161 | + assert.matches("auto-ssl: checking certificate renewals for " .. server.ngrok_hostname, error_log, nil, true) |
| 162 | + assert.matches("Skipping renew!", error_log, nil, true) |
| 163 | + assert.matches("auto-ssl: checking certificate renewals for unresolvable-sdjfklsdjf.example", error_log, nil, true) |
| 164 | + assert.matches("Ignoring because renew was forced!", error_log, nil, true) |
| 165 | + assert.matches("Name does not end in a public suffix", error_log, nil, true) |
| 166 | + assert.matches("auto-ssl: issuing renewal certificate failed: dehydrated failure", error_log, nil, true) |
| 167 | + assert.matches("auto-ssl: existing certificate is expired, deleting: unresolvable-sdjfklsdjf.example", error_log, nil, true) |
| 168 | + |
| 169 | + -- Verify that the valid cert still remains (despite being marked as |
| 170 | + -- expired). |
| 171 | + content = assert(file.read(cert_path)) |
| 172 | + assert.string(content) |
| 173 | + data = assert(cjson.decode(content)) |
| 174 | + assert.number(data["expiry"]) |
| 175 | + |
| 176 | + -- Verify that the failed renewal gets deleted. |
| 177 | + local file_content, file_err = file.read(unresolvable_cert_path) |
| 178 | + assert.equal(nil, file_content) |
| 179 | + assert.matches("No such file or directory", file_err, nil, true) |
| 180 | + |
| 181 | + error_log = server.read_error_log() |
| 182 | + assert.Not.matches("[alert]", error_log, nil, true) |
| 183 | + assert.Not.matches("[emerg]", error_log, nil, true) |
| 184 | + end) |
| 185 | +end) |
0 commit comments