paint-brush
AWS LetsEncrypt Lambda или почему я написал собственный TLS-провайдер для AWS с использованием OpenTofu и Goк@kvendingoldo
837 чтения
837 чтения

AWS LetsEncrypt Lambda или почему я написал собственный TLS-провайдер для AWS с использованием OpenTofu и Go

к Alexander Sharov15m2024/06/06
Read on Terminal Reader

Слишком долго; Читать

AWS LetsEncrypt Lambda — это приложение на базе Go 1.22, которое выдает, обновляет и управляет сертификатами AWS с помощью Let’s Encrypt. После выдачи сертификата он сохраняет сертификаты внутри AWS Certificate Manager и AWS Secret Manager. Lambda полностью настраивается и может быть развернута на AWS через Terraform или OpenTofu. Его также можно без проблем выполнить локально.
featured image - AWS LetsEncrypt Lambda или почему я написал собственный TLS-провайдер для AWS с использованием OpenTofu и Go
Alexander Sharov HackerNoon profile picture
0-item
1-item

В наши дни сложно представить системы с общедоступными конечными точками API без защиты сертификатом TLS. Выдать сертификаты можно несколькими способами:


  • Платные групповые сертификаты, которые можно купить у любого крупного провайдера TLS.
  • Платные корневые сертификаты, которые подписывают все нижестоящие сертификаты, выдаваемые корпоративными системами PKI.
  • Бесплатные сертификаты, выданные поставщиками TLS, такими как LetsEncrypt или AWS Certificate Manager.
  • Самозаверяющие сертификаты, выданные OpenSSL или другим инструментом.


В контексте этой статьи я в основном буду обсуждать бесплатные сертификаты, которые можно использовать внутри AWS, но не только сервисами AWS. Очевидно, что использование чего-либо, кроме AWS Certificate Manager, не имеет смысла, если вы используете исключительно управляемые сервисы AWS и не предъявляете строгих требований к безопасности. AWS Certificate Manager предлагает очень удобный и быстрый метод выдачи сертификатов через DNS или HTTP-запросы; однако вы сталкиваетесь с базовыми ограничениями AWS, если вам нужно использовать эти сертификаты за пределами сервисов AWS (API Gateway, ALB, NLB и т. д.), например, экземпляр EC2, на котором работает Nginx, которому требуется физический файл сертификата. Кроме того, даже если вы этого запросите, AWS Certificate Manager не отображает содержимое сертификата.


На этом этапе самое время напомнить вам о LetsEncrypt , более широко используемом инструменте, чем диспетчер сертификатов — хотя бы потому, что он не зависит от облака. К сожалению, в AWS нет встроенных методов выдачи сертификатов LetsEncrypt. Инструмент certbot можно использовать для ваших служб EC2 или ECS, но в этом случае вам нужно будет подумать о том, как настроить процесс продления. Я также не хочу комбинировать разные стратегии, поскольку считаю, что лучше иметь одну процедуру для всего, поскольку это снижает сложность всей системы.


Принимая это во внимание, я создал функцию Lambda, которая автоматически выдает и обновляет сертификаты LetsEncrypt, не требуя сложной настройки. Сертификат можно использовать в любом сервисе AWS, использующем ARN, вместе с сертификатами AWS Certificate Manager после первоначальной выдачи сертификата. Кроме того, вы можете использовать версию физического сертификата, которая хранится в AWS Secrets Manager в любом месте по вашему выбору, будь то экземпляр EC2, на котором работает Nginx, или другое место.

Как работает AWS LetsEncrypt Lambda

В этой статье я буду предполагать, что ваша зона DNS управляется AWS Route53.

