Skip to content

Generating SSL KeyStores

Scott Frederick edited this page May 2, 2024 · 10 revisions

Integration Tests

Our embedded container tests use KeyStores containing self-signed certificates to test various aspects of the container’s SSL support. The KeyStores can be created using the following steps.

  1. Delete the old .jks KeyStore:

    rm spring-boot-project/spring-boot/src/test/resources/test.jks
  2. Create a new .jks KeyStore with spring-boot and test-alias entries:

    keytool -genkeypair -storepass secret -keypass password -keystore spring-boot-project/spring-boot/src/test/resources/test.jks -storetype JKS -dname "CN=localhost, OU=Spring, O=VMware, L=Palo Alto, ST=California, C=US" -validity 36500 -alias spring-boot -keyalg RSA -ext "SAN=DNS:localhost,IP:::1,IP:127.0.0.1"
    keytool -genkeypair -storepass secret -keypass password -keystore spring-boot-project/spring-boot/src/test/resources/test.jks -storetype JKS -dname "CN=localhost, OU=Spring, O=VMware, L=Palo Alto, ST=California, C=US" -validity 36500 -alias test-alias -keyalg RSA -ext "SAN=DNS:localhost,IP:::1,IP:127.0.0.1"
  3. Delete the old .p12 KeyStore:

    rm spring-boot-project/spring-boot/src/test/resources/test.p12
  4. Create a new .p12 KeyStore from the .jks KeyStore:

    keytool -importkeystore -srckeystore spring-boot-project/spring-boot/src/test/resources/test.jks -destkeystore spring-boot-project/spring-boot/src/test/resources/test.p12 -deststoretype pkcs12 -srcstorepass secret -deststorepass secret -destkeypass secret
    Tip
    Use password when prompted for the passwords for the spring-boot and test-alias entries.
  5. Create a trusted cert entry (required by Tomcat) in the two new KeyStores:

    keytool -keystore spring-boot-project/spring-boot/src/test/resources/test.jks -storepass secret -alias spring-boot -exportcert > exported
    keytool -keystore spring-boot-project/spring-boot/src/test/resources/test.jks -storepass secret -importcert -file exported -alias spring-boot-cert -noprompt
    keytool -keystore spring-boot-project/spring-boot/src/test/resources/test.p12 -storepass secret -importcert -file exported -alias spring-boot-cert -noprompt
    
    keytool -keystore spring-boot-project/spring-boot/src/test/resources/test.jks -storepass secret -alias test-alias -exportcert > exported
    keytool -keystore spring-boot-project/spring-boot/src/test/resources/test.jks -storepass secret -importcert -file exported -alias test-alias-cert -noprompt
    keytool -keystore spring-boot-project/spring-boot/src/test/resources/test.p12 -storepass secret -importcert -file exported -alias test-alias-cert -noprompt
    
    rm exported
  6. Export the key and the certificate to PEM files:

    rm spring-boot-project/spring-boot/src/test/resources/test-cert.pem
    keytool -exportcert -alias test-alias -keystore spring-boot-project/spring-boot/src/test/resources/test.jks -rfc -file spring-boot-project/spring-boot/src/test/resources/test-cert.pem
    
    rm spring-boot-project/spring-boot/src/test/resources/test-key.pem
    keytool -importkeystore -srckeystore spring-boot-project/spring-boot/src/test/resources/test.jks -destkeystore exported -deststoretype PKCS12 -srcalias test-alias
    openssl pkcs12 -in exported -out spring-boot-project/spring-boot/src/test/resources/test-key.pem -nodes
    rm exported
    Tip
    Use secret when prompted for the keystore passwords or the import password and password when prompted for the key password of the test-alias entry.
  7. List the test-alias entry to find the serial number used to create SerialNumberValidatingTrustSelfSignedStrategy in the tests:

    keytool -list -keystore spring-boot-project/spring-boot/src/test/resources/test.jks -v -storepass secret -alias test-alias
    Alias name: test-alias
    Creation date: 19-Aug-2021
    Entry type: PrivateKeyEntry
    Certificate chain length: 1
    Certificate[1]:
    Owner: CN=127.0.0.1, OU=Spring, O=VMware, L=Palo Alto, ST=California, C=US
    Issuer: CN=127.0.0.1, OU=Spring, O=VMware, L=Palo Alto, ST=California, C=US
    Serial number: 18d36252
    Valid from: Thu Aug 19 13:40:16 BST 2021 until: Sun Aug 17 13:40:16 BST 2031
    Certificate fingerprints:
    	 SHA1: CD:1D:C0:EC:6A:EB:01:18:EF:47:9A:6D:5D:28:CF:67:EB:02:AD:E9
    	 SHA256: 44:E8:4A:15:D0:8B:12:5B:51:6A:66:2D:19:82:3C:59:F8:F3:8B:0F:8C:35:60:79:31:FA:FE:86:BB:B6:81:76
    Signature algorithm name: SHA256withRSA
    Subject Public Key Algorithm: 2048-bit RSA key
    Version: 3
    
    Extensions:
    
    #1: ObjectId: 2.5.29.17 Criticality=false
    SubjectAlternativeName [
      IPAddress: 0:0:0:0:0:0:0:1
    ]
    
    #2: ObjectId: 2.5.29.14 Criticality=false
    SubjectKeyIdentifier [
    KeyIdentifier [
    0000: E1 56 CE 8F CB 7B 42 C3   FD 45 D6 1F 5C 6D DB 2B  .V....B..E..\m.+
    0010: DE E1 17 82                                        ....
    ]
    ]

    In this case, the serial number is 18d36252.

Smoke Tests

Some smoke tests verify SSL connectivity between a server and client, mostly using two-way (mutual) TLS authentication.

If the tests contain test-*.crt and test-*.key files in /src/test/resources/ssl, the certificates and keys can be created using the following shell script:

#!/bin/bash

generate_cert() {
    local name=$1
    local cn="$2"
    local opts="$3"

    local keyfile=${name}.key
    local certfile=${name}.crt

    [ -f $keyfile ] || openssl genrsa -out $keyfile 2048
    openssl req \
        -new -sha256 \
        -subj "/O=Spring Boot Test/CN=$cn" \
        -addext "subjectAltName=DNS:example.com,DNS:localhost,DNS:127.0.0.1" \
        -key $keyfile | \
        openssl x509 \
            -req -sha256 \
            -CA test-ca.crt \
            -CAkey test-ca.key \
            -CAserial test-ca.txt \
            -CAcreateserial \
            -days 3650 \
            $opts \
            -out $certfile
}

[ -f test-ca.key ] || openssl genrsa -out test-ca.key 4096
openssl req \
    -x509 -new -nodes -sha256 \
    -key test-ca.key \
    -days 3650 \
    -subj '/O=Spring Boot Test/CN=Certificate Authority' \
    -addext "subjectAltName=DNS:example.com,DNS:localhost,DNS:127.0.0.1" \
    -out test-ca.crt

cat > openssl.cnf <<_END_
subjectAltName = @alt_names
[alt_names]
DNS.1 = example.com
DNS.2 = localhost
[ server_cert ]
keyUsage = digitalSignature, keyEncipherment
nsCertType = server
[ client_cert ]
keyUsage = digitalSignature, keyEncipherment
nsCertType = client
_END_

generate_cert test-server "localhost" "-extfile openssl.cnf -extensions server_cert"
generate_cert test-client "localhost" "-extfile openssl.cnf -extensions client_cert"

rm openssl.cnf
rm test-ca.txt

If the tests contain test-*.p12 files in /src/test/resources/ssl, the keystores can be created by first running the script above and then converting the certificates and keys to the PKCS12 format with these commands:

openssl pkcs12 -export -legacy -out test-client.p12 -in test-client.crt -inkey test-client.key
openssl pkcs12 -export -legacy -out test-server.p12 -in test-server.crt -inkey test-server.key
openssl pkcs12 -export -legacy -out test-ca.p12 -in test-ca.crt -inkey test-ca.key

Use password when prompted by openssl for the export password.

Clone this wiki locally