#!/bin/bash # # priority: 400 # # Generate SSL certificates # # Mark Huang # Copyright (C) 2006 The Trustees of Princeton University # # $Id: ssl,v 1.6 2006/06/28 20:44:17 alk Exp $ # # Source function library and configuration . /etc/plc.d/functions . /etc/planetlab/plc_config # Be verbose set -x mkcert () { CN=$1 KEY=$2 CRT=$3 # Generate a temporary CSR. We could save the CSR, but it's not # worth the trouble. csr=$(mktemp /tmp/csr.XXXXXX) mkdir -p $(dirname $KEY) openssl req -config /etc/planetlab/ssl/openssl.cnf \ -new -extensions v3_req -days 3650 -set_serial $RANDOM \ -batch -subj "/CN=$CN" \ -nodes -keyout $KEY -out $csr check chmod 600 $KEY # Generate and sign certificate from CSR serial=$(cat /etc/planetlab/ssl/serial) openssl ca -config /etc/planetlab/ssl/openssl.cnf \ -keyfile $PLC_ROOT_CA_SSL_KEY \ -cert $PLC_ROOT_CA_SSL_CRT \ -batch -infiles $csr check mv /etc/planetlab/ssl/$serial.pem $CRT chmod 644 $CRT # Delete CSR rm -f $csr } case "$1" in start) MESSAGE=$"Generating SSL certificates" dialog "$MESSAGE" # Check if root CA certificate is valid if [ -f $PLC_ROOT_CA_SSL_CRT ] ; then verify=$(openssl verify $PLC_ROOT_CA_SSL_CRT) # If self signed, assume that we generated it if grep -q "self signed certificate" <<<$verify ; then # Delete if expired or PLC name or e-mail address has changed if grep -q "expired" <<<$verify || \ [ "$(ssl_cname $PLC_ROOT_CA_SSL_CRT)" != "$PLC_NAME Root CA" ] || \ [ "$(ssl_email $PLC_ROOT_CA_SSL_CRT)" != "$PLC_MAIL_SUPPORT_ADDRESS" ] ; then rm -f $PLC_ROOT_CA_SSL_CRT fi fi fi # Generate root CA key pair and certificate if [ ! -f $PLC_ROOT_CA_SSL_CRT ] ; then mkdir -p $(dirname $PLC_ROOT_CA_SSL_CRT) openssl req -config /etc/planetlab/ssl/openssl.cnf \ -new -x509 -extensions v3_ca -days 3650 -set_serial $RANDOM \ -batch -subj "/CN=$PLC_NAME Root CA/emailAddress=$PLC_MAIL_SUPPORT_ADDRESS" \ -nodes -keyout $PLC_ROOT_CA_SSL_KEY -out $PLC_ROOT_CA_SSL_CRT check chmod 600 $PLC_ROOT_CA_SSL_KEY chmod 644 $PLC_ROOT_CA_SSL_CRT # API certificate verification requires a public key openssl rsa -pubout <$PLC_ROOT_CA_SSL_KEY >$PLC_ROOT_CA_SSL_KEY_PUB check chmod 644 $PLC_ROOT_CA_SSL_KEY_PUB # Reset DB >/etc/planetlab/ssl/index.txt echo "01" >/etc/planetlab/ssl/serial fi # Check if MA/SA certificate is valid if [ -f $PLC_MA_SA_SSL_CRT ] ; then verify=$(openssl verify -CAfile $PLC_ROOT_CA_SSL_CRT $PLC_MA_SA_SSL_CRT) # Delete if expired or not signed correctly if grep -q "error" <<<$verify ; then rm -f $PLC_MA_SA_SSL_CRT fi fi # Generate MA/SA key pair and certificate if [ ! -f $PLC_MA_SA_SSL_CRT ] ; then mkcert "$PLC_NAME Management and Slice Authority" \ $PLC_MA_SA_SSL_KEY $PLC_MA_SA_SSL_CRT # Make readable by apache so that the API can sign certificates chown apache $PLC_MA_SA_SSL_KEY chmod 600 $PLC_MA_SA_SSL_KEY # API requires a public key for slice ticket verification openssl rsa -pubout <$PLC_MA_SA_SSL_KEY >$PLC_MA_SA_SSL_KEY_PUB check chmod 644 $PLC_MA_SA_SSL_KEY_PUB fi # Generate self-signed HTTPS certificate(s). These nice # commands come from the mod_ssl spec file for Fedora Core # 2. We generate a certificate for each enabled server # with a different hostname. These self-signed # certificates may be overridden later. for server in WWW API BOOT ; do ssl_key=PLC_${server}_SSL_KEY ssl_crt=PLC_${server}_SSL_CRT hostname=PLC_${server}_HOST # Check if we have already generated a certificate for # the same hostname. for previous_server in WWW API BOOT ; do if [ "$server" = "$previous_server" ] ; then break fi previous_ssl_key=PLC_${previous_server}_SSL_KEY previous_ssl_crt=PLC_${previous_server}_SSL_CRT previous_hostname=PLC_${previous_server}_HOST if [ -f ${!previous_ssl_crt} ] && \ [ "$(ssl_cname ${!previous_ssl_crt})" = "${!hostname}" ] ; then cp -a ${!previous_ssl_key} ${!ssl_key} cp -a ${!previous_ssl_crt} ${!ssl_crt} break fi done # Check if self-signed certificate is valid if [ -f ${!ssl_crt} ] ; then verify=$(openssl verify ${!ssl_crt}) # If self-signed if grep -q "self signed certificate" <<<$verify ; then # Delete if expired or hostname changed if grep -q "expired" <<<$verify || \ [ "$(ssl_cname ${!ssl_crt})" != "${!hostname}" ] ; then rm -f ${!ssl_crt} fi fi fi # Generate new self-signed certificate if [ ! -f ${!ssl_crt} ] ; then mkdir -p $(dirname ${!ssl_crt}) openssl req -new -x509 -days 3650 -set_serial $RANDOM \ -batch -subj "/CN=${!hostname}" \ -nodes -keyout ${!ssl_key} -out ${!ssl_crt} check chmod 644 ${!ssl_crt} fi done # Install HTTPS certificates into both /etc/pki (Fedora Core # 4) and /etc/httpd/conf (Fedora Core 2). If the API, boot, # and web servers are all running on the same machine, the web # server certificate takes precedence. for server in API BOOT WWW ; do enabled=PLC_${server}_ENABLED if [ "${!enabled}" != "1" ] ; then continue fi ssl_key=PLC_${server}_SSL_KEY ssl_crt=PLC_${server}_SSL_CRT symlink ${!ssl_crt} /etc/pki/tls/certs/localhost.crt symlink ${!ssl_key} /etc/pki/tls/private/localhost.key symlink ${!ssl_crt} /etc/httpd/conf/ssl.crt/server.crt symlink ${!ssl_key} /etc/httpd/conf/ssl.key/server.key done result "$MESSAGE" ;; esac exit $ERRORS