На пути к автоматизации выпуска 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.

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

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

Нас интересует последний вывод, а именно — доступные варианты подтверждения владения доменом для выпуска 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.

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

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

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

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

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

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

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

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

Источник: habr.com

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