Функция Lambda, описанная в этой статье, написана на Go v1.22. Все выходные ресурсы, такие как записи DNS, секреты или сертификаты, контролируются ролью Amazon IAM, которая по умолчанию создается с помощью кода Terraform. Последовательность действий Lambda следующая:


  1. Получите событие, содержащее список сертификатов. Обычно это событие может быть результатом выполнения вручную или выполнения cron с помощью aws_cloudwatch_event_target . Пример события:
 { "domainName": "hackernoon.referrs.me", "acmeUrl": "prod", "acmeEmail": "[email protected]", "reImportThreshold": 10, "issueType": "default", "storeCertInSecretsManager" : true }
  1. Проверьте, существует ли сертификат в диспетчере сертификатов AWS. Если да, подтвердите срок годности.
  2. Запустите вызов LetsEncrypt DNS-01 если количество дней до истечения срока действия меньше reImportThreshold . На этом этапе Lambda создает запись TXT , соответствующую доменному имени зоне AWS Route53, и ожидает готовности вашего сертификата.
  3. Lambda обновляет сертификат в диспетчере сертификатов AWS, когда он будет готов.
  4. Lambda будет хранить файлы сертификатов внутри AWS Secrets Manager, если storeCertInSecretsManager имеет значение true.


AWS LetsEncrypt Lambda, диаграмма последовательности.

Подробности реализации Lambda

Код

Лямбда написана на Go 1.22. Использование как можно меньшего количества библиотек помогло мне сохранить мою цель — сохранить код сухим. Полный список необходимых библиотек Go:

URL-адрес

Описание

github.com/aws/aws-lambda-go

Библиотеки, примеры и инструменты, которые помогут разработчикам Go разрабатывать функции AWS Lambda.

github.com/aws/aws-sdk-go-v2

AWS SDK для языка программирования Go.

github.com/go-acme/lego

Клиент и библиотека LetsEncrypt/ACME.

github.com/guregu/null

Разумная обработка значений, допускающих значение NULL.

github.com/sirupsen/logrus

Структурированное подключаемое ведение журналов для Go.


Докер-образ

Я использовал gcr.io/distroless/static:nonroot в качестве базового образа докера. Для приложений Go, не требующих libc, этот образ идеален. Он не совсем scratch и включает в себя следующее:


  • Сертификаты CA: нет необходимости копировать их с любого другого этапа.
  • /etc/passwd: содержит пользователей и группы, такие как некорневые.
  • папка /tmp.
  • tzdata: если вы хотите установить часовой пояс, отличный от UTC.


Процесс сборки

В крупных проектах по разработке программного обеспечения наблюдение за процессом сборки может превратиться в трудоемкую и трудоемкую работу. Makefiles могут помочь автоматизировать и упростить этот процесс, гарантируя, что ваш проект будет построен эффективно и последовательно. По этой причине я предпочитаю использовать Makefile для всех своих проектов на Golang. Файл простой:


 ##@ General help: ## Display this help. @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) fmt: ## Run go fmt against code. go fmt ./... vet: ## Run go vet against code. go vet ./... ##@ Build build: fmt vet ## Build service binary. go build -o bin/lambda main.go run: vet ## Run service from your laptop. go run ./main.go ##@ Test lint: ## Run Go linter golangci-lint run ./... test: ## Run Go tests go test ./...


Со стороны CICD я использовал типичную настройку приложения Go.

  1. GitHub Actions как непрерывная интеграция.

  2. ghcr.io в качестве реестра докеров. По сравнению с DockerHub, этот предлагает две ключевые функции, которые я предпочитаю использовать:

    1. Рабочие процессы сборки, тестирования и развертывания можно легче автоматизировать прямо из репозитория GitHub благодаря плавной интеграции GHCR с GitHub Actions. Это может повысить производительность и упростить процесс разработки.
    2. GHCR использует модель разрешений GitHub, позволяя пользователям управлять доступом к образам контейнеров, используя те же команды и разрешения, которые они используют для своих репозиториев кода. Это упрощает управление пользователями и повышает безопасность.
  3. kvendingoldo/semver-action : мой плагин GitHub Actions для автоматического управления версиями. Это действие GitHub, которое генерирует теги, совместимые с SemVer, для коммитов в репозитории. Действие может управлять версиями, создавать выпуски GitHub и контролировать ветки выпусков внутри репозитория. Он прекрасно работает как с одиночными, так и с монорепозиториями.

  4. Автоматическое создание журнала изменений. Мне нравятся журналы изменений! В контексте других проектов OpenSource, которыми я управляю (например, https://github.com/tofuutils/tenv , https://github.com/tofuutils/tofuenv и т. д.), моя команда осознала важность информирования пользователей о изменения.

  5. голангчи-линт . С моей точки зрения, весь код должен проверяться статическим анализатором кода. SonarQube не может быть настроен для всех проектов, однако golangci, на мой взгляд, достаточно для малых и средних проектов Go.

  6. codespell.yml . Помимо проверки кода, неплохо проверить грамматику, особенно если у вас большой объем документации.

Как развернуть Lambda на AWS через Terraform/OpenTofu

Код, обсуждаемый на этой странице, одинаков для Terraform и OpenTofu, но, начиная с Terraform v1.6, Hashicorp изменил лицензию Terraform на Business Source License (BSL) v1.1. Если вы разрабатываете что-то коммерческое на основе Terraform, перейди на OpenTofu как можно скорее.

Если вам нужно управлять несколькими версиями OpenTofu или Terraform, используйте тенв — Менеджер версий OpenTofu, Terraform, Terragrunt и Atmos, написанный на Go.

Дополнительные примеры Terraform/OpenTofu можно найти в папке примеров в репозитории Git .

Для работы с AWS LetsEncrypt Lambda через OpenTofu необходимо выполнить следующие шаги:

  1. Добавьте модуль в ваш код OpenTofu/Terraform.

     module "letsencrypt_lambda" { source = "[email protected]:kvendingoldo/aws-letsencrypt-lambda.git//files/terraform/module?ref=0.31.4" blank_name = "kvendingoldo-letsencrypt-lambda" tags = var.tags cron_schedule = var.letsencrypt_lambda_cron_schedule events = var.letsencrypt_lambda_events ecr_proxy_username = var.ecr_proxy_username ecr_proxy_access_token = var.ecr_proxy_access_token }
  2. Укажите переменные

     variable "tags" { default = { hackernoon : "demo" } } variable "ecr_proxy_username" { default = "kvendingoldo" } variable "ecr_proxy_access_token" { default = "ghp_xxx" } variable "letsencrypt_lambda_cron_schedule" { default = "rate(168 hours)" } variable "letsencrypt_lambda_events" { default = [ { "acmRegion" : "us-east-1", "route53Region" : "us-east-1", "domainName" : "hackernoon.referrs.me", "acmeUrl" : "stage", "acmeEmail" : "[email protected]", "reImportThreshold" : 100, "issueType" : "default", "storeCertInSecretsManager" : false } ] }
  3. Обратите внимание на переменные ecr_proxy_username и ecr_proxy_access_token . По умолчанию AWS Lambda не может получать изображения из других источников, кроме AWS ECR. К счастью, команда AWS создала прокси-кеш ECR, который может получать изображения из общедоступных реестров, таких как DockerHub или GHCR, и хранить их внутри ECR. Несмотря на эту возможность, AWS не позволяет извлекать изображения без токена, даже из открытых общедоступных репозиториев, поэтому вам необходимо приобрести личный токен GitHub, чтобы получить доступ к предварительно созданным образам Docker. Альтернативно вы можете получить мой репозиторий GitHub, создать образ локально, а затем загрузить его в уже существующий репозиторий ECR. В этом сценарии пример можно изменить следующим образом:

     module "letsencrypt_lambda" { source = "../../" blank_name = "kvendingoldo-letsencrypt-lambda" tags = var.tags cron_schedule = var.letsencrypt_lambda_cron_schedule events = var.letsencrypt_lambda_events ecr_proxy_enabled = false ecr_image_uri = "<YOUR_ACCOUNT_ID>.dkr.ecr.us-east-2.amazonaws.com/aws_letsencrypt_lambda:<VERSION>" }


  4. Когда вы завершите изменение кода, выполните следующую команду, чтобы установить OpenTofu с помощью переключателя версий OpenTofu tenv :

     $ tenv tofu install
  5. И, наконец, выполните следующие команды, чтобы применить полученный код:

     $ tofu init $ tofu plan $ tofu apply
  6. Подождите, пока код будет развернут на AWS и не начнутся события. Через несколько минут вы увидите готовые сертификаты внутри менеджера сертификатов. Пример:

    Список проблем с сертификатами AWS LetsEncrypt Lambda внутри AWS Certificate Manager.

  7. Начиная с этого момента AWS может использовать выданный сертификат в любых сервисах ARN.

  8. Если вам нужно использовать сертификат вне сервисов AWS или иметь доступ к его содержимому, установите для параметра события storeCertInSecretsManager значение true . В этой ситуации, когда Lambda завершит базовое выполнение, сертификат будет сохранен в AWS Secrets Manager. Это дает пользователям больше гибкости: они могут проверять содержимое сертификата, работать с ним непосредственно из EC2 и т. д. Чтобы узнать больше об AWS Secrets Manager, прочтите официальное руководство.

    Пример выданного сертификата, который хранится внутри AWS Secrets Manager.


Переменные среды

Имя

Описание

Возможные значения

Значение по умолчанию

Пример

Необходимый

FORMATTER_TYPE

Тип форматтера для журналов

JSON | ТЕКСТ

ТЕКСТ

JSON

MODE

Режим приложения. Установите cloud режим для выполнения AWS и local режим для локального тестирования.

облако | местный

облако

облако

LOG_LEVEL

Уровень ведения журнала

паника|фатальная|ошибка|предупреждение|информация|отладка|отслеживание

предупреждать

предупреждать

AWS_REGION

Регион AWS по умолчанию. После развертывания на AWS он настраивается автоматически.

<любой действительный регион AWS>

-

США-Восток-1

DOMAIN_NAME

Доменное имя, для которого выдается или продлевается сертификат

любое действительное доменное имя

-

хакернун. Referrs.me

ACME_URL

Будет использоваться производственный URL-адрес LetsEncrypt, если для него установлено prod ; в противном случае будет использоваться URL-адрес сцены.

прод | этап

подталкивать

подталкивать

ACME_EMAIL

Адрес электронной почты, связанный с сертификатом LetsEncrypt

любой действительный адрес электронной почты

[email protected]

[email protected]

REIMPORT_THRESHOLD

Сертификат будет продлен, если его срок жизни (TTL) равен REIMPORT_THRESHOLD .

любое целое > 0

10

10

STORE_CERT_IN_SECRETSMANAGER

Если true , Lambda сохранит сертификат как в диспетчере сертификатов, так и в диспетчере секретов.

«правда» | "ЛОЖЬ"

"ЛОЖЬ"

"ЛОЖЬ"


Как проверить логи LetsEncrypt Lambda

В рамках работы с aws-letsencrypt-lambda вам может иногда потребоваться просмотреть журналы. Это довольно легко сделать:

  1. Перейдите в AWS Cloudwatch, нажмите «Журнал групп».
  2. Найдите группу журналов с именем, которое вы указали в коде OpenTofu. Например, в моем случае это /aws/lambda/kvendingoldo-letsencrypt-lambda
  3. Зайдите в группу, выберите нужный поток из списка и просмотрите логи.


Как запустить Lambda вручную через пользовательский интерфейс AWS

  1. Перейдите к функции Lambda, созданной с помощью OpenTofu. Нажмите кнопку «Тесты».

    AWS LetsEncrypt Lambda: интерфейс пользовательского интерфейса

  2. Заполните Test Event и нажмите Test

     { "domainName": "<YOUR_VALID_DOMAIN>", "acmeUrl": <stage | prod>, "acmeEmail": "<ANY_VALID_EMAIL>", "reImportThreshold": 10, "issueType": "<default | force>", "storeCertInSecretsManager" : <true | false> }

    Пример №1:

     { "domainName": "hackernoon.referrs.me", "acmeUrl": "prod", "acmeEmail": "[email protected]", "reImportThreshold": 10, "issueType": "default" }


  3. Подождите, пока выполнение не завершится. Журнал выполнения доступен в Cloudwatch. Обычно первоначальный выпуск занимает около 5 минут.

Как протестировать Lambda локально

  1. Клонируйте репозиторий https://github.com/kvendingoldo/aws-letsencrypt-lambda на свой ноутбук.

  2. Настройте учетные данные AWS Cli с помощью официального руководства .

  3. Изучите раздел переменных среды и установите минимальное количество необходимых переменных. Поскольку LetsEncrypt ограничивает количество повторов в час для ACME_URL="prod" , я советую использовать ACME_URL="stage" для тестирования. Пример переменных среды:

     export AWS_REGION="us-east-2" export MODE=local export DOMAIN_NAME="hackernoon.referrs.me" export ACME_URL="stage" export ACME_EMAIL="[email protected]" export REIMPORT_THRESHOLD=10 export ISSUE_TYPE="default" export STORE_CERT_IN_SECRETSMANAGER="true"
  4. Выполните лямбду локально с помощью следующей команды:

     go run main.go
  5. После успешного выполнения Lambda появится следующий журнал.

     INFO[0000] Starting lambda execution ... INFO[0000] Lambda will use STAGING ACME URL; If you need to use PROD URL specify it via 'ACME_URL' or pass in event body INFO[0000] Certificate found, arn is arn:aws:acm:us-east-2:004867756392:certificate/72f872fd-e577-43f4-ae38-6833962630af. Trying to renew ... INFO[0000] Checking certificate for domain 'hackernoon.referrs.me' with arn 'arn:aws:acm:us-east-2:004867756392:certificate/72f872fd-e577-43f4-ae38-6833962630af' INFO[0000] Certificate status is 'ISSUED' INFO[0000] Certificate in use by [] INFO[0000] Certificate valid until 2024-08-31 13:50:49 +0000 UTC (89 days left) INFO[0000] Try to get certificate for hackernoon.referrs.me domain 2024/06/02 17:56:23 [INFO] acme: Registering account for [email protected] 2024/06/02 17:56:24 [INFO] [hackernoon.referrs.me, www.hackernoon.referrs.me] acme: Obtaining bundled SAN certificate 2024/06/02 17:56:25 [INFO] [hackernoon.referrs.me] AuthURL: https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/12603809394 2024/06/02 17:56:25 [INFO] [www.hackernoon.referrs.me] AuthURL: https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/12603809404 2024/06/02 17:56:25 [INFO] [hackernoon.referrs.me] acme: Could not find solver for: tls-alpn-01 2024/06/02 17:56:25 [INFO] [hackernoon.referrs.me] acme: Could not find solver for: http-01 2024/06/02 17:56:25 [INFO] [hackernoon.referrs.me] acme: use dns-01 solver 2024/06/02 17:56:25 [INFO] [www.hackernoon.referrs.me] acme: Could not find solver for: tls-alpn-01 2024/06/02 17:56:25 [INFO] [www.hackernoon.referrs.me] acme: Could not find solver for: http-01 2024/06/02 17:56:25 [INFO] [www.hackernoon.referrs.me] acme: use dns-01 solver 2024/06/02 17:56:25 [INFO] [hackernoon.referrs.me] acme: Preparing to solve DNS-01 2024/06/02 17:56:26 [INFO] Wait for route53 [timeout: 5m0s, interval: 4s] 2024/06/02 17:57:00 [INFO] [www.hackernoon.referrs.me] acme: Preparing to solve DNS-01 2024/06/02 17:57:00 [INFO] Wait for route53 [timeout: 5m0s, interval: 4s] 2024/06/02 17:57:30 [INFO] [hackernoon.referrs.me] acme: Trying to solve DNS-01 2024/06/02 17:57:30 [INFO] [hackernoon.referrs.me] acme: Checking DNS record propagation. [nameservers=109.122.99.130:53,109.122.99.129:53] 2024/06/02 17:57:34 [INFO] Wait for propagation [timeout: 5m0s, interval: 4s] 2024/06/02 17:57:46 [INFO] [hackernoon.referrs.me] The server validated our request 2024/06/02 17:57:46 [INFO] [www.hackernoon.referrs.me] acme: Trying to solve DNS-01 2024/06/02 17:57:46 [INFO] [www.hackernoon.referrs.me] acme: Checking DNS record propagation. [nameservers=109.122.99.130:53,109.122.99.129:53] 2024/06/02 17:57:50 [INFO] Wait for propagation [timeout: 5m0s, interval: 4s] 2024/06/02 17:58:30 [INFO] [www.hackernoon.referrs.me] The server validated our request 2024/06/02 17:58:30 [INFO] [hackernoon.referrs.me] acme: Cleaning DNS-01 challenge 2024/06/02 17:58:30 [INFO] Wait for route53 [timeout: 5m0s, interval: 4s] 2024/06/02 17:59:09 [INFO] [www.hackernoon.referrs.me] acme: Cleaning DNS-01 challenge 2024/06/02 17:59:09 [INFO] Wait for route53 [timeout: 5m0s, interval: 4s] 2024/06/02 17:59:43 [INFO] [hackernoon.referrs.me, www.hackernoon.referrs.me] acme: Validations succeeded; requesting certificates 2024/06/02 17:59:43 [INFO] Wait for certificate [timeout: 30s, interval: 500ms] 2024/06/02 17:59:45 [INFO] [hackernoon.referrs.me] Server responded with a certificate. INFO[0203] Certificate has been successfully imported. Arn is arn:aws:acm:us-east-2:004867756392:certificate/72f872fd-e577-43f4-ae38-6833962630af INFO[0204] Secret updated successfully. SecretId: arn:aws:secretsmanager:us-east-2:004867756392:secret:hackernoon.referrs.me-NioT77 INFO[0204] Lambda has been completed
  6. Вот и все. Начиная с этого момента, AWS может использовать выданный сертификат в любых сервисах ARN или в других местах, где это физически необходимо, получив его от AWS Secrets Manager.


Практический опыт использования в AWS более 4 лет.

Я использую функцию Lambda в производстве уже почти четыре года. С течением времени различные аспекты первоначальной реализации изменились:

  1. Ранее AWS запретила использование любых реестров, не относящихся к ECR, в качестве источников Lambda. Он не изменился, однако AWS добавила прокси-сервер ECR для GitHub, DockerHub и нескольких дополнительных реестров. Без этой функции нам приходилось вручную отправлять изображения Lambda в наш личный ECR и заменять URL-адрес изображения в коде Terraform. Теперь код OpenTofu делает это автоматически через ECR Proxy.

  2. Вначале я рассматривал возможность внедрения различных задач, таких как http-01 или tls-alpn-01 , но никто не спрашивал меня об этом в течение четырех лет. Он по-прежнему присутствует в выпусках GitHub , и если такая возможность потребуется, мы можем вместе работать над ее созданием.

  3. Я не хотел использовать сертификаты LetsEncrypt в экземплярах чистого EC2, когда проект изначально стартовал, но в наши дни это стандартная практика. Как я уже говорил ранее, в определенных ситуациях сертификат можно получить из AWS Secrets Managed с помощью интерфейса AWS.

  4. За прошедшие годы я написал много нового кода на Go, поэтому могу сказать, что исходный код Lambda в моем репозитории не так хорош, как мог бы быть. Существует значительная разница между ним и моим последним проектом Go, tenv (OpenTofu, Terraform, Terragrunt и менеджер версий Atmos, написанный на Go), но в любом случае код по-прежнему в целом поддерживается, поэтому внесение в него изменений выиграло. Это будет слишком проблематично. Время от времени я буду проводить значительный рефакторинг, чтобы сделать код более элегантным.

  5. Одна и та же Lambda уже много лет используется в нескольких разных проектах. Кроме того, я являюсь соучредителем платформы DevOps cloudexpress.app , где наша команда управляет сертификатами TLS для всех наших клиентов с помощью AWS LetsEncrypt Lambda для упрощения процессов автоматизации.


Теперь поговорим о цифрах. За 4 года этот проект помог многим людям и использовался в многочисленных OpenSource и более чем 30 коммерческих проектах . Lambda выдает более 2000 сертификатов и не хочет останавливаться на достигнутом.

Заключение

AWS LetsEncrypt Lambda — подходящее решение для вас, если

  • У вас должна быть физическая версия сертификата, и вы будете использовать ее из собственных сервисов, отличных от AWS, таких как EC2 Nginx.
  • Вы не хотите полагаться на AWS Certificate Manager для управления процессом выпуска и продления сертификата TLS (проверка журналов, установка дат продления и т. д.).
  • Вы хотели бы получать уведомления по электронной почте от LetsEncrypt, когда срок действия вашего сертификата истечет или скоро истечет.
  • Вы хотите персонализировать решение, изменив код Golang (например, изменив задачу LetsEncrypt, сохранив сертификат в Hashicorp Vault и т. д.).


Если вы обнаружили, что хотя бы один из этих пунктов применим к вашей ситуации, вы можете использовать AWS Lambda. Кроме того, если вы хотите принять участие в разработке, я всегда открыт для новых вопросов и запросов на включение на GitHub. URL-адрес проекта: https://github.com/kvendingoldo/aws-letsencrypt-lambda .