Skip to content

[PLAT-2530] Test latest domain fix update #12

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 13 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Table of Contents

- [0.2.12](#0212---20201013)
- [0.2.11](#0211---20200916)
- [0.2.10](#0210---20200812)
- [0.2.9](#029---20200804)
- [0.2.8](#028---20200730)
Expand All @@ -15,6 +17,19 @@
- [0.1.1](#011---20191212)
- [0.1.0](#010---20191212)

## [0.2.12] - 2020/10/13

- Fix cache to use non-nil TTL in dbless. This fixes a bug for renewals not updating the cert
after Kong 2.0.5.
- Fix a bug in database mode the renewal config is not properly stored.

## [0.2.11] - 2020/09/16

- Add endpoint to list certificates from storage.
- Allow to pass a configurable wait time for each domain that fails in validation.
- Tweak error log and format.
- Always check with lower cased domain.
- Wrap load_certkey for dao as well.

## [0.2.10] - 2020/08/12

Expand Down Expand Up @@ -81,6 +96,8 @@ causing validation failures.
- Initial release of ACME plugin for Kong.


[0.2.12]: https://github.com/Kong/kong-plugin-acme/compare/0.2.11...0.2.12
[0.2.11]: https://github.com/Kong/kong-plugin-acme/compare/0.2.10...0.2.11
[0.2.10]: https://github.com/Kong/kong-plugin-acme/compare/0.2.9...0.2.10
[0.2.9]: https://github.com/Kong/kong-plugin-acme/compare/0.2.8...0.2.9
[0.2.8]: https://github.com/Kong/kong-plugin-acme/compare/0.2.7...0.2.8
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ config.api_uri | | `"https://acme-v02.api.letsencrypt.org/direc
config.cert_type | | `"rsa"` | The certificate type to create. The possible values are `"rsa"` for RSA certificate or `"ecc"` for EC certificate.
config.domains | | `[]` | The list of domains to create certificate for. To match subdomains under `example.com`, use `*.example.com`. Regex pattern is not supported. Note this config is only used to match domains, not to specify the Common Name or Subject Alternative Name to create certifcates; each domain will have its own certificate.
config.renew_threshold_days| | `14` | Days before expire to renew the certificate.
config.fail_backoff_minutes| | `5` | Minutes to wait for each domain that fails to create a certificate. This applies to both new certificate and renewal.
config.storage | | `"shm"` | The backend storage type to use. The possible values are `"kong"`, `"shm"`, `"redis"`, `"consul"`, or `"vault"`. In DB-less mode, `"kong"` storage is unavailable. Note that `"shm"` storage does not persist during Kong restarts and does not work for Kong running on different machines, so consider using one of `"kong"`, `"redis"`, `"consul"`, or `"vault"` in production.
config.storage_config| | (See below)| Storage configs for each backend storage.
config.tos_accepted | | `false` | If you are using Let's Encrypt, you must set this to true to agree the [Terms of Service](https://letsencrypt.org/repository/).
Expand Down
29 changes: 29 additions & 0 deletions kong-plugin-acme-0.2.12-2.rockspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package = "kong-plugin-acme"
version = "0.2.12-2"
source = {
url = "git+https://github.com/Kong/kong-plugin-acme.git",
tag = "0.2.12",
}
description = {
homepage = "https://github.com/Kong/kong-plugin-acme",
summary = "Let's Encrypt integration with Kong",
license = "Apache 2.0",
}
build = {
type = "builtin",
modules = {
["kong.plugins.acme.api"] = "kong/plugins/acme/api.lua",
["kong.plugins.acme.client"] = "kong/plugins/acme/client.lua",
["kong.plugins.acme.daos"] = "kong/plugins/acme/daos.lua",
["kong.plugins.acme.handler"] = "kong/plugins/acme/handler.lua",
["kong.plugins.acme.migrations.000_base_acme"] = "kong/plugins/acme/migrations/000_base_acme.lua",
["kong.plugins.acme.migrations.001_022_to_030"] = "kong/plugins/acme/migrations/001_022_to_030.lua",
["kong.plugins.acme.migrations.init"] = "kong/plugins/acme/migrations/init.lua",
["kong.plugins.acme.schema"] = "kong/plugins/acme/schema.lua",
["kong.plugins.acme.storage.kong"] = "kong/plugins/acme/storage/kong.lua"
}
}
dependencies = {
--"kong >= 1.2.0",
"lua-resty-acme ~> 0.5"
}
97 changes: 95 additions & 2 deletions kong/plugins/acme/api.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
local client = require "kong.plugins.acme.client"
local http = require "resty.http"

local x509 = require "resty.openssl.x509"

local function find_plugin()
for plugin, err in kong.db.plugins:each(1000) do
if err then
Expand All @@ -13,6 +15,39 @@ local function find_plugin()
end
end

local function to_hex(s)
s = s:gsub("(.)", function(s) return string.format("%02X:", string.byte(s)) end)
-- strip last ":"
return string.sub(s, 1, #s-1)
end

local function bn_to_hex(bn)
local s = bn:to_hex():gsub("(..)", function (s) return s..":" end)
-- strip last ":"
return string.sub(s, 1, #s-1)
end

local function parse_certkey(certkey)
local cert = x509.new(certkey.cert)
local key = cert:get_pubkey()

local subject_name = cert:get_subject_name()
local host = subject_name:find("CN")
local issuer_name = cert:get_issuer_name()
local issuer_cn = issuer_name:find("CN")

return {
digest = to_hex(cert:digest()),
host = host.blob,
issuer_cn = issuer_cn.blob,
not_before = os.date("%Y-%m-%d %H:%M:%S", cert:get_not_before()),
not_after = os.date("%Y-%m-%d %H:%M:%S", cert:get_not_after()),
valid = cert:get_not_before() < ngx.time() and cert:get_not_after() > ngx.time(),
serial_number = bn_to_hex(cert:get_serial_number()),
pubkey_type = key:get_key_type().sn,
}
end

return {
["/acme"] = {
POST = function(self)
Expand Down Expand Up @@ -54,7 +89,7 @@ return {
return kong.response.exit(400, { message = "problem found running sanity check for " .. host .. ": " .. err})
end

err = client.update_certificate(conf, host, nil)
local _, err = client.update_certificate(conf, host, nil)
if err then
return kong.response.exit(500, { message = "failed to update certificate: " .. err })
end
Expand All @@ -67,8 +102,66 @@ return {
end,

PATCH = function()
client.renew_certificate()
ngx.timer.at(0, client.renew_certificate)
return kong.response.exit(202, { message = "Renewal process started successfully" })
end,
},

["/acme/certificates"] = {
GET = function(self)
local plugin, err = find_plugin()
if err then
return kong.response.exit(500, { message = err })
elseif not plugin then
return kong.response.exit(404)
end

local conf = plugin.config
local renew_hosts, err = client.load_renew_hosts(conf)
if err then
return kong.response.exit(500, { message = err })
end

local data = {}
local idx = 1
for i, host in ipairs(renew_hosts) do
local certkey, err = client.load_certkey(conf, host)
if err then
return kong.response.exit(500, { message = err })
end
if not certkey then
kong.log.warn("[acme]", host, " is defined in renew_config but its cert and key is missing")
else
certkey = parse_certkey(certkey)
if not self.params.invalid_only or not certkey.valid then
data[idx] = certkey
idx = idx + 1
end
end
end
return kong.response.exit(200, { data = data })
end,
},

["/acme/certificates/:ceritificates"] = {
GET = function(self)
local plugin, err = find_plugin()
if err then
return kong.response.exit(500, { message = err })
elseif not plugin then
return kong.response.exit(404)
end

local conf = plugin.config
local host = self.params.ceritificates
local certkey, err = client.load_certkey(conf, host)
if err then
return kong.response.exit(500, { message = err })
end
if not certkey then
return kong.response.exit(404, { message = "Certificate for host " .. host .. "not found in storage" })
end
return kong.response.exit(200, { data = parse_certkey(certkey) })
end,
},
}
Loading