Pular para conteúdo

acme: Servindo automaticamente certificados Let's Encrypt e implementação Lua do protocolo ACMEv2

Instalação

Se você ainda não configurou a assinatura do repositório RPM, inscreva-se. Em seguida, você pode prosseguir com os seguintes passos.

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

Para usar esta biblioteca Lua com NGINX, certifique-se de que o nginx-module-lua está instalado.

Este documento descreve lua-resty-acme v0.16.0 lançado em 01 de setembro de 2025.


Serviço automático de certificados Let's Encrypt (RSA + ECC) e implementação pura em Lua do protocolo ACMEv2.

Desafios http-01 e tls-alpn-01 são suportados.

Build Status luarocks opm

简体中文

Descrição

Esta biblioteca consiste em duas partes:

  • resty.acme.autossl: gerenciamento automático do ciclo de vida dos certificados Let's Encrypt
  • resty.acme.client: implementação Lua do protocolo ACME v2

Instale usando opm:

opm install fffonion/lua-resty-acme

Alternativamente, para instalar usando luarocks:

luarocks install lua-resty-acme
## instale manualmente um luafilesystem
luarocks install luafilesystem

Observe que você precisará instalar manualmente luafilesystem ao usar LuaRocks. Isso é feito para manter a compatibilidade retroativa.

Esta biblioteca usa um backend openssl baseado em FFI, que atualmente suporta as séries OpenSSL 1.1.1, 1.1.0 e 1.0.2.

Sinopse

Crie a chave privada da conta e certificados de fallback:

## crie a chave da conta
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -out /etc/openresty/account.key
## crie o certificado e a chave de fallback
openssl req -newkey rsa:2048 -nodes -keyout /etc/openresty/default.key -x509 -days 365 -out /etc/openresty/default.pem

Use a seguinte configuração de exemplo:

events {}

http {
    resolver 8.8.8.8 ipv6=off;

    lua_shared_dict acme 16m;

    # necessário para verificar a 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({
            -- definir o seguinte como verdadeiro
            -- implica que você leu e aceitou https://letsencrypt.org/repository/
            tos_accepted = true,
            -- descomente o seguinte para configuração inicial
            -- staging = true,
            -- descomente o seguinte para habilitar certificado duplo RSA + ECC
            -- domain_key_types = { 'rsa', 'ecc' },
            -- descomente o seguinte para habilitar o desafio 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 fallback, certifique-se de criá-los previamente
        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()
            }
        }
    }
}

Ao testar a implantação, é recomendado descomentar o staging = true para permitir um teste de ponta a ponta do seu ambiente. Isso pode evitar que falhas de configuração resultem em muitas solicitações que atingem limites de taxa na API Let's Encrypt.

Por padrão, autossl cria apenas certificados RSA. Para usar certificados ECC ou ambos, descomente domain_key_types = { 'rsa', 'ecc' }. Observe que múltiplas cadeias de certificados são suportadas apenas pelo NGINX 1.11.0 ou posterior.

Um certificado será enfileirado para criação após o Nginx ter visto uma solicitação com tal SNI, o que pode levar dezenas de segundos para ser concluído. Durante esse tempo, solicitações com tal SNI são respondidas com o certificado de fallback.

Observe que domain_whitelist ou domain_whitelist_callback devem ser definidos para incluir seu domínio que você deseja servir autossl, para evitar possíveis abusos usando SNI falso na negociação SSL.

domain_whitelist define uma tabela que inclui todos os domínios que devem ser incluídos e o CN a ser usado para criar o certificado. Apenas um único * é permitido como um curinga.

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

Certificados curinga

Para habilitar esta biblioteca a criar certificados curinga, os seguintes requisitos devem ser atendidos:

  • O domínio curinga aparece exatamente como *.somedomain.com em domain_whitelist.
  • O desafio dns-01 está habilitado e um provedor DNS que possui domains correspondendo ao domínio está configurado.

Caso contrário, um certificado não curinga será criado como fallback.

Por padrão, o domínio curinga *.example.com aparecerá no Nome Comum. Quando wildcard_domain_in_san é definido como true, no entanto, um certificado com Nome Comum example.com e Nome Alternativo do Sujeito *.example.com será criado. Observe que tanto *.example.com quanto example.com devem aparecer em dns_provider_accounts.

Uso Avançado

Usar uma função para incluir domínios

domain_whitelist_callback define uma função que aceita o domínio como parâmetro e retorna um booleano para indicar se deve ser incluído.

Para corresponder a um padrão no seu nome de domínio, por exemplo, todos os subdomínios sob example.com, use:

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

Além disso, como a verificação da lista de domínios está sendo executada na fase do certificado, é possível usar a API de cosocket aqui. Observe que isso aumentará a latência da negociação SSL.

domain_whitelist_callback = function(domain, is_new_cert_needed)
    -- enviar solicitação HTTP
    local http = require("resty.http")
    local res, err = httpc:request_uri("http://example.com")
    -- acessar o armazenamento
    local acme = require("resty.acme.autossl")
    local value, err = acme.storage:get("key")
    -- obter certificado do cache LRU do resty
    -- cached = { pkey, cert } ou nil se o certificado não estiver no cache
    local cached, staled, flags = acme.get_cert_from_cache(domain, "rsa")
    -- fazer algo para verificar o domínio
    -- retornar is_domain_included
end

A função domain_whitelist_callback é fornecida com um segundo argumento, que indica se o certificado está prestes a ser servido em uma solicitação HTTP recebida (falso) ou se um novo certificado está prestes a ser solicitado (verdadeiro). Isso permite usar valores em cache no caminho quente (servindo solicitações) enquanto busca dados frescos do armazenamento para novos certificados. Também é possível implementar uma lógica diferente, por exemplo, fazer verificações extras antes de solicitar um novo certificado.

Definir período de resfriamento em caso de falha

Em caso de falha na solicitação do certificado, pode-se querer evitar que o cliente ACME solicite outro certificado imediatamente. Por padrão, o período de resfriamento é definido como 300 segundos (5 minutos). Pode ser personalizado com failure_cooloff ou com a função failure_cooloff_callback, por exemplo, para implementar backoff 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

Desafio tls-alpn-01

O desafio tls-alpn-01 é atualmente suportado no Openresty 1.15.8.x, 1.17.8.x e 1.19.3.x.

Clique para expandir a configuração de exemplo
events {}

http {
    resolver 8.8.8.8 ipv6=off;

    lua_shared_dict acme 16m;

    # necessário para verificar a 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({
            -- definir o seguinte como verdadeiro
            -- implica que você leu e aceitou https://letsencrypt.org/repository/
            tos_accepted = true,
            -- descomente o seguinte para configuração inicial
            -- staging = true,
            -- descomente o seguinte para habilitar certificado duplo RSA + ECC
            -- domain_key_types = { 'rsa', 'ecc' },
            -- descomente o seguinte para habilitar o desafio 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 fallback, certifique-se de criá-los previamente
        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({
            -- definir o seguinte como verdadeiro
            -- implica que você leu e aceitou https://letsencrypt.org/repository/
            tos_accepted = true,
            -- descomente o seguinte para configuração inicial
            -- staging = true,
            -- descomente o seguinte para habilitar certificado duplo RSA + ECC
            -- domain_key_types = { 'rsa', 'ecc' },
            -- descomente o seguinte para habilitar o desafio 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;

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

Na configuração de exemplo acima, configuramos um servidor http e dois servidores de stream.

O servidor de stream na frente escuta na porta 443 e roteia para diferentes upstreams com base no ALPN do cliente. O respondedor tls-alpn-01 escuta em unix:/tmp/nginx-tls-alpn.sock. Todo o tráfego https normal escuta em unix:/tmp/nginx-default.sock.

                                                [stream server unix:/tmp/nginx-tls-alpn.sock ssl]
                                            Y /
[stream server 443] --- ALPN é acme-tls ?
                                            N \
                                                [http server unix:/tmp/nginx-default.sock ssl]
  • A configuração passada para require("resty.acme.autossl").init em ambos os subsistemas deve ser mantida o mais semelhante possível.
  • O manipulador de desafio tls-alpn-01 não precisa de nenhuma dependência de terceiros.
  • Você pode habilitar os manipuladores de desafio http-01 e tls-alpn-01 ao mesmo tempo.
  • Os subsistemas http e stream não compartilham shm, portanto, considere usar um armazenamento diferente de shm. Se você precisar usar shm, precisará aplicar este patch.

Desafio dns-01

O desafio DNS-01 é suportado no lua-resty-acme > 0.13.0. Atualmente, os seguintes provedores DNS são suportados:

  • cloudflare: Cloudflare
  • dynv6: Dynv6
  • dnspod-intl: Dnspod Internacional (apenas o token Dnspod é suportado e use id,token no campo secreto)

Para saber como estender um novo provedor DNS para trabalhar com o desafio dns-01, veja Provedor DNS.

Uma configuração de exemplo para usar o desafio dns-01 seria:

require("resty.acme.autossl").init({
  -- definir o seguinte como verdadeiro
  -- implica que você leu e aceitou https://letsencrypt.org/repository/
  tos_accepted = true,
  -- descomente o seguinte para configuração inicial
  -- staging = true,
  -- descomente o seguinte para habilitar certificado duplo RSA + ECC
  -- domain_key_types = { 'rsa', 'ecc' },
  -- não defina `http-01` ou `tls-alpn-01` se você apenas planeja 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 of cloudflare",
      domains = { "example.com" },
    },
    {
      name = "dynv6_staging",
      provider = "dynv6",
      secret = "apikey of dynv6",
      domains = { "*.anotherdomain.com" },
    },
  },
  -- descomente o seguinte para criar anotherdomain.com em CN e *.anotherdomain.com em SAN
  -- wildcard_domain_in_san = true,
})

Por padrão, esta biblioteca tenta até 5 minutos para a propagação DNS. Se o TTL padrão para o provedor DNS for maior que isso, o usuário pode querer ajustar manualmente challenge_start_delay para esperar mais.

resty.acme.autossl

Uma tabela de configuração pode ser passada para resty.acme.autossl.init(), os valores padrão são:

default_config = {
  -- aceitar termos de serviço https://letsencrypt.org/repository/
  tos_accepted = false,
  -- se usar a API de staging do Let's Encrypt
  staging = false,
  -- o caminho para a chave privada da conta em formato PEM
  account_key_path = nil,
  -- o e-mail da conta para registro
  account_email = nil,
  -- número de cache de certificados, por tipo
  cache_size = 100,
  domain_key_paths = {
    -- a chave privada RSA global do domínio
    rsa = nil,
    -- a chave privada ECC global do domínio
    ecc = nil,
  },
  -- o algoritmo de chave privada a ser usado, pode ser um ou ambos de
  -- 'rsa' e 'ecc'
  domain_key_types = { 'rsa' },
  -- restringir o registro de novos certificados apenas aos domínios definidos nesta tabela
  domain_whitelist = nil,
  -- restringir o registro de novos certificados apenas aos domínios verificados por esta função
  domain_whitelist_callback = nil,
  -- intervalo a esperar antes de tentar novamente após falha na solicitação do certificado
  failure_cooloff = 300,
  -- função que retorna o intervalo a esperar antes de tentar novamente após falha na solicitação do certificado
  failure_cooloff_callback = nil,
  -- o limite para renovar um certificado antes de expirar, em segundos
  renew_threshold = 7 * 86400,
  -- intervalo para verificar a renovação do certificado, em segundos
  renew_check_interval = 6 * 3600,
  -- o adaptador de armazenamento de certificados
  storage_adapter = "shm",
  -- a configuração de armazenamento passada para o adaptador de armazenamento
  storage_config = {
    shm_name = 'acme',
  },
  -- os tipos de desafios habilitados
  enabled_challenge_handlers = { 'http-01' },
  -- tempo a esperar antes de sinalizar o servidor ACME para validar em segundos
  challenge_start_delay = 0,
  -- se verdadeiro, a solicitação para o nginx espera até que o certificado tenha sido gerado e é usado imediatamente
  blocking = false,
  -- se verdadeiro, o certificado para domínio não na lista de permissões será excluído do armazenamento
  enabled_delete_not_whitelisted_domain = false,
  -- o dicionário de provedores DNS, cada provedor deve ter a seguinte estrutura:
  -- {
  --   name = "prod_account",
  --   provider = "provider_name", -- "cloudflare" ou "dynv6"
  --   secret  = "the api key or token",
  --   domains = { "example.com", "*.example.com" }, -- a lista de domínios que podem ser usados com este provedor
  -- }
  dns_provider_accounts = {},
  -- se habilitado, domínios curinga como *.example.com serão criados como SAN e CN será example.com
  wildcard_domain_in_san = false,
}

Se account_key_path não for especificado, uma nova chave de conta será criada toda vez que o Nginx recarregar a configuração. Observe que isso pode acionar Limite de Taxa de Nova Conta rate limiting na API Let's Encrypt.

Se domain_key_paths não for especificado, uma nova chave privada será gerada para cada certificado (RSA de 4096 bits e ECC de 256 bits prime256v1). Observe que gerar tal chave bloqueará o trabalhador e será especialmente notável em VMs onde a entropia é baixa.

Passe a tabela de configuração diretamente para o cliente ACME como segundo parâmetro. O seguinte exemplo demonstra como usar um provedor CA diferente do Let's Encrypt e também definir a cadeia 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",
  }
)

Veja também Adaptadores de Armazenamento abaixo.

Ao usar tipos de armazenamento distribuídos, é útil aumentar challenge_start_delay para permitir que as mudanças no armazenamento se propaguem. Quando challenge_start_delay é definido como 0, nenhuma espera será realizada antes de começar a validar desafios.

autossl.get_certkey

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

Retorna o certificado codificado em PEM e a chave privada para domain do armazenamento. Opcionalmente aceita um parâmetro type que pode ser "rsa" ou "ecc"; se omitido, type será padrão para "rsa".

resty.acme.client

client.new

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

Cria um cliente ACMEv2.

Os valores padrão para config são:

default_config = {
  -- o endpoint da API ACME v2 a ser usado
  api_uri = "https://acme-v02.api.letsencrypt.org/directory",
  -- o e-mail da conta para registro
  account_email = nil,
  -- a chave da conta em texto no formato PEM
  account_key = nil,
  -- o kid da conta (como uma URL)
  account_kid = nil,
  -- id da chave de vinculação de conta externa
  eab_kid = nil,
  -- chave hmac de vinculação de conta externa, codificada em base64url
  eab_hmac_key = nil,
  -- manipulador de registro de conta externa
  eab_handler = nil,
  -- armazenamento para desafio
  storage_adapter = "shm",
  -- a configuração de armazenamento passada para o adaptador de armazenamento
  storage_config = {
    shm_name = "acme"
  },
  -- os tipos de desafios habilitados, seleção de `http-01` e `tls-alpn-01`
  enabled_challenge_handlers = {"http-01"},
  -- selecione o Nome Comum do emissor CA raiz preferido, se aplicável
  preferred_chain = nil,
  -- função de callback que permite esperar antes de sinalizar o servidor ACME para validar
  challenge_start_callback = nil,
  -- o dicionário de provedores DNS, cada provedor deve ter a seguinte estrutura:
  dns_provider_accounts = {},
}

Se account_kid for omitido, o usuário deve chamar client:new_account() para registrar uma nova conta. Observe que ao usar a mesma account_key, client:new_account() retornará o mesmo kid que foi registrado anteriormente.

Se a CA exigir Vinculação de Conta Externa, o usuário pode definir eab_kid e eab_hmac_key para carregar uma conta existente ou definir account_email e eab_handler para registrar uma nova conta. eab_hmac_key deve ser codificado em base64 url. Neste último caso, o usuário deve chamar client:new_account() para registrar uma nova conta. eab_handler deve ser uma função que aceita account_email como parâmetro e retorna eab_kid, eab_hmac_key e erro, se houver.

eab_handler = function(account_email)
  -- faça algo para registrar uma conta com account_email
  -- se err então
  --  return nil, nil, err
  -- end
  return eab_kid, eab_hmac_key
end

O manipulador EAB do seguinte provedor CA é suportado pelo lua-resty-acme e o usuário não precisa implementar seu próprio eab_handler:

preferred_chain é usado para selecionar uma cadeia com Nome Comum correspondente em sua CA raiz. Por exemplo, o usuário pode usar "ISRG Root X1" para forçar o uso da nova cadeia padrão no Let's Encrypt. Quando nenhum valor é configurado ou o nome configurado não é encontrado em nenhuma cadeia, a cadeia padrão será usada.

challenge_start_callback é uma função de callback para permitir que o cliente espere antes de sinalizar o servidor ACME para começar a validar o desafio. É útil em uma configuração distribuída onde os desafios levam tempo para se propagar. challenge_start_callback aceita challenge_type e challenge_token. O cliente chama essa função a cada segundo até que ela retorne true, indicando que o desafio deve começar; se esse challenge_start_callback não estiver definido, nenhuma espera será realizada.

challenge_start_callback = function(challenge_type, challenge_token)
  -- faça algo aqui
  -- se estivermos bem
  return true
end

Veja também Adaptadores de Armazenamento abaixo.

client:init

sintaxe: err = client:init()

Inicializa o cliente, requer disponibilidade da API de cosocket. Esta função fará login ou registrará uma conta.

client:order_certificate

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

Cria um certificado com um ou mais domínios. Observe que domínios curinga não são suportados, pois só podem ser verificados pelo desafio dns-01.

client:serve_http_challenge

sintaxe: client:serve_http_challenge()

Serve o desafio http-01. Um caso de uso comum será colocá-lo como um bloco content_by_* para o caminho /.well-known.

client:serve_tls_alpn_challenge

sintaxe: client:serve_tls_alpn_challenge()

Serve o desafio tls-alpn-01. Veja esta seção sobre como usar este manipulador.

Adaptadores de Armazenamento

Os adaptadores de armazenamento são usados em autossl ou no cliente acme para armazenar dados temporários ou persistentes. Dependendo do ambiente de implantação, atualmente existem cinco adaptadores de armazenamento disponíveis para seleção. Para implementar um adaptador de armazenamento personalizado, consulte este documento.

file

Armazenamento baseado em sistema de arquivos. Configuração de exemplo:

storage_config = {
    dir = '/etc/openresty/storage',
}
Se dir for omitido, o diretório temporário do SO será usado.

luafilesystem ou luafilesystem-ffi é necessário ao usar o armazenamento file para renovação.

shm

Armazenamento baseado em dicionário compartilhado Lua. Observe que este armazenamento é volátil entre reinicializações do Nginx (não recarregamentos). Configuração de exemplo:

storage_config = {
    shm_name = 'dict_name',
}

redis

Armazenamento baseado em Redis. A configuração padrão é:

storage_config = {
    host = '127.0.0.1',
    port = 6379,
    database = 0,
    -- chave de autenticação do Redis
    auth = nil,
    ssl = false,
    ssl_verify = false,
    ssl_server_name = nil,
    -- namespace como um prefixo da chave
    namespace = "",
}

Redis >= 2.6.12 é necessário, pois este armazenamento requer SET EX.

vault

Armazenamento baseado em Hashicorp Vault. Apenas o backend KV V2 é suportado. A configuração padrão é:

storage_config = {
    host = '127.0.0.1',
    port = 8200,
    -- caminho do prefixo de segredos kv
    kv_path = "acme",
    -- timeout em ms
    timeout = 2000,
    -- usar HTTPS
    https = false,
    -- ativar verificação tls
    tls_verify = true,
    -- SNI usado na solicitação, padrão para host se omitido
    tls_server_name = nil,
    -- Método de Autenticação, padrão para token, pode ser "token" ou "kubernetes"
    auth_method = "token",
    -- Token do Vault
    token = nil,
    -- Caminho de autenticação do Vault a ser usado
    auth_path =  "kubernetes",
    -- O papel a tentar atribuir
    auth_role = nil,
    -- O caminho para o JWT
    jwt_path = "/var/run/secrets/kubernetes.io/serviceaccount/token",
    -- Namespace do Vault
    namespace = nil,
}

Suporte para diferentes métodos de autenticação

  • Token: Este é o padrão e permite passar um "token" literal na configuração.
  • Kubernetes: Por meio deste método, pode-se utilizar o método de autenticação interno do vault para kubernetes. Basicamente, isso pega o token da conta de serviço e valida que foi assinado pela CA do Kubernetes. O principal benefício aqui é que os arquivos de configuração não expõem mais seu token.

As seguintes configurações se aplicam aqui: lua -- Caminho de autenticação do Vault a ser usado auth_path = "kubernetes", -- O papel a tentar atribuir auth_role = nil, -- O caminho para o JWT jwt_path = "/var/run/secrets/kubernetes.io/serviceaccount/token",

consul

Armazenamento baseado em Hashicorp Consul. A configuração padrão é:

storage_config = {
    host = '127.0.0.1',
    port = 8500,
    -- caminho do prefixo kv
    kv_path = "acme",
    -- token ACL do Consul
    token = nil,
    -- timeout em ms
    timeout = 2000,
}

etcd

Armazenamento baseado em etcd. Atualmente, apenas o protocolo v3 é suportado, e a versão do servidor etcd deve ser >= v3.4.0. A configuração padrão é:

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

O armazenamento etcd requer a biblioteca lua-resty-etcd instalada. Pode ser instalada manualmente com opm install api7/lua-resty-etcd ou luarocks install lua-resty-etcd.

Provedores DNS

Para criar um provedor DNS personalizado, siga estas etapas:

  • Crie um arquivo como route53.lua em lib/resty/acme/dns_provider
  • Implemente a seguinte assinatura de função
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

Onde token é a chave da API, fqdn é o nome do registro DNS a ser definido, e content é o valor do registro.

Testes

Configure o ambiente de teste e2e executando bash t/fixtures/prepare_env.sh.

Em seguida, execute cpanm install Test::Nginx::Socket e depois prove -r t.

Veja Também

GitHub

Você pode encontrar dicas adicionais de configuração e documentação para este módulo no repositório GitHub do nginx-module-acme.