acme: Service automatique de certificats Let's Encrypt et implémentation Lua du protocole ACMEv2
Installation
Si vous n'avez pas encore configuré l'abonnement au dépôt RPM, inscrivez-vous. Ensuite, vous pouvez procéder avec les étapes suivantes.
CentOS/RHEL 7 ou Amazon Linux 2
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install lua-resty-acme
CentOS/RHEL 8+, Fedora Linux, Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install lua5.1-resty-acme
Pour utiliser cette bibliothèque Lua avec NGINX, assurez-vous que nginx-module-lua est installé.
Ce document décrit lua-resty-acme v0.16.0 publié le 01 septembre 2025.
Service automatique de certificats Let's Encrypt (RSA + ECC) et implémentation pure Lua du protocole ACMEv2.
Les défis http-01 et tls-alpn-01 sont pris en charge.
Description
Cette bibliothèque se compose de deux parties :
resty.acme.autossl: gestion automatique du cycle de vie des certificats Let's Encryptresty.acme.client: implémentation Lua du protocole ACME v2
Installez en utilisant opm :
opm install fffonion/lua-resty-acme
Alternativement, pour installer en utilisant luarocks :
luarocks install lua-resty-acme
## installer manuellement un luafilesystem
luarocks install luafilesystem
Notez que vous devrez installer manuellement luafilesystem lorsque vous utilisez LuaRocks. Cela est fait pour maintenir la compatibilité avec les versions antérieures.
Cette bibliothèque utilise un backend openssl basé sur FFI, qui prend actuellement en charge OpenSSL 1.1.1, 1.1.0 et 1.0.2.
Synopsis
Créez la clé privée du compte et les certificats de secours :
## créer la clé du compte
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -out /etc/openresty/account.key
## créer le certificat et la clé de secours
openssl req -newkey rsa:2048 -nodes -keyout /etc/openresty/default.key -x509 -days 365 -out /etc/openresty/default.pem
Utilisez la configuration d'exemple suivante :
events {}
http {
resolver 8.8.8.8 ipv6=off;
lua_shared_dict acme 16m;
# requis pour vérifier l'API Let's Encrypt
lua_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;
lua_ssl_verify_depth 2;
init_by_lua_block {
require("resty.acme.autossl").init({
-- définir ce qui suit sur true
-- implique que vous avez lu et accepté https://letsencrypt.org/repository/
tos_accepted = true,
-- décommentez ce qui suit pour la première configuration
-- staging = true,
-- décommentez ce qui suit pour activer le certificat double RSA + ECC
-- domain_key_types = { 'rsa', 'ecc' },
-- décommentez ce qui suit pour activer le défi tls-alpn-01
-- enabled_challenge_handlers = { 'http-01', 'tls-alpn-01' },
account_key_path = "/etc/openresty/account.key",
account_email = "[email protected]",
domain_whitelist = { "example.com" },
})
}
init_worker_by_lua_block {
require("resty.acme.autossl").init_worker()
}
server {
listen 80;
listen 443 ssl;
server_name example.com;
# certificats de secours, assurez-vous de les créer à l'avance
ssl_certificate /etc/openresty/default.pem;
ssl_certificate_key /etc/openresty/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()
}
}
}
}
Lors du test de déploiement, il est recommandé de décommenter staging = true pour permettre un test de bout en bout de votre environnement. Cela peut éviter que des échecs de configuration ne résultent en trop de demandes qui atteignent la limitation de taux sur l'API Let's Encrypt.
Par défaut, autossl ne crée que des certificats RSA. Pour utiliser des certificats ECC ou les deux, décommentez domain_key_types = { 'rsa', 'ecc' }. Notez que la chaîne de certificats multiples n'est prise en charge que par NGINX 1.11.0 ou version ultérieure.
Un certificat sera mis en file d'attente pour être créé après que Nginx ait vu une demande avec un tel SNI, ce qui peut prendre plusieurs dizaines de secondes pour se terminer. Pendant ce temps, les demandes avec un tel SNI sont répondues avec le certificat de secours.
Notez que domain_whitelist ou domain_whitelist_callback doit être défini pour inclure votre domaine que vous souhaitez servir avec autossl, afin de prévenir tout abus potentiel utilisant un faux SNI lors de la poignée SSL.
domain_whitelist définit une table qui inclut tous les domaines qui doivent être inclus et le CN à utiliser pour créer le certificat. Un seul * est autorisé comme caractère générique.
domain_whitelist = { "domain1.com", "domain2.com", "domain3.com", "*.domain4.com" },
Certificats wildcard
Pour permettre à cette bibliothèque de créer des certificats wildcard, les exigences suivantes doivent être remplies :
- Le domaine wildcard doit apparaître exactement sous la forme
*.somedomain.comdansdomain_whitelist. - Le défi
dns-01doit être activé et un fournisseur DNS qui a desdomainscorrespondant au domaine doit être configuré.
Sinon, un certificat non wildcard sera créé comme secours.
Par défaut, le domaine wildcard *.example.com apparaîtra dans le Nom Commun. Lorsque wildcard_domain_in_san est défini sur true, un certificat avec le Nom Commun example.com et le Nom Alternatif du Sujet *.example.com sera créé. Notez que *.example.com et example.com doivent tous deux apparaître dans dns_provider_accounts.
Utilisation avancée
Utiliser une fonction pour inclure des domaines
domain_whitelist_callback définit une fonction qui accepte le domaine comme paramètre et retourne un booléen pour indiquer s'il doit être inclus.
Pour faire correspondre un motif dans votre nom de domaine, par exemple tous les sous-domaines sous example.com, utilisez :
domain_whitelist_callback = function(domain, is_new_cert_needed)
return ngx.re.match(domain, [[\.example\.com$]], "jo")
end
De plus, puisque la vérification de la liste blanche des domaines s'exécute dans la phase de certificat, il est possible d'utiliser l'API cosocket ici. Notez que cela augmentera la latence de la poignée SSL.
domain_whitelist_callback = function(domain, is_new_cert_needed)
-- envoyer une requête HTTP
local http = require("resty.http")
local res, err = httpc:request_uri("http://example.com")
-- accéder au stockage
local acme = require("resty.acme.autossl")
local value, err = acme.storage:get("key")
-- obtenir le certificat du cache LRU resty
-- cached = { pkey, cert } ou nil si le certificat n'est pas dans le cache
local cached, staled, flags = acme.get_cert_from_cache(domain, "rsa")
-- faire quelque chose pour vérifier le domaine
-- retourner is_domain_included
end
La fonction domain_whitelist_callback est fournie avec un deuxième argument, qui indique si le certificat est sur le point d'être servi lors d'une demande HTTP entrante (false) ou si un nouveau certificat est sur le point d'être demandé (true). Cela permet d'utiliser des valeurs mises en cache sur le chemin chaud (servant des demandes) tout en récupérant des données fraîches du stockage pour de nouveaux certificats. On peut également mettre en œuvre une logique différente, par exemple effectuer des vérifications supplémentaires avant de demander un nouveau certificat.
Définir une période de refroidissement en cas d'échec
En cas d'échec de la demande de certificat, on peut vouloir empêcher le client ACME de demander un autre certificat immédiatement. Par défaut, la période de refroidissement est fixée à 300 secondes (5 minutes). Elle peut être personnalisée avec failure_cooloff ou avec la fonction failure_cooloff_callback, par exemple pour mettre en œuvre un retour exponentiel.
failure_cooloff_callback = function(domain, count)
if count == 1 then
return 600 -- 10 minutes
elseif count == 2 then
return 1800 -- 30 minutes
elseif count == 3 then
return 3600 -- 1 heure
elseif count == 4 then
return 43200 -- 12 heures
elseif count == 5 then
return 43200 -- 12 heures
else
return 86400 -- 24 heures
end
end
Défi tls-alpn-01
Le défi tls-alpn-01 est actuellement pris en charge sur Openresty 1.15.8.x, 1.17.8.x et 1.19.3.x.
Cliquez pour développer un exemple de configuration
events {}
http {
resolver 8.8.8.8 ipv6=off;
lua_shared_dict acme 16m;
# requis pour vérifier l'API Let's Encrypt
lua_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;
lua_ssl_verify_depth 2;
init_by_lua_block {
require("resty.acme.autossl").init({
-- définir ce qui suit sur true
-- implique que vous avez lu et accepté https://letsencrypt.org/repository/
tos_accepted = true,
-- décommentez ce qui suit pour la première configuration
-- staging = true,
-- décommentez ce qui suit pour activer le certificat double RSA + ECC
-- domain_key_types = { 'rsa', 'ecc' },
-- décommentez ce qui suit pour activer le défi tls-alpn-01
enabled_challenge_handlers = { 'http-01', 'tls-alpn-01' },
account_key_path = "/etc/openresty/account.key",
account_email = "[email protected]",
domain_whitelist = { "example.com" },
storage_adapter = "file",
})
}
init_worker_by_lua_block {
require("resty.acme.autossl").init_worker()
}
server {
listen 80;
listen unix:/tmp/nginx-default.sock ssl;
# listen unix:/tmp/nginx-default.sock ssl proxy_protocol;
server_name example.com;
# set_real_ip_from unix:;
# real_ip_header proxy_protocol;
# certificats de secours, assurez-vous de les créer à l'avance
ssl_certificate /etc/openresty/default.pem;
ssl_certificate_key /etc/openresty/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()
}
}
}
}
stream {
init_worker_by_lua_block {
require("resty.acme.autossl").init({
-- définir ce qui suit sur true
-- implique que vous avez lu et accepté https://letsencrypt.org/repository/
tos_accepted = true,
-- décommentez ce qui suit pour la première configuration
-- staging = true,
-- décommentez ce qui suit pour activer le certificat double RSA + ECC
-- domain_key_types = { 'rsa', 'ecc' },
-- décommentez ce qui suit pour activer le défi tls-alpn-01
enabled_challenge_handlers = { 'http-01', 'tls-alpn-01' },
account_key_path = "/etc/openresty/account.key",
account_email = "[email protected]",
domain_whitelist = { "example.com" },
storage_adapter = "file"
})
require("resty.acme.autossl").init_worker()
}
map $ssl_preread_alpn_protocols $backend {
~\bacme-tls/1\b unix:/tmp/nginx-tls-alpn.sock;
default unix:/tmp/nginx-default.sock;
}
server {
listen 443;
listen [::]:443;
ssl_preread on;
proxy_pass $backend;
# proxy_protocol on;
}
server {
listen unix:/tmp/nginx-tls-alpn.sock ssl;
# listen unix:/tmp/nginx-tls-alpn.sock ssl proxy_protocol;
ssl_certificate certs/default.pem;
ssl_certificate_key certs/default.key;
# nécessite --with-stream_realip_module
# set_real_ip_from unix:;
ssl_certificate_by_lua_block {
require("resty.acme.autossl").serve_tls_alpn_challenge()
}
content_by_lua_block {
ngx.exit(0)
}
}
}
Dans l'exemple de configuration ci-dessus, nous avons défini un serveur http et deux serveurs de flux.
Le serveur de flux très en avant écoute le port 443 et dirige vers différents en amont en fonction de l'ALPN du client. Le répondeur tls-alpn-01 écoute sur unix:/tmp/nginx-tls-alpn.sock. Tout le trafic https normal écoute sur unix:/tmp/nginx-default.sock.
[serveur de flux unix:/tmp/nginx-tls-alpn.sock ssl]
Y /
[serveur de flux 443] --- ALPN est acme-tls ?
N \
[serveur http unix:/tmp/nginx-default.sock ssl]
- La configuration passée à
require("resty.acme.autossl").initdans les deux sous-systèmes doit être maintenue aussi similaire que possible. - Le gestionnaire de défi
tls-alpn-01n'a besoin d'aucune dépendance tierce. - Vous pouvez activer les gestionnaires de défi
http-01ettls-alpn-01en même temps. - Les sous-systèmes
httpetstreamne partagent pas de shm, donc envisagez d'utiliser un stockage autre queshm. Si vous devez utilisershm, vous devrez appliquer ce patch.
Défi dns-01
Le défi DNS-01 est pris en charge sur lua-resty-acme > 0.13.0. Actuellement, les fournisseurs DNS suivants sont pris en charge :
cloudflare: Cloudflaredynv6: Dynv6dnspod-intl: Dnspod International (seul le token Dnspod est pris en charge et utilisezid,tokendans le champ secret)
Pour lire comment étendre un nouveau fournisseur DNS pour travailler avec le défi dns-01, voir Fournisseur DNS.
Un exemple de configuration pour utiliser le défi dns-01 serait :
require("resty.acme.autossl").init({
-- définir ce qui suit sur true
-- implique que vous avez lu et accepté https://letsencrypt.org/repository/
tos_accepted = true,
-- décommentez ce qui suit pour la première configuration
-- staging = true,
-- décommentez ce qui suit pour activer le certificat double RSA + ECC
-- domain_key_types = { 'rsa', 'ecc' },
-- ne définissez pas `http-01` ou `tls-alpn-01` si vous prévoyez uniquement d'utiliser dns-01.
enabled_challenge_handlers = { 'dns-01' },
account_key_path = "/etc/openresty/account.key",
account_email = "[email protected]",
domain_whitelist = { "example.com", "subdomain.anotherdomain.com" },
dns_provider_accounts = {
{
name = "cloudflare_prod",
provider = "cloudflare",
secret = "apikey de cloudflare",
domains = { "example.com" },
},
{
name = "dynv6_staging",
provider = "dynv6",
secret = "apikey de dynv6",
domains = { "*.anotherdomain.com" },
},
},
-- décommentez ce qui suit pour créer anotherdomain.com dans CN et *.anotherdomain.com dans SAN
-- wildcard_domain_in_san = true,
})
Par défaut, cette bibliothèque essaie jusqu'à 5 minutes pour la propagation DNS. Si le TTL par défaut pour le fournisseur DNS est plus long que cela, l'utilisateur peut vouloir ajuster challenge_start_delay manuellement pour attendre plus longtemps.
resty.acme.autossl
Une table de configuration peut être passée à resty.acme.autossl.init(), les valeurs par défaut sont :
default_config = {
-- accepter les termes de service https://letsencrypt.org/repository/
tos_accepted = false,
-- si vous utilisez l'API de staging de Let's Encrypt
staging = false,
-- le chemin vers la clé privée du compte au format PEM
account_key_path = nil,
-- l'email du compte à enregistrer
account_email = nil,
-- nombre de certificats en cache, par type
cache_size = 100,
domain_key_paths = {
-- la clé privée RSA globale du domaine
rsa = nil,
-- la clé privée ECC globale du domaine
ecc = nil,
},
-- l'algorithme de clé privée à utiliser, peut être un ou les deux de
-- 'rsa' et 'ecc'
domain_key_types = { 'rsa' },
-- restreindre l'enregistrement de nouveaux certificats uniquement avec les domaines définis dans cette table
domain_whitelist = nil,
-- restreindre l'enregistrement de nouveaux certificats uniquement avec les domaines vérifiés par cette fonction
domain_whitelist_callback = nil,
-- intervalle à attendre avant de réessayer après un échec de demande de certificat
failure_cooloff = 300,
-- fonction qui retourne l'intervalle à attendre avant de réessayer après un échec de demande de certificat
failure_cooloff_callback = nil,
-- le seuil pour renouveler un certificat avant son expiration, en secondes
renew_threshold = 7 * 86400,
-- intervalle pour vérifier le renouvellement du certificat, en secondes
renew_check_interval = 6 * 3600,
-- le stockage des certificats
storage_adapter = "shm",
-- la configuration de stockage passée à l'adaptateur de stockage
storage_config = {
shm_name = 'acme',
},
-- les types de défis activés
enabled_challenge_handlers = { 'http-01' },
-- temps à attendre avant de signaler au serveur ACME de valider en secondes
challenge_start_delay = 0,
-- si vrai, la demande à nginx attend jusqu'à ce que le certificat ait été généré et est utilisé immédiatement
blocking = false,
-- si vrai, le certificat pour le domaine non dans la liste blanche sera supprimé du stockage
enabled_delete_not_whitelisted_domain = false,
-- le dictionnaire des fournisseurs DNS, chaque fournisseur doit avoir la structure suivante :
-- {
-- name = "prod_account",
-- provider = "provider_name", -- "cloudflare" ou "dynv6"
-- secret = "la clé API ou le token",
-- domains = { "example.com", "*.example.com" }, -- la liste des domaines pouvant être utilisés avec ce fournisseur
-- }
dns_provider_accounts = {},
-- si activé, les domaines wildcard comme *.example.com seront créés comme SAN et CN sera example.com
wildcard_domain_in_san = false,
}
Si account_key_path n'est pas spécifié, une nouvelle clé de compte sera créée à chaque fois que Nginx recharge la configuration. Notez que cela peut déclencher la limitation de taux New Account sur l'API Let's Encrypt.
Si domain_key_paths n'est pas spécifié, une nouvelle clé privée sera générée pour chaque certificat (RSA 4096 bits et ECC prime256v1 256 bits). Notez que la génération d'une telle clé bloquera le travail et sera particulièrement perceptible sur les VM où l'entropie est faible.
Passez la table de configuration directement au client ACME comme deuxième paramètre. L'exemple suivant démontre comment utiliser un fournisseur CA autre que Let's Encrypt et également définir la chaîne préférée.
resty.acme.autossl.init({
tos_accepted = true,
account_email = "[email protected]",
}, {
api_uri = "https://acme.otherca.com/directory",
preferred_chain = "OtherCA PKI Root CA",
}
)
Voir aussi Adaptateurs de stockage ci-dessous.
Lors de l'utilisation de types de stockage distribués, il est utile d'augmenter challenge_start_delay pour permettre aux modifications dans le stockage de se propager. Lorsque challenge_start_delay est défini sur 0, aucune attente ne sera effectuée avant de commencer à valider les défis.
autossl.get_certkey
syntax : certkey, err = autossl.get_certkey(domain, type?)
Retourne le certificat encodé en PEM et la clé privée pour domain depuis le stockage. Accepte en option un paramètre type qui peut être "rsa" ou "ecc" ; s'il est omis, type sera par défaut "rsa".
resty.acme.client
client.new
syntax : c, err = client.new(config)
Crée un client ACMEv2.
Les valeurs par défaut pour config sont :
default_config = {
-- le point de terminaison API ACME v2 à utiliser
api_uri = "https://acme-v02.api.letsencrypt.org/directory",
-- l'email du compte à enregistrer
account_email = nil,
-- la clé du compte au format texte PEM
account_key = nil,
-- le kid du compte (sous forme d'URL)
account_kid = nil,
-- identifiant de clé de liaison de compte externe
eab_kid = nil,
-- clé hmac de liaison de compte externe, encodée en base64url
eab_hmac_key = nil,
-- gestionnaire d'enregistrement de compte externe
eab_handler = nil,
-- stockage pour le défi
storage_adapter = "shm",
-- la configuration de stockage passée à l'adaptateur de stockage
storage_config = {
shm_name = "acme"
},
-- les types de défis activés, sélection de `http-01` et `tls-alpn-01`
enabled_challenge_handlers = {"http-01"},
-- sélectionnez le Nom Commun de l'émetteur CA racine préféré si applicable
preferred_chain = nil,
-- fonction de rappel qui permet d'attendre avant de signaler au serveur ACME de valider
challenge_start_callback = nil,
-- le dictionnaire des fournisseurs DNS, chaque fournisseur doit avoir la structure suivante :
dns_provider_accounts = {},
}
Si account_kid est omis, l'utilisateur doit appeler client:new_account() pour enregistrer un nouveau compte. Notez que lors de l'utilisation de la même account_key, client:new_account() renverra le même kid qui a été précédemment enregistré.
Si le CA nécessite External Account Binding, l'utilisateur peut définir eab_kid et eab_hmac_key pour charger un compte existant, ou définir account_email et eab_handler pour enregistrer un nouveau compte. eab_hmac_key doit être encodé en base64 url. Dans ce dernier cas, l'utilisateur doit appeler client:new_account() pour enregistrer un nouveau compte. eab_handler doit être une fonction qui accepte account_email comme paramètre et retourne eab_kid, eab_hmac_key et une erreur si elle existe.
eab_handler = function(account_email)
-- faire quelque chose pour enregistrer un compte avec account_email
-- if err then
-- return nil, nil, err
-- end
return eab_kid, eab_hmac_key
end
Le gestionnaire EAB du fournisseur CA suivant est pris en charge par lua-resty-acme et l'utilisateur n'a pas besoin de mettre en œuvre son propre eab_handler :
preferred_chain est utilisé pour sélectionner une chaîne avec un Nom Commun correspondant dans son CA racine. Par exemple, l'utilisateur peut utiliser "ISRG Root X1" pour forcer l'utilisation de la nouvelle chaîne par défaut dans Let's Encrypt. Lorsque aucune valeur n'est configurée ou que le nom configuré n'est trouvé dans aucune chaîne, la chaîne par défaut sera utilisée.
challenge_start_callback est une fonction de rappel pour permettre au client d'attendre avant de signaler au serveur ACME de commencer à valider le défi. C'est utile dans une configuration distribuée où les défis prennent du temps à se propager. challenge_start_callback accepte challenge_type et challenge_token. Le client appelle cette fonction chaque seconde jusqu'à ce qu'elle retourne true indiquant que le défi doit commencer ; si ce challenge_start_callback n'est pas défini, aucune attente ne sera effectuée.
challenge_start_callback = function(challenge_type, challenge_token)
-- faire quelque chose ici
-- si nous sommes bons
return true
end
Voir aussi Adaptateurs de stockage ci-dessous.
client:init
syntax : err = client:init()
Initialise le client, nécessite la disponibilité de l'API cosocket. Cette fonction se connectera ou enregistrera un compte.
client:order_certificate
syntax : err = client:order_certificate(domain,...)
Crée un certificat avec un ou plusieurs domaines. Notez que les domaines wildcard ne sont pas pris en charge car ils ne peuvent être vérifiés que par le défi dns-01.
client:serve_http_challenge
syntax : client:serve_http_challenge()
Sert le défi http-01. Un cas d'utilisation courant sera de le mettre comme un bloc content_by_* pour le chemin /.well-known.
client:serve_tls_alpn_challenge
syntax : client:serve_tls_alpn_challenge()
Sert le défi tls-alpn-01. Voir cette section sur comment utiliser ce gestionnaire.
Adaptateurs de stockage
Les adaptateurs de stockage sont utilisés dans autossl ou le client acme pour stocker des données temporaires ou persistantes. En fonction de l'environnement de déploiement, il existe actuellement cinq adaptateurs de stockage disponibles. Pour mettre en œuvre un adaptateur de stockage personnalisé, veuillez vous référer à ce document.
file
Stockage basé sur le système de fichiers. Exemple de configuration :
storage_config = {
dir = '/etc/openresty/storage',
}
dir est omis, le répertoire temporaire de l'OS sera utilisé.
luafilesystem ou luafilesystem-ffi est nécessaire lors de l'utilisation du stockage file pour le renouvellement.
shm
Stockage basé sur le dictionnaire partagé Lua. Notez que ce stockage est volatil entre les redémarrages de Nginx (pas de recharges). Exemple de configuration :
storage_config = {
shm_name = 'dict_name',
}
redis
Stockage basé sur Redis. La configuration par défaut est :
storage_config = {
host = '127.0.0.1',
port = 6379,
database = 0,
-- clé d'authentification Redis
auth = nil,
ssl = false,
ssl_verify = false,
ssl_server_name = nil,
-- namespace comme préfixe de clé
namespace = "",
}
Redis >= 2.6.12 est requis car ce stockage nécessite SET EX.
vault
Stockage basé sur Hashicorp Vault. Seul le backend KV V2 est pris en charge. La configuration par défaut est :
storage_config = {
host = '127.0.0.1',
port = 8200,
-- chemin de préfixe de secrets kv
kv_path = "acme",
-- délai d'attente en ms
timeout = 2000,
-- utiliser HTTPS
https = false,
-- activer la vérification tls
tls_verify = true,
-- SNI utilisé dans la demande, par défaut au host si omis
tls_server_name = nil,
-- Méthode d'authentification, par défaut au token, peut être "token" ou "kubernetes"
auth_method = "token",
-- Token de Vault
token = nil,
-- Chemin d'authentification de Vault à utiliser
auth_path = "kubernetes",
-- Le rôle à essayer d'assigner
auth_role = nil,
-- Le chemin vers le JWT
jwt_path = "/var/run/secrets/kubernetes.io/serviceaccount/token",
-- Namespace de Vault
namespace = nil,
}
Support pour différentes méthodes d'authentification
- Token : C'est le défaut et permet de passer un "token" littéral dans la configuration.
- Kubernetes : Via cette méthode, on peut utiliser la méthode d'authentification intégrée de vault pour kubernetes. Ce que cela fait essentiellement, c'est prendre le token du compte de service et valider qu'il a été signé par le CA de Kubernetes. Le principal avantage ici est que les fichiers de configuration n'exposent plus votre token.
Les configurations suivantes s'appliquent ici :
lua
-- Chemin d'authentification de Vault à utiliser
auth_path = "kubernetes",
-- Le rôle à essayer d'assigner
auth_role = nil,
-- Le chemin vers le JWT
jwt_path = "/var/run/secrets/kubernetes.io/serviceaccount/token",
consul
Stockage basé sur Hashicorp Consul. La configuration par défaut est :
storage_config = {
host = '127.0.0.1',
port = 8500,
-- chemin de préfixe kv
kv_path = "acme",
-- token ACL de Consul
token = nil,
-- délai d'attente en ms
timeout = 2000,
}
etcd
Stockage basé sur etcd. Actuellement, seul le protocole v3 est pris en charge, et la version du serveur etcd doit être >= v3.4.0.
La configuration par défaut est :
storage_config = {
http_host = 'http://127.0.0.1:4001',
key_prefix = '',
timeout = 60,
ssl_verify = false,
}
Le stockage etcd nécessite la bibliothèque lua-resty-etcd à installer.
Il peut être installé manuellement avec opm install api7/lua-resty-etcd ou luarocks install lua-resty-etcd.
Fournisseurs DNS
Pour créer un fournisseur DNS personnalisé, suivez ces étapes :
- Créez un fichier comme
route53.luasouslib/resty/acme/dns_provider - Implémentez la signature de fonction suivante
function _M.new(token)
-- ...
return self
end
function _M:post_txt_record(fqdn, content)
return ok, err
end
function _M:delete_txt_record(fqdn)
return ok, err
end
Où token est la clé API, fqdn est le nom de l'enregistrement DNS à définir, et content est la valeur de l'enregistrement.
Tests
Configurez l'environnement de test e2e en exécutant bash t/fixtures/prepare_env.sh.
Ensuite, exécutez cpanm install Test::Nginx::Socket puis prove -r t.
Voir aussi
- Environnement de gestion automatique des certificats (ACME)
- haproxytech/haproxy-lua-acme L'implémentation ACME Lua utilisée dans HAProxy.
- GUI/lua-resty-auto-ssl
- lua-resty-openssl
- Limites de taux de l'API Let's Encrypt
GitHub
Vous pouvez trouver des conseils de configuration supplémentaires et de la documentation pour ce module dans le dépôt GitHub pour nginx-module-acme.