Развертывание центра сертификации (pki-manager)
Установка
Клонирование репозитория
git clone https://github.com/thecybergardener/pki-manager.git
cd pki-manager
Правка конфигурации
Создаем конфиги из шаблонов
cp openssl.conf.example openssl.conf
cp config.env.example config.env
Вносим правки/
В config.env увеличиваем сроки жизни сертификатов корневого и промежуточного центров сертификации, вносим инфу о локации и компании
diff config.env.example config.env
8,10c8,10
< ROOT_VALIDITY=1460 # 4 years
< INTERMEDIATE_VALIDITY=730 # 2 years
< LEAF_VALIDITY=180 # 6 months
---
> ROOT_VALIDITY=14600 # 40 years
> INTERMEDIATE_VALIDITY=7300 # 20 years
> LEAF_VALIDITY=1800 # 60 months
17,22c17,22
< COUNTRY="US" # Use 2 letter country code
< STATE="State"
< LOCALITY="City"
< ORGANIZATION="Home"
< ROOT_CN="Root CA"
< INTERMEDIATE_CN="Intermediate CA"
---
> COUNTRY="RU" # Use 2 letter country code
> STATE="MSK"
> LOCALITY="Moscow"
> ORGANIZATION="Taburetka Inc."
> ROOT_CN="Qiwi Root CA"
> INTERMEDIATE_CN="Qiwi Intermediate CA"
В openssl.conf увеличиваем срок жизни клиентских сертификатов (например 2 или 3 года), разрешаем выпуск нескольких сертификатов для одного домена, и дефолтные значения локации и компании
diff openssl.conf.example openssl.conf
31c31
< default_days = 1825 # Default cert validity duration
---
> default_days = 18250 # Default cert validity duration
51c51
< default_days = 365 # 1 years
---
> default_days = 36500 # 100 years
57c57
< unique_subject = yes
---
> unique_subject = no
109,112c109,112
< countryName_default = US
< stateOrProvinceName_default = State
< localityName_default = City
< organizationName_default = Home
---
> countryName_default = RU
> stateOrProvinceName_default = MSK
> localityName_default = Moscow
> organizationName_default = Taburetka Inc.
Развертывание центра сертификации
./pki-manager.sh init
На все вопросы отвечаем Y.
[2025-12-06 06:44:49] Creating PKI directory structure
[2025-12-06 06:44:49] Generating root CA key using prime256v1 curve
[2025-12-06 06:44:49] Generating root CA certificate (valid for 14600 days)
[2025-12-06 06:44:49] Generating intermediate CA key using prime256v1 curve
[2025-12-06 06:44:49] Generating intermediate CA CSR
[2025-12-06 06:44:49] Signing intermediate CA certificate (valid for 7300 days)
Using configuration from openssl.conf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName :PRINTABLE:'RU'
stateOrProvinceName :ASN.1 12:'MSK'
localityName :ASN.1 12:'Moscow'
organizationName :ASN.1 12:'Taburetka Inc.'
commonName :ASN.1 12:'Qiwi Intermediate CA'
Certificate is to be certified until Dec 1 03:44:49 2045 GMT (7300 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Database updated
[2025-12-06 06:45:18] Creating certificate chain file
[2025-12-06 06:45:18] Certificate chains created at:
[2025-12-06 06:45:18] Full chain (root + intermediate): pki/chains/taburetka-inc.-ca-chain.crt
[2025-12-06 06:45:18] Intermediate chain: pki/chains/taburetka-inc.-intermediate-chain.crt
[2025-12-06 06:45:18] Creating backup at backups/pki_backup_20251206_064518.tar.gz
[2025-12-06 06:45:18] Backup completed successfully
[2025-12-06 06:45:18] PKI initialization complete. Important files:
[2025-12-06 06:45:18] Root CA: pki/root/certs/ca.crt
[2025-12-06 06:45:18] Intermediate CA: pki/intermediate/certs/intermediate.crt
[2025-12-06 06:45:18] Full Chain: pki/chains/ca-chain.crt
[2025-12-06 06:45:18] Intermediate Chain: pki/chains/intermediate-chain.crt
Готовим корневой и промежуточный сертификаты к распространению
Для удобства делаем симлинки
ln -sv pki/intermediate/certs/intermediate.crt ./intermediate-.home_$(date +%Y.%m.%d-%H%M%S).crt
ln -sv pki/root/certs/ca.crt ./ca-.home_$(date +%Y.%m.%d-%H%M%S).crt
Далее забираем эти 2 сертификата и добавляем в доверенные
sudo cp *.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates
На браузеры это не распространяется, нужно или добавлять руками, или погуглить скрипты для автоматизации.
Выпуск сертификата из файла запроса (*.csr)
dom=zbx.home
dt=$(date +%Y-%m-%d_%H-%M-%S)
./pki-manager.sh new-cert $dom-$dt $dom /tmp/request.csr
[2025-12-06 07:38:55] Signing CSR from /tmp/request.csr for service zbx.home-2025-12-06_07-38-55
Using configuration from openssl.conf
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number: 4096 (0x1000)
Validity
Not Before: Dec 6 04:38:55 2025 GMT
Not After : Nov 10 04:38:55 2030 GMT
Subject:
countryName = RU
stateOrProvinceName = MSK
organizationName = Taburetka Inc.
organizationalUnitName = IT
commonName = zbx.home
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Cert Type:
SSL Server
Netscape Comment:
OpenSSL Generated Server Certificate
X509v3 Subject Key Identifier:
C9:16:DE:5E:1C:69:3D:73:18:50:27:6A:E4:53:FD:F2:50:31:41:1D
X509v3 Authority Key Identifier:
keyid:BD:6F:D5:8C:52:20:B3:DA:28:60:0F:A4:D5:D5:32:C0:1B:41:A8:E3
DirName:/C=RU/ST=MSK/L=Moscow/O=Taburetka Inc./CN=Qiwi Root CA
serial:10:00
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Subject Alternative Name:
IP Address:192.168.1.70
Certificate is to be certified until Nov 10 04:38:55 2030 GMT (1800 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Database updated
[2025-12-06 07:39:15] Certificate generated successfully for zbx.home-2025-12-06_07-38-55 from provided CSR
[2025-12-06 07:39:15] Creating backup at backups/pki_backup_20251206_073915.tar.gz
[2025-12-06 07:39:15] Backup completed successfully
Сертификат выпущен и лежит в pki/services/`
ll pki/services/
total 12
drwxr-xr-x 3 root root 4096 Dec 6 07:38 ./
drwxr-xr-x 6 root root 4096 Dec 6 07:38 ../
drwxr-xr-x 3 root root 4096 Dec 6 07:38 zbx.home-2025-12-06_07-38-55/
Наш сертификат:
cat pki/services/$dom-$dt/certs/$dom-$dt.crt
Скрипт генерации файла запроса сертификата (csr) (первичного ключа)
Выполняется, как правило, на сервере, для которого нужно выпустить сертификат (скрипт стоит положить в отдельную папку)
#!/bin/bash
# v.2025.12.06
# Файлы для хранения ключа и шаблона
KEY_FILE="server.key"
CSR_FILE="server.csr"
CONFIG_FILE="openssl.cnf"
# Функция для отображения справки
function show_help {
echo "Использование: $0 [опции]"
echo
echo "Этот скрипт генерирует SSL-сертификаты."
echo "При первом запуске он создает ключ и конфигурационный файл."
echo "При повторном запуске он генерирует запрос на сертификат."
echo
echo "Опции:"
echo " -h, --help Показать эту справку и выйти"
echo
echo "Пример использования:"
echo " ./generate_ssl.sh"
echo
echo "После первого запуска следуйте инструкциям на экране для ввода необходимых данных."
}
# Проверка на наличие опции помощи
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
show_help
exit 0
fi
# Проверка наличия ключа
if [ ! -f "$KEY_FILE" ]; then
# Генерация ключа
openssl genrsa -out "$KEY_FILE" 2048
echo "Ключ сгенерирован и сохранен в $KEY_FILE."
# Запрос данных у пользователя
read -p "Введите страну (C) [RU]: " COUNTRY
read -p "Введите область (ST) [MSK]: " STATE
read -p "Введите город (L) [Moscow]: " LOCALITY
read -p "Введите организацию (O) [Taburetka Inc.]: " ORGANIZATION
read -p "Введите подразделение (OU) [IT]: " ORG_UNIT
read -p "Введите адрес электронной почты [mail@example.com]: " EMAIL
read -p "Введите общее имя (CN) [my.domain.com]: " COMMON_NAME
read -p "Введите IP-адрес (IP.1) [127.0.0.1]: " IP_ADDRESS
# Установка значений по умолчанию, если пользователь ничего не ввел
COUNTRY=${COUNTRY:-RU}
STATE=${STATE:-MSK}
LOCALITY=${LOCALITY:-Moscow}
ORGANIZATION=${ORGANIZATION:-Taburetka Inc.}
ORG_UNIT=${ORG_UNIT:-IT}
EMAIL=${EMAIL:-mail@example.com}
COMMON_NAME=${COMMON_NAME:-my.domain.com}
IP_ADDRESS=${IP_ADDRESS:-127.0.0.1}
# Создание конфигурационного файла
cat <<EOL > "$CONFIG_FILE"
[req]
default_bits = 2048
prompt = no
default_md = sha256
req_extensions = req_ext
distinguished_name = dn
[dn]
C=$COUNTRY
ST=$STATE
L=$LOCALITY
O=$ORGANIZATION
OU=$ORG_UNIT
emailAddress=$EMAIL
CN=$COMMON_NAME
[req_ext]
subjectAltName = @alt_names
[alt_names]
IP.1 = $IP_ADDRESS
DNS.1 = $COMMON_NAME
EOL
echo "Конфигурационный файл сгенерирован и сохранен в $CONFIG_FILE."
else
# Генерация запроса на сертификат
if [ -f "$CONFIG_FILE" ]; then
openssl req -new -key "$KEY_FILE" -out "$CSR_FILE" -config "$CONFIG_FILE"
echo "Запрос на сертификат сгенерирован и сохранен в $CSR_FILE."
else
echo "Конфигурационный файл не найден. Пожалуйста, запустите скрипт в первый раз для его создания."
fi
fi