Saltar a contenido

acme: Servicio automático de certificados Let's Encrypt e implementación en Lua del protocolo ACMEv2

Instalación

Si no has configurado la suscripción al repositorio RPM, regístrate. Luego puedes proceder con los siguientes pasos.

CentOS/RHEL 7 o 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

Para usar esta biblioteca Lua con NGINX, asegúrate de que nginx-module-lua esté instalado.

Este documento describe lua-resty-acme v0.16.0 lanzado el 01 de septiembre de 2025.


Servicio automático de certificados Let's Encrypt (RSA + ECC) e implementación pura en Lua del protocolo ACMEv2.

Se admiten los desafíos http-01 y tls-alpn-01.

Estado de Construcción luarocks opm

简体中文

Descripción

Esta biblioteca consta de dos partes:

  • resty.acme.autossl: gestión automática del ciclo de vida de los certificados Let's Encrypt
  • resty.acme.client: implementación en Lua del protocolo ACME v2

Instala usando opm:

opm install fffonion/lua-resty-acme

Alternativamente, para instalar usando luarocks:

luarocks install lua-resty-acme
## instalar manualmente un luafilesystem
luarocks install luafilesystem

Ten en cuenta que necesitarás instalar manualmente luafilesystem al usar LuaRocks. Esto se hace para mantener la compatibilidad hacia atrás.

Esta biblioteca utiliza un backend de openssl basado en FFI, que actualmente soporta las series OpenSSL 1.1.1, 1.1.0 y 1.0.2.

Sinopsis

Crea la clave privada de la cuenta y los certificados de respaldo:

## crear clave de cuenta
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -out /etc/openresty/account.key
## crear certificado y clave de respaldo
openssl req -newkey rsa:2048 -nodes -keyout /etc/openresty/default.key -x509 -days 365 -out /etc/openresty/default.pem

Usa la siguiente configuración de ejemplo:

events {}

http {
    resolver 8.8.8.8 ipv6=off;

    lua_shared_dict acme 16m;

    # requerido para verificar la API de 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({
            -- establecer lo siguiente en verdadero
            -- implica que has leído y aceptado https://letsencrypt.org/repository/
            tos_accepted = true,
            -- descomentar lo siguiente para la configuración inicial
            -- staging = true,
            -- descomentar lo siguiente para habilitar certificado doble RSA + ECC
            -- domain_key_types = { 'rsa', 'ecc' },
            -- descomentar lo siguiente para habilitar el desafío 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;

        # certificados de respaldo, asegúrate de crearlos de antemano
        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()
            }
        }
    }
}

Al probar la implementación, se recomienda descomentar staging = true para permitir una prueba de extremo a extremo de tu entorno. Esto puede evitar que un fallo de configuración resulte en demasiadas solicitudes que golpeen la limitación de tasa en la API de Let's Encrypt.

Por defecto, autossl solo crea certificados RSA. Para usar certificados ECC o ambos, descomenta domain_key_types = { 'rsa', 'ecc' }. Ten en cuenta que la cadena de múltiples certificados solo es compatible con NGINX 1.11.0 o posterior.

Un certificado será enviado a la cola para crear después de que Nginx haya visto una solicitud con tal SNI, lo que puede tardar decenas de segundos en completarse. Mientras tanto, las solicitudes con tal SNI se responden con el certificado de respaldo.

Ten en cuenta que domain_whitelist o domain_whitelist_callback deben configurarse para incluir tu dominio que deseas servir con autossl, para prevenir posibles abusos usando SNI falso en el apretón de manos SSL.

domain_whitelist define una tabla que incluye todos los dominios que deben incluirse y el CN que se utilizará para crear el certificado. Solo se permite un único * como comodín.

domain_whitelist = { "domain1.com", "domain2.com", "domain3.com", "*.domain4.com" },

Certificados comodín

Para habilitar que esta biblioteca cree certificados comodín, se deben cumplir los siguientes requisitos:

  • El dominio comodín debe aparecer exactamente como *.somedomain.com en domain_whitelist.
  • El desafío dns-01 debe estar habilitado y se debe configurar un proveedor de DNS que tenga domains que coincidan con el dominio.

De lo contrario, se creará un certificado no comodín como respaldo.

Por defecto, el dominio comodín *.example.com aparecerá en el Nombre Común. Sin embargo, cuando wildcard_domain_in_san se establece en true, se creará un certificado con Nombre Común example.com y Nombre Alternativo de Sujeto *.example.com. Ten en cuenta que tanto *.example.com como example.com deben aparecer en dns_provider_accounts.

Uso Avanzado

Usar una función para incluir dominios

domain_whitelist_callback define una función que acepta el dominio como parámetro y devuelve un booleano para indicar si debe incluirse.

Para hacer coincidir un patrón en tu nombre de dominio, por ejemplo, todos los subdominios bajo example.com, usa:

domain_whitelist_callback = function(domain, is_new_cert_needed)
    return ngx.re.match(domain, [[\.example\.com$]], "jo")
end

Además, dado que la verificación de la lista blanca de dominios se ejecuta en la fase de certificado, es posible utilizar la API de cosocket aquí. Ten en cuenta que esto aumentará la latencia del apretón de manos SSL.

domain_whitelist_callback = function(domain, is_new_cert_needed)
    -- enviar solicitud HTTP
    local http = require("resty.http")
    local res, err = httpc:request_uri("http://example.com")
    -- acceder al almacenamiento
    local acme = require("resty.acme.autossl")
    local value, err = acme.storage:get("key")
    -- obtener certificado de la caché LRU de resty
    -- cached = { pkey, cert } o nil si el cert no está en caché
    local cached, staled, flags = acme.get_cert_from_cache(domain, "rsa")
    -- hacer algo para verificar el dominio
    -- devolver is_domain_included
end

La función domain_whitelist_callback se proporciona con un segundo argumento, que indica si el certificado está a punto de ser servido en una solicitud HTTP entrante (falso) o si se está a punto de solicitar un nuevo certificado (verdadero). Esto permite usar valores en caché en la ruta caliente (sirviendo solicitudes) mientras se obtienen datos frescos del almacenamiento para nuevos certificados. También se puede implementar una lógica diferente, por ejemplo, realizar verificaciones adicionales antes de solicitar un nuevo certificado.

Definir un período de enfriamiento por fallos

En caso de fallo en la solicitud de certificado, es posible que desees evitar que el cliente ACME solicite otro certificado inmediatamente. Por defecto, el período de enfriamiento se establece en 300 segundos (5 minutos). Puede personalizarse con failure_cooloff o con la función failure_cooloff_callback, por ejemplo, para implementar un retroceso exponencial.

    failure_cooloff_callback = function(domain, count)
      if count == 1 then
        return 600 -- 10 minutos
      elseif count == 2 then
        return 1800 -- 30 minutos
      elseif count == 3 then
        return 3600 -- 1 hora
      elseif count == 4 then
        return 43200 -- 12 horas
      elseif count == 5 then
        return 43200 -- 12 horas
      else
        return 86400 -- 24 horas
      end
    end

Desafío tls-alpn-01

El desafío tls-alpn-01 es actualmente compatible con Openresty 1.15.8.x, 1.17.8.x y 1.19.3.x.

Haz clic para expandir la configuración de ejemplo
events {}

http {
    resolver 8.8.8.8 ipv6=off;

    lua_shared_dict acme 16m;

    # requerido para verificar la API de 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({
            -- establecer lo siguiente en verdadero
            -- implica que has leído y aceptado https://letsencrypt.org/repository/
            tos_accepted = true,
            -- descomentar lo siguiente para la configuración inicial
            -- staging = true,
            -- descomentar lo siguiente para habilitar certificado doble RSA + ECC
            -- domain_key_types = { 'rsa', 'ecc' },
            -- descomentar lo siguiente para habilitar el desafío 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;

        # certificados de respaldo, asegúrate de crearlos de antemano
        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({
            -- establecer lo siguiente en verdadero
            -- implica que has leído y aceptado https://letsencrypt.org/repository/
            tos_accepted = true,
            -- descomentar lo siguiente para la configuración inicial
            -- staging = true,
            -- descomentar lo siguiente para habilitar certificado doble RSA + ECC
            -- domain_key_types = { 'rsa', 'ecc' },
            -- descomentar lo siguiente para habilitar el desafío 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;

            # requiere --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)
            }
    }
}

En la configuración de ejemplo anterior, configuramos un servidor http y dos servidores de stream.

El servidor de stream frontal escucha el puerto 443 y enruta a diferentes upstream según el ALPN del cliente. El respondedor tls-alpn-01 escucha en unix:/tmp/nginx-tls-alpn.sock. Todo el tráfico https normal escucha en unix:/tmp/nginx-default.sock.

                                                [servidor de stream unix:/tmp/nginx-tls-alpn.sock ssl]
                                            Y /
[servidor de stream 443] --- ¿ALPN es acme-tls?
                                            N \
                                                [servidor http unix:/tmp/nginx-default.sock ssl]
  • La configuración pasada a require("resty.acme.autossl").init en ambos subsistemas debe mantenerse lo más igual posible.
  • El controlador de desafío tls-alpn-01 no necesita ninguna dependencia de terceros.
  • Puedes habilitar los controladores de desafío http-01 y tls-alpn-01 al mismo tiempo.
  • Los subsistemas http y stream no comparten shm, por lo que se considera usar un almacenamiento diferente a shm. Si debes usar shm, necesitarás aplicar este parche.

Desafío dns-01

El desafío DNS-01 es compatible con lua-resty-acme > 0.13.0. Actualmente, se admiten los siguientes proveedores de DNS:

  • cloudflare: Cloudflare
  • dynv6: Dynv6
  • dnspod-intl: Dnspod Internacional (solo se admite el token de Dnspod y se usa id,token en el campo secreto)

Para leer cómo extender un nuevo proveedor de DNS para trabajar con el desafío dns-01, consulta Proveedores de DNS.

Una configuración de ejemplo para usar el desafío dns-01 sería:

require("resty.acme.autossl").init({
  -- establecer lo siguiente en verdadero
  -- implica que has leído y aceptado https://letsencrypt.org/repository/
  tos_accepted = true,
  -- descomentar lo siguiente para la configuración inicial
  -- staging = true,
  -- descomentar lo siguiente para habilitar certificado doble RSA + ECC
  -- domain_key_types = { 'rsa', 'ecc' },
  -- no establecer `http-01` o `tls-alpn-01` si solo planeas usar 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" },
    },
  },
  -- descomentar lo siguiente para crear anotherdomain.com en CN y *.anotherdomain.com en SAN
  -- wildcard_domain_in_san = true,
})

Por defecto, esta biblioteca intenta hasta 5 minutos para la propagación DNS. Si el TTL predeterminado para el proveedor de DNS es más largo que eso, el usuario puede querer ajustar manualmente challenge_start_delay para esperar más tiempo.

resty.acme.autossl

Se puede pasar una tabla de configuración a resty.acme.autossl.init(), los valores predeterminados son:

default_config = {
  -- aceptar términos de servicio https://letsencrypt.org/repository/
  tos_accepted = false,
  -- si se utiliza la API de staging de Let's Encrypt
  staging = false,
  -- la ruta a la clave privada de la cuenta en formato PEM
  account_key_path = nil,
  -- el correo electrónico de la cuenta para registrarse
  account_email = nil,
  -- número de caché de certificados, por tipo
  cache_size = 100,
  domain_key_paths = {
    -- la clave privada RSA global del dominio
    rsa = nil,
    -- la clave privada ECC global del dominio
    ecc = nil,
  },
  -- el algoritmo de clave privada a utilizar, puede ser uno o ambos de
  -- 'rsa' y 'ecc'
  domain_key_types = { 'rsa' },
  -- restringir el registro de nuevos certificados solo con dominios definidos en esta tabla
  domain_whitelist = nil,
  -- restringir el registro de nuevos certificados solo con dominios verificados por esta función
  domain_whitelist_callback = nil,
  -- intervalo a esperar antes de reintentar después de una solicitud de certificado fallida
  failure_cooloff = 300,
  -- función que devuelve el intervalo a esperar antes de reintentar después de una solicitud de certificado fallida
  failure_cooloff_callback = nil,
  -- el umbral para renovar un certificado antes de que expire, en segundos
  renew_threshold = 7 * 86400,
  -- intervalo para verificar la renovación del certificado, en segundos
  renew_check_interval = 6 * 3600,
  -- el almacenamiento de certificados
  storage_adapter = "shm",
  -- la configuración de almacenamiento pasada al adaptador de almacenamiento
  storage_config = {
    shm_name = 'acme',
  },
  -- los tipos de desafío habilitados
  enabled_challenge_handlers = { 'http-01' },
  -- tiempo a esperar antes de señalar al servidor ACME para validar en segundos
  challenge_start_delay = 0,
  -- si es verdadero, la solicitud a nginx espera hasta que el certificado ha sido generado y se utiliza de inmediato
  blocking = false,
  -- si es verdadero, el certificado para dominios no en la lista blanca será eliminado del almacenamiento
  enabled_delete_not_whitelisted_domain = false,
  -- el diccionario de proveedores de DNS, cada proveedor debe tener la siguiente estructura:
  -- {
  --   name = "prod_account",
  --   provider = "provider_name", -- "cloudflare" o "dynv6"
  --   secret  = "la clave API o token",
  --   domains = { "example.com", "*.example.com" }, -- la lista de dominios que se pueden usar con este proveedor
  -- }
  dns_provider_accounts = {},
  -- si está habilitado, los dominios comodín como *.example.com se crearán como SAN y CN será example.com
  wildcard_domain_in_san = false,
}

Si account_key_path no se especifica, se creará una nueva clave de cuenta cada vez que Nginx recargue la configuración. Ten en cuenta que esto puede activar la limitación de tasa de Nueva Cuenta en la API de Let's Encrypt.

Si domain_key_paths no se especifica, se generará una nueva clave privada para cada certificado (RSA de 4096 bits y ECC de 256 bits prime256v1). Ten en cuenta que generar tal clave bloqueará el trabajador y será especialmente notable en VMs donde la entropía es baja.

Pasa la tabla de configuración directamente al cliente ACME como segundo parámetro. El siguiente ejemplo demuestra cómo usar un proveedor de CA diferente a Let's Encrypt y también establecer la cadena preferida.

resty.acme.autossl.init({
    tos_accepted = true,
    account_email = "[email protected]",
  }, {
    api_uri = "https://acme.otherca.com/directory",
    preferred_chain = "OtherCA PKI Root CA",
  }
)

Consulta también Adaptadores de Almacenamiento a continuación.

Al usar tipos de almacenamiento distribuidos, es útil aumentar challenge_start_delay para permitir que los cambios en el almacenamiento se propaguen. Cuando challenge_start_delay se establece en 0, no se realizará ninguna espera antes de comenzar a validar desafíos.

autossl.get_certkey

sintaxis: certkey, err = autossl.get_certkey(domain, type?)

Devuelve el certificado y la clave privada codificados en PEM para domain desde el almacenamiento. Opcionalmente acepta un parámetro type que puede ser "rsa" o "ecc"; si se omite, type se establecerá de forma predeterminada en "rsa".

resty.acme.client

client.new

sintaxis: c, err = client.new(config)

Crea un cliente ACMEv2.

Los valores predeterminados para config son:

default_config = {
  -- el punto final de la API ACME v2 a utilizar
  api_uri = "https://acme-v02.api.letsencrypt.org/directory",
  -- el correo electrónico de la cuenta para registrarse
  account_email = nil,
  -- la clave de la cuenta en texto de formato PEM
  account_key = nil,
  -- el kid de la cuenta (como una URL)
  account_kid = nil,
  -- id de clave de enlace de cuenta externa
  eab_kid = nil,
  -- clave hmac de enlace de cuenta externa, codificada en base64url
  eab_hmac_key = nil,
  -- controlador de registro de cuenta externa
  eab_handler = nil,
  -- almacenamiento para el desafío
  storage_adapter = "shm",
  -- la configuración de almacenamiento pasada al adaptador de almacenamiento
  storage_config = {
    shm_name = "acme"
  },
  -- los tipos de desafío habilitados, selección de `http-01` y `tls-alpn-01`
  enabled_challenge_handlers = {"http-01"},
  -- seleccionar el nombre común del emisor de CA raíz preferido si es aplicable
  preferred_chain = nil,
  -- función de callback que permite esperar antes de señalar al servidor ACME para validar
  challenge_start_callback = nil,
  -- el diccionario de proveedores de DNS, cada proveedor debe tener la siguiente estructura:
  dns_provider_accounts = {},
}

Si se omite account_kid, el usuario debe llamar a client:new_account() para registrar una nueva cuenta. Ten en cuenta que al usar la misma account_key, client:new_account() devolverá el mismo kid que se registró previamente.

Si la CA requiere Vinculación de Cuenta Externa, el usuario puede establecer eab_kid y eab_hmac_key para cargar una cuenta existente, o establecer account_email y eab_handler para registrar una nueva cuenta. eab_hmac_key debe estar codificado en base64 url. En este último caso, el usuario debe llamar a client:new_account() para registrar una nueva cuenta. eab_handler debe ser una función que acepte account_email como parámetro y devuelva eab_kid, eab_hmac_key y error si lo hay.

eab_handler = function(account_email)
  -- hacer algo para registrar una cuenta con account_email
  -- si err entonces
  --  return nil, nil, err
  -- end
  return eab_kid, eab_hmac_key
end

El siguiente controlador EAB de proveedor de CA es compatible con lua-resty-acme y el usuario no necesita implementar su propio eab_handler:

preferred_chain se utiliza para seleccionar una cadena con un Nombre Común coincidente en su CA raíz. Por ejemplo, el usuario puede usar "ISRG Root X1" para forzar el uso de la nueva cadena predeterminada en Let's Encrypt. Cuando no se configura ningún valor o el nombre configurado no se encuentra en ninguna cadena, se utilizará la cadena predeterminada.

challenge_start_callback es una función de callback que permite al cliente esperar antes de señalar al servidor ACME para comenzar a validar el desafío. Es útil en una configuración distribuida donde los desafíos tardan en propagarse. challenge_start_callback acepta challenge_type y challenge_token. El cliente llama a esta función cada segundo hasta que devuelve true, indicando que el desafío debe comenzar; si este challenge_start_callback no está configurado, no se realizará ninguna espera.

challenge_start_callback = function(challenge_type, challenge_token)
  -- hacer algo aquí
  -- si estamos bien
  return true
end

Consulta también Adaptadores de Almacenamiento a continuación.

client:init

sintaxis: err = client:init()

Inicializa el cliente, requiere disponibilidad de la API de cosocket. Esta función iniciará sesión o registrará una cuenta.

client:order_certificate

sintaxis: err = client:order_certificate(domain,...)

Crea un certificado con uno o más dominios. Ten en cuenta que los dominios comodín no son compatibles, ya que solo se pueden verificar mediante el desafío dns-01.

client:serve_http_challenge

sintaxis: client:serve_http_challenge()

Sirve el desafío http-01. Un caso de uso común será poner esto como un bloque content_by_* para la ruta /.well-known.

client:serve_tls_alpn_challenge

sintaxis: client:serve_tls_alpn_challenge()

Sirve el desafío tls-alpn-01. Consulta esta sección sobre cómo usar este controlador.

Adaptadores de Almacenamiento

Los adaptadores de almacenamiento se utilizan en autossl o en el cliente acme para almacenar datos temporales o persistentes. Dependiendo del entorno de implementación, actualmente hay cinco adaptadores de almacenamiento disponibles para seleccionar. Para implementar un adaptador de almacenamiento personalizado, consulta este documento.

file

Almacenamiento basado en el sistema de archivos. Configuración de muestra:

storage_config = {
    dir = '/etc/openresty/storage',
}
Si se omite dir, se utilizará el directorio temporal del sistema operativo.

Se necesita luafilesystem o luafilesystem-ffi al usar el almacenamiento file para la renovación.

shm

Almacenamiento basado en el diccionario compartido de Lua. Ten en cuenta que este almacenamiento es volátil entre reinicios de Nginx (no recargas). Configuración de muestra:

storage_config = {
    shm_name = 'dict_name',
}

redis

Almacenamiento basado en Redis. La configuración predeterminada es:

storage_config = {
    host = '127.0.0.1',
    port = 6379,
    database = 0,
    -- Clave de autenticación de Redis
    auth = nil,
    ssl = false,
    ssl_verify = false,
    ssl_server_name = nil,
    -- espacio de nombres como prefijo de clave
    namespace = "",
}

Se requiere Redis >= 2.6.12 ya que este almacenamiento requiere SET EX.

vault

Almacenamiento basado en Hashicorp Vault. Solo se admite el backend KV V2. La configuración predeterminada es:

storage_config = {
    host = '127.0.0.1',
    port = 8200,
    -- ruta de prefijo de secretos kv
    kv_path = "acme",
    -- tiempo de espera en ms
    timeout = 2000,
    -- usar HTTPS
    https = false,
    -- activar la verificación tls
    tls_verify = true,
    -- SNI utilizado en la solicitud, predeterminado al host si se omite
    tls_server_name = nil,
    -- Método de Autenticación, predeterminado a token, puede ser "token" o "kubernetes"
    auth_method = "token",
    -- Token de Vault
    token = nil,
    -- Ruta de autenticación de Vault a utilizar
    auth_path =  "kubernetes",
    -- El rol a intentar asignar
    auth_role = nil,
    -- La ruta al JWT
    jwt_path = "/var/run/secrets/kubernetes.io/serviceaccount/token",
    -- Espacio de nombres de Vault
    namespace = nil,
}

Soporte para diferentes métodos de autenticación

  • Token: Este es el predeterminado y permite pasar un "token" literal en la configuración.
  • Kubernetes: A través de este método, se puede utilizar el método de autenticación integrado de vault para kubernetes. Básicamente, esto toma el token de la cuenta de servicio y valida que ha sido firmado por la CA de Kubernetes. El principal beneficio aquí es que los archivos de configuración ya no exponen tu token.

Las siguientes configuraciones se aplican aquí: lua -- Ruta de autenticación de Vault a utilizar auth_path = "kubernetes", -- El rol a intentar asignar auth_role = nil, -- La ruta al JWT jwt_path = "/var/run/secrets/kubernetes.io/serviceaccount/token",

consul

Almacenamiento basado en Hashicorp Consul. La configuración predeterminada es:

storage_config = {
    host = '127.0.0.1',
    port = 8500,
    -- ruta de prefijo kv
    kv_path = "acme",
    -- token ACL de Consul
    token = nil,
    -- tiempo de espera en ms
    timeout = 2000,
}

etcd

Almacenamiento basado en etcd. En este momento solo se admite el protocolo v3, y la versión del servidor etcd debe ser >= v3.4.0. La configuración predeterminada es:

storage_config = {
    http_host = 'http://127.0.0.1:4001',
    key_prefix = '',
    timeout = 60,
    ssl_verify = false,
}

El almacenamiento de etcd requiere que se instale la biblioteca lua-resty-etcd. Se puede instalar manualmente con opm install api7/lua-resty-etcd o luarocks install lua-resty-etcd.

Proveedores de DNS

Para crear un proveedor de DNS personalizado, sigue estos pasos:

  • Crea un archivo como route53.lua en lib/resty/acme/dns_provider.
  • Implementa la siguiente firma de función
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

Donde token es la clave API, fqdn es el nombre del registro DNS para establecer el registro, y content es el valor del registro.

Pruebas

Configura el entorno de prueba e2e ejecutando bash t/fixtures/prepare_env.sh.

Luego ejecuta cpanm install Test::Nginx::Socket y luego prove -r t.

Ver También

GitHub

Puedes encontrar consejos de configuración adicionales y documentación para este módulo en el repositorio de GitHub para nginx-module-acme.