]>
git.proxmox.com Git - mirror_ovs.git/blob - utilities/ovs-pki.in
0255251321e411a32f2cc7fcb4ac61821d1b2ea6
3 # Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks, Inc.
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at:
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
24 log
='@LOGDIR@/ovs-pki.log'
28 # This option-parsing mechanism borrowed from a Autoconf-generated
29 # configure script under the following license:
31 # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
32 # 2002, 2003, 2004, 2005, 2006, 2009 Free Software Foundation, Inc.
33 # This configure script is free software; the Free Software Foundation
34 # gives unlimited permission to copy, distribute and modify it.
36 # If the previous option needs an argument, assign it.
37 if test -n "$prev"; then
43 *=*) optarg
=`expr "X$option" : '[^=]*=\(.*\)'` ;;
47 case $dashdash$option in
52 ovs-pki, for managing a simple OpenFlow public key infrastructure
53 usage: $0 [OPTION...] COMMAND [ARG...]
55 The valid stand-alone commands and their arguments are:
56 init Initialize the PKI
57 req NAME Create new private key and certificate request
58 named NAME-privkey.pem and NAME-req.pem, resp.
59 sign NAME [TYPE] Sign switch certificate request NAME-req.pem,
60 producing certificate NAME-cert.pem
61 req+sign NAME [TYPE] Combine the above two steps, producing all three files.
62 verify NAME [TYPE] Checks that NAME-cert.pem is a valid TYPE certificate
63 fingerprint FILE Prints the fingerprint for FILE
64 self-sign NAME Sign NAME-req.pem with NAME-privkey.pem,
65 producing self-signed certificate NAME-cert.pem
67 The following additional commands manage an online PKI:
68 ls [PREFIX] [TYPE] Lists incoming requests of the given TYPE, optionally
69 limited to those whose fingerprint begins with PREFIX
70 flush [TYPE] Rejects all incoming requests of the given TYPE
71 reject PREFIX [TYPE] Rejects the incoming request(s) whose fingerprint begins
72 with PREFIX and has the given TYPE
73 approve PREFIX [TYPE] Approves the incoming request whose fingerprint begins
74 with PREFIX and has the given TYPE
75 expire [AGE] Rejects all incoming requests older than AGE, in
76 one of the forms Ns, Nmin, Nh, Nday (default: 1day)
77 prompt [TYPE] Interactively prompts to accept or reject each incoming
78 request of the given TYPE
80 Each TYPE above is a certificate type: 'switch' (default) or 'controller'.
82 Options for 'init', 'req', and 'req+sign' only:
83 -k, --key=rsa|dsa Type of keys to use (default: rsa)
84 -B, --bits=NBITS Number of bits in keys (default: 2048). For DSA keys,
85 this has an effect only on 'init'.
86 -D, --dsaparam=FILE File with DSA parameters (DSA only)
87 (default: dsaparam.pem within PKI directory)
88 Options for use with the 'sign' and 'approve' commands:
89 -b, --batch Skip fingerprint verification
90 Options that apply to any command:
91 -d, --dir=DIR Directory where the PKI is located
93 -f, --force Continue even if file or directory already exists
94 -l, --log=FILE Log openssl output to FILE (default: ovs-log.log)
95 -h, --help Print this usage message.
136 echo "unrecognized option $option" >&2
140 if test -z "$command"; then
142 elif test -z "${arg1+set}"; then
144 elif test -z "${arg2+set}"; then
147 echo "$option: only two arguments may be specified" >&2
154 if test -n "$prev"; then
155 option
=--`echo $prev | sed 's/_/-/g'`
156 { echo "$as_me: error: missing argument to $option" >&2
157 { (exit 1); exit 1; }; }
159 if test -z "$command"; then
160 echo "$0: missing command name; use --help for help" >&2
163 if test "$keytype" != rsa
&& test "$keytype" != dsa
; then
164 echo "$0: argument to -k or --key must be rsa or dsa" >&2
167 if test "$bits" -lt 1024; then
168 echo "$0: argument to -B or --bits must be at least 1024" >&2
171 if test -z "$dsaparam"; then
172 dsaparam
=$pkidir/dsaparam.pem
176 *) log
="$PWD/$log" ;;
179 logdir
=$
(dirname "$log")
180 if test ! -d "$logdir"; then
181 mkdir
-p -m755 "$logdir" 2>/dev
/null || true
182 if test ! -d "$logdir"; then
183 echo "$0: log directory $logdir does not exist and cannot be created" >&2
188 if test "$command" = "init"; then
189 if test -e "$pkidir" && test "$force" != "yes"; then
190 echo "$0: $pkidir already exists and --force not specified" >&2
194 if test ! -d "$pkidir"; then
200 if test $keytype = dsa
&& test ! -e dsaparam.pem
; then
201 echo "Generating DSA parameters, please wait..." >&2
202 openssl dsaparam
-out dsaparam.pem
$bits 1>&3 2>&3
205 # Get the current date to add some uniqueness to this certificate
206 curr_date
=`date +"%Y %b %d %T"`
209 for ca
in controllerca switchca
; do
210 echo "Creating $ca..." >&2
215 mkdir
-p certs crl newcerts
216 mkdir
-p -m 0700 private
217 mkdir
-p -m 0733 incoming
219 test -e crlnumber ||
echo 01 > crlnumber
220 test -e serial ||
echo 01 > serial
222 # Put DSA parameters in directory.
223 if test $keytype = dsa
&& test ! -e dsaparam.pem
; then
227 # Write CA configuration file.
228 if test ! -e ca.cnf
; then
229 sed "s/@ca@/$ca/g;s/@curr_date@/$curr_date/g" > ca.cnf
<<'EOF'
232 distinguished_name = req_distinguished_name
234 [ req_distinguished_name ]
240 CN = OVS @ca@ CA Certificate (@curr_date@)
247 database = $dir/index.txt # index file.
248 new_certs_dir = $dir/newcerts # new certs dir
249 certificate = $dir/cacert.pem # The CA cert
250 serial = $dir/serial # serial no file
251 private_key = $dir/private/cakey.pem# CA private key
252 RANDFILE = $dir/private/.rand # random number file
253 default_days = 365 # how long to certify for
254 default_crl_days= 30 # how long before next CRL
255 default_md = md5 # md to use
256 policy = policy # default policy
257 email_in_dn = no # Don't add the email into cert DN
258 name_opt = ca_default # Subject name display option
259 cert_opt = ca_default # Certificate display option
260 copy_extensions = none # Don't copy extensions from request
261 unique_subject = no # Allow certs with duplicate subjects
265 countryName = optional
266 stateOrProvinceName = optional
267 organizationName = match
268 organizationalUnitName = optional
269 commonName = supplied
270 emailAddress = optional
274 # Create certificate authority.
275 if test $keytype = dsa
; then
276 newkey
=dsa
:dsaparam.pem
280 openssl req
-config ca.cnf
-nodes \
281 -newkey $newkey -keyout private
/cakey.pem
-out careq.pem \
283 openssl ca
-config ca.cnf
-create_serial -out cacert.pem \
284 -days 2191 -batch -keyfile private
/cakey.pem
-selfsign \
285 -infiles careq.pem
1>&3 2>&3
286 chmod 0700 private
/cakey.pem
294 if test -z "$arg1" ||
test -n "$arg2"; then
295 echo "$0: $command must have exactly one argument; use --help for help" >&2
301 if test -n "$arg2"; then
302 echo "$0: $command must have zero or one arguments; use --help for help" >&2
308 if test -z "$arg1"; then
309 echo "$0: $command must have one or two arguments; use --help for help" >&2
315 if test -e "$1" && test "$force" != "yes"; then
316 echo "$0: $1 already exists and --force not supplied" >&2
322 test -n "$type" ||
exit 123 # Forgot to call check_type?
328 echo "Prefix $arg1 is too short (less than 4 hex digits)" >&2
333 fingerprint
=$
(cd "$pkidir/${type}ca/incoming" && echo "$1"*-req.pem |
sed 's/-req\.pem$//')
336 echo "No certificate requests matching $1" >&2
340 echo "$1 matches more than one certificate request:" >&2
341 echo $fingerprint |
sed 's/ /\
349 req
="$pkidir/${type}ca/incoming/$fingerprint-req.pem"
350 cert
="$pkidir/${type}ca/certs/$fingerprint-cert.pem"
354 TMP
=/tmp
/ovs-pki.tmp$$
363 date=$
(date -r $file)
364 if grep -e '-BEGIN CERTIFICATE-' "$file" > /dev
/null
; then
365 fingerprint
=$
(openssl x509
-noout -in "$file" -fingerprint |
366 sed 's/SHA1 Fingerprint=//' |
tr -d ':')
368 fingerprint
=$
(sha1sum "$file" |
awk '{print $1}')
370 printf "$name\\t$date\\n"
373 printf "\\t(correct fingerprint in filename)\\n"
376 printf "\\tfingerprint $fingerprint\\n"
381 verify_fingerprint
() {
383 if test $batch != yes; then
384 echo "Does fingerprint match? (yes/no)"
386 if test "$answer" != yes; then
387 echo "Match failure, aborting" >&2
394 if test x
= x
"$1"; then
396 elif test "$1" = switch ||
test "$1" = controller
; then
399 echo "$0: type argument must be 'switch' or 'controller'" >&2
405 number
=$
(echo $1 |
sed 's/^\([0-9]\+\)\([[:alpha:]]\+\)/\1/')
406 unit
=$
(echo $1 |
sed 's/^\([0-9]\+\)\([[:alpha:]]\+\)/\2/')
421 echo "$1: age not in the form Ns, Nmin, Nh, Nday (e.g. 1day)" >&2
425 echo $
(($number * $factor))
429 if test ! -e "$1"; then
430 echo "$0: $1 does not exist" >&2
435 pkidir_must_exist
() {
436 if test ! -e "$pkidir"; then
437 echo "$0: $pkidir does not exist (need to run 'init' or use '--dir'?)" >&2
439 elif test ! -d "$pkidir"; then
440 echo "$0: $pkidir is not a directory" >&2
446 must_not_exist
"$arg1-privkey.pem"
447 must_not_exist
"$arg1-req.pem"
449 cat > "$TMP/req.cnf" <<EOF
452 distinguished_name = req_distinguished_name
454 [ req_distinguished_name ]
459 OU = Open vSwitch certifier
460 CN = Open vSwitch certificate for $arg1
462 if test $keytype = rsa
; then
463 (umask 077 && openssl genrsa
-out "$1-privkey.pem" $bits) 1>&3 2>&3 \
466 must_exist
"$dsaparam"
467 (umask 077 && openssl gendsa
-out "$1-privkey.pem" "$dsaparam") \
470 openssl req
-config "$TMP/req.cnf" -new -text \
471 -key "$1-privkey.pem" -out "$1-req.pem" 1>&3 2>&3
479 (cd "$pkidir/${type}ca" &&
480 openssl ca
-config ca.cnf
-batch -in /dev
/stdin
) \
481 < "$1" > "$2.tmp$$" 2>&3
487 if test "$files" != "$1"; then
493 if test "$command" = req
; then
497 fingerprint
"$arg1-req.pem"
498 elif test "$command" = sign
; then
501 verify_fingerprint
"$arg1-req.pem"
503 sign_request
"$arg1-req.pem" "$arg2-cert.pem"
504 elif test "$command" = req
+sign
; then
510 sign_request
"$arg1-req.pem" "$arg1-cert.pem"
511 fingerprint
"$arg1-req.pem"
512 elif test "$command" = verify
; then
514 must_exist
"$arg1-cert.pem"
518 openssl verify
-CAfile "$pkidir/${type}ca/cacert.pem" "$arg1-cert.pem"
519 elif test "$command" = fingerprint
; then
523 elif test "$command" = self-sign
; then
525 must_exist
"$arg1-req.pem"
526 must_exist
"$arg1-privkey.pem"
527 must_not_exist
"$arg1-cert.pem"
529 # Create both the private key and certificate with restricted permissions.
531 openssl x509
-in "$arg1-req.pem" -out "$arg1-cert.pem.tmp" \
532 -signkey "$arg1-privkey.pem" -req -text) 2>&3 ||
exit $?
534 # Reset the permissions on the certificate to the user's default.
535 cat "$arg1-cert.pem.tmp" > "$arg1-cert.pem"
536 rm -f "$arg1-cert.pem.tmp"
537 elif test "$command" = ls; then
540 cd "$pkidir/${type}ca/incoming"
541 for file in $
(glob
"$arg1*-req.pem"); do
544 elif test "$command" = flush
; then
547 rm -f "$pkidir/${type}ca/incoming/"*
548 elif test "$command" = reject
; then
551 resolve_prefix
"$arg1"
554 elif test "$command" = approve
; then
557 resolve_prefix
"$arg1"
560 cp "$req" "$TMP/$req"
561 verify_fingerprint
"$TMP/$req"
562 sign_request
"$TMP/$req"
563 rm -f "$req" "$TMP/$req"
564 elif test "$command" = prompt
; then
569 cd "$pkidir/${type}ca/incoming"
570 for req
in $
(glob
"*-req.pem"); do
571 cp "$req" "$TMP/$req"
573 cert
=$
(echo "$pkidir/${type}ca/certs/$req" |
574 sed 's/-req.pem/-cert.pem/')
575 if test -f $cert; then
576 echo "Request $req already approved--dropping duplicate request"
577 rm -f "$req" "$TMP/$req"
583 fingerprint
"$TMP/$req" "$req"
584 printf "Disposition for this request (skip/approve/reject)? "
588 echo "Approving $req"
589 sign_request
"$TMP/$req" "$cert"
590 rm -f "$req" "$TMP/$req"
593 echo "Rejecting $req"
594 rm -f "$req" "$TMP/$req"
601 elif test "$command" = expire
; then
603 cutoff
=$
(($
(date +%s
) - $
(parse_age
${arg1-1day})))
604 for type in switch controller
; do
605 cd "$pkidir/${type}ca/incoming" ||
exit 1
606 for file in $
(glob
"*"); do
607 time=$
(date -r "$file" +%s
)
608 if test "$time" -lt "$cutoff"; then
614 echo "$0: $command command unknown; use --help for help" >&2