allow apache to read PLC_MA_SA_SSL_KEY so it can make user certs
[myplc.git] / plc.d / ssl
1 #!/bin/bash
2 #
3 # priority: 400
4 #
5 # Generate SSL certificates
6 #
7 # Mark Huang <mlhuang@cs.princeton.edu>
8 # Copyright (C) 2006 The Trustees of Princeton University
9 #
10 # $Id: ssl,v 1.5 2006/06/23 21:47:18 mlhuang Exp $
11 #
12
13 # Source function library and configuration
14 . /etc/plc.d/functions
15 . /etc/planetlab/plc_config
16
17 # Be verbose
18 set -x
19
20 mkcert ()
21 {
22     CN=$1
23     KEY=$2
24     CRT=$3
25
26     # Generate a temporary CSR. We could save the CSR, but it's not
27     # worth the trouble.
28     csr=$(mktemp /tmp/csr.XXXXXX)
29
30     mkdir -p $(dirname $KEY)
31     openssl req -config /etc/planetlab/ssl/openssl.cnf \
32         -new -extensions v3_req -days 365 -set_serial $RANDOM \
33         -batch -subj "/CN=$CN" \
34         -nodes -keyout $KEY -out $csr
35     check
36     chmod 600 $KEY
37
38     # Generate and sign certificate from CSR
39     serial=$(cat /etc/planetlab/ssl/serial)
40
41     openssl ca -config /etc/planetlab/ssl/openssl.cnf \
42         -keyfile $PLC_ROOT_CA_SSL_KEY \
43         -cert $PLC_ROOT_CA_SSL_CRT \
44         -batch -infiles $csr
45     check
46
47     mv /etc/planetlab/ssl/$serial.pem $CRT
48     chmod 644 $CRT
49
50     # Delete CSR
51     rm -f $csr
52 }
53
54 case "$1" in
55     start)
56         MESSAGE=$"Generating SSL certificates"
57         dialog "$MESSAGE"
58
59         # Check if root CA certificate is valid
60         if [ -f $PLC_ROOT_CA_SSL_CRT ] ; then
61             verify=$(openssl verify $PLC_ROOT_CA_SSL_CRT)
62             # If self signed, assume that we generated it
63             if grep -q "self signed certificate" <<<$verify ; then
64                 # Delete if expired or PLC name or e-mail address has changed
65                 if grep -q "expired" <<<$verify || \
66                     [ "$(ssl_cname $PLC_ROOT_CA_SSL_CRT)" != "$PLC_NAME Root CA" ] || \
67                     [ "$(ssl_email $PLC_ROOT_CA_SSL_CRT)" != "$PLC_MAIL_SUPPORT_ADDRESS" ] ; then
68                     rm -f $PLC_ROOT_CA_SSL_CRT
69                 fi
70             fi
71         fi
72
73         # Generate root CA key pair and certificate
74         if [ ! -f $PLC_ROOT_CA_SSL_CRT ] ; then
75             mkdir -p $(dirname $PLC_ROOT_CA_SSL_CRT)
76             openssl req -config /etc/planetlab/ssl/openssl.cnf \
77                 -new -x509 -extensions v3_ca -days 3650 -set_serial $RANDOM \
78                 -batch -subj "/CN=$PLC_NAME Root CA/emailAddress=$PLC_MAIL_SUPPORT_ADDRESS" \
79                 -nodes -keyout $PLC_ROOT_CA_SSL_KEY -out $PLC_ROOT_CA_SSL_CRT
80             check
81             chmod 600 $PLC_ROOT_CA_SSL_KEY
82             chmod 644 $PLC_ROOT_CA_SSL_CRT
83
84             # API certificate verification requires a public key
85             openssl rsa -pubout <$PLC_ROOT_CA_SSL_KEY >$PLC_ROOT_CA_SSL_KEY_PUB
86             check
87             chmod 644 $PLC_ROOT_CA_SSL_KEY_PUB
88
89             # Reset DB
90             >/etc/planetlab/ssl/index.txt
91             echo "01" >/etc/planetlab/ssl/serial
92         fi
93
94         # Check if MA/SA certificate is valid
95         if [ -f $PLC_MA_SA_SSL_CRT ] ; then
96             verify=$(openssl verify -CAfile $PLC_ROOT_CA_SSL_CRT $PLC_MA_SA_SSL_CRT)
97             # Delete if expired or not signed correctly
98             if grep -q "error" <<<$verify ; then
99                 rm -f $PLC_MA_SA_SSL_CRT
100             fi
101         fi
102
103         # Generate MA/SA key pair and certificate
104         if [ ! -f $PLC_MA_SA_SSL_CRT ] ; then
105             mkcert "$PLC_NAME Management and Slice Authority" \
106                 $PLC_MA_SA_SSL_KEY $PLC_MA_SA_SSL_CRT
107
108             # make readable by apache to sign certificates
109             chown apache $PLC_MA_SA_SSL_KEY
110             chmod 600 $PLC_MA_SA_SSL_KEY
111
112             # API requires a public key for slice ticket verification
113             openssl rsa -pubout <$PLC_MA_SA_SSL_KEY >$PLC_MA_SA_SSL_KEY_PUB
114             check
115             chmod 644 $PLC_MA_SA_SSL_KEY_PUB
116         fi
117
118         # Generate HTTPS certificate(s). We generate a certificate for
119         # each enabled server with a different hostname.
120         for server in WWW API BOOT ; do
121             ssl_key=PLC_${server}_SSL_KEY
122             ssl_crt=PLC_${server}_SSL_CRT
123             hostname=PLC_${server}_HOST
124
125             # Check if we have already generated a certificate for
126             # the same hostname.
127             for previous_server in WWW API BOOT ; do
128                 if [ "$server" = "$previous_server" ] ; then
129                     break
130                 fi
131                 previous_ssl_key=PLC_${previous_server}_SSL_KEY
132                 previous_ssl_crt=PLC_${previous_server}_SSL_CRT
133                 previous_hostname=PLC_${previous_server}_HOST
134
135                 if [ -f ${!previous_ssl_crt} ] && \
136                     [ "$(ssl_cname ${!previous_ssl_crt})" = "${!hostname}" ] ; then
137                     cp -a ${!previous_ssl_key} ${!ssl_key}
138                     cp -a ${!previous_ssl_crt} ${!ssl_crt}
139                     break
140                 fi
141             done
142
143             # Check if certificate is valid
144             if [ -f ${!ssl_crt} ] ; then
145                 verify=$(openssl verify -CAfile $PLC_ROOT_CA_SSL_CRT ${!ssl_crt})
146                 # Delete if expired or hostname changed. These
147                 # certificates do not necessarily have to be signed by
148                 # the root CA; they may be signed by a third party,
149                 # e.g., Entrust or Verisign.
150                 if grep -q "expired" <<<$verify || \
151                     [ "$(ssl_cname ${!ssl_crt})" != "${!hostname}" ] ; then
152                     rm -f ${!ssl_crt}
153                 fi
154             fi
155
156             # Generate and sign certificate
157             if [ ! -f ${!ssl_crt} ] ; then
158                 mkcert ${!hostname} ${!ssl_key} ${!ssl_crt}
159             fi
160         done
161
162         # Install HTTPS certificates into both /etc/pki (Fedora Core
163         # 4) and /etc/httpd/conf (Fedora Core 2). If the API, boot,
164         # and web servers are all running on the same machine, the web
165         # server certificate takes precedence.
166         for server in API BOOT WWW ; do
167             enabled=PLC_${server}_ENABLED
168             if [ "${!enabled}" != "1" ] ; then
169                 continue
170             fi
171             ssl_key=PLC_${server}_SSL_KEY
172             ssl_crt=PLC_${server}_SSL_CRT
173
174             symlink ${!ssl_crt} /etc/pki/tls/certs/localhost.crt
175             symlink ${!ssl_key} /etc/pki/tls/private/localhost.key
176             symlink ${!ssl_crt} /etc/httpd/conf/ssl.crt/server.crt
177             symlink ${!ssl_key} /etc/httpd/conf/ssl.key/server.key
178         done
179
180         result "$MESSAGE"
181         ;;
182 esac
183
184 exit $ERRORS