fffonion / lua-resty-acme Goto Github PK
View Code? Open in Web Editor NEWAutomatic Let's Encrypt certificate serving and Lua implementation of ACMEv2 procotol
Automatic Let's Encrypt certificate serving and Lua implementation of ACMEv2 procotol
Hi, this my config redis
init_by_lua_block {
require("resty.acme.autossl").init({
tos_accepted = true,
account_email = "[email protected]",
api_uri = "https://acme.zerossl.com/v2/DV90",
eab_kid = "key",
eab_hmac_key = "key",
challenge_start_delay = 0,
storage_adapter = "redis",
storage_config = {
host = '127.0.0.1',
port = 6379,
database = 5,
auth = 'password',
},
},{
api_uri = "https://acme.zerossl.com/v2/DV90",
})
}
But it does not work
first of all, awesome job. thanks for your kind work 👍 .
I need to check domain certkey exists or not, but I found this method only private.
It would be very convenient if this method can be exposed.
local autossl = require("resty.acme.autossl")
local certkey, err = autossl.get_certkey({domain=ngx.var.server_name, type="rsa"})
if certkey and scheme == http then
ngx.redirect(new_uri, 301)
end
-- I had to hack autoss.lua to make this work
-- make get_certkey visible
AUTOSSL.get_certkey = get_certkey
Hi,
I am trying to invoke the lua-resty-acme library from kong
using the acme plugin . I have been successfully using this workflow with LetsEncrypt for a long time now. Recently, I have started to hit rate limit concerns from letsencrypt and have been investigating switching over to a paid CA. My overall goal is to use this same kong
+ lua-resty-acme
workflow with ZeroSSL. Howver, it is not working.
Originally I was specifying EAB credentials into client initialization acme.new
. This was getting the error:
2022/06/27 16:13:17 [error] 20949#0: *1900 [kong] handler.lua:118 failed to update certificate: eab_handler undefined while EAB is required by CA, context: ngx.timer, client: 205.209.24.227, server: 0.0.0.0:443
I believe this is because I have provided the eab credentials in the config, this handler is unable to be loaded due to this condition here. Because the eab_handler is not set here, later in the execution flow, there is a condition that explicitly requires the eab handler here. This causes the error log that I am seeing.
Overall - I think this is because I am specifying EAB credentials and then also invoking the acme_client:new_account()
. From the ZeroSSL discovery at https://acme.zerossl.com/v2/DV90
, clearly "externalAccountRequired" = true
and so I orignally thought that I needed to provied external EAB credentials. This was probably my initial misundersanding of the role of the EAB credentials.
In any case, I tried removed the eab_kid
and eab_hmac_key
from the acme client instantiation and instead let the account (and credentials) be created by the handler in the library.
From the logs, the zerossl eab handler is successfully creating eab credentials (I assume that these credentials are related to my account through the account_email though I am not sure.). The error occurs in the first request to the acme server that needs to use the credentials to create an account. Following the logs, the library injects some JWS stuff into the request which includes the credentials generated in the previous step.
2022/06/27 17:23:45 [debug] 30427#0: *802 [acme] client.lua:259: jws payload: {"payload":{"termsOfServiceAgreed":true,"contact":["mailto:[email protected]"],"externalAccountBinding":{"protected":"eyJraWQiOiJKUVNqQmVqNjVDdmdxdGhRZW1DTjRnIiwiYWxnIjoiSFMyNTYiLCJ1cmwiOiJodHRwczpcL1wvYWNtZS56ZXJvc3NsLmNvbVwvdjJcL0RWOTBcL25ld0FjY291bnQifQ","payload":"eyJrdHkiOiJSU0EiLCJlIjoiQVFBQiIsIm4iOiJyTlhzRFJWQU9DV1RKNU1ZbUY2am1RZTRNNmJyUUMxa0Iycng2RVZXd0xHZ1B6d3FkLUhzZEZzTFRPb0ZuU240Q0lnRXM4MXgzLXRlQkhVLVZ6dnRMOGNDYVR2RTB2THd6N0xKcEtHYnF1eThhZEJpSUJGUEJubTZaQVBLaDRUNFI0OVpwQTV5eTZiNDBaZ1BIMUJlNk5idXR4U2QwQVBWSlNYcjhlbWhKYTg4SkZKSW9LRDZyRGVRUU1tTnRLY2dRQnd6ZEpnSzlWVWR1OG5HUzJKTGFjZEFRQ3NpY1h0XzdQTm9jLVJBQTdXdnpkMGszbURITXRxNU9mMWNtV2lxMTFxUHZVSGNpLUM5eEVoaDVwV3BIT3pDV2x4TDRsOTB6Wnp4SUtobXJRbjkwU0FzZFZtMUdzSmlQZVVxNHR5Snp5VXFQWkN5UWdCeHZOQ1V2VDg1akZpdzI0SGxPLTNQOHRkNW9nLTFDYkpGZnZQUWN3V2ZtN2pJZXVnVE1fV1dKNDNOX1ZrY2FLOElvdlhRSDlkVm42YlppMWFfUzk5X2diQ2syWVRIVlJiWVZYNmZZY042aUw2Zmc5cldEWmxvcjl4Qi1zdFZ3TzZmNFpEV2w3UzBlbGJiTDhhUU1qclFGZmhreGJ3dVkxVVp6MDZ6eW16bl9MT1lGNVdTOGFpVW5fUzQ5ZF92LTdNWFY2RkNXR1JTdmZqQ3g3ZjNVdGdaUHozRFQwTzZ1WlBPOENYSVdPeXpkZWpkN0pTVzZEZUcwNzJwQUZRXzJWRTR4U05kQUppOTM5OEZKdUIyRmdiblNEaEpfQmxyUmw2d3RaMzc5a3poM3lHTERjdTdPaG9LRGluTEVnSklLUXpwS2lGblA2RE83MFFXVEdpMmVVajlpRy1XQWRPaFBUVSJ9","signature":"kXv0CIP3tXrEY5WiJi6VrzXm2EAlrE--SfskgfFlwoE"}},"protected":{"jwk":{"kty":"RSA","e":"AQAB","n":"rNXsDRVAOCWTJ5MYmF6jmQe4M6brQC1kB2rx6EVWwLGgPzwqd-HsdFsLTOoFnSn4CIgEs81x3-teBHU-VzvtL8cCaTvE0vLwz7LJpKGbquy8adBiIBFPBnm6ZAPKh4T4R49ZpA5yy6b40ZgPH1Be6NbutxSd0APVJSXr8emhJa88JFJIoKD6rDeQQMmNtKcgQBwzdJgK9VUdu8nGS2JLacdAQCsicXt_7PNoc-RAA7Wvzd0k3mDHMtq5Of1cmWiq11qPvUHci-C9xEhh5pWpHOzCWlxL4l90zZzxIKhmrQn90SAsdVm1GsJiPeUq4tyJzyUqPZCyQgBxvNCUvT85jFiw24HlO-3P8td5og-1CbJFfvPQcwWfm7jIeugTM_WWJ43N_VkcaK8IovXQH9dVn6bZi1a_S99_gbCk2YTHVRbYVX6fYcN6iL6fg9rWDZlor9xB-stVwO6f4ZDWl7S0elbbL8aQMjrQFfhkxbwuY1UZz06zymzn_LOYF5WS8aiUn_S49d_v-7MXV6FCWGRSvfjCx7f3UtgZPz3DT0O6uZPO8CXIWOyzdejd7JSW6DeG072pAFQ_2VE4xSNdAJi9398FJuB2FgbnSDhJ_BlrRl6wtZ379kzh3yGLDcu7OhoKDinLEgJIKQzpKiFnP6DO70QWTGi2eUj9iG-WAdOhPTU"},"url":"https:\/\/acme.zerossl.com\/v2\/DV90\/newAccount","alg":"RS256","nonce":"4M4Zycv7nLVzo1YX_CnhM7fEMIG40OJx3T0jckTnyV8"}}
2022/06/27 17:23:52 [debug] 30427#0: *802 [acme] client.lua:305: acme request: https://acme.zerossl.com/v2/DV90/newAccount response: {"type":"urn:ietf:params:acme:error:unauthorized","status":401,"detail":"The Request URL in the JWS Protected Header does not match the actual Request URL"}
2022/06/27 17:00:02 [error] 28754#0: *163 [kong] handler.lua:118 failed to update certificate: failed to create account: The Request URL in the JWS Protected Header does not match the actual Request URL, context: ngx.timer, client: 205.209.24.227, server: 0.0.0.0:443
Parsing the logs, you can see that the request is going to https://acme.zerossl.com/v2/DV90/newAccount
but the information in the protected section of the payload has that the url is https:\/\/acme.zerossl.com\/v2\/DV90\/newAccount
.
Is this an error with the jws encoding that is happening? Am I misunderstanding the role of the EAB credentials? What is the recommended approach to generated certificates throug ZeroSSL?
Thank you so much for your help!
Hi, I config for openresty, but when I request domain Nginx log error
2022/08/02 02:17:58 [error] 12907#12907: *35 [acme] autossl.lua:224: error during acme init: acme directory request failed: 20: unable to get local issuer certificate, context: ngx.timer, client: 14.161.31.54, server: 0.0.0.0:443
2022/08/02 02:17:58 [error] 12907#12907: *39 lua ssl certificate verify error: (20: unable to get local issuer certificate), context: ngx.timer, client: 14.161.31.54, server: 0.0.0.0:443
This is my config
require("resty.acme.autossl").init({
tos_accepted = true,
account_email = "",
api_uri = "https://acme.zerossl.com/v2/DV90",
eab_kid = "",
eab_hmac_key = "",
})
How to fix it.
Thank you so much for your help!
Hello
storage file not work
storage_adapter = "file",
storage_config = {
dir = '/etc/openresty/storage',
},
cert not get and not save.
Can I add domains to domain_whitelist
without restarting OpenResty or reloading the config?
I'm new to Lua but maybe since domain_whitelist
is a "metatable", one can define an __index()
function: (see http://lua-users.org/wiki/MetatableEvents )
__index - Control 'prototype' inheritance. When accessing "myTable[key]" and the key does not appear in the table, but the metatable has an __index property:
if the value is a function, the function is called, passing in the table and the key; the return value of that function is returned as the result
Could such an __index
function use lua-resty-http
and ask my app server if the new domain is allowed? Sth like:
domain_whitelist = setmetatable({}, { __index = function(_, k)
return lua-resty-http.askMyAppServerIfDomainAllowed(k)
end}),
***
The other project, lua-resty-autossl, has an allow-domain()
callback, and apparently one can query Redis dynamically from it:
When using the Redis storage adapter, you can access the current Redis connection inside the allow_domain callback by accessing auto_ssl.storage.adapter:get_connection().
Hi,
We're looking at using this internally and I was wondering around the order of actions in ssl_certificate
At present you check if the certificate is whitelisted before serving the certificate.
Is there any reason why you don't swap those two actions around?
IE
This seems it would solve the issues around the slower times when using dynamic whitelists as it would only be checked if there isn't a valid certificate.
Whilst working on #20 I noted that errors aren't being returned in update_cert_handler
lua-resty-acme/lib/resty/acme/autossl.lua
Lines 173 to 190 in 35fbb9c
The code is relying on that error for further down
lua-resty-acme/lib/resty/acme/autossl.lua
Lines 223 to 228 in 35fbb9c
Question:
( Now finally trying out lua-resty-acme :- )
8 months after my last topic: #5 "Differences from lua-resty-auto-ssl" )
The lua-resty-acme installation — it's basically just opm
downloading files and placing in /usr/local/openresty/site/
typically?
But does not involve things like compiling C code?
Background: I'd like my OpenResty Docker image to build offline, including installing lua-resty-acme without any Internet access.
However, lua-resty-acme is installed via opm
which, it seems to me, wants to download the package plus dependencies, from a server somewhere (default opm.openresty.org
, right).
I found a "workaround" — and I wonder what do you think about it? Would you expect lua-resty-acme to function properly, after having gotten installed as described below? (For example, if opm
compiles any C code as part of installing lua-resty-acme, then, that wouldn't happen )
From inside the Docker image (launched as a container), I ran tree
to get a list of the files in the Docker image.
Then, installed: opm install fffonion/lua-resty-acme
I ran tree
again. And then diffed files after, with files before. Apparently opm
installed lua-resty-acme and dependencies in /usr/local/openresty/site
.
I copied that site/
dir from the container filesystem, to the host filesystem.
Now in the Dockerfile, I just COPY
that site/
dir into the Docker image, instead of runnig opm install ...
. — So, no network access needed.
I've tried this a little bit, seems to work fine — but I'm thinking it can be good to ask if you can think of problems with this approach?
(To upgrade, I'd just run opm install ...
again, and repeat the steps above.)
( Sorry if maybe this is off-topic. Maybe could also ask the opm
people. However, I'm thinking this is a bit specific to lua-resty-acme in that this depends on what installation steps it does and doesn't.)
我准备使用的域名是foo.example.com
. 我期望的按官网配置部署到生产服务器上之后, 访问这个网站就应该显示lets encrypt的https.
我尝试源码打log,require("resty.acme.autossl").init
是成功了的,比如
{
/*7fb97f9d9ed8*/
account_pkey : {
/*7fb97fb096f0*/
buf : "cdata<unsigned char [?]>: 0x7fb97fb25b28",
buf_size : 512,
ctx : "cdata<struct evp_pkey_st *>: 0x55f0fab6fb70",
key_type : 6,
key_type_is_ecx: false,
},
account_thumbprint: "tOQBt1lI_7wTbeVzZlcWa6ImndYUA76kfvAUW3v9QJ8",
challenge_handlers: {
/*7fb97f9d9f20*/
"http-01": {
/*7fb97f9dba78*/
storage : {
/*7fb97f9dabd0*/
shm: [
/*7fb9804e6958*/
"userdata: 0x7fb9804e69e0",
],
},
uri_prefix: "acme-challenge",
},
},
conf : {
/*7fb97f9d9a78*/
account_email : "[email protected]",
account_key : "-----BEGIN PRIVATE KEY-----\nbasdfsfds\n-----END PRIVATE KEY-----\n",
api_uri : "https://acme-staging-v02.api.letsencrypt.org/directory",
challenge_start_callback : "function: 0x7fb97f9d9af8",
enabled_challenge_handlers: [
/*7fb97f9d8e40*/
"http-01",
],
storage_adapter : "resty.acme.storage.shm",
storage_config : {
/*7fb97f9d8dc0*/
shm_name: "acme",
},
},
eab_required : false,
storage : {/*7fb97f9dabd0*/},
}
{
/*7ff2fa6ba140*/
account_email : "[email protected]",
account_key_path: "conf/account.key",
domain_whitelist: {
/*7ff2fa76c9c8*/
1 : "foo.example.com",
"foo.example.com": true,
},
staging : true,
storage_adapter : "resty.acme.storage.shm",
tos_accepted : true,
}
Hi Wangchong @fffonion
Nice with automatic https for Nginx / OpenResty :- )
Can I ask, 1) what are the differences between this project, lua-resty-acme and https://github.com/auto-ssl/lua-resty-auto-ssl ? And 2) what are the reasons this is a different project than lua-resty-auto-ssl (instead of building on lua-resty-auto-ssl)?
Some differences I noticed: This project can be installed using opm (OpenResty Package Manager), and supports more storages: Valut and Consul too. And this project supports tls-alpn-01 — maybe lua-resty-auto-ssl doesn't? (didn't see -alpn- mentioned in that project)
During certificate renewal, a list() operation is done on the storage to get all the certificates. While it is rare that local storage might throw any error on the list operation, a storage like consul might have errors on this operation: for example here.
So what is happening right now when there is an error in the list operation is
nil, err
as outputkeys
, which is nilkeys
is nillist()
operation failed is lostInstead what should happen is
nil, err
require("resty.acme.autossl").init({
staging = true,
tos_accepted = true,
domain_key_types = {'ecc'},
challenge_start_delay = 300,
renew_threshold = 7 * 86400,
renew_check_interval = 24 * 3600,
account_email = "[email protected]",
account_key_path = "/etc/openresty/account.key",
enabled_challenge_handlers = { 'dns-01' },
api_uri = "https://acme-v02.api.letsencrypt.org/directory",
domain_whitelist = domains_whitelist,
dns_provider_accounts = {
{
name = "cloudflare_prod",
provider = "cloudflare",
secret = "<apikey of cloudflare>",
domains = domains_whitelist,
},
},
})
At present the Unit tests are a bit haphazard. Based off reading the latest logs quite a few of the problems appear to be around frp.
I had a few options on what could be done to make this more consistent / easier for people to join.
Positives?
Negatives
Positives
Negatives
Maybe it would be best to do a combination of both.
Pebble sidecar runs on forks so no setup is required on people doing work for forks etc before creating MRs.
MRs run against the staging LE server using either frp or ngrok
Would like your thoughts on this and if you want to look at going down either of these paths @fffonion !
If file-system is used as storage for cert, the only reason why getting certificate from storage fails is because the certificate does not exist in the first place. If it is a storage system like vault, it can fail due to networking errors, timeout due to vault being busy etc. Not serving a certificate when this happens would result in HTTPS connection errors.
So it makes sense that we provide stale certificate from cache, if it is present, when the request to get certificate from storage fails. Just logging errors would be enough. This way we can improve the reliability of the HTTPS requests.
Do I have to call the zeroSSL lua file in the eab_handler
config?
Hello,
The documentation says that we can configure other storage, and points to this part:
https://docs.konghq.com/hub/kong-inc/acme/#storage-config
But I'm not sure how I'm supposed to write a record type in DB-less (yaml format).
I tried this:
plugins:
- name: acme
config:
account_email: mymail
cert_type: ecc
domains: ["*.mydomain"]
tos_accepted: true
storage: vault
storage_config:
host: myvault
port: 443
token: mytoken
kv_path: mypath
but I got this parsing error:
2022/08/01 14:29:18 [error] 169559#0: init_by_lua error: /usr/local/share/lua/5.1/kong/init.lua:553: error parsing declarative config file /etc/kong/kong.yml:
in 'plugins':
- in entry 1 of 'plugins':
in 'config':
in 'storage_config':
in 'kv_path': unknown field
in 'token': unknown field
in 'host': unknown field
in 'port': unknown field
Did I miss some part of the documentation?
i use storage_adapter redis and trying to setup tls-alpn-01 challenge.
but at start I get an error:
stack traceback:
[C]: in function 'error'
...al/openresty/luajit/share/lua/5.1/resty/acme/autossl.lua:344: in function 'init'
init_worker_by_lua:2: in main chunk
patch cross-module is needed anyway?
Since some time, my certificates have stopped updating. I error log I see such error for all my domains:
[lua] autossl.lua:174: update_cert_handler(): error updating cert for domain.com err: failed to create new order: can't get new nonce from acme server, context: ngx.timer
I tried to get nonce by hand and it works:
# curl -k -I https://acme-v02.api.letsencrypt.org/acme/new-nonce
HTTP/2 200
server: nginx
date: Wed, 12 May 2021 08:21:14 GMT
cache-control: public, max-age=0, no-cache
link: <https://acme-v02.api.letsencrypt.org/directory>;rel="index"
replay-nonce: 0103MSkULKV6LUWKI59T_afSuNeQRtcuI5Wp6NEtPRgZ-Bs
x-frame-options: DENY
strict-transport-security: max-age=604800
Also I found that from Jan 17 response code for HEAD request changed from 204 to 200 but as I see in client.lua you don't check the response code.
Hi,
I'm not sure where the problem is but when trying to whitelist and issue certificate for subdomain with underscore symbol _
issuing fails with the fallowing error:
[error] 23251#23251: *2978 [acme] autossl.lua:189: error updating cert for smart_panel.example.com err: failed to create new order: Error creating new order :: Cannot issue for "smart_panel.example.com ": Domain name contains an invalid character, context: ngx.timer, client ...
end whenever I drop _ symbol everything works as expected.
对于泛解析证书来说, dns-01 是唯一的验证方式,是出于什么原因没有支持吗?
Hi folks,
Thank you for this awesome package! I have a quick question: is it possible to check for the existence in the domain certs in the cache from within the domain_whitelist_callback function?
The idea is that we'd query our domain whitelist endpoint only if certs can't be found in cache, to improve performance.
Since certs are cached for 1h, it means a domain previously whitelisted but no longer whitelisted will still get its certs served for 1h, but that's acceptable compared to the performance gain.
I have configured package according to the docs and yet any domain i point to this server gets a certificate
resolver 127.0.0.53 ipv6=off;
init_by_lua_block {
require("resty.acme.autossl").init({
tos_accepted = true,
enabled_challenge_handlers = { 'http-01', 'tls-alpn-01' },
account_key_path = "/etc/openresty/account.key",
account_email = "[email protected]",
domain_whitelist = { "kust.domain.tld", "another.tld", "domain.tld" },
})
}
init_worker_by_lua_block {
require("resty.acme.autossl").init_worker()
}
include mime.types;
default_type application/application-json;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
access_log /var/log/openresty/access.log;
error_log /var/log/openresty/error.log;
gzip on;
server {
listen 80;
listen 443 ssl;
server_name _;
lua_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;
lua_ssl_verify_depth 2;
ssl_certificate /etc/letsencrypt/live/domain.tld/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/domain.tld/privkey.pem;
ssl_certificate_by_lua_block {
require("resty.acme.autossl").ssl_certificate()
}
location /.well-known {
content_by_lua_block {
require("resty.acme.autossl").serve_http_challenge()
}
}
location / {
proxy_pass http://10.110.0.2:3000;
}
}
}
openresty v: 1.19.3.1 with opm
When I point diffferent.tld or sub.domain.tld to gateway it still gets certificate, besides not being in the whitelist.
what I might be doing wrong?
Installed lua-resty-acme using opm, configuring it according to the readme, getting the following errors:
2020/02/09 18:08:21 [error] 23589#23589: *12 lua entry thread aborted: runtime error: /usr/local/openresty/site/lualib/resty/acme/util.lua:63: attempt to concatenate local 'err' (a boolean value)
stack traceback:
coroutine 0:
/usr/local/openresty/site/lualib/resty/acme/util.lua: in function 'create_csr'
/usr/local/openresty/site/lualib/resty/acme/client.lua:423: in function 'order_certificate'
/usr/local/openresty/site/lualib/resty/acme/autossl.lua:169: in function 'update_cert_handler'
/usr/local/openresty/site/lualib/resty/acme/autossl.lua:219: in function 'update_cert'
/usr/local/openresty/site/lualib/resty/acme/autossl.lua:388: in function </usr/local/openresty/site/lualib/resty/acme/autossl.lua:385>, context: ngx.timer, client: 1.1.1.1, server: 0.0.0.0:443
2020/02/09 18:43:22 [error] 23802#23802: *12 lua entry thread aborted: runtime error: /usr/local/openresty/site/lualib/resty/acme/util.lua:63: attempt to concatenate local 'err' (a boolean value)
stack traceback:
coroutine 0:
/usr/local/openresty/site/lualib/resty/acme/util.lua: in function 'create_csr'
/usr/local/openresty/site/lualib/resty/acme/client.lua:423: in function 'order_certificate'
/usr/local/openresty/site/lualib/resty/acme/autossl.lua:169: in function 'update_cert_handler'
/usr/local/openresty/site/lualib/resty/acme/autossl.lua:219: in function 'update_cert'
/usr/local/openresty/site/lualib/resty/acme/autossl.lua:388: in function </usr/local/openresty/site/lualib/resty/acme/autossl.lua:385>, context: ngx.timer, client: 1.1.1.1, server: 0.0.0.0:443
2020/02/09 18:45:08 [error] 23802#23802: *10 lua entry thread aborted: runtime error: ...l/openresty/site/lualib/resty/acme/challenge/http-01.lua:37: attempt to index local 'captures' (a nil value)
stack traceback:
coroutine 0:
...l/openresty/site/lualib/resty/acme/challenge/http-01.lua: in function 'serve_challenge'
/usr/local/openresty/site/lualib/resty/acme/client.lua:446: in function 'serve_http_challenge'
/usr/local/openresty/site/lualib/resty/acme/autossl.lua:342: in function 'serve_http_challenge'
content_by_lua(myserver.tld.conf:30):2: in main chunk, client: 1.1.1.1, server: myserver.tld, request: "GET /.well-known HTTP/2.0", host: "myserver.tld"
May this be a misconfiguration or a bug?
tls-alpn-01
challenge is currently failing with fhe following error.
challenge invalid: tls-alpn-01: invalid: Incorrect validation certificate for tls-alpn-01 challenge.
Requested <domain> from <letsencrypt_ip>:443. Received 1 certificate(s), first certificate had names ""
The error location seems to be this in boulder:
The error is basically that it could not get any of the DNS Subject Alternetive Names. Boulder expects exactly one DNS SAN with the same name as the domain name.
When you look at the golang crypto/x509 code, the dns names will be parsed only if the version is 3.
We are not setting any version in tls-alpn-01.lua
. Which means the version is 1. Setting the version as 3 might fix this issue
When you use openssl, you can clearly see the DNS SANs.
$ echo | openssl s_client -alpn acme-tls/1 -connect <domain>:443 2>/dev/null | openssl x509 -text -noout
Certificate:
Data:
Version: 1 (0x0)
Serial Number: 0 (0x0)
Signature Algorithm: sha256WithRSAEncryption
Issuer:
Validity
Not Before: Sep 3 06:00:21 2021 GMT
Not After : Sep 3 06:00:21 2021 GMT
Subject:
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
Modulus:
00:c5:83:b4:53:03:0d:1d:d8:70:75:fa:1c:c2:8b:
77:23:40:a5:3d:3b:e9:32:45:96:7e:88:19:3c:99:
77:d1:1f:af:52:58:27:c5:f6:d3:d9:b8:b9:3a:7d:
2e:13:3d:a4:2b:62:28:1c:b0:89:9c:b7:db:8c:5f:
64:3a:9e:58:06:ae:b6:a0:63:86:d8:72:f1:e2:e6:
a0:41:54:28:b0:cf:a4:f9:e5:48:e1:d3:51:e8:f0:
23:8f:58:7a:8d:77:33:80:bd:00:40:d8:4d:a1:a3:
81:43:45:a1:e4:36:3e:58:b5:ab:cb:3a:38:3c:81:
b4:bc:38:27:9b:b3:67:37:37:1d:aa:26:d6:63:14:
ad:45:ed:d9:f4:dd:9b:c8:db:a6:1e:ab:64:72:13:
5a:88:c9:e7:e2:0d:b8:a3:4f:58:c0:b2:b8:ed:45:
30:4c:e0:e4:e0:a1:50:1e:d0:f8:6f:8a:95:94:c5:
b5:a9:45:ac:e9:fa:61:3e:67:5d:19:e0:4f:fc:6b:
66:7d:96:87:7a:f3:a1:65:7f:5c:67:ac:d1:f3:66:
91:1d:2b:a2:49:ca:74:34:0e:ea:53:45:98:57:28:
49:3b:71:8d:ca:8a:00:85:cc:ba:54:c5:ab:30:75:
42:c8:75:fa:cc:6a:5d:c7:b9:84:2e:7c:a7:b2:b7:
29:9b
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Alternative Name:
DNS:<domain>
..................: critical
...........................
Signature Algorithm: sha256WithRSAEncryption
59:5d:60:59:3c:31:a9:c5:db:84:e4:92:57:bd:d0:e8:42:53:
9f:8d:75:cd:d4:ec:89:e9:66:95:35:a1:3a:5d:8d:b7:9c:2f:
8e:86:f5:bc:0e:7a:bf:80:40:58:85:e3:30:d7:f8:f8:72:09:
b0:48:8d:61:8a:47:db:43:8e:bd:9d:8b:58:c5:b2:82:b2:5e:
24:9b:b7:dd:1d:a5:a8:93:8f:19:19:22:54:a6:e1:2d:4a:43:
3c:13:0b:b4:e1:26:a6:59:10:d7:23:1e:05:76:a3:21:cb:33:
dd:b0:a8:7a:e4:f1:d4:58:61:33:ac:22:79:62:99:94:35:11:
93:ec:f6:24:06:68:25:73:75:a4:b4:46:04:97:81:26:76:ad:
33:10:78:d3:e3:d9:88:aa:6a:24:7e:d4:bb:89:e1:b9:56:07:
2e:20:f7:78:40:fc:0b:9d:7c:0c:88:85:0a:4c:d3:21:f4:1e:
5e:37:4b:b4:16:a7:ad:1f:9e:83:ba:2d:38:cb:57:13:60:0b:
a6:40:64:67:04:bb:69:df:10:ae:86:54:5b:37:3b:4c:6e:9c:
ec:68:22:11:62:a6:31:1e:31:e9:93:78:47:51:9e:df:a2:fb:
d9:98:a5:d1:9e:a9:a6:e2:19:40:8c:2f:a6:cb:be:ff:7c:91:
d7:db:31:3a
Is this deliberate? It seems like an odd mismatch to me. My nginx is a Kubernetes pod so the local storage may disappear. My etcd storage, however, is persistent. And yes, my colleague is writing an etcd backend for this project. 😄
Perhaps you can convince me why files are more appropriate here. Otherwise would you accept a patch to change this behaviour? Or perhaps make it configurable?
While I'm here, I'm changing api_uri
to point to my test ACME server but it's still trying to use the real one. Haven't figured out why yet.
We're working on this as a company hackathon project over the next day so a speedy response would be appreciated.
Would you be happy to move to lua-resty-redis-connector over base lua-resty-redis so that redis sentinel instances can be supported?
This will make it easier to load balance it and make redis HA.
Hey,
thanks for your work!
I'm trying to use this package but for some reason https://
connections aren't working. So I'm wondering how to best debug such an issue.
When using http://
all is fine:
curl --verbose http://subdomain.my-domain.com/test
* Trying xxx.xxx.xxx.xxx...
* TCP_NODELAY set
* Connected to subdomain.my-domain.com (xxx.xxx.xxx.xxx) port 80 (#0)
> GET /test HTTP/1.1
> Host: subdomain.my-domain.com
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: openresty/1.19.3.1
< Date: Wed, 23 Dec 2020 22:41:17 GMT
< Content-Type: text/plain
< Content-Length: 11
< Connection: keep-alive
< Content-Type: text/plain
<
* Connection #0 to host subdomain.my-domain.com left intact
OK - test
* Closing connection 0
When using https://
I won't get any response – it will eventually close the connection with a t timeout:
curl --verbose https://subdomain.my-domain.com/test
* Trying xxx.xxx.xxx.xxx...
* TCP_NODELAY set
* Connection failed
* connect to xxx.xxx.xxx.xxx port 443 failed: Operation timed out
* Failed to connect to subdomain.my-domain.com port 443: Operation timed out
* Closing connection 0
curl: (7) Failed to connect to subdomain.my-domain.com port 443: Operation timed out
Here's my nginx.conf
file:
worker_processes 1;
error_log logs/error.log;
events {
worker_connections 1024;
}
http {
resolver 8.8.8.8 ipv6=off;
lua_shared_dict acme 16m;
# required to verify Let's Encrypt API
lua_ssl_trusted_certificate /etc/ssl/certs/ca-bundle.trust.crt;
lua_ssl_verify_depth 2;
init_by_lua_block {
require("resty.acme.autossl").init({
-- setting the following to true
-- implies that you read and accepted https://letsencrypt.org/repository/
tos_accepted = true,
account_key_path = "/home/ec2-user/openresty/certs/account.key",
account_email = "[email protected]",
domain_whitelist = { "my-domain.com", "subdomain.my-domain.com" },
})
}
init_worker_by_lua_block {
require("resty.acme.autossl").init_worker()
}
server {
listen 80;
listen 443 ssl;
server_name subdomain.my-domain.com;
# fallback certs, make sure to create them before hand
ssl_certificate /home/ec2-user/openresty/certs/default.pem;
ssl_certificate_key /home/ec2-user/openresty/certs/default.key;
ssl_certificate_by_lua_block {
require("resty.acme.autossl").ssl_certificate()
}
location /.well-known {
content_by_lua_block {
require("resty.acme.autossl").serve_http_challenge()
}
}
location / {
add_header Content-Type text/plain;
return 200 'ok';
}
location /test {
add_header Content-Type text/plain;
return 200 'OK - test';
}
}
}
On the first time a whitelisted domain is reached, is there a way to block the request until the certificate is created?
So that certs are used even on that first request? Similarly to what https://github.com/auto-ssl/lua-resty-auto-ssl does.
This is the tracking issue for development.
I tried using curl -k -v
to visit, it returns, but http status code 501.
f64f57fa93b1a00fdf2f670560eb49a4 117.143.104.231 [04/Jan/2022:22:02:59 +0800] TLSv1.2/ECDHE-RSA-AES256-GCM-SHA384 "GET / HTTP/2.0" 200 22879 "-" "xxx.yyy.com" curl/7.77.0 - 0.005 - - -
164be1733737f2b7420e80ad2cff68e9 34.221.255.206 [04/Jan/2022:22:03:01 +0800] -/- "GET /.well-known/acme-challenge/hVTbVb1_VF7doKTvlk-myup0q4Cx_4kDN_ozlKa7f6A HTTP/1.1" 301 162 "-" "xxx.yyy.com" Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org) - 0.000 - - -
f9781deba06461ccec4b4732125d0f28 18.159.196.172 [04/Jan/2022:22:03:01 +0800] -/- "GET /.well-known/acme-challenge/hVTbVb1_VF7doKTvlk-myup0q4Cx_4kDN_ozlKa7f6A HTTP/1.1" 301 162 "-" "xxx.yyy.com" Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org) - 0.000 - - -
d7f7a73dba67490c8c5a5124291b1070 3.19.56.43 [04/Jan/2022:22:03:02 +0800] -/- "GET /.well-known/acme-challenge/hVTbVb1_VF7doKTvlk-myup0q4Cx_4kDN_ozlKa7f6A HTTP/1.1" 301 162 "-" "xxx.yyy.com" Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org) - 0.000 - - -
81fbbeb690b0021a1e53ea954463091d 66.133.109.36 [04/Jan/2022:22:03:02 +0800] -/- "GET /.well-known/acme-challenge/hVTbVb1_VF7doKTvlk-myup0q4Cx_4kDN_ozlKa7f6A HTTP/1.1" 301 162 "-" "xxx.yyy.com" Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org) - 0.000 - - -
d15dcb78c5a27cc21b912e2683db09ec 34.221.255.206 [04/Jan/2022:22:03:03 +0800] TLSv1.3/TLS_AES_128_GCM_SHA256 "GET /.well-known/acme-challenge/hVTbVb1_VF7doKTvlk-myup0q4Cx_4kDN_ozlKa7f6A HTTP/1.1" 501 99 "http://xxx.yyy.com/.well-known/acme-challenge/hVTbVb1_VF7doKTvlk-myup0q4Cx_4kDN_ozlKa7f6A" "xxx.yyy.com" Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org) - 0.000 - - -
1a02f4abfe7ef999b8595c5b7bdaf709 3.19.56.43 [04/Jan/2022:22:03:03 +0800] TLSv1.3/TLS_AES_128_GCM_SHA256 "GET /.well-known/acme-challenge/hVTbVb1_VF7doKTvlk-myup0q4Cx_4kDN_ozlKa7f6A HTTP/1.1" 501 99 "http://xxx.yyy.com/.well-known/acme-challenge/hVTbVb1_VF7doKTvlk-myup0q4Cx_4kDN_ozlKa7f6A" "xxx.yyy.com" Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org) - 0.001 - - -
f45fb99fe0b352717f597f30fc0465e0 18.159.196.172 [04/Jan/2022:22:03:03 +0800] TLSv1.3/TLS_AES_128_GCM_SHA256 "GET /.well-known/acme-challenge/hVTbVb1_VF7doKTvlk-myup0q4Cx_4kDN_ozlKa7f6A HTTP/1.1" 501 99 "http://xxx.yyy.com/.well-known/acme-challenge/hVTbVb1_VF7doKTvlk-myup0q4Cx_4kDN_ozlKa7f6A" "xxx.yyy.com" Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org) - 0.001 - - -
6e2e5873255f61ab0493ce0c61342ca4 66.133.109.36 [04/Jan/2022:22:03:04 +0800] TLSv1.3/TLS_AES_128_GCM_SHA256 "GET /.well-known/acme-challenge/hVTbVb1_VF7doKTvlk-myup0q4Cx_4kDN_ozlKa7f6A HTTP/1.1" 501 99 "http://xxx.yyy.com/.well-known/acme-challenge/hVTbVb1_VF7doKTvlk-myup0q4Cx_4kDN_ozlKa7f6A" "xxx.yyy.com" Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org) - 0.001 - - -
==> /var/log/nginx/error.log <==
2022/01/04 22:03:06 [error] 8#8: *97 [acme] autossl.lua:182: error updating cert for xxx.yyy.com err: error checking challenge: challenge invalid: http-01: invalid: Invalid response from https://xxx.yyy.com/.well-known/acme-challenge/hVTbVb1_VF7doKTvlk-myup0q4Cx_4kDN_ozlKa7f6A [47.116.64.248]: 501, context: ngx.timer, client: 117.143.104.231, server: 0.0.0.0:443
2022/01/04 22:03:06 [error] 8#8: *97 [acme] autossl.lua:470: failed to create rsa certificate for domain xxx.yyy.com: error checking challenge: challenge invalid: http-01: invalid: Invalid response from https://xxx.yyy.com/.well-known/acme-challenge/hVTbVb1_VF7doKTvlk-myup0q4Cx_4kDN_ozlKa7f6A [47.116.64.248]: 501, context: ngx.timer, client: 117.143.104.231, server: 0.0.0.0:443
In our usage of this library a domain which is in the whitelist might be removed from the whitelist later. We would appreciate it if the domain is then removed from the storage used by this library, too. This could be done in the certificate upate process.
In AUTOSSL.update_cert
an error message is returned when a domain is not whitelisted. It would be nice to have an option that instead of returning an error message the domain is deleted from storage. That way a none whitlisted domain would not have to be checked every time the worker is running and there would not be unnecessary messages in the log.
2022/08/29 10:45:32 [debug] 1143097#0: *11 [acme] client.lua:307: acme request: https://acme.zerossl.com/v2/DV90/newAccount response: {"type":"urn:ietf:params:acme:error:unauthorized","status":401,"detail":"The Request URL in the JWS Protected Header does not match the actual Request URL"}
2022/08/29 10:45:32 [error] 1143097#0: *11 [acme] autossl.lua:229: error during acme login: failed to create account: The Request URL in the JWS Protected Header does not match the actual Request URL, context: ngx.timer, client: 0.1.10.0, server: 0.0.0.0:443
2022/08/29 10:45:33 [debug] 1143097#0: *20 [acme] client.lua:307: acme request: https://acme.zerossl.com/v2/DV90/newAccount response: {"type":"urn:ietf:params:acme:error:unauthorized","status":401,"detail":"The Request URL in the JWS Protected Header does not match the actual Request URL"}
2022/08/29 10:45:33 [error] 1143097#0: *20 [acme] autossl.lua:229: error during acme login: failed to create account: The Request URL in the JWS Protected Header does not match the actual Request URL, context: ngx.timer, client: 0.1.10.0, server: 0.0.0.0:443
2022/08/29 10:45:33 [debug] 1143097#0: *16 [acme] client.lua:307: acme request: https://acme.zerossl.com/v2/DV90/newAccount response: {"type":"urn:ietf:params:acme:error:unauthorized","status":401,"detail":"The Request URL in the JWS Protected Header does not match the actual Request URL"}
2022/08/29 10:45:33 [error] 1143097#0: *16 [acme] autossl.lua:229: error during acme login: failed to create account: The Request URL in the JWS Protected Header does not match the actual Request URL, context: ngx.timer, client: 0.1.10.0, server: 0.0.0.0:443
Hello!
I am getting a certificate renewal error. I cannot understand what is the matter.
Thank you in advance.
`
2020/11/11 12:05:33 [error] 12#12: *47966 lua ssl certificate verify error: (20: unable to get local issuer certificate), context: ngx.timer
2020/11/11 12:05:33 [error] 12#12: *47966 [lua] autossl.lua:196: update_cert(): error during acme init: acme directory request failed: 20: unable to get local issuer certificate, context: ngx.timer
2020/11/11 12:05:34 [error] 12#12: *47966 lua ssl certificate verify error: (20: unable to get local issuer certificate), context: ngx.timer
2020/11/11 12:05:34 [error] 12#12: *47966 [lua] autossl.lua:196: update_cert(): error during acme init: acme directory request failed: 20: unable to get local issuer certificate, context: ngx.timer
`
Hi so I installed
luarocks install lua-resty-acme
luarocks install luafilesystem
also did everything here https://github.com/fffonion/lua-resty-acme#synopsis
but still don't get the certificate when I go to my website.
How do you use it? 😄
Do I need to run a command to get a SSL? I want to get SSL from zerossl.com because let's encrypt does not work.
My config:
events {}
http {
resolver 8.8.8.8;
lua_shared_dict acme 16m;
# required to verify Let's Encrypt API
lua_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;
lua_ssl_verify_depth 2;
init_by_lua_block {
require("resty.acme.autossl").init({
-- you current configs
tos_accepted = true,
account_key_path = "/etc/openresty/account.key",
account_email = "[email protected]",
eab_kid = "130jnnbfmhTA2-kCDWe5FAg",
-- external account binding hmac key, base64url encoded
eab_hmac_key = "15BVuaSD82WD2q3C5Q-l1Xn8X9L6m9i5jhlPMx3LTooiXr4xBoBwnD9mzf16JKdyzxrKKHGFaI6kZU5eE7hPcJA",
--domain_whitelist = { " yyy.com" }
},
{
api_url = "https://acme.zerossl.com/v2/DV90"
})}
init_worker_by_lua_block {
require("resty.acme.autossl").init_worker()
}
server {
listen 80;
listen 443 ssl;
server_name yyy.com;
location = /.well-known {
content_by_lua_block {
require("resty.acme.autossl").serve_http_challenge()
}
}
# fallback certs, make sure to create them before hand
ssl_certificate /etc/openresty/default.pem;
ssl_certificate_key /etc/openresty/default.key;
ssl_certificate_by_lua_block {
require("resty.acme.autossl").ssl_certificate()
}
}
}
As one popular platform to use this plugin in is Kong, which in turn has excellent support for kubernetes, it should be made possible to allow storage in a vault KV secrets database by using your service account instead.
3 parameters should be definable:
Would it be possible to add a hook or something along those lines for a user supplied function for when certification generation fails.
The problem I'm trying to solve is that the application that sits behind openresty is configurable to have any user supplied domain. We then gather those domains and add them to the whitelist used by resty acme.
However there are times that those domains either aren't publicly available or resolvable.
My thoughts are that if we had a user configurable function that could be used on certification creation failure user supplied code could then handle these situations, or adding a configurable cool down period so that acme doesn't keep trying to generate a failed certificate.
how to set "domain_whitelist = { "domain1.com", "domain2.com", "domain3.com" },"
domain_whitelist = setmetatable({}, { __index = function(_, k)
return ngx.re.match(k, [[.example.domain1$] | [.domain2.com$]], "jo")
end}),
Executing systemctl reload openresty
is resulting in the check_renew()
function in autossl being run before the old workers are killed. This could be a problem if the reload has to executed quite often.
Hi,
we are occasionally seeing a problem with an update_lock
not being released, which causes certificates not to be renewed until the lock is manually cleared.
2022/02/14 14:38:02 [info] 16#16: *37134811 [lua] autossl.lua:250: update_cert(): update is already running (lock key update_lock::www.somedomain.com exists), current type rsa, context: ngx.timer
Any idea what could lead to this?
Thank you very much!
Hi how could this error be resolved?
journalctl -xe [log]
nginx: [error] init_by_lua error: /usr/local/share/lua/5.1/resty/openssl/version.lua:60: OpenSSL has encountered an error: /usr/local/share/lua/5.1/resty/openssl/version.lua:45: /usr/local/lib/libluajit-5.1.so.2: undefined symbol: SSLeay; is OpenSSL library loaded?
Aug 18 15:44:15 localserver nginx[71449]: stack traceback:
Aug 18 15:44:15 localserver nginx[71449]: [C]: in function 'error'
Aug 18 15:44:15 localserver nginx[71449]: /usr/local/share/lua/5.1/resty/openssl/version.lua:60: in main chunk
Aug 18 15:44:15 localserver nginx[71449]: [C]: in function 'require'
Aug 18 15:44:15 localserver nginx[71449]: /usr/local/share/lua/5.1/resty/acme/openssl.lua:4: in main chunk
Aug 18 15:44:15 localserver nginx[71449]: [C]: in function 'require'
Aug 18 15:44:15 localserver nginx[71449]: /usr/local/share/lua/5.1/resty/acme/util.lua:4: in main chunk
Aug 18 15:44:15 localserver nginx[71449]: [C]: in function 'require'
Aug 18 15:44:15 localserver nginx[71449]: /usr/local/share/lua/5.1/resty/acme/client.lua:3: in main chunk
Aug 18 15:44:15 localserver nginx[71449]: [C]: in function 'require'
Aug 18 15:44:15 localserver nginx[71449]: /usr/local/share/lua/5.1/resty/acme/autossl.lua:2: in main chunk
Aug 18 15:44:15 localserver nginx[71449]: [C]: in function 'require'
Aug 18 15:44:15 localserver nginx[71449]: init_by_lua:3: in main chunk
Aug 18 15:44:15 localserver systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE
nginx -V
root@localserver:/etc/nginx# nginx -V
nginx version: nginx/1.19.6
built with OpenSSL 1.1.1 (compatible; BoringSSL) (running with BoringSSL)
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --with-openssl=quiche/quiche/deps/boringssl --with-quiche=quiche --with-http_ssl_module --with-http_v2_module --with-http_v3_module --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --with-pcre --lock-path=/var/lock/nginx.lock --pid-path=/var/run/nginx.pid --with-http_ssl_module --with-http_sub_module --with-http_image_filter_module=dynamic --modules-path=/etc/nginx/modules --add-module=modules/ngx_devel_kit-0.3.1 --add-module=modules/ngx_pagespeed --add-module=modules/ngx_brotli --add-module=modules/headers-more-nginx-module-0.33 --add-module=modules/lua-nginx-module-0.10.21 --with-cc-opt='-I quiche/quiche/deps/boringssl/include' --with-ld-opt='-L quiche/quiche/deps/boringssl/build/ssl -L quiche/quiche/deps/boringssl/build/crypto'
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.