Apache SSL TLS Certificate Creation Script
Overview
Brief notes on how to create an Apache OpenSSL certificate using a bash script under Debian 10. A website that is not encrypted can become a threat to visitors, and often many providers block websites that are not SSL/TLS enabled. The audience is experienced Linux administrators.
Definitions
-
* Root CA certificate = the main self-signed certificate from the Root certificate authority that signs all other certificates or intermediate certificates.
* Intermediate CA certificate = a certificate created by an intermediate certificate authority (CA), signed by the Root CA.
* CA Bundle certificate = the merge of Root CA certificate an the Intermadiate CA certificate, valid as a root certificate.
* Certificate = the certificate received and signed by the Intermediate CA certificate.
* Certificate Chain = the end certificate, along with the CA Bundle certificate.
* The intermediate method has more security, so that intrusion of one intermediate certificate authority does not affect the entire root.
The Script
The OpenSSL script below is simple; the variables need to be modified inside. It creates the following (4) four files:
-
* Raw private key.
* RSA private key.
* CSR, certificate signing request.
* Self-signed certificate, for testing.
Creating the private key in at least two formats seems like a good idea. Always keep private keys truly private and secure.
#!/bin/bash # ### Create self signed certificate for local SSL virtual hosts. # by Ramses Soto-Navarro <ramses@sotosystems.com> 7/12/2010 f_syntax () { echo "SYNTAX: $0 <virtualhost.name.org>" exit 1 } if [ $# -lt 1 ]; then f_syntax; fi VHOST=$1 ######################### # MODIFY VARIABLES BELOW: ######################### f_setvars () { #### Modify only the variables below: C=US ST=FL L="Winter Haven" O="Example Company" OU="Information Technology Department" EMAIL="admin@example.com" DAYS="3650" OWNERS=root.root ######################### # Do not modify anything below: CN=$VHOST RAWPRIVKEY=$VHOST.raw.privkey.pem CSR=$VHOST.csr RSAPRIVKEY=$VHOST.rsa.privkey.pem CERT=$VHOST.self-signed.crt CONFIG=/dev/shm/sslconfig-$$.txt cat > $CONFIG <<EOF [ req ] default_bits = 2048 default_keyfile = $RAWPRIVKEY.pem distinguished_name = req_distinguished_name attributes = req_attributes prompt = no output_password = mypass [ req_distinguished_name ] C=$C ST=$ST L=$L O=$O OU=$OU CN=$VHOST emailAddress=$EMAIL [ req_attributes ] challengePassword = $RANDOM challenge password EOF } f_create-self-signed-cert () { f_setvars echo "*** Creating Raw Private Key $RAWPRIVKEY" echo "*** Creating Certificate Signing Request $CSR" openssl req -config $CONFIG -new -nodes -keyout $RAWPRIVKEY -out $CSR echo "*** Converting Raw Private Key to RSA format" openssl rsa -in $RAWPRIVKEY -out $RSAPRIVKEY echo "*** Creating Self-sign Certificate $CERT" openssl x509 -in $CSR -req -signkey $RSAPRIVKEY -days $DAYS -out $CERT chmod 0640 $VHOST* #chown $OWNERS $VHOST* echo " --------------------------------------- Create the following entries in Apache: SSLEngine on SSLCertificateFile $PWD/$CERT SSLCertificateKeyFile $PWD/$RSAPRIVKEY " rm $CONFIG } echo -en "Create self-signed certificate for $VHOST [y/n] " read continue case $continue in y|Y) f_create-self-signed-cert ;; n|N) exit 0 ;; *) f_syntax ;; esac
Results
What running the script looks like and the result.
# mkdir -p /etc/ssl/www.example.com # cd /etc/ssl/www.example.com # create-cert.sh www.example.com Create self-signed certificate for www.example.com [y/n] y *** Creating Raw Private Key www.example.com.raw.privkey.pem *** Creating Certificate Signing Request www.example.com.csr Generating a RSA private key ........+++++ ..............+++++ writing new private key to 'www.example.com.raw.privkey.pem' ----- *** Converting Raw Private Key to RSA format writing RSA key *** Creating Self-sign Certificate www.example.com.self-signed.crt Signature ok subject=C = US, ST = FL, L = Winter Haven, O = Example Company, OU = Information Technology Department, CN = www.example.com, emailAddress = admin@example.com Getting Private key --------------------------------------- Create the following entries in Apache: SSLEngine on SSLCertificateFile /etc/ssl/www.example.com.self-signed.crt SSLCertificateKeyFile /etc/ssl/www.example.com.rsa.privkey.pem
The files created:
# ls -lh total 16K -rw-r----- 1 root root 1.2K Sep 11 01:21 www.example.com.csr -rw-r----- 1 root root 1.7K Sep 11 01:21 www.example.com.raw.privkey.pem -rw-r----- 1 root root 1.7K Sep 11 01:21 www.example.com.rsa.privkey.pem -rw-r----- 1 root root 1.4K Sep 11 01:21 www.example.com.self-signed.crt
Official Certificate Process
The self-signed certificate is fine for testing. However, for official certificate encryption you’ll need to do the following:
-
* Subscribe to a certificate issuer.
* Purchase a certificate validation.
* Send the certificate signing request; the *,csr file above.
* The CSR is basically a temporary key sent to the intermediate certificate authorities, so that they can create and sign your public certificate.
* Wait for your certificate request to be processed; sometimes it takes a few hours, but it can take 24 hours or more.
* You’ll receive an Email with the signed certificate or a link to download it.
* File www_example_com.zip may extract to: www_example_com.crt and www_example_com.ca-bundle. Refer to the above definitions for clarification.
Check Certificate Validity
Check if the certificate returned is valid. Important matching areas to inspect: “Subject: CN=”, “Not After”, “Issuer”.
# openssl x509 -subject -noout -in www.example.com.crt # openssl x509 -enddate -noout -in www.example.com.crt # openssl x509 -issuer -noout -in www.example.com.crt # openssl x509 -text -in www.example.com.crt | more
Configure Apache Virtual Host with SSL
Modify the Apache SSL configuration:
# vi /etc/apache2/sites-available/www.example.com-ssl.conf <VirtualHost *:443> Header edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure ServerAdmin "admin@example.com" ServerName "example.com:443" DocumentRoot "/var/www/www.example.com" <Directory "/var/www/www.example.com"> Options Indexes FollowSymLinks MultiViews AllowOverride All Require all granted </Directory> SSLEngine on SSLCertificateFile /etc/ssl/www.example.com/www.example.com.crt SSLCertificateKeyFile /etc/ssl/www.example.com/ww.example.com.rsa.privkey.pem SSLCertificateChainFile /etc/ssl/www.example.com/www.example.com.ca-bundle </VirtualHost>
Create the test file:
# mkdir -p /var/www/www.example.com # echo "Hello World" >> /var/www/www.example.com/index.html
Restart Apache:
# systemctl restart apache2
Open the page in your browser and verify that the certificate is valid by clicking on the certificate lockpad next to or near the URL entry box.
Subject Alternative Certificate Script
Follow the logic:
# by Ramses Soto-Navarro <ramses@sotosystems.com>, 3/1/2023 # Create a self-signed certificate with subject alternative name # in order to server URLs with the same domain suffix. # Also create the private key, public key and CSR. # Modify the variable below: # === VARIABLES === export DOMAIN="example.com" export DAYS=3650 cat > req.cnf <<EOF [ req ] prompt = no default_bits = 4096 distinguished_name = req_distinguished_name req_extensions = req_ext [ req_distinguished_name ] C=US ST=FL L=Bartow O=Example LLC OU=IT Dept CN=$DOMAIN emailAddress=info@$DOMAIN [ req_ext ] subjectAltName = @alt_names [alt_names] DNS.1 = $DOMAIN DNS.2 = *.$DOMAIN IP.1 = 10.20.30.40 EOF # === Do not modify below === # Create priv key f_privkey () { echo -e "nn=== Generating private key $DOMAIN.priv.key ===" openssl genrsa -out $DOMAIN.priv.key 2048 # Verify: openssl rsa -in privateKey.key -check } f_pubkey () { echo -e "nn=== Generating public key $DOMAIN.pub.pem ===" openssl rsa -in $DOMAIN.priv.key -pubout -out $DOMAIN.pub.pem # Verify: cat $DOMAIN.pub.pem } # Create CSR f_csr () { echo -e "nn=== Creating CSR $DOMAIN.csr ===" openssl req -new -key $DOMAIN.priv.key -config req.cnf -out $DOMAIN.csr # Verify: openssl req -text -noout -verify -in $DOMAIN.csr # Verify CSR subjectAltName: openssl req -in $DOMAIN.csr -text -noout | grep DNS } # Create self-signed cert f_cert () { echo -e "nn=== Generating Self-signed Certificate $DOMAIN.crt ===" openssl x509 -signkey $DOMAIN.priv.key -in $DOMAIN.csr -req -days 365 -extfile req.cnf -extensions req_ext -out $DOMAIN.crt # Verify: openssl x509 -text -noout -in $DOMAIN.crt } f_privkey f_pubkey f_csr f_cert
The End.