blob: f7dcffa32d5d8ba447fd8f8d2f2e49dd868287d2 [file] [log] [blame]
Dean Troyerc83a7e12012-11-29 11:47:58 -06001# lib/tls
2# Functions to control the configuration and operation of the TLS proxy service
3
4# Dependencies:
5# !! source _before_ any services that use ``SERVICE_HOST``
6# ``functions`` file
7# ``DEST``, ``DATA_DIR`` must be defined
8# ``HOST_IP``, ``SERVICE_HOST``
9# ``KEYSTONE_TOKEN_FORMAT`` must be defined
10
11# Entry points:
12# configure_CA
13# init_CA
14
15# configure_proxy
16# start_tls_proxy
17
18# make_root_ca
19# make_int_ca
20# new_cert $INT_CA_DIR int-server "abc"
21# start_tls_proxy HOST_IP 5000 localhost 5000
22
23
Dean Troyercc6b4432013-04-08 15:38:03 -050024# Defaults
25# --------
26
Dean Troyerc83a7e12012-11-29 11:47:58 -060027if is_service_enabled tls-proxy; then
28 # TODO(dtroyer): revisit this below after the search for HOST_IP has been done
29 TLS_IP=${TLS_IP:-$SERVICE_IP}
30
31 # Set the default ``SERVICE_PROTOCOL`` for TLS
32 SERVICE_PROTOCOL=https
33fi
34
35# Make up a hostname for cert purposes
36# will be added to /etc/hosts?
37DEVSTACK_HOSTNAME=secure.devstack.org
38DEVSTACK_CERT_NAME=devstack-cert
39DEVSTACK_CERT=$DATA_DIR/$DEVSTACK_CERT_NAME.pem
40
41# CA configuration
42ROOT_CA_DIR=${ROOT_CA_DIR:-$DATA_DIR/CA/root-ca}
43INT_CA_DIR=${INT_CA_DIR:-$DATA_DIR/CA/int-ca}
44
45ORG_NAME="OpenStack"
46ORG_UNIT_NAME="DevStack"
47
48# Stud configuration
49STUD_PROTO="--tls"
50STUD_CIPHERS='TLSv1+HIGH:!DES:!aNULL:!eNULL:@STRENGTH'
51
52
53# CA Functions
54# ============
55
56# There may be more than one, get specific
57OPENSSL=${OPENSSL:-/usr/bin/openssl}
58
59# Do primary CA configuration
60function configure_CA() {
61 # build common config file
62
63 # Verify ``TLS_IP`` is good
64 if [[ -n "$HOST_IP" && "$HOST_IP" != "$TLS_IP" ]]; then
65 # auto-discover has changed the IP
66 TLS_IP=$HOST_IP
67 fi
68}
69
70# Creates a new CA directory structure
71# create_CA_base ca-dir
72function create_CA_base() {
73 local ca_dir=$1
74
75 if [[ -d $ca_dir ]]; then
76 # Bail out it exists
77 return 0
78 fi
79
80 for i in certs crl newcerts private; do
81 mkdir -p $ca_dir/$i
82 done
83 chmod 710 $ca_dir/private
84 echo "01" >$ca_dir/serial
85 cp /dev/null $ca_dir/index.txt
86}
87
88
89# Create a new CA configuration file
90# create_CA_config ca-dir common-name
91function create_CA_config() {
92 local ca_dir=$1
93 local common_name=$2
94
95 echo "
96[ ca ]
97default_ca = CA_default
98
99[ CA_default ]
100dir = $ca_dir
101policy = policy_match
102database = \$dir/index.txt
103serial = \$dir/serial
104certs = \$dir/certs
105crl_dir = \$dir/crl
106new_certs_dir = \$dir/newcerts
107certificate = \$dir/cacert.pem
108private_key = \$dir/private/cacert.key
109RANDFILE = \$dir/private/.rand
110default_md = default
111
112[ req ]
113default_bits = 1024
114default_md = sha1
115
116prompt = no
117distinguished_name = ca_distinguished_name
118
119x509_extensions = ca_extensions
120
121[ ca_distinguished_name ]
122organizationName = $ORG_NAME
123organizationalUnitName = $ORG_UNIT_NAME Certificate Authority
124commonName = $common_name
125
126[ policy_match ]
127countryName = optional
128stateOrProvinceName = optional
129organizationName = match
130organizationalUnitName = optional
131commonName = supplied
132
133[ ca_extensions ]
134basicConstraints = critical,CA:true
135subjectKeyIdentifier = hash
136authorityKeyIdentifier = keyid:always, issuer
137keyUsage = cRLSign, keyCertSign
138
139" >$ca_dir/ca.conf
140}
141
142# Create a new signing configuration file
143# create_signing_config ca-dir
144function create_signing_config() {
145 local ca_dir=$1
146
147 echo "
148[ ca ]
149default_ca = CA_default
150
151[ CA_default ]
152dir = $ca_dir
153policy = policy_match
154database = \$dir/index.txt
155serial = \$dir/serial
156certs = \$dir/certs
157crl_dir = \$dir/crl
158new_certs_dir = \$dir/newcerts
159certificate = \$dir/cacert.pem
160private_key = \$dir/private/cacert.key
161RANDFILE = \$dir/private/.rand
162default_md = default
163
164[ req ]
165default_bits = 1024
166default_md = sha1
167
168prompt = no
169distinguished_name = req_distinguished_name
170
171x509_extensions = req_extensions
172
173[ req_distinguished_name ]
174organizationName = $ORG_NAME
175organizationalUnitName = $ORG_UNIT_NAME Server Farm
176
177[ policy_match ]
178countryName = optional
179stateOrProvinceName = optional
180organizationName = match
181organizationalUnitName = optional
182commonName = supplied
183
184[ req_extensions ]
185basicConstraints = CA:false
186subjectKeyIdentifier = hash
187authorityKeyIdentifier = keyid:always, issuer
188keyUsage = digitalSignature, keyEncipherment, keyAgreement
189extendedKeyUsage = serverAuth, clientAuth
190subjectAltName = \$ENV::SUBJECT_ALT_NAME
191
192" >$ca_dir/signing.conf
193}
194
Dean Troyerca802172013-01-09 19:08:02 -0600195# Create root and intermediate CAs
Dean Troyerc83a7e12012-11-29 11:47:58 -0600196# init_CA
197function init_CA {
198 # Ensure CAs are built
199 make_root_CA $ROOT_CA_DIR
200 make_int_CA $INT_CA_DIR $ROOT_CA_DIR
201
202 # Create the CA bundle
203 cat $ROOT_CA_DIR/cacert.pem $INT_CA_DIR/cacert.pem >>$INT_CA_DIR/ca-chain.pem
Dean Troyerca802172013-01-09 19:08:02 -0600204}
Dean Troyerc83a7e12012-11-29 11:47:58 -0600205
Dean Troyerca802172013-01-09 19:08:02 -0600206# Create an initial server cert
207# init_cert
208function init_cert {
Dean Troyerc83a7e12012-11-29 11:47:58 -0600209 if [[ ! -r $DEVSTACK_CERT ]]; then
210 if [[ -n "$TLS_IP" ]]; then
211 # Lie to let incomplete match routines work
212 TLS_IP="DNS:$TLS_IP"
213 fi
214 make_cert $INT_CA_DIR $DEVSTACK_CERT_NAME $DEVSTACK_HOSTNAME "$TLS_IP"
215
216 # Create a cert bundle
217 cat $INT_CA_DIR/private/$DEVSTACK_CERT_NAME.key $INT_CA_DIR/$DEVSTACK_CERT_NAME.crt $INT_CA_DIR/cacert.pem >$DEVSTACK_CERT
218 fi
219}
220
221
222# make_cert creates and signs a new certificate with the given commonName and CA
223# make_cert ca-dir cert-name "common-name" ["alt-name" ...]
224function make_cert() {
225 local ca_dir=$1
226 local cert_name=$2
227 local common_name=$3
228 local alt_names=$4
229
230 # Generate a signing request
231 $OPENSSL req \
232 -sha1 \
233 -newkey rsa \
234 -nodes \
235 -keyout $ca_dir/private/$cert_name.key \
236 -out $ca_dir/$cert_name.csr \
237 -subj "/O=${ORG_NAME}/OU=${ORG_UNIT_NAME} Servers/CN=${common_name}"
238
239 if [[ -z "$alt_names" ]]; then
240 alt_names="DNS:${common_name}"
241 else
242 alt_names="DNS:${common_name},${alt_names}"
243 fi
244
245 # Sign the request valid for 1 year
246 SUBJECT_ALT_NAME="$alt_names" \
247 $OPENSSL ca -config $ca_dir/signing.conf \
248 -extensions req_extensions \
249 -days 365 \
250 -notext \
251 -in $ca_dir/$cert_name.csr \
252 -out $ca_dir/$cert_name.crt \
253 -subj "/O=${ORG_NAME}/OU=${ORG_UNIT_NAME} Servers/CN=${common_name}" \
254 -batch
255}
256
257
258# Make an intermediate CA to sign everything else
259# make_int_CA ca-dir signing-ca-dir
260function make_int_CA() {
261 local ca_dir=$1
262 local signing_ca_dir=$2
263
264 # Create the root CA
265 create_CA_base $ca_dir
266 create_CA_config $ca_dir 'Intermediate CA'
267 create_signing_config $ca_dir
268
269 # Create a signing certificate request
270 $OPENSSL req -config $ca_dir/ca.conf \
271 -sha1 \
272 -newkey rsa \
273 -nodes \
274 -keyout $ca_dir/private/cacert.key \
275 -out $ca_dir/cacert.csr \
276 -outform PEM
277
278 # Sign the intermediate request valid for 1 year
279 $OPENSSL ca -config $signing_ca_dir/ca.conf \
280 -extensions ca_extensions \
281 -days 365 \
282 -notext \
283 -in $ca_dir/cacert.csr \
284 -out $ca_dir/cacert.pem \
285 -batch
286}
287
288# Make a root CA to sign other CAs
289# make_root_CA ca-dir
290function make_root_CA() {
291 local ca_dir=$1
292
293 # Create the root CA
294 create_CA_base $ca_dir
295 create_CA_config $ca_dir 'Root CA'
296
297 # Create a self-signed certificate valid for 5 years
298 $OPENSSL req -config $ca_dir/ca.conf \
299 -x509 \
300 -nodes \
301 -newkey rsa \
302 -days 21360 \
303 -keyout $ca_dir/private/cacert.key \
304 -out $ca_dir/cacert.pem \
305 -outform PEM
306}
307
308
309# Proxy Functions
310# ===============
311
312# Starts the TLS proxy for the given IP/ports
313# start_tls_proxy front-host front-port back-host back-port
314function start_tls_proxy() {
315 local f_host=$1
316 local f_port=$2
317 local b_host=$3
318 local b_port=$4
319
320 stud $STUD_PROTO -f $f_host,$f_port -b $b_host,$b_port $DEVSTACK_CERT 2>/dev/null
321}
Sean Dague584d90e2013-03-29 14:34:53 -0400322
Dean Troyercc6b4432013-04-08 15:38:03 -0500323
Sean Dague584d90e2013-03-29 14:34:53 -0400324# Local variables:
325# mode: shell-script
326# End: