Vytvoření vlastní certifikační autority a tvorba vlastních self-signed certifikátů s vyplněným Subject Alternative Name (funkční v Chromu 58+)

V tomto krátkém článku si ukážeme, jak si vygenerovat vlastní certifikační autoritu a s její pomocí podepisovat vlastní self-signed certifikáty, které budou mít vyplněné subjectAltName (Subject Alternative Name) a díky tomu budou v pořádku fungovat v Chromu 58 a vyšším. Hodit se vám to bude hlavně pro vývoj, kdy si chceme lokálně zprovoznit https připojení a chceme, aby se tvářilo jako důvěryhodné. Ale případně si takto můžeme generovat certifikáty třeba i pro intranetové domény a v nejhorším případě i pro veřejné domény.

Proč se vůbec dělat s vlastní certifikační autoritou a nevytvářet pouze vlastní self-signed certifikáty? Hlavní výhoda je, že do systému/prohlížeče (třeba Firefox má vlastní úložiště certifikátů) stačí naimportovat certifikát certifikační autority a pak všechny podepsané certifikáty touto autoritou budou automaticky důvěryhodné. Podotýkám, že nejsem bezpečnostní ani linux expert a pouze jsem pospojoval návody, které jsem našel do funkčního celku. Je tedy možné, že něco by šlo řešit elegantněji, případně nebudu používat úplně správnou terminologii. Nebojte se mě opravit v komentářích 🙂 Tento návod je funkční minimálně na Debianu Jessie a Stretch, ale je dost pravděpodobné, že poběží na více systémech.

Nejprve si vygenerujeme certifikační autoritu. Zde jsou dvě možnosti, pokud chceme a nebo nechceme mít soukromý klíč chráněný heslem. Jde o zjednodušený návod z https://datacenteroverlords.com/2012/03/01/creating-your-own-ssl-certificate-authority/. Pokud nechceme mít soukromí klíč chráněný heslem, použijeme příkaz:

sudo openssl genrsa -out /etc/ssl/private/rootCA-Development.key 2048

A pokud chceme, přidáme přepínač -des3 takto:

sudo openssl genrsa -des3 -out /etc/ssl/private/rootCA-Development.key 2048

Následující postup je už stejný:

sudo chmod 600 /etc/ssl/private/rootCA-Development.key
sudo openssl req -x509 -new -nodes -key /etc/ssl/private/rootCA-Development.key -sha256 -days 3650 -subj "/C=CZ/ST=Prague/L=Prague/O=Development" -out /etc/ssl/certs/rootCA-Development.pem

Samořejmě si můžete upravit parametry v -subj. Jejich význam je C=country, ST=state, L=locality a O=organization. Soubor /etc/ssl/certs/rootCA-Development.pem si pak naimportujeme jako důvěryhodný do systému nebo prohlížeče (tady si každý musí vygooglit jak to udělat ve svém systému/prohlížeči).

Zbývá nám si jenom vytvoříme skript, který nám bude generovat samotné certifikáty pro domény. Do jednoho certifikátu může zadat jednu a více domén. Vždy se generuje wildcard certifikát, takže bude platný i pro všechny subdomény. Z toho důvodu domény zadáváme bez www. Vytvoříme tedy skript s název generate-certificate:

sudo nano /usr/local/bin/generate-certificate

S obsahem:

#!/bin/bash

###
# How to generate certificate authority:
#  -> without password:
#    sudo openssl genrsa -out /etc/ssl/private/rootCA-Development.key 2048
#  -> with password:
#    sudo openssl genrsa -des3 -out /etc/ssl/private/rootCA-Development.key 2048
#
#    sudo chmod 600 /etc/ssl/private/rootCA-Development.key 2048
#    sudo openssl req -x509 -new -nodes -key /etc/ssl/private/rootCA-Development.key -sha256 -days 3650 -subj "/C=CZ/ST=Prague/L=Prague/O=Development" -out /etc/ssl/certs/rootCA-Development.pem
###

if [ "$EUID" -ne 0 ]; then
  echo "Please run as root"
  exit 1
fi

if [ $# -eq 0 ]; then
  echo "Please specify domain(s)."
  echo "Usage: $0 <main domain> [another domain] [another domain] ..."
  exit 2
fi

ROOTCA="Development"

# -> for certificate authority with password uncomment the line below:
#read -p "Enter rootCA-${ROOTCA}.key password: " PASSWORD

DOMAIN=$1
CONF="/tmp/$DOMAIN.openssl.cnf"
PRIVATE_KEY="/etc/ssl/private/$DOMAIN.key"
CERTIFICATE_REQUEST="/etc/ssl/certs/$DOMAIN.crt.req"
CERTIFICATE="/etc/ssl/certs/$DOMAIN.crt"
ANOTHER_DOMAINS=""
ANOTHER_DOMAINS_INFO=""

ANOTHER_DOMAIN_INDEX=3
for ANOTHER_DOMAIN in ${@:2}
do
  ANOTHER_DOMAINS="${ANOTHER_DOMAINS}DNS.${ANOTHER_DOMAIN_INDEX} = ${ANOTHER_DOMAIN}"$'\n'
  ANOTHER_DOMAIN_INDEX=$((ANOTHER_DOMAIN_INDEX + 1))
  ANOTHER_DOMAINS="${ANOTHER_DOMAINS}DNS.${ANOTHER_DOMAIN_INDEX} = *.${ANOTHER_DOMAIN}"$'\n'
  ANOTHER_DOMAIN_INDEX=$((ANOTHER_DOMAIN_INDEX + 1))

  ANOTHER_DOMAINS_INFO="-> ${ANOTHER_DOMAIN}"$'\n'
done

cat > $CONF <<-EOF
[req]
default_bits = 2048
prompt = no
x509_extensions = v3_req
distinguished_name = dn

[dn]
C = CZ
ST = Prague
L = Prague
O = $ROOTCA
CN = *.$DOMAIN

[v3_req]
subjectAltName = @alt_names

[alt_names]
DNS.1 = $DOMAIN
DNS.2 = *.$DOMAIN
$ANOTHER_DOMAINS
EOF

openssl genrsa -out $PRIVATE_KEY 2048
chmod 600 $PRIVATE_KEY
openssl req -new -config $CONF -key $PRIVATE_KEY -out $CERTIFICATE_REQUEST

openssl x509 -req -in $CERTIFICATE_REQUEST -CA /etc/ssl/certs/rootCA-${ROOTCA}.pem -CAkey /etc/ssl/private/rootCA-${ROOTCA}.key \
  -CAcreateserial -out $CERTIFICATE -days 3650 -sha256 -extfile $CONF -extensions 'v3_req'
# -> for certificate authority with password uncomment the line below and remove this line and the one up
#  -CAcreateserial -out $CERTIFICATE -days 3650 -sha256 -extfile $CONF -extensions 'v3_req' -passin pass:$PASSWORD

rm $CERTIFICATE_REQUEST
rm $CONF

chmod 600 $PRIVATE_KEY

echo "Self signed certificate ${CERTIFICATE} and private key ${PRIVATE_KEY} for main domain ${DOMAIN} were generated with 10 years expiration time"

if [ -z "$ANOTHER_DOMAINS_INFO" ]; then
  echo "Another domains:"
  echo ${ANOTHER_DOMAINS_INFO}
fi

A nastavíme skript jako spustitelný:

sudo chmod a+x /usr/local/bin/generate-certificate

Pokud jsme vygenerovali soukromý klíč pro certifikační autoritu chráněný heslem, odkomentujeme řádek začínající #read -p ... a u příkazu openssl x509 ... odkomentujeme třetí řádek a druhý vymažeme. Skript se nás pak před generováním vždy zeptá na heslo. Můžeme ještě upravit informace o certifikátu v sekci [dn] stejně jako jsme upravili informace o certifikační autoritě.

Nakones si ukážeme jednoduchý příklad. Certifikát, pro domény domain1.com a domain2.org vygenerujeme takto:

sudo generate-certificate domain1.com domain2.org

Vygenerovaný certifikát je pak v souborech /etc/ssl/private/domain1.com.key (privátní klíč) a /etc/ssl/private/domain1.com.crt (certifikát). Tyto soubory pak už jen použijeme v nastavení nginx, Apache, případně jiného softwaru. A bude platit pro domény domain1.com, *.domain1.com, domain2.org a *.domain2.org.

Napsat komentář

Vaše emailová adresa nebude zveřejněna.