Skip to content

Creating TLS material for Pravega security

Ravi Sharda edited this page Apr 1, 2020 · 12 revisions

Motivation

Pull request (PR) 3693 updated the default TLS material (certificates, keys, keystore, and truststore) supplied with Pravega packages. This material is primarily intended for use in Standalone mode cluster for development/testing purposes, but may also be used in distributed mode cluster for the same purposes.

Here, we document the steps taken to create the new TLS material, primarily for the benefit of Pravega developers. Users may also use similar steps to create their own custom material.

The recipe

The overall process comprises of two stages:

  1. Creating a Certificate Authority (CA)
  2. Obtaining Server Certificates and keys

The output artifacts of these stages can be found under /path/to/pravega/config directory in the Pravega source code.

Note:

In the following steps we use CN=Pravega-Stack-CA and the following in the subject alternative names (SAN):

  • DNS names: server.pravegastack.io, localhost
  • IP addresses: 192.168.222.221

Be sure to update the DNS names/IP addresses you intend to use. IP addresses are shown for illustration only. For Pravega standalone, the DNS name localhost should be sufficient, since the clients access the standalone server over the localhost interface.

Also, note that you cannot assign an IP address as the CN, but you can use IP addresses in the SAN field if you will be using IP address(es) to access the server.

Stage 1: Creating a Certificate Authority (CA)

In stage 1, we generate a CA in the form of a public/private key pair and a self-signed certificate. Later, we use the CA certificate/key bundle to sign the server certificate.

  1. Generate a certificate and public/private key pair for use as a CA.

    # All inputs provided using command line arguments
    $ openssl req -new -x509 -keyout ca-key.key -out ca-cert.crt -days 730 \
             -subj "/CN=Pravega-Stack-CA" \
             -passout pass:1111_aaaa
  2. Create a truststore containing the CA's certificate.

    This truststore is by external and internal TLS clients. External clients are client applications connected to a Pravega cluster. Internal clients are server components that play the role of clients when communicating with other components, such as Controller in Controller-to-Zookeeper communications.

    $ keytool -keystore client.truststore.jks -noprompt -alias CARoot \
              -import -file ca-cert.crt \
              -storepass 1111_aaaa

At this point, the following artifacts shall be available:

File Description Command for Inspecting the Contents
ca-cert.crt PEM-encoded X.509 certificate of the CA $ openssl x509 -in ca-cert.crt -text -noout
ca-key.key PEM-encoded file containing the CA's encrypted private key $ openssl pkcs8 -inform PEM -in ca-key.key -topk8
client.truststore.jks A password-protected truststore file containing the CA's certificate $ keytool -list -v -keystore client.truststore.jks -storepass 1111_aaaa

Stage 2: Obtaining Server Certificates and keys

In this stage, the following steps were performed.

  1. Generate server certificates and keys.
  2. Generate a Certificate Signing Request (CSR) for the server.
  3. Submit the CSR to a CA and obtain a signed certificate.
  4. Prepare a keystore containing the signed server certificate and the CA's certificate.
  5. Export the server certificate's private key.

The steps in detail were as follows:

  1. Generate a public/private key-pair and an X.509 certificate for the server.

    This certificate is used for TLS connections with clients and by clients to verify the server's identity.

    $ keytool -keystore server.keystore.jks \
         -genkey -keyalg RSA -keysize 2048 -keypass 1111_aaaa \
         -alias server -validity 730 \
         -dname "CN=server.pravegastack.io" \
         -ext SAN=dns:server.pravegastack.io,dns:localhost,ip:192.168.222.221 \
         -storepass 1111_aaaa
  2. Generate a certificate signing request (CSR) for the server.

    $ keytool -keystore server.keystore.jks -alias server -certreq -file server.csr \
              -storepass 1111_aaaa \
              -ext SAN=dns:server.pravegastack.io,dns:localhost,ip:192.168.222.221
  3. Submit the CSR to a CA and obtain a signed certificate for each service.

    To do this, first create a custom extfile named custom-csr.conf file (see https://stackoverflow.com/questions/30977264/subject-alternative-name-not-present-in-certificate):

    [req]
    req_extensions = v3_req
    prompt = no
    
    [v3_req]
    subjectAltName = @alt_names
    
    [alt_names]
    DNS.1 = server.pravegastack.io
    DNS.2 = localhost
    IP.1 = 192.168.222.221
    

    To use the custom CA generated earlier, use the following command to generate a CA-signed server certificate in PEM format:

    $ openssl x509 -req -CA ca-cert.crt -CAkey ca-key.key \
         -in server.csr -out server-cert.crt \
         -days 730 -CAcreateserial -passin pass:1111_aaaa \
         -extfile custom-csr.conf -extensions v3_req
    
    # Optionally, check the contents of the signed certificate
    $ openssl x509 -in server-cert.crt -text -noout
  4. Prepare a keystore containing the signed server certificate and the CA's certificate.

    # Import the CA certificate into the keystore file.
    $ keytool -keystore server.keystore.jks -alias CARoot -noprompt \
            -import -file ca-cert.crt -storepass 1111_aaaa
    
    # Import the signed server certificate into the keystore.
    $ keytool -keystore server.keystore.jks -alias server -noprompt \
            -import -file server-cert.crt -storepass 1111_aaaa
            
    # Optionally, list the contents of the keystore file to inspect its contents.
    $ keytool -list -v -storepass 1111_aaaa -keystore server.keystore.jks
  5. Export the server's key into a separate file.

    This is a two-step process.

    • First, convert the server's keystore in .jks format into .p12 format.

      $ keytool -importkeystore \
              -srckeystore server.keystore.jks \
              -destkeystore server.keystore.p12 \
              -srcstoretype jks -deststoretype pkcs12 \
              -srcstorepass 1111_aaaa -deststorepass 1111_aaaa
    • Then, export the private key of the server into a PEM file. Note that the generated PEM file is not protected by a password. The key itself is password-protected, as we are using the -nodes flag. So, be sure to protect it using the operating system's technical controls as well as procedural controls.

      $ openssl pkcs12 -in server.keystore.p12 -out server-key.key \
               -passin pass:1111_aaaa -nodes

Step 5 concludes this stage. The major output artifacts of this stage are:

File Description Command for Inspecting the Contents
server-cert.crt PEM-encoded CA-signed server certificate file $ openssl x509 -in server-cert.crt -text -noout
server-key.key PEM-encoded file containing the server's encrypted private key $ openssl pkcs8 -inform PEM -in server-key.key -topk8
server.keystore.jks The server keystore file in .jks format $ keytool -list -v -keystore server.keystore.jks -storepass 1111_aaaa
Clone this wiki locally