Generating Certificates

What To Expect

This guide includes helpful commands to get started with self-signed certificates:

Prerequisites

You need a recent version of OpenSSL.

Generating self-signed certificate authority

Generate a key for our certificate authority:

openssl genrsa -aes256 -passout pass:TRUSTSTORE_PASS -out ca.key 2048 

Replace TRUSTSTORE_PASS with your own CA password.

Important: Keep ca.key secure and do not distribute it.

Next, generate the certificate of the CA:

openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 -out ca.pem -passin pass:TRUSTSTORE_PASS -subj /C=US/ST=California/O=Acme Corp/OU=Devops/CN=mydomain.com"

Replace the values of the subj parameter with your own. Only the CN part is required and doesn’t need to match a real domain.

Generating a PKCS12 truststore (Java)

Import the ca.pem file you generated into a Java truststore:

keytool -importcert -storetype PKCS12 -keystore services/ca.p12 -storepass TRUSTSTORE_PASS -alias ca -file ca.pem -noprompt

Generating a keystore for a Java server

The CN attribute must match the hostname of the service. It will generally be spin-[service].[namespace] or spin-[service], for example spin-clouddriver.spinnaker.

Generate the keystore with the following commands:

openssl genrsa -aes256 -passout pass:KEY_PASSWORD -out svc.key 2048
openssl req -new -key svc.key -out svc.csr -subj /C=US/CN=spin-svc.spinnaker -passin pass:KEY_PASSWORD
openssl x509 -req -in svc.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out svc.crt -days 3649 -sha256 -passin pass:TRUSTSTORE_PASS
openssl pkcs12 -export -out svc.p12 -inkey svc.key -in svc.crt -passout pass:KEY_PASSWORD -passin pass:KEY_PASSWORD

Alternate names

If you want the Spinnaker service to support alternate names, replace the openssl pkcs12 command in the previous section with:

openssl x509 -req -sha256 -in svc.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out svc.crt -days 3650 -extfile svc-cert.ext -passin pass:TRUSTSTORE_PASS

The svc-cert.ext referenced in the command should contain the following (example for Clouddriver):

authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = spin-clouddriver.spinnaker
DNS.2 = spin-clouddriver

Note: If you are setting up mTLS, you can use the same command (or the same file) for client-side certificates.

Generating keys and certificates (Golang)

openssl genrsa -aes256 -passout pass:KEY_PASSWORD -out svc.key 2048
openssl req -new -key svc.key -out svc.csr -subj /C=US/CN=spin-svc.spinnaker -passin pass:KEY_PASSWORD
openssl x509 -req -in svc.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out svc.crt -days 3650 -sha256 -passin pass:TRUSTSTORE_PASS

Putting it together (TLS)

The following script generates these files in the services directory:

  • Self-signed CA (ca.pem) and its PKCS12 truststore (ca.p12)
  • Keystore files for each Java service (clouddriver.p12, …)
  • Certificate and key files for each Golang services (terraformer.crt and terraformer.key, …)
#!/bin/bash -e

CA_PASSWORD="password"
SERVER_PASSWORD="password"
CLIENT_PASSWORD="password"
# Don't change me actually
TRUSTSTORE_PASSWORD="password"
USERS=("user1" "user2" "user3")
JAVA_SVCS=("clouddriver" "orca" "echo" "fiat" "igor" "rosco" "front50" "kayenta" "gate")
JAVA_SVCS_PASS=("clouddriver123" "orca123" "echo123" "fiat123" "igor123" "rosco123" "front50123" "kayenta123" "gate123")
GOLANG_SVCS=("dinghy" "terraformer")
GOLANG_SVCS_PASS=("dinghy123" "terraformer123")


echo "Cleaning up..."
rm -rf services/*
mkdir -p services/

echo "Generating CA key..."
openssl genrsa -aes256 -passout pass:${CA_PASSWORD} -out services/ca.key 2048 

echo "Generate self signed root certificate"
openssl req -x509 -new -nodes -key services/ca.key -sha256 -days 3650 -out services/ca.pem -passin pass:${CA_PASSWORD} -subj /C=US/CN=Test

echo "Generate trust store as PKCS12"
keytool -importcert -storetype PKCS12 -keystore services/ca.p12 -storepass $TRUSTSTORE_PASSWORD -alias ca -file services/ca.pem -noprompt


for i in ${!JAVA_SVCS[@]};
do
  svc=${JAVA_SVCS[$i]}
  password=${JAVA_SVCS_PASS[$i]}
  echo "Generating $svc key and certificate..."
  openssl genrsa -aes256 -passout pass:${password} -out services/${svc}.key 2048
  openssl req -new -key services/${svc}.key -out services/${svc}.csr -subj /C=US/CN=spin-${svc}.spinnaker -passin pass:${password}
  openssl x509 -req -in services/${svc}.csr -CA services/ca.pem -CAkey services/ca.key -CAcreateserial -out services/${svc}.crt -days 3649 -sha256 -passin pass:${CA_PASSWORD}
  openssl pkcs12 -export -out services/${svc}.p12 -inkey services/${svc}.key -in services/${svc}.crt -passout pass:${password} -passin pass:${password}
done


for i in ${!GOLANG_SVCS[@]};
do
  svc=${GOLANG_SVCS[$i]}
  password=${GOLANG_SVCS_PASS[$i]}
  echo "Generating $svc key and certificate..."
  openssl genrsa -aes256 -passout pass:${password} -out services/${svc}.key 2048
  openssl req -new -key services/${svc}.key -out services/${svc}.csr -subj /C=US/CN=spin-${svc}.spinnaker -passin pass:${password}
  openssl x509 -req -in services/${svc}.csr -CA services/ca.pem -CAkey services/ca.key -CAcreateserial \
    -out services/${svc}.crt -days 3650 -sha256 -passin pass:${CA_PASSWORD}
done