Привет, Хабр! Недавно делал одну интересную задачу, связанную с актуализацией просроченных сертификатов (открытых ключей), используемых для подписания и шифрования файлов при помощи Криптопро 5. Решил поделиться опытом. Возможно, это поможет сэкономить время при решении похожей задачи или будет просто интересным чтивом для вас.

Дисклеймер

Я буду очень рад вашим замечаниям и предложениям по оптимизации bash скрипта, генерирующего сервисный json с информацией о сроке годности сертификатов. Так же буду рад услышать советы по оптимизации Dockerfile. Заранее спасибо.

Что будет в статье

  • подготовка скрипта для сбора данных о состоянии сертификатов

  • сборка Docker образа с Криптопро 5 на основе Fedora 38

  • загрузка сертификатов в контейнер

Подготовка скрипта для сбора данных о состоянии сертификатов

Основная проблема сотрудников организации, для которой я делал эту доработку, заключалась в том, что они имели в распоряжении большое количество сертификатов, используемых для подписания и шифрования файлов. У сертификатов, разумеется, были разные сроки действия, и было очень трудно отслеживать просроченные сертификаты для того, чтобы своевременно выпустить новую версию.

Чтобы решить эту проблему, было принято решение разработать небольшое дополнение к Криптопро 5, которое помогло актуализировать информацию об имеющихся сертификатах.

#!/usr/bin/env bash

CERTS_CHECK="$(certmgr -list | grep -E "Subject ")"

# check if certs exists
if [[ $CERTS_CHECK == *"Subject "* ]]; then
	touch ./result.json
else
	echo "[]" > ./result.json
    exit 0
fi

COUNTER=1

# prepare data from certmgr
certmgr -list | grep -E "Subject " | awk -F'CN=' '{ print $2 }' | tr -d '"' > ./names.txt
certmgr -list | grep -E "Subject " | awk -F'E=' '{ print $2 }' | cut -d "," -f 1 | tr -d '"' > ./emails.txt
certmgr -list | grep -E "Not valid after" | cut -d ":" -f 2 | cut -d " " -f 2 | tr -d '"' > ./valid_to.txt

# count certs qty
CERTS_QTY=$(wc -l < names.txt)

# prepare result json
echo "[" > ./result.json
while (($COUNTER <= $CERTS_QTY ))
do
	echo '	{' >> ./result.json
	echo '		"name": "'"$(cat ./names.txt | tail -n $COUNTER | head -n 1)"'",'>> ./result.json
	echo '		"e-mail": "'"$(cat ./emails.txt | tail -n $COUNTER | head -n 1)"'",' >> ./result.json
	echo '		"valid-to": "'"$(cat ./valid_to.txt | tail -n $COUNTER | head -n 1)"'"' >> ./result.json
	echo '	}' >> ./result.json
	echo "	," >> ./result.json
	COUNTER=$((COUNTER + 1))
done
sed -i '$ d' ./result.json
echo "]" >> ./result.json

# remove tmp files
rm -f ./names.txt
rm -f ./emails.txt
rm -f ./valid_to.txt

# print result
if [[ $CERTS_CHECK == *"Subject "* ]]; then
	cat ./result.json
fi

Результатом работы скрипта является файл result.json, содержащий информацию о сроке действия сертификатов, электронной почте владельцев сертификатов и CN.

Пример вывода содержимого файла result.json
Пример вывода содержимого файла result.json

Также скрипт выводит в консоль содержание файла result.json, если в Криптопро установлены сертификаты или предупреждение об отсутствии сертификатов, если их нет.

Пример вывода предупреждение об отсутствии сертификатов
Пример вывода предупреждение об отсутствии сертификатов

Сборка Docker образа с Криптопро 5 на основе fedora 38

Здесь все просто, как пять копеек. Качаем rpm дистрибутив, делаем Dockerfile и собираем образ. Дистрибутив доступен по этой ссылке - https://www.cryptopro.ru/products/csp.

Обратите внимание, что есть возможность выбрать и deb и rpm дистрибутив.

Варианты дистрибутивов Криптопро 5
Варианты дистрибутивов Криптопро 5

Содержимое Dockerfile:

FROM fedora:38

WORKDIR /usr/src/cryptopro

COPY ./distr ./distr

RUN yes Y | ./distr/install.sh kc1
RUN ln -s /opt/cprocsp/sbin/amd64/cpconfig /usr/bin/cpconfig
RUN ln -s /opt/cprocsp/bin/amd64/certmgr /usr/bin/certmgr
RUN ln -s /opt/cprocsp/bin/amd64/cryptcp /usr/bin/cryptcp

COPY ./src/certs_info /usr/bin/certs_info

CMD [ "tail", "-f", "/dev/null" ]

Папка distr содержит распакованный архив с дистрибутивом Криптопро 5. Папка src содержит исполняемый скрипт certs_info, который был описан ранее.

Обратите внимание, что после установки нужно сделать soft link на исполняемые файлы, чтобы н�� указывать полный путь до них каждый раз, когда запускаете ту или иную команду. В этом примере используются только три исполняемые команды: cpconfig, certmgr и cryptcp. Если вам нужны другие команды, не забудьте их добавить в этот перечень.

Чтобы собрать образ, нужно выполнить команду docker build.

docker build -t cryptopro5 .

Чтобы запустить контейнер, нужно выполнить команду docker run.

docker run -v ./cer:/cer -d --name cryptopro5 cryptopro5

Обратите внимание на расшареную директорию сer. Она понадобится для установки сертификатов.

Чтобы проверить статус лицензии, нужно выполнить команду в запущенном контейнере.

docker exec cryptopro5 cpconfig -license -view
Результат проверки состояния лицензии
Результат проверки состояния лицензии

Загрузка сертификатов в контейнер

В целях упрощения тестирования на сайте Криптопро есть возможность загрузить тестовые сертификаты. Они доступны по этой ссылке - http://testca2012.cryptopro.ru/ui/.

Пункты 3 и 4
Пункты 3 и 4

Чтобы установить корневой сертификат, нужно воспользоваться параметром -store со значением root. Также обратите внимание, что в процессе установки сертификата утилита ожидает ответа от пользователя, ответ не буква Y а буква o.

docker exec cryptopro5 bash -c "yes o | certmgr -install -store root -file /cer/rootca.cer"

Чтобы установить сторонний сертификат, параметр -store не нужен.

docker exec cryptopro5 certmgr -install -file /cer/subca.cer

Теперь можно проверить состояние сторонних сертификатов при помощи написанного ранее скрипта.

docker exec cryptopro5 certs_info

Заключение

Дальнейшие шаги по автоматизации процесса обновления сертификатов выполнялись при помощи SOAR, они включали в себя периодический опрос контейнера с Криптопро на предмет устаревающих сертификатов (здесь как раз использовался json сформированный скриптом), формирование предупреждающих уведомлений до того как сертификат просрочиться и отправку инструкций по замене сертификата на электронную почту ответственных лиц.