In this article, I wanted to briefly talk about how to generate keys and certificates in OpenSSL using a configuration file. In how to configure encrypted connections in Bacula, I wrote about how to do this via the command line. After the article, I was doing some research on OpenSSL and came across the configuration file option. This option allows you to add specific details to a configuration file. When generating keys and certificate requests, you can use the configuration file instead of being prompted at the command line.
A quick recap of the manual way
First, lets look at how I did it originally. For the article, I had to generate a keys and certificates for a self-signed certificate authority, a server and a client. So, to set up the certificate authority, I first generated a set of keys.
openssl genrsa -out bacula_ca.key 2048
The command generates the RSA keypair and writes the keypair to bacula_ca.key. So far pretty straight forward. The next step is to generate an x509 certificate which I can then use to sign certificate requests from clients.
openssl req -new -x509 -key bacula_ca.key -out bacula_ca.crt
As you can see, OpenSSL prompts for some details that needs to be filled in.
Next step, generate the server keypair.
openssl req -new -newkey rsa:2048 -nodes -keyout bacula_server.key -out bacula_server.csr
Again, here we need to fill out some of the same details for the certificate signing request. Not too much information needs to be entered, but it can be repetitive.
Final step is to sign the certificate, however, there is no input required for that, so I’m skipping the recap of that step.
One of the ways that we can speed this up, is by supplying the information as a part of the arguments to OpenSSL. Lets generate the Bacula Certificate Authority certificate, but this time, we’ll add the Distinguished Name properties as part of the arguments.
openssl req -new -newkey rsa:2048 -nodes -keyout bacula_server.key -out bacula_server.csr -subj "/C=US/ST=Some State/L=Some City/O=Some Company/OU=Some IT department/CN=bacula_server/emailAddress=some@some_company.domain.local/"
So, this time, we just add the information as part of the command line arguments and OpenSSL puts that information into the certificate.
To verify, we can check the certificate signing request.
openssl req -in bacula_server.csr -noout -text
So, as we can see, all the details are filled out for us by OpenSSL. If, for example, we did not want to add Organizational Unit Name, we could just omit OU from the list.
Again, we would have to do the same when we request the certificate for the Certificate Authority. Though we could copy, modify the parts that we want, and then past it back in. However, this is also a little bit cumbersome. We could take this one step further and add all the data into a configuration file.
Automated approach with configuration file
We can generate a configuration file to hold some of the information we supplied on the command line. That way, we don’t need to copy, change and paste the information directly on the command line, rather we can do it in the configuration file. I’ve generated a configuration file that contain the data we previously had on the command line.
[ req ] default_bits = 2048 default_md = sha256 prompt = no encrypt_key = no distinguished_name = bacula_server # bacula_ca [ bacula_ca ] countryName = "US" # C= stateOrProvinceName = "Some State" # ST= localityName = "Some City" # L= organizationName = "Some Company" # O= organizationalUnitName = "Some IT department # OU= commonName = "bacula_ca" # CN= emailAddress = "firstname.lastname@example.org" # CN/emailAddress= # bacula_server [ bacula_server ] countryName = "US" # C= stateOrProvinceName = "Some State" # ST= localityName = "Some City" # L= organizationName = "Some Company" # O= organizationalUnitName = "Some IT department # OU= commonName = "bacula_server" # CN= emailAddress = "email@example.com" # CN/emailAddress=
The information in this configuration file captures just a subset of the available configurations and parameters, but it solves the current issue. If we step through it, the first part : [ req ] describes default properties used to generate keys and certificates.
defaults_bits = 2048; tells OpenSSL to use 2048 bits when generating the keypair.
default_md = sha256; tells OpenSSL to use sha256 as the signature algorithm/message digest.
prompt = no; tells OpenSSL not to prompt at the command line and use the data in the configuration file.
encrypt_key = no; is the same as providing -nodes on the command line. It tells OpenSSL not to encrypt the keypair.
distinguished_name = bacula_ca; tells OpenSSL which block, if you have multiple, to fill out the fields for the certificate.
The fields in bacula_ca and bacula_server is fairly self-explanatory, so I am not going into details on those.
If you would like to exclude a field, such as the organizationalUnitName, you can comment it out with the # character. OpenSSL will then omit the value from the certificate.
Now, we can use this to generate the keys and certificates with OpenSSL using the configuration file.
Using the configuration file to auto-fill the necessary values
First, lets generate the certificate for the Certificate Authority using the configuration file.
openssl req -new -x509 -key bacula_ca.key -out bacula_ca.crt -config openssl.cnf -days 365
That will generate the certificate using the configuration file and setting the expiration date of the certificate to one year out. As far as I know, there is currently no way to supply the number of days until the certificate expires in the configuration file.
Next, I can modify the configuration file to make the distinguished_name point to bacula_server and then run;
openssl req -new -keyout bacula_server.key -out bacula_server.csr -config openssl.cnf
That generates the keys for the bacula_server and the certificate signing request without prompting me for any values. Next steps is to have the Certificate Authority sign the certificate signing request, but there are no prompts required in that process, so I will skip that.
In this article, I briefly discussed how to generate keys in OpenSSL utilizing the configuration file option. Though you can generate keys and certificates using all of these approaches, using the configuration file option may save you some time. Personally, I also prefer the last approach as it is easier to remember the distinguished names that have been used.
Finally, you can create one configuration file for each domain. Thus, you could have a configuration file for the bacula_ca and one for bacula_server. Inside, you could add additional fields, such as default keyfile and certificate file. This will speed things up, however, if you need to change any information in the distinguished_name section, you now need to do this over multiple files. I would encourage you to go to the OpenSSL documentation page and see the other fields you can add to the configuration file.