This document describes the steps we took to set up a multi-level OpenSSL-based Certificate Authority for use with Globus' GSI.
Our goal was to establish a multi-level CA. The difference between a multi-level CA and a single-level CA is that in a single-level CA, the root key is also the signing key for host and user certificates. We wanted to establish a root key which we could use to sign (and revoke if necessary) several signing keys which will be used for different purposes. So, if a local PKI is represented a tree where nodes are keys and edges are certificates, a single-level tree is height two and has just one non-leaf node, while our tree is height three and has a single root node, and several second level nodes.
For more information on setting up a single-level CA, see the mod_ssl FAQ.
Setting up a CA for GSI is very similar to setting up a CA for
Apache's mod_ssl
. However, in the multi-level case,
there are some differences. Specifically, Apache
w/mod_ssl
doesn't care if the signing keys do not have
the "CA:TRUE" bit set, while GSI does.
While this step isn't strictly necessary for the following process,
doing it makes subsequent steps a bit easier, and increases the
chances of getting things right, and consistent.
Make a copy of the openssl.cnf
file, and change the defaults to suit your installation. Scroll
to the section labeled [ req_distinguished_name ]
and
change the lines with the suffix _default
.
For example, our altered section reads as follows:
[ req_distinguished_name ] countryName = Country Name (2 letter code) countryName_default = US countryName_min = 2 countryName_max = 2 stateOrProvinceName = State or Province Name (full name) stateOrProvinceName_default = Wisconsin localityName = Locality Name (eg, city) localityName_default = Madison 0.organizationName = Organization Name (eg, company) 0.organizationName_default = University of Wisconsin -- Madison 1.organizationName = Second Organization Name (eg, company) 1.organizationName_default = Computer Sciences Department organizationalUnitName = Organizational Unit Name (eg, section) organizationalUnitName_default = Condor Project commonName = Common Name (eg, YOUR name) commonName_max = 64 emailAddress = Email Address emailAddress_max = 40
For now we ignore the certificate revocation issues.
The key size must be determined: we used 1024 bits.
Two periods must be determined: the validity period of the root certificate, and the validity period of the signing certificate. For the first pass at the CA, we used twenty years (7300 days) for the former, and three years (1095 days) for the latter. Ten years (3650 days) may be more reasonable for the root key.
The security of the root key is critical, because it is so long lived, and because it can be used to revoke the signing key if necessary. So, we established the policy that the root key is never stored or decrypted on a machine which has an active network connection. I turn off my laptop's wireless connection, create the key, create a cd with just the key on it, burn the cd, and remove the key from the laptop. In the openssl directory, the key is a link to the cd filesystem. When I need to create a signing key, I turn off the network connection, put in the CD, create the key, eject the CD, then turn on the network connection.
There are two people who have copies of the root key CD and know the password.
openssl genrsa -des3 -out root-ca.key 1024
You will be asked for a password which will be the CA password, and
then you'll be asked for that password again. The output of this
command, the file root-ca.key
, contains an RSA keypair which
is encryped using the password you supply. So, for someone to use
this key to create new certificates (either host or client), they'll
need both this file and the password.
openssl req -new -x509 -days 3650 -key root-ca.key -out root-ca.crt \
-config openssl.cnf
This reads, "create a new, self-signed X.509 certificate valid for
ten years, for the keypair in the file root-ca.key
, and place
the output in the file root-ca.crt
."
You will be prompted to input identifying information for the
certificate. It's important not to use single quotes in the responses
due to a quirk in the Globus implementation: for example don't use a
Common Name such as "Alice's CA
". If you have
customized the configuration file as suggested above, the defaults you
specified there will make this step easier. The openssl req
command recognizes that the request is for a self signed certificate, and
automatically applies suitable options, such as setting the "CA:TRUE" bit.
Don't use an email address. This avoids this interaction bug in signing policy files.
openssl.cnf
files, or one with multiple CA sections.
We'll take the latter approach.
Here's our modified replacement.
Basically what we do
is to copy the entire section marked CA_default to a section labeled
CA_root, and specify a different directory name for the directory
where CA files are stored. Of course, we also need to change the
names of the files that contain the key and certificate appropriately.
The next step in this process is to set up a CA directory for
the openssl ca
command. Note that the directory contents
must reflect the settings in the openssl.cnf
file just
created. This can be done by executing this perl script, which performs the
following steps:
sign.sh
.
openssl genrsa -des3 -out signing-ca-1.key 1024
Now, instead of creating the request and signing it with the private key just created, as is done above, here we create a request in one step, and then sign it using the root key in another. First, we create the request. (Don't use an email address here either.)
openssl req -new -days 1095 -key signing-ca-1.key -out signing-ca-1.csr \
-config openssl.cnf
Then, we sign the request, using the "-name
" argument to
specify the section in the altered openssl.cnf
file:
openssl ca -config openssl.cnf -name CA_root -extensions v3_ca \
-out signing-ca-1.crt -infiles signing-ca-1.csr
openssl.cnf
file.
/usr/bin/openssl req -newkey rsa:1024 -keyout kosart.key \
-config openssl.cnf -out kosart.req
Then sign it, remembering the signing key password:
/usr/bin/openssl ca -config openssl.cnf \
-out kosart.crt \
-infiles kosart.req
/usr/bin/openssl req -newkey rsa:1024 \
-keyout host_nmi-redhat62-build.key -nodes \
-config openssl.cnf -out host_nmi-redhat62-build.req
/usr/bin/openssl ca -config openssl.cnf \
-out host_nmi-redhat62-build.crt \
-infiles host_nmi-redhat62-build.req
There's a perl script for generating certs from an input file.
Other handy OpenSSL commmand line tools:
/usr/bin/openssl x509 -noout -hash -in host.crt
/usr/bin/openssl x509 -noout -subject -in host.crt
/usr/bin/openssl x509 -noout -text -in host.crt