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 | [root@localhost ~]# locate openssl.cnf |
Change the dir configuration in the openssl.cnf file:
1 | #################################################################### |
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 | [andrew@localhost CA]$ pwd |
This directory structure is very similar with the default data directory of CA:
1 | [andrew@localhost CA]$ pwd |
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 | openssl req -new -key private/cakey.pem -out private/ca.csr -subj \ |
- generate root certificate
here is the command, and the root ceritficate is stored at certs/ca.cer
:
1 | openssl x509 -req -days 365 -sha1 -extensions v3_ca -signkey \ |
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 | [andrew@localhost CA]$ cat myserver.conf |
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 | openssl req -new -key private/client-key.pem -out private/client.csr -subj \ |
- sign client certificate
1 | openssl x509 -req -days 365 -sha1 -extensions v3_req -CA certs/ca.cer -CAkey private/cakey.pem \ |
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:
- http://serverfault.com/questions/9708/what-is-a-pem-file-and-how-does-it-differ-from-other-openssl-generated-key-file
- http://info.ssl.com/article.aspx?id=12149
remove passphrase from key file: