acme: Автоматическое обслуживание сертификатов Let's Encrypt и реализация протокола ACMEv2 на Lua
Установка
Если вы еще не подписались на RPM репозиторий, зарегистрируйтесь. После этого вы можете продолжить с следующими шагами.
CentOS/RHEL 7 или 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
Чтобы использовать эту библиотеку Lua с NGINX, убедитесь, что nginx-module-lua установлен.
Этот документ описывает lua-resty-acme v0.16.0, выпущенную 1 сентября 2025 года.
Автоматическое обслуживание сертификатов Let's Encrypt (RSA + ECC) и чистая реализация протокола ACMEv2 на Lua.
Поддерживаются вызовы http-01 и tls-alpn-01.
Описание
Эта библиотека состоит из двух частей:
resty.acme.autossl: автоматическое управление жизненным циклом сертификатов Let's Encryptresty.acme.client: реализация протокола ACME v2 на Lua
Установите с помощью opm:
opm install fffonion/lua-resty-acme
В качестве альтернативы, для установки с помощью luarocks:
luarocks install lua-resty-acme
## вручную установите luafilesystem
luarocks install luafilesystem
Обратите внимание, что вам нужно будет вручную установить luafilesystem, когда вы используете LuaRocks. Это сделано для поддержания обратной совместимости.
Эта библиотека использует бэкенд openssl на основе FFI, который в настоящее время поддерживает серии OpenSSL 1.1.1, 1.1.0 и 1.0.2.
Синопсис
Создайте закрытый ключ учетной записи и резервные сертификаты:
## создайте ключ учетной записи
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -out /etc/openresty/account.key
## создайте резервный сертификат и ключ
openssl req -newkey rsa:2048 -nodes -keyout /etc/openresty/default.key -x509 -days 365 -out /etc/openresty/default.pem
Используйте следующий пример конфигурации:
events {}
http {
resolver 8.8.8.8 ipv6=off;
lua_shared_dict acme 16m;
# требуется для проверки 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({
-- установка следующего в true
-- подразумевает, что вы прочитали и приняли https://letsencrypt.org/repository/
tos_accepted = true,
-- раскомментируйте следующее для первого запуска
-- staging = true,
-- раскомментируйте следующее, чтобы включить двойной сертификат RSA + ECC
-- domain_key_types = { 'rsa', 'ecc' },
-- раскомментируйте следующее, чтобы включить вызов 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;
# резервные сертификаты, убедитесь, что вы создали их заранее
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()
}
}
}
}
При тестировании развертывания рекомендуется раскомментировать staging = true, чтобы позволить провести тестирование вашей среды от начала до конца. Это может помочь избежать сбоя конфигурации, который приведет к слишком большому количеству запросов, попадающих под ограничения по количеству запросов на API Let's Encrypt.
По умолчанию autossl создает только сертификаты RSA. Чтобы использовать сертификаты ECC или оба, раскомментируйте domain_key_types = { 'rsa', 'ecc' }. Обратите внимание, что несколько цепочек сертификатов поддерживаются только в NGINX 1.11.0 или более поздних версиях.
Сертификат будет поставлен в очередь на создание после того, как Nginx увидит запрос с таким SNI, что может занять десятки секунд для завершения. В это время запросы с таким SNI будут отвечены резервным сертификатом.
Обратите внимание, что domain_whitelist или domain_whitelist_callback должны быть установлены, чтобы включить ваш домен, который вы хотите обслуживать с помощью autossl, чтобы предотвратить потенциальное злоупотребление с использованием поддельного SNI в SSL-рукопожатии.
domain_whitelist определяет таблицу, которая включает все домены, которые должны быть включены, и CN, который будет использоваться для создания сертификата. Разрешен только один * в качестве подстановочного знака.
domain_whitelist = { "domain1.com", "domain2.com", "domain3.com", "*.domain4.com" },
Подстановочные сертификаты
Чтобы эта библиотека могла создавать подстановочный сертификат, должны быть выполнены следующие требования:
- Подстановочный домен должен точно появляться как
*.somedomain.comвdomain_whitelist. - Вызов
dns-01должен быть включен, и необходимо настроить провайдера DNS, у которого естьdomains, соответствующие домену.
В противном случае будет создан не подстановочный сертификат в качестве резервного.
По умолчанию подстановочный домен *.example.com будет появляться в общем имени. Однако, когда wildcard_domain_in_san установлен в true, будет создан сертификат с общим именем example.com и альтернативным именем субъекта *.example.com. Обратите внимание, что как *.example.com, так и example.com должны появляться в dns_provider_accounts.
Расширенное использование
Используйте функцию для включения доменов
domain_whitelist_callback определяет функцию, которая принимает домен в качестве параметра и возвращает булево значение, чтобы указать, следует ли его включать.
Чтобы сопоставить шаблон в вашем доменном имени, например, все поддомены под example.com, используйте:
domain_whitelist_callback = function(domain, is_new_cert_needed)
return ngx.re.match(domain, [[\.example\.com$]], "jo")
end
Более того, поскольку проверка белого списка доменов выполняется на этапе сертификата, здесь можно использовать API cosocket. Обратите внимание, что это увеличит задержку SSL-рукопожатия.
domain_whitelist_callback = function(domain, is_new_cert_needed)
-- отправить HTTP запрос
local http = require("resty.http")
local res, err = httpc:request_uri("http://example.com")
-- получить доступ к хранилищу
local acme = require("resty.acme.autossl")
local value, err = acme.storage:get("key")
-- получить сертификат из кэша resty LRU
-- cached = { pkey, cert } или nil, если сертификат не в кэше
local cached, staled, flags = acme.get_cert_from_cache(domain, "rsa")
-- сделайте что-то, чтобы проверить домен
-- верните is_domain_included
end
Функция domain_whitelist_callback предоставляется со вторым аргументом, который указывает, будет ли сертификат обслуживаться по входящему HTTP-запросу (false) или новый сертификат будет запрашиваться (true). Это позволяет использовать кэшированные значения на горячем пути (обслуживание запросов), в то время как свежие данные извлекаются из хранилища для новых сертификатов. Также можно реализовать различную логику, например, выполнять дополнительные проверки перед запросом нового сертификата.
Определите период охлаждения при сбое
В случае сбоя запроса сертификата может возникнуть необходимость предотвратить немедленный запрос другого сертификата клиентом ACME. По умолчанию период охлаждения установлен на 300 секунд (5 минут). Его можно настроить с помощью failure_cooloff или с помощью функции failure_cooloff_callback, например, для реализации экспоненциального увеличения времени ожидания.
failure_cooloff_callback = function(domain, count)
if count == 1 then
return 600 -- 10 минут
elseif count == 2 then
return 1800 -- 30 минут
elseif count == 3 then
return 3600 -- 1 час
elseif count == 4 then
return 43200 -- 12 часов
elseif count == 5 then
return 43200 -- 12 часов
else
return 86400 -- 24 часа
end
end
Вызов tls-alpn-01
Вызов tls-alpn-01 в настоящее время поддерживается в Openresty 1.15.8.x, 1.17.8.x и 1.19.3.x.
Нажмите, чтобы развернуть пример конфигурации
events {}
http {
resolver 8.8.8.8 ipv6=off;
lua_shared_dict acme 16m;
# требуется для проверки 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({
-- установка следующего в true
-- подразумевает, что вы прочитали и приняли https://letsencrypt.org/repository/
tos_accepted = true,
-- раскомментируйте следующее для первого запуска
-- staging = true,
-- раскомментируйте следующее, чтобы включить двойной сертификат RSA + ECC
-- domain_key_types = { 'rsa', 'ecc' },
-- раскомментируйте следующее, чтобы включить вызов 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;
# резервные сертификаты, убедитесь, что вы создали их заранее
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({
-- установка следующего в true
-- подразумевает, что вы прочитали и приняли https://letsencrypt.org/repository/
tos_accepted = true,
-- раскомментируйте следующее для первого запуска
-- staging = true,
-- раскомментируйте следующее, чтобы включить двойной сертификат RSA + ECC
-- domain_key_types = { 'rsa', 'ecc' },
-- раскомментируйте следующее, чтобы включить вызов 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;
# требует --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)
}
}
}
В приведенном выше примере конфигурации мы настраиваем HTTP-сервер и два стрим-сервера.
Самый передний стрим-сервер слушает порт 443 и маршрутизирует на разные upstream в зависимости от ALPN клиента. Ответчик tls-alpn-01 слушает на unix:/tmp/nginx-tls-alpn.sock. Весь обычный HTTPS-трафик слушает на unix:/tmp/nginx-default.sock.
[стрим-сервер unix:/tmp/nginx-tls-alpn.sock ssl]
Y /
[стрим-сервер 443] --- ALPN это acme-tls ?
N \
[HTTP-сервер unix:/tmp/nginx-default.sock ssl]
- Конфигурация, переданная в
require("resty.acme.autossl").initв обеих подсистемах, должна быть как можно более одинаковой. - Обработчик вызова
tls-alpn-01не требует никаких сторонних зависимостей. - Вы можете одновременно включить обработчики вызовов
http-01иtls-alpn-01. - Подсистемы
httpиstreamне делят shm, поэтому рассмотрите возможность использования хранилища, отличного отshm. Если вы должны использоватьshm, вам нужно будет применить этот патч.
Вызов dns-01
Вызов DNS-01 поддерживается в lua-resty-acme > 0.13.0. В настоящее время поддерживаются следующие провайдеры DNS:
cloudflare: Cloudflaredynv6: Dynv6dnspod-intl: Dnspod International (поддерживается только токен Dnspod и используйтеid,tokenв поле secret)
Чтобы узнать, как расширить новый провайдер DNS для работы с вызовом dns-01, смотрите DNS provider.
Пример конфигурации для использования вызова dns-01 будет следующим:
require("resty.acme.autossl").init({
-- установка следующего в true
-- подразумевает, что вы прочитали и приняли https://letsencrypt.org/repository/
tos_accepted = true,
-- раскомментируйте следующее для первого запуска
-- staging = true,
-- раскомментируйте следующее, чтобы включить двойной сертификат RSA + ECC
-- domain_key_types = { 'rsa', 'ecc' },
-- не устанавливайте `http-01` или `tls-alpn-01`, если вы планируете использовать только 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" },
},
},
-- раскомментируйте следующее, чтобы создать anotherdomain.com в CN и *.anotherdomain.com в SAN
-- wildcard_domain_in_san = true,
})
По умолчанию эта библиотека пытается подождать до 5 минут для распространения DNS. Если TTL по умолчанию для провайдера DNS больше, чем это, пользователю может понадобиться вручную настроить challenge_start_delay, чтобы подождать дольше.
resty.acme.autossl
Конфигурационная таблица может быть передана в resty.acme.autossl.init(), значения по умолчанию:
default_config = {
-- принять условия обслуживания https://letsencrypt.org/repository/
tos_accepted = false,
-- если используется тестовый API Let's Encrypt
staging = false,
-- путь к закрытому ключу учетной записи в формате PEM
account_key_path = nil,
-- адрес электронной почты учетной записи для регистрации
account_email = nil,
-- количество кэша сертификатов, по типу
cache_size = 100,
domain_key_paths = {
-- глобальный закрытый ключ RSA домена
rsa = nil,
-- глобальный закрытый ключ ECC домена
ecc = nil,
},
-- алгоритм закрытого ключа для использования, может быть один или оба
-- 'rsa' и 'ecc'
domain_key_types = { 'rsa' },
-- ограничить регистрацию нового сертификата только доменами, определенными в этой таблице
domain_whitelist = nil,
-- ограничить регистрацию нового сертификата только доменами, проверяемыми этой функцией
domain_whitelist_callback = nil,
-- интервал ожидания перед повторной попыткой после неудачного запроса сертификата
failure_cooloff = 300,
-- функция, которая возвращает интервал ожидания перед повторной попыткой после неудачного запроса сертификата
failure_cooloff_callback = nil,
-- порог для обновления сертификата до его истечения, в секундах
renew_threshold = 7 * 86400,
-- интервал проверки обновления сертификата, в секундах
renew_check_interval = 6 * 3600,
-- хранилище сертификатов
storage_adapter = "shm",
-- конфигурация хранилища, переданная адаптеру хранилища
storage_config = {
shm_name = 'acme',
},
-- включенные типы вызовов
enabled_challenge_handlers = { 'http-01' },
-- время ожидания перед сигнализацией серверу ACME для проверки в секундах
challenge_start_delay = 0,
-- если true, запрос к nginx ждет, пока сертификат будет сгенерирован, и используется сразу
blocking = false,
-- если true, сертификат для домена, не входящего в белый список, будет удален из хранилища
enabled_delete_not_whitelisted_domain = false,
-- словарь провайдеров DNS, каждый провайдер должен иметь следующую структуру:
-- {
-- name = "prod_account",
-- provider = "provider_name", -- "cloudflare" или "dynv6"
-- secret = "api key или token",
-- domains = { "example.com", "*.example.com" }, -- список доменов, которые можно использовать с этим провайдером
-- }
dns_provider_accounts = {},
-- если включено, подстановочные домены, такие как *.example.com, будут созданы как SAN, а CN будет example.com
wildcard_domain_in_san = false,
}
Если account_key_path не указан, новый ключ учетной записи будет создаваться каждый раз, когда Nginx перезагружает конфигурацию. Обратите внимание, что это может вызвать ограничение по количеству запросов на API Let's Encrypt.
Если domain_key_paths не указаны, новый закрытый ключ будет генерироваться для каждого сертификата (4096-битный RSA и 256-битный prime256v1 ECC). Обратите внимание, что генерация такого ключа будет блокировать рабочий процесс и будет особенно заметна на ВМ, где низкая энтропия.
Передайте конфигурационную таблицу непосредственно клиенту ACME в качестве второго параметра. Следующий пример демонстрирует, как использовать провайдера CA, отличного от Let's Encrypt, и также установить предпочитаемую цепочку.
resty.acme.autossl.init({
tos_accepted = true,
account_email = "[email protected]",
}, {
api_uri = "https://acme.otherca.com/directory",
preferred_chain = "OtherCA PKI Root CA",
}
)
Смотрите также Адаптеры хранилища ниже.
При использовании распределенных типов хранилища полезно увеличить challenge_start_delay, чтобы изменения в хранилище могли распространиться. Когда challenge_start_delay установлен в 0, никакого ожидания не будет перед началом проверки вызовов.
autossl.get_certkey
синтаксис: certkey, err = autossl.get_certkey(domain, type?)
Возвращает сертификат в формате PEM и закрытый ключ для domain из хранилища. Опционально принимает параметр type, который может быть "rsa" или "ecc"; если он опущен, type по умолчанию будет равен "rsa".
resty.acme.client
client.new
синтаксис: c, err = client.new(config)
Создает клиент ACMEv2.
Значения по умолчанию для config:
default_config = {
-- конечная точка API ACME v2 для использования
api_uri = "https://acme-v02.api.letsencrypt.org/directory",
-- адрес электронной почты учетной записи для регистрации
account_email = nil,
-- ключ учетной записи в формате PEM
account_key = nil,
-- kid учетной записи (как URL)
account_kid = nil,
-- внешний идентификатор ключа для привязки учетной записи
eab_kid = nil,
-- внешний ключ HMAC для привязки учетной записи, закодированный в base64url
eab_hmac_key = nil,
-- обработчик регистрации внешней учетной записи
eab_handler = nil,
-- хранилище для вызова
storage_adapter = "shm",
-- конфигурация хранилища, переданная адаптеру хранилища
storage_config = {
shm_name = "acme"
},
-- включенные типы вызовов, выбор `http-01` и `tls-alpn-01`
enabled_challenge_handlers = {"http-01"},
-- выберите предпочитаемое общее имя корневого CA, если применимо
preferred_chain = nil,
-- функция обратного вызова, которая позволяет ждать перед сигнализацией серверу ACME для проверки
challenge_start_callback = nil,
-- словарь провайдеров DNS, каждый провайдер должен иметь следующую структуру:
dns_provider_accounts = {},
}
Если account_kid опущен, пользователю необходимо вызвать client:new_account(), чтобы зарегистрировать новую учетную запись. Обратите внимание, что при использовании одного и того же account_key, client:new_account() вернет тот же kid, который был зарегистрирован ранее.
Если CA требует Привязки внешней учетной записи, пользователь может установить eab_kid и eab_hmac_key, чтобы загрузить существующую учетную запись, или установить account_email и eab_handler, чтобы зарегистрировать новую учетную запись. eab_hmac_key должен быть закодирован в base64 url. В последнем случае пользователю необходимо вызвать client:new_account(), чтобы зарегистрировать новую учетную запись. eab_handler должен быть функцией, которая принимает account_email в качестве параметра и возвращает eab_kid, eab_hmac_key и ошибку, если таковая имеется.
eab_handler = function(account_email)
-- сделайте что-то для регистрации учетной записи с account_email
-- если err тогда
-- return nil, nil, err
-- end
return eab_kid, eab_hmac_key
end
Следующий обработчик EAB провайдера CA поддерживается lua-resty-acme, и пользователю не нужно реализовывать собственный eab_handler:
preferred_chain используется для выбора цепочки с совпадающим общим именем в ее корневом CA. Например, пользователь может использовать "ISRG Root X1", чтобы заставить использовать новую цепочку по умолчанию в Let's Encrypt. Когда значение не настроено или настроенное имя не найдено в какой-либо цепочке, будет использоваться цепочка по умолчанию.
challenge_start_callback — это функция обратного вызова, которая позволяет клиенту ждать перед сигнализацией серверу ACME для начала проверки вызова. Это полезно в распределенной настройке, где вызовы требуют времени на распространение. challenge_start_callback принимает challenge_type и challenge_token. Клиент вызывает эту функцию каждую секунду, пока она не вернет true, указывая, что вызов должен начаться; если этот challenge_start_callback не установлен, ожидание не будет выполнено.
challenge_start_callback = function(challenge_type, challenge_token)
-- сделайте что-то здесь
-- если все хорошо
return true
end
Смотрите также Адаптеры хранилища ниже.
client:init
синтаксис: err = client:init()
Инициализирует клиент, требует доступности API cosocket. Эта функция войдет в систему или зарегистрирует учетную запись.
client:order_certificate
синтаксис: err = client:order_certificate(domain,...)
Создает сертификат с одним или несколькими доменами. Обратите внимание, что подстановочные домены не поддерживаются, так как их можно проверить только с помощью вызова dns-01.
client:serve_http_challenge
синтаксис: client:serve_http_challenge()
Обслуживает вызов http-01. Общий случай использования будет заключаться в том, чтобы поместить это в блок content_by_* для пути /.well-known.
client:serve_tls_alpn_challenge
синтаксис: client:serve_tls_alpn_challenge()
Обслуживает вызов tls-alpn-01. Смотрите этот раздел о том, как использовать этот обработчик.
Адаптеры хранилища
Адаптеры хранилища используются в autossl или клиенте acme для хранения временных или постоянных данных. В зависимости от среды развертывания в настоящее время доступно пять адаптеров хранилища на выбор. Чтобы реализовать пользовательский адаптер хранилища, пожалуйста, обратитесь к этому документу.
file
Хранилище на основе файловой системы. Пример конфигурации:
storage_config = {
dir = '/etc/openresty/storage',
}
dir опущен, будет использоваться временный каталог ОС.
luafilesystem или luafilesystem-ffi необходимы при использовании хранилища file для обновления.
shm
Хранилище на основе общего словаря Lua. Обратите внимание, что это хранилище является временным между перезапусками Nginx (не перезагрузками). Пример конфигурации:
storage_config = {
shm_name = 'dict_name',
}
redis
Хранилище на основе Redis. Конфигурация по умолчанию:
storage_config = {
host = '127.0.0.1',
port = 6379,
database = 0,
-- Ключ аутентификации Redis
auth = nil,
ssl = false,
ssl_verify = false,
ssl_server_name = nil,
-- пространство имен в качестве префикса ключа
namespace = "",
}
Требуется Redis >= 2.6.12, так как это хранилище требует SET EX.
vault
Хранилище на основе Hashicorp Vault. Поддерживается только KV V2 бэкенд. Конфигурация по умолчанию:
storage_config = {
host = '127.0.0.1',
port = 8200,
-- путь префикса секретов kv
kv_path = "acme",
-- тайм-аут в мс
timeout = 2000,
-- использовать HTTPS
https = false,
-- включить проверку tls
tls_verify = true,
-- SNI, используемый в запросе, по умолчанию хост, если опущен
tls_server_name = nil,
-- Метод аутентификации, по умолчанию токен, может быть "token" или "kubernetes"
auth_method = "token",
-- Токен Vault
token = nil,
-- Путь аутентификации Vault для использования
auth_path = "kubernetes",
-- Роль, которую нужно попытаться назначить
auth_role = nil,
-- Путь к JWT
jwt_path = "/var/run/secrets/kubernetes.io/serviceaccount/token",
-- Пространство имен Vault
namespace = nil,
}
Поддержка различных методов аутентификации
- Токен: Это значение по умолчанию и позволяет передавать буквальный "токен" в конфигурации.
- Kubernetes: С помощью этого метода можно использовать встроенный метод аутентификации Vault для Kubernetes. Что это в основном делает, так это берет токен сервисной учетной записи и проверяет, что он был подписан CA Kubernetes. Основное преимущество здесь в том, что конфигурационные файлы больше не раскрывают ваш токен.
Применяются следующие конфигурации:
lua
-- Путь аутентификации Vault для использования
auth_path = "kubernetes",
-- Роль, которую нужно попытаться назначить
auth_role = nil,
-- Путь к JWT
jwt_path = "/var/run/secrets/kubernetes.io/serviceaccount/token",
consul
Хранилище на основе Hashicorp Consul. Конфигурация по умолчанию:
storage_config = {
host = '127.0.0.1',
port = 8500,
-- путь префикса kv
kv_path = "acme",
-- токен ACL Consul
token = nil,
-- тайм-аут в мс
timeout = 2000,
}
etcd
Хранилище на основе etcd. В настоящее время поддерживается только протокол v3, и версия сервера etcd должна быть >= v3.4.0. Конфигурация по умолчанию:
storage_config = {
http_host = 'http://127.0.0.1:4001',
key_prefix = '',
timeout = 60,
ssl_verify = false,
}
Хранилище etcd требует установленной библиотеки lua-resty-etcd. Его можно установить вручную с помощью opm install api7/lua-resty-etcd или luarocks install lua-resty-etcd.
Провайдеры DNS
Чтобы создать пользовательский провайдер DNS, выполните следующие шаги:
- Создайте файл, например
route53.lua, в каталогеlib/resty/acme/dns_provider - Реализуйте следующую сигнатуру функции
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
Где token — это api-ключ, fqdn — это имя DNS-записи для установки записи, а content — это значение записи.
Тестирование
Настройте среду e2e тестирования, запустив bash t/fixtures/prepare_env.sh.
Затем выполните cpanm install Test::Nginx::Socket, а затем prove -r t.
Смотрите также
- Автоматическое управление сертификатами (ACME)
- haproxytech/haproxy-lua-acme Реализация ACME на Lua, используемая в HAProxy.
- GUI/lua-resty-auto-ssl
- lua-resty-openssl
- Ограничения по количеству запросов API Let's Encrypt
GitHub
Вы можете найти дополнительные советы по конфигурации и документацию для этого модуля в репозитории GitHub для nginx-module-acme.