Skip to content

Instantly share code, notes, and snippets.

@alhoqbani
Last active September 26, 2018 10:36
Show Gist options
  • Select an option

  • Save alhoqbani/4635bdf31cb96d68193341e00556d846 to your computer and use it in GitHub Desktop.

Select an option

Save alhoqbani/4635bdf31cb96d68193341e00556d846 to your computer and use it in GitHub Desktop.
Apache self-signed certificate for use in development.
#!/usr/bin/env bash
# Script to generate self-signed certificate to use with Apache in localhost.
# Author: Hamoud Alhoqbani
# For details: https://gist.github.com/alhoqbani/4635bdf31cb96d68193341e00556d846
[ $# -eq 0 ] && { echo "Usage: $0 domain"; exit 1; }
function print_info() {
printf "\033[0;32m$@\033[0m\n"
}
ROOT_DIR="/usr/local/etc/httpd/extra/ssl"
DOMAIN=$1
DIRNAME=$(echo ${DOMAIN} | rev | cut -d . -f 2- | rev);
DIR="${ROOT_DIR}/${DIRNAME}"
if [ ! -d "$DIR" ]; then
mkdir -p ${DIR}
fi
print_info "Cert files will be stored at ${DIR} for domain ${DOMAIN}"
cat << EOF > "${DIR}/domain.csr.cnf"
[req]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
[dn]
C=US
ST=California
L=Los Angeles
O=End Point
OU=Testing Domain
emailAddress=admin@${DOMAIN}
CN = ${DOMAIN}
EOF
cat << EOF > "${DIR}/v3.ext"
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = ${DOMAIN}
DNS.2 = www.${DOMAIN}
EOF
CA_KEY=${ROOT_DIR}/rootCA.key
CA_PEM=${ROOT_DIR}/rootCA.pem
# Generate issuer certificate only if it does not exist.
if [ ! -f ${CA_KEY} -o ! -f ${CA_PEM} ]; then
cat << EOF > "${ROOT_DIR}/server.csr.cnf"
[req]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
[dn]
C=US
ST=California
L=Los Angeles
O=End Point
OU=Testing Domain
emailAddress=admin@${LOGNAME}
CN = Self-signed Certificate Authority For ${LOGNAME}
EOF
openssl genrsa -out ${CA_KEY} 2048
openssl req -x509 -new -nodes -key ${CA_KEY} -sha256 -days 1024 \
-out ${CA_PEM} \
-config <( cat "${ROOT_DIR}/server.csr.cnf" )
print_info "New Root CA was created. Make sure you trust the certificate ${CA_PEM}"
open ${CA_PEM}
fi
openssl req -new -sha256 -nodes -out "${DIR}/server.csr" -newkey rsa:2048 \
-keyout "${DIR}/server.key" \
-config <( cat "${DIR}/domain.csr.cnf" )
openssl x509 -req -in "${DIR}/server.csr" \
-CA ${CA_PEM} \
-CAkey ${CA_KEY} -CAcreateserial \
-out "${DIR}/server.crt" -days 500 -sha256 \
-extfile "${DIR}/v3.ext"
print_info "Make sure you the certificate ${CA_PEM} is trusted in Keychain."
print_info Done.

Apache self-signed certificate

This setup assume you are on a Mac and installed Apache using Homebrew, and Apache configuation directory in /usr/local/etc/httpd

brew install httpd

Create a directory to hold ssl certificate and files.

mkdir /usr/local/etc/httpd/extra/ssl

Create Diffie-Hellman group key file.

openssl dhparam -out /usr/local/etc/httpd/extra/ssl/dhparam.pem 2048

Add ssl-params to Apache confuguration.

create the file /usr/local/etc/httpd/extra/ssl/ssl-params.conf with the content:

Listen 443
SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH
SSLProtocol All -SSLv2 -SSLv3
SSLHonorCipherOrder On
Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains"
Header always set X-Frame-Options DENY
Header always set X-Content-Type-Options nosniff
SSLCompression off 
SSLSessionTickets Off
SSLUseStapling on 
SSLStaplingCache "shmcb:logs/stapling-cache(150000)"
SSLOpenSSLConfCmd DHParameters "/usr/local/etc/httpd/extra/ssl/dhparam.pem"

Add this line to apache configuration file /usr/local/etc/httpd/httpd.conf to include the ssl-params file:

Include /usr/local/etc/httpd/extra/ssl/ssl-params.conf

Enable Apache SSL module by uncommenting the following line in /usr/local/etc/httpd/httpd.conf

LoadModule ssl_module lib/httpd/modules/mod_ssl.so

Generate the certificate for the domain.

This step involed many commands and requirs creating copuple of files and keys. The script new-cert.sh will do all these step, but here is the details:

This example will generate a certificate for the domain sandbox.test

  1. Create a directory to hold the certificates:
mkdir /usr/local/etc/httpd/extra/ssl/sandbox && cd /usr/local/etc/httpd/extra/ssl/sandbox 
  1. create an extension file to use for creating X509 v3 certificate: (notice the domain name for the DNS.1 value)
cat << EOF > /usr/local/etc/httpd/extra/ssl/sandbox/v3.ext
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = sandbox.test
EOF
  1. create server configuratin file to use when generating the certificate.
cat << EOF > /usr/local/etc/httpd/extra/ssl/sandbox/server.csr.cnf
[req]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn

[dn]
C=US
ST=California
L=Los Angeles
O=End Point
OU=Testing Domain
[email protected]
CN = sandbox.test
EOF
  1. Create a root CA certificate:
openssl genrsa -out /usr/local/etc/httpd/extra/ssl/sandbox/rootCA.key 2048
openssl req -x509 -new -nodes -key /usr/local/etc/httpd/extra/ssl/sandbox/rootCA.key -sha256 -days 1024 \
-out /usr/local/etc/httpd/extra/ssl/sandbox/rootCA.pem \
-config <( cat /usr/local/etc/httpd/extra/ssl/sandbox/server.csr.cnf )

The generated certificate /usr/local/etc/httpd/extra/ssl/sandbox/rootCA.pem need to be trusted by Mac using keychain. See below.

  1. Generate the certificate for the domain:
openssl req -new -sha256 -nodes -out /usr/local/etc/httpd/extra/ssl/sandbox/server.csr -newkey rsa:2048 \
-keyout /usr/local/etc/httpd/extra/ssl/sandbox/server.key -config <(cat /usr/local/etc/httpd/extra/ssl/sandbox/server.csr.cnf)


openssl x509 -req -in /usr/local/etc/httpd/extra/ssl/sandbox/server.csr \
-CA /usr/local/etc/httpd/extra/ssl/sandbox/rootCA.pem \
-CAkey /usr/local/etc/httpd/extra/ssl/sandbox/rootCA.key -CAcreateserial \
-out /usr/local/etc/httpd/extra/ssl/sandbox/server.crt -days 500 -sha256 \
-extfile /usr/local/etc/httpd/extra/ssl/sandbox/v3.ext

Configure the virtual host:

<VirtualHost *:443>
  #   General setup for the virtual host
  DocumentRoot "/Users/hamoud/Sites/sandbox"
  ServerName www.sandbox.test
  ServerAlias sandbox.test
  ServerAdmin [email protected]

  ErrorLog "/usr/local/var/log/httpd/ssl-sandbox-error_log"
  TransferLog "/usr/local/var/log/httpd/ssl-sandbox-access_log"
  
  <Directory "/Users/hamoud/Sites/sandbox">
      AllowOverride All
      Require all granted
  </Directory>

  SSLEngine on
  SSLCertificateFile "/usr/local/etc/httpd/extra/ssl/sandbox/server.crt"
  SSLCertificateKeyFile "/usr/local/etc/httpd/extra/ssl/sandbox/server.key"
  <FilesMatch "\.(cgi|shtml|phtml|php)$">
      SSLOptions +StdEnvVars
  </FilesMatch>

  BrowserMatch "MSIE [2-5]" \
          nokeepalive ssl-unclean-shutdown \
          downgrade-1.0 force-response-1.0
  CustomLog "/usr/local/var/log/httpd/sandbox-ssl_request_log" \
            "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
</VirtualHost>   
  1. Restart apache and test
sudo apachectl -k restart
  1. Add the root key to trusted certificates:
  • open the file rootCA.pem in Keychain.
open /usr/local/etc/httpd/extra/ssl/sandbox/rootCA.pem
  • Double click on the certificate with the domain sandbox.test.
  • Click on trust ‣ and choose Always Trust form "When using this certificate dropdown menu.
  • Check this link for details.

Sources:

https://www.digitalocean.com/community/tutorials/how-to-create-a-self-signed-ssl-certificate-for-apache-in-ubuntu-16-04 https://alexanderzeitler.com/articles/Fixing-Chrome-missing_subjectAltName-selfsigned-cert-openssl/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment