Получение wildcard-сертификатов от удостоверяющего центра Let's Encrypt возможно только при подтверждение владения доменом, путём создания временной TXT записи вида _acme-challenge.oldfag.ru с определённым значением.
Самое простое решение для автоматизации получения сертификатов от Let’s Encrypt - использование Cetrbot или acme.sh.
Мой выбор пал на Certbot. Он имеет уже готовые плагины для работы с некоторыми DNS-провайдерами. К несчастью, он не имеет плагина для работы с DNS Яндекс.Коннект, но возможность использовать свои скрипты исправляет эту ситуацию.
Acme.sh умеет работать с DNS Яндекс.Коннект, дак зачем же использовать велосипед в виде Certbot и самописных скриптов?
Ответ прост. Проверка существования TXT записи производится запросом к NS серверам домена, в нашем случае dns1.yandex.net и dns2.yandex.net. Вот тут может возникнуть ошибка валидации домена, т.к. на одном из серверов запись уже существует, а на втором ещё нет. Тут нам на помощь и приходит Certbot с самописными скриптами.
Для использования собственных скриптов создания DNS-записей у certbot есть 2 ключа:
Все предварительные этапы завершены, приступим к созданию скриптов для работы с dns-записями. Первым создадим скрипт создания необходимых записей
Теперь создадим скрипт для удаления временных записей
Последний файл, который осталось создать - хранилище API-токенов
После того, как сертификат будет успешно выпущен, в каталоге /etc/letsencrypt/renewal будет создан файл с параметрами перевыпуска сертификата. Отслеживая срок действия сертификата в /etc/letsencrypt/live/имя домена/cert.pem можно автоматизировать перевыпуск сертификатов при помощи команды
Для автоматического перевыпуска сертификата, без участия пользователя, нужно в файле /etc/letsencrypt/renewal/домен.conf раскомментировать строку, указывающую оставшийся срок действия сертификата, при достижении которого будет предпринята поптка его обновления
Самое простое решение для автоматизации получения сертификатов от Let’s Encrypt - использование Cetrbot или acme.sh.
Мой выбор пал на Certbot. Он имеет уже готовые плагины для работы с некоторыми DNS-провайдерами. К несчастью, он не имеет плагина для работы с DNS Яндекс.Коннект, но возможность использовать свои скрипты исправляет эту ситуацию.
Acme.sh умеет работать с DNS Яндекс.Коннект, дак зачем же использовать велосипед в виде Certbot и самописных скриптов?
Ответ прост. Проверка существования TXT записи производится запросом к NS серверам домена, в нашем случае dns1.yandex.net и dns2.yandex.net. Вот тут может возникнуть ошибка валидации домена, т.к. на одном из серверов запись уже существует, а на втором ещё нет. Тут нам на помощь и приходит Certbot с самописными скриптами.
- --manual-auth-hook путь к скрипту - для создания TXT записи для авторизации;
- --manual-cleanup-hook путь к скрипту - для удаления TXT записи после завершения проверки.
Все предварительные этапы завершены, приступим к созданию скриптов для работы с dns-записями. Первым создадим скрипт создания необходимых записей
mkdir -p /scripts/certbot-dns-pddyandex touch /scripts/certbot-dns-pddyandex/yandex-auth-hook.shс таким содержанием
#!/bin/bash
_dir="$(dirname "$0")"
source "$_dir/config.sh"
# Get API key for current domain
API_KEY=${API_KEYMAP["$CERTBOT_DOMAIN"]}
if [ -z "$API_KEY" ]; then
echo "No API key found for domain $CERTBOT_DOMAIN, exit"
exit
fi
# Create TXT record
CREATE_DOMAIN="_acme-challenge"
RECORD_ID=$(curl -s -X POST "https://pddimp.yandex.ru/api2/admin/dns/add" \
-H "PddToken: $API_KEY" \
-d "domain=$CERTBOT_DOMAIN&type=TXT&content=$CERTBOT_VALIDATION&ttl=3600&subdomain=$CREATE_DOMAIN" \
| python -c "import sys,json;print(json.load(sys.stdin)['record']['record_id'])")
# Save info for cleanup
if [ ! -d /tmp/CERTBOT_$CERTBOT_DOMAIN ];then
mkdir -m 0700 /tmp/CERTBOT_$CERTBOT_DOMAIN
echo $RECORD_ID > /tmp/CERTBOT_$CERTBOT_DOMAIN/RECORD_ID
else
echo $RECORD_ID >> /tmp/CERTBOT_$CERTBOT_DOMAIN/RECORD_ID
fi
# Sleep to make sure the change has time to propagate over to DNS (max: 20 min)
c_time=0
end_time=1200
while [ "$c_time" -le "$end_time" ]; do
if [ `dig $CREATE_DOMAIN.$CERTBOT_DOMAIN TXT +short @dns1.yandex.net | grep $CERTBOT_VALIDATION` ]; then
sleep 5
if [ `dig $CREATE_DOMAIN.$CERTBOT_DOMAIN TXT +short @dns2.yandex.net | grep $CERTBOT_VALIDATION` ]; then
sleep 5
if [ `dig $CREATE_DOMAIN.$CERTBOT_DOMAIN TXT +short @8.8.8.8 | grep $CERTBOT_VALIDATION` ]; then
sleep 5
break
else
sleep 50
c_time=$[c_time+50]
fi
else
sleep 55
c_time=$[c_time+55]
fi
else
sleep 60
c_time=$[c_time+60]
fi
done
Он берёт из файла API-токен для конкретного домена и при его помощи создаёт необходимые для проверки TXT записи. Идентификаторы записей для их последующего удаления сохраняются в файле RECORD_ID.Теперь создадим скрипт для удаления временных записей
touch /scripts/certbot-dns-pddyandex/yandex-cleanup-hook.shс таким содержанием
#!/bin/bash
_dir="$(dirname "$0")"
source "$_dir/config.sh"
# Get API key for current domain
API_KEY=${API_KEYMAP["$CERTBOT_DOMAIN"]}
if [ -z "$API_KEY" ]; then
echo "No API key found for domain $CERTBOT_DOMAIN, exit"
exit
fi
# Remove the challenge TXT record from the zone
remove_record() {
RECORD_ID="$1"
if [ -n "${RECORD_ID}" ]; then
RESULT=$(curl -s -X POST "https://pddimp.yandex.ru/api2/admin/dns/del" \
-H "PddToken: $API_KEY" \
-d "domain=$CERTBOT_DOMAIN&record_id=$RECORD_ID" \
| python -c "import sys,json;print(json.load(sys.stdin)['success'])")
echo $RESULT
fi
}
if [ -f /tmp/CERTBOT_$CERTBOT_DOMAIN/RECORD_ID ]; then
while read RECORD; do
remove_record $RECORD
done < /tmp/CERTBOT_$CERTBOT_DOMAIN/RECORD_ID
rm -f /tmp/CERTBOT_$CERTBOT_DOMAIN/RECORD_ID
fi
Он так же, как и скрипт для создания записей, берёт API-токен для конкретного домена и удаляет записи, идентификаторы которых записаны в файле RECORD_ID.Последний файл, который осталось создать - хранилище API-токенов
touch /scripts/certbot-dns-pddyandex/config.shс таким содержанием
declare -A API_KEYMAP
API_KEYMAP["domain1.tld"]='52 symbols of key ....'
API_KEYMAP["domain2.tld"]='52 symbols of key....'
Все файлы созданы, теперь сделаем файлы скриптов исполняемыми
chmod +x yandex-auth-hook.sh yandex-cleanup-hook.shи попробуем получить wildcard-сертификат, для того, чтобы сертификаты не выпускались на самом деле добавим к команде ключ --dry-run
certbot certonly --manual-public-ip-logging-ok --agree-tos --renew-by-default \
-d oldfag.ru -d *.oldfag.ru --manual \
--manual-auth-hook /scripts/certbot-dns-pddyandex/yandex-auth-hook.sh \
--manual-cleanup-hook /scripts/certbot-dns-pddyandex/yandex-cleanup-hook.sh \
--preferred-challenges dns-01 --server https://acme-v02.api.letsencrypt.org/directory \
--register-unsafely-without-email --dry-run
Если всё прошло удачно, то можно выпустить сертификаты уже на самом деле, убрав последний ключ из предыдущей команды.После того, как сертификат будет успешно выпущен, в каталоге /etc/letsencrypt/renewal будет создан файл с параметрами перевыпуска сертификата. Отслеживая срок действия сертификата в /etc/letsencrypt/live/имя домена/cert.pem можно автоматизировать перевыпуск сертификатов при помощи команды
certbot renew
Для автоматического перевыпуска сертификата, без участия пользователя, нужно в файле /etc/letsencrypt/renewal/домен.conf раскомментировать строку, указывающую оставшийся срок действия сертификата, при достижении которого будет предпринята поптка его обновления
renew_before_expiry = 45 daysВсе скрипты и краткая инструкция лежат на GitHub.
Ругается на ошибку в 17 строке yandex-auth-hook.sh — python: command not found
ОтветитьУдалитьИ потом (23) Failed writing body
Но завершается как бы успешно — The dry run was successful
Просветите, чего он хочет?
Похоже, скрипт не знает, где искать python. Возможно он отсутствует в системе, или сломана ссылка на него.
УдалитьНа новом ubuntu заменить python на python3
УдалитьСпасибо, помогло заменить на python3
Удалитьхотя и без этого работало, но теперь и на ошибку не ругается.
При попытке получить сертификат для поддомена, говорит что не нашел ключ...
ОтветитьУдалитьСкрипт рассчитан на выпуск wildcard сертификатов для доменов второго уровня. Для доменов третьего и выше уровней можно использовать скрипты из репозитория https://github.com/myallod/certbot-dns-pddyandex
УдалитьСтранно, при попытке получения токена для домена, пишет что Error: no_such_domain хотя домен делегирован на сервера яндекса. Может что-то еще нужно проденлать?
ОтветитьУдалитьНужно на страницу https://connect.yandex.ru/ войти под именем владельца домена, а после успешной авторизации, перейти на страницу получения токена.
УдалитьКак-то инструкция слегка неполная без определения когда же заканчивается сертификат, если доменов не один, то надо по крону запускать какой-то скрипт который бы проверял все сертификаты, допустим раз в день и если осталось меньше 3 дней до конца выпускал новый для домена
ОтветитьУдалитьПочитал требования к продлению и решил что тупо поставлю команду в крон на обновление каждый месяц и норм
УдалитьНа самом деле не нужно создавать отдельное задание в крон. Certbot создаёт задание на обновление сертификатов и сохраняет параметры выпуска сертификатов в /etc/letsencrypt/renewal.
УдалитьСрок действия сертификата можно проверять с помощью openssl.
Срок, по наступлении которого нужно перевыпустить сертификат указан в параметре renew_before_expiry = 45 days, который указан в файле /etc/letsencrypt/renewal/домен.conf. По умолчанию он закомментирован, комментарий нужно убрать и указать количество дней до истечения срока действия сертификата, когда его нужно обновить.
УдалитьО как, спасибо, в статье в конце сбивает с толку что надо что-то отслеживать и автоматизировать, хотя вы говорите что уже всё автоматизировано и надо только в конфиге раскомментировать
Удалитьогромное спасибо, работает отлично!
ОтветитьУдалить