X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=plc.d%2Fssl;h=ddbfe8166640263ed201115ed3e1f1aa6673745a;hb=96fdd23864b959c06ecec267b65eede59ea48e07;hp=fc3fa748599dbafacbc2f62818165b1960433b03;hpb=309572ab8b4843bb6507b0b3f6dc5e5240af257b;p=myplc.git diff --git a/plc.d/ssl b/plc.d/ssl index fc3fa74..ddbfe81 100755 --- a/plc.d/ssl +++ b/plc.d/ssl @@ -1,102 +1,156 @@ #!/bin/bash # -# priority: 400 +# priority: 300 # # Generate SSL certificates # # Mark Huang # Copyright (C) 2006 The Trustees of Princeton University # -# $Id: ssl,v 1.3 2006/04/07 04:28:16 mlhuang Exp $ -# # Source function library and configuration . /etc/plc.d/functions . /etc/planetlab/plc_config +# Be verbose +set -x + +# Print the CNAME of an SSL certificate +ssl_cname () +{ + openssl x509 -noout -in $1 -subject | \ + sed -n -e 's@.*/CN=\([^/]*\).*@\1@p' | \ + lower +} + +backup_file () +{ + filepath=$1 + filename=$(basename ${filepath}) + dir=$(dirname ${filepath}) + mv -f ${filepath} ${dir}/${filename}-`date +%Y-%m-%d-%H-%M-%S`.bak +} + +# Verify a certificate. If invalid, generate a new self-signed +# certificate. +verify_or_generate_certificate() { + crt=$1 + key=$2 + ca=$3 + cname=$(lower $4) + + # If the CA certificate does not exist, assume that the + # certificate is self-signed. + if [ ! -f $ca ] ; then + cp -a $crt $ca + fi + + if [ -f $crt ] ; then + # Check if certificate is valid + # Backup if invalid or if the subject has changed + if openssl verify -CAfile $ca $crt | grep -q "error" || \ + [ "$(ssl_cname $crt)" != "$cname" ] ; then + backup_file $crt + backup_file $ca + backup_file $key + fi + fi + + if [ ! -f $crt ] ; then + # Set subject + subj= + if [ -n "$cname" ] ; then + subj="$subj/CN=$cname" + fi + + # Generate new self-signed certificate + mkdir -p $(dirname $crt) + openssl req -new -x509 -days 3650 -set_serial $RANDOM \ + -batch -subj "$subj" \ + -nodes -keyout $key -out $crt + check + + # The certificate it self-signed, so it is its own CA + cp -a $crt $ca + fi + + # Fix permissions + chmod 644 $crt $ca +} + case "$1" in start) - MESSAGE=$"Generating SSL certificates" - dialog "$MESSAGE" - - # Generate self-signed SSL 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 + + # Generate HTTPS certificates if necessary. We generate a + # certificate for each enabled server with a different + # hostname. These self-signed certificates may be overridden + # later. + MESSAGE=$"Generating SSL certificates for" + dialog "$MESSAGE" + + for server in WWW API BOOT MONITOR; do + eval "a=\$PLC_${server}_ENABLED" + echo $a + if [ "$a" -ne 1 ] ; then + echo "Skipping" + continue + fi + dialog "$server" + ssl_key=PLC_${server}_SSL_KEY ssl_crt=PLC_${server}_SSL_CRT + ca_ssl_crt=PLC_${server}_CA_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 + for previous_server in WWW API BOOT MONITOR; 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_ca_ssl_crt=PLC_${previous_server}_CA_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} + cp -a ${!previous_ca_ssl_crt} ${!ca_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 - else - echo "$verify" >&2 - fi - fi - - # Generate new self signed certificate - if [ ! -f ${!ssl_crt} ] ; then - mkdir -p $(dirname ${!ssl_crt}) - openssl req -new -x509 -days 365 -set_serial $RANDOM \ - -batch -subj "/CN=${!hostname}" \ - -nodes -keyout ${!ssl_key} -out ${!ssl_crt} - check - chmod 644 ${!ssl_crt} - fi + verify_or_generate_certificate \ + ${!ssl_crt} ${!ssl_key} ${!ca_ssl_crt} \ + ${!hostname} done - # API requires a public key for slice ticket verification - if [ ! -f $PLC_API_SSL_KEY_PUB ] ; then - openssl rsa -pubout <$PLC_API_SSL_KEY >$PLC_API_SSL_KEY_PUB - check - fi - - # Install 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 + # 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 + for server in API BOOT MONITOR WWW; do enabled=PLC_${server}_ENABLED if [ "${!enabled}" != "1" ] ; then continue fi ssl_key=PLC_${server}_SSL_KEY ssl_crt=PLC_${server}_SSL_CRT + ssl_ca_crt=PLC_${server}_CA_SSL_CRT symlink ${!ssl_crt} /etc/pki/tls/certs/localhost.crt symlink ${!ssl_key} /etc/pki/tls/private/localhost.key + symlink ${!ssl_ca_crt} /etc/pki/tls/certs/server-chain.crt symlink ${!ssl_crt} /etc/httpd/conf/ssl.crt/server.crt symlink ${!ssl_key} /etc/httpd/conf/ssl.key/server.key done + # Ensure that the server-chain gets used, as it is off by + # default. + sed -i -e 's/^#SSLCertificateChainFile /SSLCertificateChainFile /' \ + /etc/httpd/conf.d/ssl.conf + result "$MESSAGE" ;; esac