# Mark Huang <mlhuang@cs.princeton.edu>
# Copyright (C) 2006 The Trustees of Princeton University
#
-# $Id: api-config,v 1.12 2006/05/30 15:06:20 mlhuang Exp $
+# $Id: api-config,v 1.13 2006/06/23 20:33:28 mlhuang Exp $
#
from plc_config import PLCConfiguration
globals()[category_id] = dict(zip(variablelist.keys(),
[variable['value'] for variable in variablelist.values()]))
- # Get the issuer e-mail address of the root CA certificate
+ # Get the issuer e-mail address and public key from the root CA certificate
root_ca_email = commands.getoutput("openssl x509 -in %s -noout -email" % \
- plc['root_ca_ssl_crt'])
+ plc_ma_sa['ca_ssl_crt'])
+ root_ca_key_pub = commands.getoutput("openssl x509 -in %s -noout -pubkey" % \
+ plc_ma_sa['ca_ssl_crt'])
# Verify API certificate
if os.path.exists(plc_ma_sa['api_crt']):
try:
cert_xml = file(plc_ma_sa['api_crt']).read().strip()
# Verify root CA signature
- CertOps.authenticate_cert(cert_xml,
- {root_ca_email:
- file(plc['root_ca_ssl_key_pub']).read().strip()})
+ CertOps.authenticate_cert(cert_xml, {root_ca_email: root_ca_key_pub})
# Check if MA/SA e-mail address has changed
dom = xml.dom.minidom.parseString(cert_xml)
- for issuer in dom.getElementsByTagName('issuer'):
- if issuer.getAttribute('email') != plc_mail['support_address']:
+ for subject in dom.getElementsByTagName('subject'):
+ if subject.getAttribute('email') != plc_mail['support_address']:
raise Exception, "E-mail address '%s' in certificate '%s' does not match support address '%s'" % \
- (issuer.getAttribute('email'), plc_ma_sa['api_crt'], plc_mail['support_address'])
+ (subject.getAttribute('email'), plc_ma_sa['api_crt'], plc_mail['support_address'])
except Exception, e:
# Delete invalid API certificate
print "Warning: ", e
os.unlink(plc_ma_sa['api_crt'])
- # Generate API certificate
+ # Generate self-signed API certificate
if not os.path.exists(plc_ma_sa['api_crt']):
print "Generating new API certificate"
try:
cert = Certificate.Certificate('ticket-cert-0')
- ma_sa_ssl_key_pub = file(plc_ma_sa['ssl_key_pub']).read().strip()
+ ma_sa_ssl_key_pub = commands.getoutput("openssl x509 -in %s -noout -pubkey" % \
+ plc_ma_sa['ssl_crt'])
cert.add_subject_pubkey(pubkey = ma_sa_ssl_key_pub, email = plc_mail['support_address'])
root_ca_subject = commands.getoutput("openssl x509 -in %s -noout -subject" % \
- plc['root_ca_ssl_crt'])
+ plc_ma_sa['ssl_crt'])
m = re.search('/CN=([^/]*).*', root_ca_subject)
if m is None:
- root_ca_cn = plc['name'] + " Root CA"
+ root_ca_cn = plc['name'] + " Management and Slice Authority"
else:
root_ca_cn = m.group(1)
cert.set_issuer(email = root_ca_email, cn = root_ca_cn)
- cert_xml = cert.sign(plc['root_ca_ssl_key'])
+ cert_xml = cert.sign(plc_ma_sa['ssl_key'])
ma_sa_api_crt = file(plc_ma_sa['api_crt'], "w")
ma_sa_api_crt.write(cert_xml)
ma_sa_api_crt.close()
'MA_SA_NAMESPACE': plc_ma_sa['namespace'],
'SESSION_LENGTH_HOURS': "24",
'ROOT_CA_EMAIL': root_ca_email,
- 'ROOT_CA_PUB_KEY': plc['root_ca_ssl_key_pub'],
+ 'ROOT_CA_PUB_KEY': plc_ma_sa['ca_ssl_key_pub'],
'API_CERT_PATH': plc_ma_sa['api_crt'],
'MA_SA_PRIVATE_KEY': plc_ma_sa['ssl_key'],
'PL_API_TICKET_KEY_FILE': plc_ma_sa['ssl_key']}
# Mark Huang <mlhuang@cs.princeton.edu>
# Copyright (C) 2006 The Trustees of Princeton University
#
-# $Id: ssl,v 1.6 2006/06/28 20:44:17 alk Exp $
+# $Id: ssl,v 1.7 2006/06/28 21:34:18 mlhuang Exp $
#
# Source function library and configuration
# Be verbose
set -x
-mkcert ()
+# Print the CNAME of an SSL certificate
+ssl_cname ()
{
- 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
+ openssl x509 -noout -in $1 -subject | \
+ sed -n -e 's@.*/CN=\([^/]*\).*@\1@p'
}
-case "$1" in
- start)
- MESSAGE=$"Generating SSL certificates"
- dialog "$MESSAGE"
+# Print the emailAddress of an SSL certificate
+ssl_email ()
+{
+ openssl x509 -noout -in $1 -subject | \
+ sed -n -e 's@.*/emailAddress=\([^/]*\).*@\1@p'
+}
- # 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
+# Verify a certificate. If invalid, generate a new self-signed
+# certificate.
+verify_or_generate_certificate() {
+ crt=$1
+ key=$2
+ ca=$3
+ cname=$4
+ email=$5
+
+ if [ -f $crt ] ; then
+ # Check if certificate is valid
+ verify=$(openssl verify -CAfile $ca $crt)
+ # Delete if invalid or if the subject has changed
+ if grep -q "error" <<<$verify || \
+ [ "$(ssl_cname $crt)" != "$cname" ] || \
+ [ "$(ssl_email $crt)" != "$email" ] ; then
+ rm -f $crt $ca
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
+ if [ ! -f $crt ] ; then
+ # Set subject
+ subj=
+ if [ -n "$cname" ] ; then
+ subj="$subj/CN=$cname"
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
+ if [ -n "$email" ] ; then
+ subj="$subj/emailAddress=$email"
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
+ # 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
+ chmod 644 $crt
+ fi
+
+ if [ ! -f $ca ] ; then
+ # The certificate it self-signed, so it is its own CA
+ cp -a $crt $ca
+ fi
+}
- # 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
+case "$1" in
+ start)
+ MESSAGE=$"Generating SSL certificates"
+ dialog "$MESSAGE"
- # 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.
+ # Verify or generate MA/SA certificate if necessary. This
+ # self-signed certificate may be overridden later.
+ verify_or_generate_certificate \
+ $PLC_MA_SA_SSL_CRT $PLC_MA_SA_SSL_KEY $PLC_MA_SA_CA_SSL_CRT \
+ "$PLC_NAME Management and Slice Authority" \
+ $PLC_MAIL_SUPPORT_ADDRESS
+
+ # Make MA/SA key readable by apache so that the API can sign
+ # certificates
+ chown apache $PLC_MA_SA_SSL_KEY
+ chmod 600 $PLC_MA_SA_SSL_KEY
+
+ # Extract the public key of the root CA (if any) that signed
+ # the MA/SA certificate.
+ openssl x509 -in $PLC_MA_SA_CA_SSL_CRT -noout -pubkey >$PLC_MA_SA_CA_SSL_KEY_PUB
+ check
+ chmod 644 $PLC_MA_SA_CA_SSL_KEY_PUB
+
+ # 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.
for server in WWW API BOOT ; do
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
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
- fi
- fi
+ verify_or_generate_certificate \
+ ${!ssl_crt} ${!ssl_key} ${!ca_ssl_crt} \
+ ${!hostname} $PLC_MAIL_SUPPORT_ADDRESS
- # 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