Setup your own CA

Recently, in our project we need enable tokenless auth for keystone, which means client or service can use client certificate to auth with out the token generated by keystone.

Following steps are the experiment I made on my development environment, and the os is centos7, my user account is andrew, you should change it to your account accordingly.

Setup my own CA

Fristly, we need setup a CA to sign our client certificate.

Install openssl:

1
sudo yum install openssl

After openssl is installed, find the openssl conf file, and change the data directory of the CA.

1
2
3
[root@localhost ~]# locate openssl.cnf
/etc/pki/tls/openssl.cnf
/usr/share/man/man5/openssl.cnf.5ssl.gz

Change the dir configuration in the openssl.cnf file:

1
2
3
4
5
6
7
8
9
####################################################################
[ ca ]
default_ca = CA_default # The default ca section

####################################################################
[ CA_default ]

#dir = /etc/pki/CA # Where everything is kept
dir = /home/andrew/CA # Where everything is kept

Then you should create related diretorys in /home/andrew/CA to store related files, such as CSR(Certificate Signing Request) file, private key file, or certificates.

1
2
3
4
5
[andrew@localhost CA]$ pwd
/home/andrew/CA
[andrew@localhost CA]$ mkdir certs newcerts private crl
[andrew@localhost CA]$ touch index.txt
[andrew@localhost CA]$ echo 01 > serial

This directory structure is very similar with the default data directory of CA:

1
2
3
4
[andrew@localhost CA]$ pwd
/etc/pki/CA
[andrew@localhost CA]$ ls
certs crl newcerts private

certs is for signed certificates, newcerts is for new generated certificates, private is for private key files, crl is for revocation certificates.

Before generating any certificates, we need generated an random seed.

1
openssl rand -out private/.rand 1000

generate root certificate

  • generate private key for root certificate

Openssl used PEM(Privacy Enbanced Mail) to store private key. Here is the command to generate the private key.

1
openssl genrsa -aes256 -out private/cakey.pem 1024

when executed this command, it will ask you to input a password for your key, you need to remember that, because openssl will ask you to input that password when it using this key file.

  • generate csr

The CSR(Certificate Signing Request) is the file you send to CA to generate your Certificate, here is how to generate it:

1
2
openssl req -new -key private/cakey.pem -out private/ca.csr -subj \
"/C=CN/ST=myprovince/L=mycity/O=myorganization/OU=mygroup/CN=myname"
  • generate root certificate

here is the command, and the root ceritficate is stored at certs/ca.cer:

1
2
openssl x509 -req -days 365 -sha1 -extensions v3_ca -signkey \
private/cakey.pem -in private/ca.csr -out certs/ca.cer

here file extension suffix is cer, and for some certificate file, the extension suffix is crt, actually, file content for this two kind file are representing certificate data. the extension only related how to open it on the windows. you can check it here: How to convert CER to CRT certificates?

generate server certificate

  • generate key file
1
openssl genrsa -aes256 -out private/server-key.pem 1024

like the root certificate key file, you also need to remember the password for this key file.

  • generate csr

Edit an conf file, and use it for openssl to generate server csr, because we need to add subjectAltName, which defines the certificat can be used for multi domains.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[andrew@localhost CA]$ cat myserver.conf
[req]
default_bits = 2048
distinguished_name = req_distinguished_name
req_extensions = v3_req
x509_extensions = v3_req

[req_distinguished_name]
countryName = CN
countryName_default = GB
stateOrProvinceName = Sichuan
stateOrProvinceName_default = West Midlands
localityName = Chengdu
localityName_default = Birmingham
organizationName = Flying Spaghetti Monster
organizationName_default = Example
commonName = Andrew
commonName_max = 64
[v3_req]
subjectAltName = @alt_names
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
[alt_names]
DNS.1 = openstack.andrew.com
DNS.2 = dev-openstack.andrew.com
DNS.3 = test-openstack.andrew.com
DNS.4 = local-openstack.andrew.com

then use this command to generate server csr (Certificate Signing Request) file:

1
openssl req -new -key private/server-key.pem -out private/server.csr -config myserver.conf

using the following command to verify the csr file.

1
openssl req -noout -text -in private/server.csr

  • generate server Certificate
1
openssl x509 -req -days 365 -sha1 -extfile myserver.conf -extensions v3_req -CA certs/ca.cer -CAkey private/cakey.pem -CAserial ca.srl -CAcreateserial -in private/server.csr -out certs/server.cer

please pay attention to this two pramaters -extfile myserver.conf -extensions v3_req, it will use the v3_req section of myserver.conf as cert extentsion, andd add the subjectAltName to the certificate.

using the following command to check the certificate

1
openssl x509 -noout -text -in certs/server.cer

generate client certificate

  • generate client private key

    1
    openssl genrsa -aes256 -out private/client-key.pem 1024

  • generate client csr file

1
2
openssl req -new -key private/client-key.pem -out private/client.csr -subj \
"/C=CN/ST=myprovince/L=mycity/O=myorganization/OU=mygroup/CN=andrew"
  • sign client certificate
1
2
openssl x509 -req -days 365 -sha1 -extensions v3_req -CA certs/ca.cer -CAkey private/cakey.pem \
-CAserial ca.srl -in private/client.csr -out certs/client.cer

install ceritificates

After we genenerate all kind of certificates, we need install the CA certificate to our system, because it’s not a trust certificate.

If we want to use the ceritficate for a server, then we need install the CA certificate on our client system.

If we want to use the client certificate for authenticate, for example in apache httpd, we need to config the CA certificate in the httpd configuration file.

This article shows how to install certificate on various system: Adding trusted root certificates to the server

for python requests to add CA

Install the CA certificates on server, it works for the system tools, such as curl, but for the python requests libraray, it needs some extra work.

here in the ca-certificates document of requests, it shows request used the certifi to manage CA certificates.

In the pythone package of certifi, you can find the following documents:

using pip install certifi

1
$ pip install certifi

find the path of the cacert.pem file

1
2
3
>>> import certifi
>>> certifi.where()
'/usr/lib/python2.7/site-packages/certifi/cacert.pem'

then add your own ca file in to that cacert.pem

1
cat /home/andrew/CA/certs/ca.cer >> cacert.pem

then the requests can request the website, which using the certificate signed by your ca.

remove passowrd of the key file

The key file is encrypted by the password which you input when you generate it.

If you used this key file for apache, when apache starts, it will ask you to input the password, if you unencrypt the key with openssl, then apache will skip this part.

You’ll need the passphrase for the decryption process:

1
# openssl rsa -in www.key -out new.key

Now copy the new.key to the www.key file and you’re done. Next time you restart the web server, it should not prompt you for the passphrase.

Acknowledge

Thanks to Jack (甯尤刚) to point out serveral errors of this article.

Reference

trust ca on system:

certificate extensions:

remove passphrase from key file: