Expect Dialog CA

This repository contains scripts meant to make managing an openssl ca less painful inside a terminal environment

View the Project on GitHub elbosso/expect-dialog-ca

How to build an actual PKI from all this?

Root CA

First lets assume you cloned the repository (or checked it out or exported it - whatever floats your boat). We assume that you start your journey inside this directory - to make sure we are on the same page (or in the same directory - so to speak) this is the directory holding - among others - the script create_ca.sh. The first thing to do then is to create a root CA. For this you need to call the script

create_ca.sh

Before you do so for the first time - please refer to the step-by-step instructions for using this script - it can save some headaches…

You might want to consider making your life a little easier before starting create_ca.sh: The script offers an optional way to specify some of the information the user has to enter during this process beforehand - by writing an ini file named ca_presets.ini. This file has to reside in the current directory. Its format is key="value". The double quotes can be omitted if the value does not contain spaces. Allowed keys at this time are:

A template for this file can be generated by calling create_ca.sh with command line switch -g.

Then the script takes you by the hand and asks you a few questions. When it asks, what kind of CA you want to create - choose root CA. Only two things are important here (and from here on):

  1. When you choose a file make sure it is actually selected (its full name appears in the field below the two boxes showing directories and files) - mere highlighting the file inside those boxes doesnt count!
  2. Dont name the CA simply “root” - that confuses the scripts and does not bode well…

When the script is successful, you get a directory named __ inside the directory you started the script `create_ca.sh` in. Additionally, there will be a file named _-ca.csr_ - the signing request.

Now cd into the directory of the ca:

cd <whatever you called your root CA>

and start signing its signing request:

../sign_request.sh

During the execution of this script it asks what kind of certificate you want to issue and shows you a menu with the available choices. Because we are currently self-signing, you have to choose root at this point.

When this is done - remember what was said earlier about selecting files? - a file is created inside the directory you are currently in called deliverables_.zip. *You may want to check the validity duration of CRLs from this CA before actually doing the next step - it can be found inside the configuration file for your shiny new CA. The key to look for is `default_crl_days` - it accepts positive whole numbers interpreted as a duration in days.* Now - without leaving the directory, you install the certificate inside the CA directory structure by executing the script

../install_ca_certificate.sh

This - among other things - creates your first CRL and stores the certificate in the appropriate place.

Intermediary CA

Tired yet? If not - lets create another CA - this time it will be one not fit for issuing end entity certificates but acting as parent for CAs issuing actual end user certificates. For that, we go up one level in the directory structure:

cd ..

Now we start over by executing the script for CA creation again:

create_ca.sh

Now we dont chose a root CA but an intermediate CA as its type. You may be confused because there is no “intermediate” to choose. The reason for this: it is called network CA here. So lets create a network CA next - and always remember: you must not name it after its type - so as was the name root when creating the root CA, this time the name intermediate is forbidden!

After the script completed successfully, another CSR has been created along with a directory holding all the files that make up our new CA. This time we do not change directory into this new CAs home dir: We change into the directory holding the root ca:

cd <whatever you called your root CA>

and start signing its signing request:

../sign_request.sh

Again - choose the right kind of certificate to be issued - this time, that will be intermediate. When this is done, a file named deliverables_.zip. is created. Now you have to change directory into the directory that holds your newly created intermediate CA:

cd ../<whatever you called your intermediate CA>

You may want to check the validity duration of CRLs from this CA before actually doing the next step - it can be found inside the configuration file for your shiny new CA. The key to look for is default_crl_days - it accepts positive whole numbers interpreted as a duration in days. Now, you install the certificate inside the CA directory structure by executing the script

../install_ca_certificate.sh

This - among other things - creates your first CRL and stores the certificate in the appropriate place.

Signing CA (Identity)

Now we have a CA that acts as authority for other CAs that are actually able to issue end user certificates. We need to create some of those. First, lets start with an identity CA - for this, we first need to change back to our top-level directory

cd ..

and start by creating another CA:

create_ca.sh

Now we chose yet a different kind of CA - namely an identity CA. So lets create such a CA next - and always remember: you must not name it after its type - so as was the name root when creating the root CA, this time the name identity is forbidden!

One new aspect comes into play here: The script lets you specify default values for the different kinds of certificates it can issue. Later, when the PKI is finished you may want to give the configuration files to prospective customers that are a result of the execution of this script. They reside in <whatever you called your identity CA>. The default values you gave when creating the identity CA are merged into those config files and when someone builds a certificate request using one of them, she sees them and can just click through the tedious process of entering data - if the defaults suit her of course.

After the script completed successfully, another CSR has been created along with a directory holding all the files that make up our new CA. This time we do not change directory into the root CAs home dir: We change into the directory holding the intermediate ca:

cd <whatever you called your intermediate CA>

and start signing its signing request:

../sign_request.sh

Again - choose the right kind of certificate to be issued - this time, that will be identity. When this is done, a file named deliverables_.zip. is created. Now you have to change directory into the directory that holds your newly created identity CA:

cd ../<whatever you called your intermediate CA>

You may want to check the validity duration of CRLs from this CA before actually doing the next step - it can be found inside the configuration file for your shiny new CA. The key to look for is default_crl_days - it accepts positive whole numbers interpreted as a duration in days. Now, you install the certificate inside the CA directory structure by executing the script

../install_ca_certificate.sh

This - among other things - creates your first CRL and stores the certificate in the appropriate place.

Signing CA (Components)

Now that we have success fully established our first CA for issuing end entity certificates, lets do this again - after all: it was fun right? So now we create another kind of those: this time it will be a component CA - for this, we first need to change back to our top-level directory

cd ..

and start by creating another CA:

create_ca.sh

Now we chose yet a different kind of CA - namely a component CA. So lets create such a CA next - and always remember: you must not name it after its type - so as was the name root when creating the root CA, this time the name component is forbidden!

As with the identity CA, the script lets you specify default values for the different kinds of certificates it can issue - and for the same reasons.

After the script completed successfully, another CSR has been created along with a directory holding all the files that make up our new CA. This time we do not change directory into the root CAs home dir: We change into the directory holding the intermediate ca:

cd <whatever you called your intermediate CA>

and start signing its signing request:

../sign_request.sh

Again - choose the right kind of certificate to be issued - this time, that will be identity. When this is done, a file named deliverables_.zip. is created. Now you have to change directory into the directory that holds your newly created identity CA:

cd ../<whatever you called your intermediate CA>

You may want to check the validity duration of CRLs from this CA before actually doing the next step - it can be found inside the configuration file for your shiny new CA. The key to look for is default_crl_days - it accepts positive whole numbers interpreted as a duration in days. Now, you install the certificate inside the CA directory structure by executing the script

../install_ca_certificate.sh

This - among other things - creates your first CRL and stores the certificate in the appropriate place.

How to operate an actual Issuing CA

Remember when there was a sentence that said that building a CA also made sure that convenient OpenSSL configuration files were created? If not, now is the time to pay those files some attention:

The directory called etc inside the CAs folder structure holds various config files: one that is responsible for operating the CA and several others useful for clients wanting a signature from this CA. For example: if you had a component CA set up named issuecomp - that is one that for example issues TLS server certificates or code signing certificates and so on - the contents of folder etc would look somewhat like this:

The one that is named _-ca.conf_ is the configuration used when you actually operate the CA - for example issuing or revoking certificates. The other configuration files are for your prospective customers - so if someone wants to request a signature on his or her private key of a new TLS server - you give him or her the server.conf file. Then - using this configuration - a certificate request is created and sent for you to sign it.

This holds for all CA types this PKI structure offers. If you read the section about creating the PKI hierarchy again, you can see this already working when requesting and issuing the intermediary CA certificates.

Subject Alternative Names

Requesting Subject Alternative Names

One important thing needs to be mentioned however: the configuration for the TLS server certificates slightly differ from all the others in one important aspect: Other than the others, it does not suffice to just call OpenSSL with the config and be done with it:

Because a TLS server may have many different names and the certificate has to be issued for all of them, these names must be specified by an environment variable that must be set prior to calling OpenSSL for creating the certificate request. The name of this environment variable is SAN (Subject Alternative Name) - for example:

SAN=DNS:server1.example.lab,server2.example.lab,IP:127.0.0.1 \
openssl req -new \
    -config server.conf \
    -out multi_server.csr \
    -keyout multi_server.key

For Domain Names it is also possible to specify wildcard names here. Wildcard names begin with *. - for example:

SAN=DNS:*.example.lab \
openssl req -new \
    -config server.conf \
    -out multi_server.csr \
    -keyout multi_server.key

Further information about this specific scenario can be found for example here:

This is also true for the Identity CA as the second kind of issuing CA supported by this project: After creating an Identity CA, several configuration files exist inside etc for the purpose of easing the life for end users during enrollment. For example there is a file called smime.conf that allows to create a certificate signing request for email signing and encryption using s-mime. It can be used as follows:

openssl req -new \
    -config smime.conf \
    -out joe_user.csr \
    -keyout joe_user.key

Alternatively you can also use configuration smime_multi.conf - it allows to request (and later issue) certificates for multiple email addresses at once like so (also setting the email address that is part of the CN):

SAN="email:user1@emailpriovider2.net, user1@emailprovider3.net" \
openssl req -new \
    -config smime_multi.conf \
    -out multi_server.csr \
    -keyout multi_server.key

In case more elaborate Subject Alternative Names are needed, it is also possible to adjust the config file manually. The folowing snippet shows an excerpt that creates at least one of all the supported kinds of SANS:

[ default ]
oid_section = additional_oids

[ additional_oids ]

mySubjectAlternativeName = 1.2.3.4.5.6.7.2

# ... some stuff omitted for brevity ...
  
subjectAltName          = @alt_names

[alt_names]
IP.1 = 10.10.10.13
IP.2 = 10.10.10.14
IP.3 = 10.10.10.17
DNS.1 = expect.example.com
DNS.2 = ca.example.com
otherName=mySubjectAlternativeName;PRINTABLESTRING:"PRINTABLESTRING"
URI=http://my.url.here/
email=q@q.qq
dirName=dir_sect

[dir_sect]
C=DE
O=EMA
OU=Security
CN=ServerName

Checking Subject Alternative Names

Let’s Encrypt (and other CAs) allow for automatic enrollment for TLS server certificates: They issue a challenge when receiving a request for such a certificate. This challenge can be automatically satisfied - either by putting a file with a certain content on a HTTP server or putting a record with a certain content into the DNS. This is described in RFC 8555. This however is not in the scope here: To prevent fraudulently issued certificates, there is another nethod besides the one just mentioned: The in RFC 8659 described DNS Certification Authority Authorization (CAA) Resource Record. With it, a domain owner can specify which CAs are allowed to issue certificates for this domain. This information is saved in the DNS and thus publicly available. Any CA should check therefore if a name in a TLS server certificate request has such an entry in the DNS and if so - should check wether it is listed there. If not, the CA should decline the certificate signing request and inform the domain owner. To facilitate this, the project brings a script that does these checks for you: caa.sh takes a name as input and then does the DNS lookup for CAA records, extracts the information contained within and presents a human-readable summary of the constraints laid down there (if there are any).