На пути к автоматизации выпуска SSL

—

от автора

Достаточно часто нам приходится работать с SSL сертификатами. Давайте вспомним процесс создания и установки сертификата (в общем случае для большинства).

  • Найти провайдера (сайт на котором мы можем купить SSL).
  • Сгенерировать CSR.
  • Отправить его провайдеру.
  • Отправить его провайдеру.
  • Подтвердить владение доменом.
  • Подтвердить владение доменом.
  • Получить сертификат.
  • Преобразовать сертификат в нужную форму (опционально). Например, из pem в PKCS #12.
  • Установить сертификат на веб сервер.

Относительно быстро, не сложно и понятно. Этот вариант вполне годится, если у нас есть максимум десяток проектов. А если их больше, и у них минимум по три окружения? Классический dev — staging — production. В этом случае стоит задуматься об автоматизации этого процесса. Предлагаю, немного углубиться в проблему и найти решение которое в дальнейшем минимизирует временные затраты на создание и обслуживание сертификатов. В статье будет присутствовать анализ проблемы и небольшое руководство к повторению.

Заранее оговорюсь: основная специализация нашей компании — .net, а соответственно IIS и прочие виндовые вытекающие. Поэтому, ACME клиент и все действия для него тоже будут описаны с точки зрения использования windows.

Для кого это актуально и некоторые исходные данные

Компания К в лице автора. URL (для примера): company.tld

Проект X — один из наших проектов, занимаясь которым я пришел к выводу что все таки нужно двигаться в сторону максимальной экономии времени при работе с сертификатами. У этого проекта есть четыре окружения: dev, test, staging и production. Dev и test находятся на нашей стороне, staging и production на клиентской.

Особенностью проекта является то, что у него есть большое количество модулей, которые доступны как поддомены.

То-есть, имеем следующую картину:

Dev Test Staging Production
projectX.dev.company.tld projectX.test.company.tld staging.projectX.tld projectX.tld
module1.projectX.dev.company.tld module1.projectX.test.company.tld module1.staging.projectX.tld module1.projectX.tld
module2.projectX.dev.company.tld module2.projectX.test.company.tld module2.staging.projectX.tld module2.projectX.tld
… … … …
moduleN.projectX.dev.company.tld moduleN.projectX.test.company.tld moduleN.staging.projectX.tld moduleN.projectX.tld

Для production используется купленный wildcard сертификат, тут вопросов не возникает. Но он покрывает только первый уровень поддомена. Соответственно, если есть сертификат для *.projectX.tld — то для staging.projectX.tld он работать будет, а вот для module1.staging.projectX.tld уже нет. А покупать отдельный как-то не хочется.

И это только на примере одного проекта одной компании. А проект, естественно, не один.

Общие для всех причины заняться решением этого вопроса выглядят примерно так:

  • Относительно недавно Google предложили уменьшить максимальный срок действия SSL сертификатов. Со всеми вытекающими.
  • Облегчить процесс выпуска и обслуживания SSL для внутренних нужд проектов и компании в целом.
  • Централизованное хранение записей о сертификатах, которое частично решает проблему подтверждения домена с помощью DNS и последующего автоматического обновления, а также решает вопрос доверия клиента. Все же, больше доверия вызывает CNAME на сервер компании партнера/исполнителя, чем на сторонний ресурс.
  • Ну, и наконец, в этом случае фраза “лучше иметь чем не иметь” подходит отлично.

Выбор провайдера SSL и подготовительные шаги

Из доступных вариантов бесплатных SSL сертификатов рассматривались cloudflare и letsencrypt. DNS для этого (и некоторых других проектов) как располагается на cloudflare, но я не сторонник использования их сертификатов. Поэтому, было решено использовать letsencrypt.
Для создания wildcard SSL сертификата нужно подтвердить владение доменом. Эта процедура предполагает создание некоторой DNS записи (TXT или CNAME), с последующей ее проверкой при выпуске сертификата. В Linux есть утилита — certbot, которая позволяет частично (или полностью для некоторых DNS провайдеров) автоматизировать этот процесс. Для Windows же из найденных и проверенных вариантов ACME клиентов я остановился на WinACME.

А запись для домена создана, переходим к созданию сертификата:

image

Нас интересует последний вывод, а именно — доступные варианты подтверждения владения доменом для выпуска wildcard сертификата:

  1. Создание DNS записей вручную (автоматическое обновление не поддерживается)
  2. Создание DNS записей с помощью acme-dns сервера (подробнее можно почитать тут.
  3. Создание DNS записей с помощью собственного скрипта (аналог плагина cloudflare для certbot).

На первый взгляд, третий пункт вполне подходит, но если DNS провайдер не поддерживает этот функционал? А нам необходим общий случай. А общий случай — это CNAME записи, уж их то все поддерживают. Следовательно, останавливаемся на пункте 2, и идем настраивать свой ACME-DNS сервер.

Настройка ACME-DNS сервера и процесс выпуска сертификата

Для примера, я создал домен 2nd.pp.ua, и в дальнейшем буду использовать его.

Обязательным требованием для корректной работы сервера является создание NS и А записи для его домена. И первый неприятный момент с которым я столкнулся — cloudflare (по крайней мере в режиме бесплатного использования) не позволяет одновременно создать NS и A запись для одного и того же хоста. Не то чтобы это было проблемой, но в bind это можно. Саппорт ответил, что их панель так делать не позволяет. Не беда, создадим две записи:

acmens.2nd.pp.ua. IN A 35.237.128.147 acme.2nd.pp.ua. IN NS acmens.2nd.pp.ua.

На данном этапе у нас должен резолвиться хост acmens.2nd.pp.ua.

$ ping acmens.2nd.pp.ua PING acmens.2nd.pp.ua (35.237.128.147) 56(84) bytes of data

А вот acme.2nd.pp.ua резолвиться не будет, так как DNS сервер который его обслуживает еще не запущен.

Записи созданы, переходим к настройке и запуску ACME-DNS сервера. Жить он у меня будет на ubuntu server в docker контейнере, но запустить его можно везде где есть golang. Windows тоже вполне подойдет, но я все же предпочитаю Linux сервер.

Создаем необходимые директории и файлы:

$ mkdir config $ mkdir data $ touch config/config.cfg

Воспользуемся vim вашим любимым текстовым редактором и вставим в config.cfg образец конфигурации.

Для успешной работы достаточно подправить секции general и api:

[general] listen = "0.0.0.0:53" protocol = "both" domain = "acme.2nd.pp.ua" nsname = "acmens.2nd.pp.ua"  nsadmin = "admin.2nd.pp.ua"  records =      "acme.2nd.pp.ua. A 35.237.128.147",     "acme.2nd.pp.ua. NS acmens.2nd.pp.ua.",                                                                                                                                                                                                  ] ... [api] ... tls = "letsencrypt" …

Также, по желанию, создадим docker-compose файл в основной директории сервиса:

version: '3.7' services:   acmedns:     image: joohoi/acme-dns:latest     ports:       - "443:443"       - "53:53"       - "53:53/udp"       - "80:80"     volumes:       - ./config:/etc/acme-dns:ro       - ./data:/var/lib/acme-dns

Готово. Можно запускать.

$ docker-compose up -d

На данном этапе должен начать резолвиться хост acme.2nd.pp.ua, и появиться 404 на https://acme.2nd.pp.ua

$ ping acme.2nd.pp.ua PING acme.2nd.pp.ua (35.237.128.147) 56(84) bytes of data.  $ curl https://acme.2nd.pp.ua 404 page not found

Если этого не появилось — docker logs -f <container_name> в помощь, благо, логи вполне читабельные.

Можем приступать к созданию сертификата. Открываем powershell от имени администратора и запускаем winacme. Нас интересуют выборы:

  • M: Create new certificate (full options)
  • 2: Manual input
  • 2: [dns-01] Create verification records with acme-dns (https://github.com/joohoi/acme-dns)
  • На вопрос о ссылке на ACME-DNS сервер вводим в ответ URL созданного сервера (https). URL of the acme-dns server: https://acme.2nd.pp.ua

В отвер клиент выдает запись которую надо добавить в существующий DNS сервер (процедура единоразовая):

[INFO] Creating new acme-dns registration for domain 1nd.pp.ua  Domain:              1nd.pp.ua Record:               _acme-challenge.1nd.pp.ua Type:                   CNAME Content:              c82a88a5-499f-464f-96e4-be7f606a3b47.acme.2nd.pp.ua. Note:                   Some DNS control panels add the final dot automatically.                            Only one is required.

image

Создаем необходимую запись, и убеждаемся что она создалась корректно:

image

$ dig CNAME _acme-challenge.1nd.pp.ua +short c82a88a5-499f-464f-96e4-be7f606a3b47.acme.2nd.pp.ua.

Подтверждаем что мы создали нужную запись в winacme, и продолжаем процесс создания сертификата:

image

Как использовать certbot в качестве клиента описано тут.

На этом процесс создания сертификата закончен, можно устанавливать его на веб-сервер и использовать. Если при создании сертификата создать также и задание в планировщике, то в дальнейшем процесс обновления сертификата будет происходить автоматически.


ссылка на оригинал статьи https://habr.com/ru/post/483770/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *