Anyone who wants to expose services over the web that are protected with Transport Layer Security (TLS) must get their certificates signed by a trusted certificate authority (CA). Few trusted CAs are available globally, and their public keys are embedded in all browsers. When a browser talks to amazon.com over TLS, for example, it can verify that Amazon’s certificate is valid (not forged) by verifying its signature against the corresponding CA’s public key that’s embedded in the browser. The certificate also includes the hostname of Amazon (which is called the common name), so the browser knows it’s communicating with the right server.
In this appendix, we show you how to create a CA by using OpenSSL. OpenSSL is a commercial-grade toolkit and cryptographic library for TLS, available for multiple platforms. You can download and set up the distribution that fits your platform from www.openssl.org/source. But the easiest way to try OpenSSL is to use Docker. In this appendix, you’ll use an OpenSSL Docker image. You need to install Docker, following the instructions at https://docs.docker.com/install/#supported-platforms. The process is straightforward. A deeper understanding of how Docker works isn’t necessary to follow along in this appendix (we talk about Docker and containers in detail in appendix E).
Assuming that you have Docker installed, follow the instructions in this section to set up the CA. To begin, download the appendix G samples from GitHub (https://github.com/microservices-security-in-action/samples) to your computer. Let’s spin up the OpenSSL Docker container from the appendix-g/sample01/ directory.
The following docker
run
command starts OpenSSL in a Docker container with a bind mount that maps the appendix-g/sample01/ directory (or the current directory, which is indicated by $(pwd)
in listing G.1) from the host filesystem to the /export directory of the container filesystem. This bind mount lets you share part of the host filesystem with the container filesystem. When the OpenSSL container generates certificates, those are written to the /export directory of the container filesystem. Because we have a bind mount, everything inside the /export directory of the container filesystem is also accessible from the appendix-g/sample01/ directory of the host filesystem.
Listing G.1 Running OpenSSL in a Docker container
> docker run -it -v $(pwd):/export prabath/openssl #
When you run this command for the first time, its execution can take a couple of minutes. It ends with a command prompt, where you can execute your OpenSSL commands to create the CA. Use the command in the following listing to generate a private key for the CA.
Listing G.2 Generating a private key for the certificate authority
# openssl genrsa -aes256 -passout pass:"manning123" -out /export/ca/ca_key.pem 4096 Generating RSA private key, 4096 bit long modulus
The generated key file is stored in the /export/ca directory of the Docker container (as specified by the -out
argument). Then again, because you mapped the appendix-g/sample01/ directory of the host filesystem to the /export directory, the generated key file is also available inside the appendix-g/sample01/ca directory of the host machine. In listing G.2, the genrsa
command generates a private key of 4,096 bits and encrypts it with AES-256 and the provided passphrase. We use manning123
as the passphrase, which is passed to the genrsa
command under the -passout
argument.
Note The value of the passphrase must be prefixed with pass:
and must be defined within double quotes.
Next, use the command (req -new
) in the following listing to generate a public key that points to the already generated private key (-key
) with an expiration time of 365 days (-days
).
Listing G.3 Generating a public key for the certificate authority
# openssl req -new -passin pass:"manning123" -key /export/ca/ca_key.pem -x509 -days 365 -out /export/ca/ca_cert.pem -subj "/CN=ca.ecomm.com"
While creating the public key, OpenSSL needs to know the details related to the organization behind the CA (country, state, organization name, and so on). Of those details, what matters most is the common name (CN). You need to provide something meaningful. The CN may not be important here, but when a client application talks to a TLS-secured endpoint, the client validates whether the hostname of the endpoint matches the value of the CN in the certificate; if not, it rejects the certificate.
In listing G.3, we provide the value of the CN under the -subj
argument; make sure the corresponding value starts with a /
. (OpenSSL requires the forward slash.) The -out
argument specifies where to store the generated public key. Now you can find two files in the appendix-g/sample01/ca directory: ca_cert.pem
, which is the public key, and ca_key.pem
, which is the private key of the certificate authority.
In this section, we discuss how to create a public/private key pair for an application and get those keys signed by the CA you created in section G.1. This application can be a microservice, a web server, a client application, and so on. To generate the public/ private key pair for an application, you’re going to use the same OpenSSL Docker container started in section G.1. Run the command in the following listing to generate a private key for the application.
Listing G.4 Generating a private key for the application
# openssl genrsa -aes256 -passout pass:"manning123" -out /export/application/app_key.pem 4096
This code generates the private key file (app_key.pem) inside the appendix-g/sample01/application directory. When you have the private key for the application, to get it signed by the CA, you need to create a certificate-signing request (CSR) first. Run the command in the following listing in the OpenSSL Docker container command prompt. It produces a file named csr-for-app, which you have to share with your CA to get a signed certificate.
Listing G.5 Generating a certificate-signing request for the application
# openssl req -passin pass:"manning123" -new -key /export/application/app_key.pem -out /export/application/csr-for-app -subj "/CN=app.ecomm.com"
The OpenSSL command in listing G.6 gets the CSR generated in listing G.5, signed by the CA. The output of the command in the following listing is the signed certificate of the application (app_cert.pem). You can find it inside the appendix-g/sample01/application directory.
Listing G.6 Generating the application’s CA signed certificate
# openssl x509 -req -passin pass:"manning123" -days 365 -in /export/application/csr-for-app -CA /export/ca/ca_cert.pem -CAkey /export/ca/ca_key.pem -set_serial 01 -out /export/application/app_cert.pem
Now we have a private key and signed certificate for the application. For some Java applications (for example, Spring Boot microservices), we need to have this key stored in a Java KeyStore (JKS), which is Java-specific key storage.
In listing G.7, we generate a JKS from the application’s private key and the public certificate. In the first command of the listing, we remove the passphrase of the private key (app_key.pem), and in the second command, we create a single file (application_keys.pem) with both the private key and the public certificate. With the third command, we create a keystore of type PKCS with these keys. At the end of the third command, you can find the PKCS keystore (app.p12
) inside the appendix-g/sample01/application directory. Finally, in the last command, we use the Java Keytool to create a JKS file from the app.p12
PKCS keystore. There we pass the passphrase of the source (app.p12
) keystore under the argument srcstorepass
, and the passphrase of the destination (app.jks
) keystore under the argument deststorepass
. For app.p12
, we used manning123
as the keystore passphrase. For simplicity, we use the same passphrase for the destination keystore (app.jks
) as well.
Listing G.7 Creating a Java KeyStore with the application’s public/private keys
# openssl rsa -passin pass:"manning123" -in /export/application/app_key.pem -out /export/application/app_key.pem ❶ # cat /export/application/app_key.pem /export/application/app_cert.pem >> /export/application/application_keys.pem ❷ # openssl pkcs12 -export -passout pass:"manning123" -in /export/application/application_keys.pem -out /export/application/app.p12 ❸ # keytool -importkeystore -srcstorepass manning123 -srckeystore /export/application/app.p12 -srcstoretype pkcs12 -deststorepass manning123 -destkeystore /export/application/app.jks -deststoretype JKS ❹
❶ Removes the passphrase of the private key: app_key.pem
❷ Creates a single file (application_keys.pem) with both the private key and the public certificate
❸ Creates a keystore of type PKCS with the keys in the application_keys.pem file
❹ Uses the Java Keytool to create a JKS file from the app.p12 PKCS keystore
18.216.230.107