Skip to main content

Configuring Spinnaker to Use Internal Certificate Authorities

Introduction

There are a lot of places in Spinnaker which support the ability to configure custom trust/key stores for organizations who use internally signed certificates. In some cases, however, it isn’t supported yet but the environment will still need to talk to a service which serves one of these certificates. This article shows how to import certificates into the trust/key store and configure a Spinnaker service with it.Most services in Spinnaker are written in Java. There are a few Armory specific services written in Golang, such as Dinghy and Terraformer. If the particular certificate is not configured properly, it is possible that errors such as the one below will be found in the logs of the service x509: certificate signed by unknown authority

Prerequisites

This document assumes that kubectl access is available to the Kubernetes cluster and the latest version of Halyard (either OSS or Armory’s extension) is being used.

Instructions

Create a temporary copy of your system’s trust/key store and import your internal certificate. For a Java truststore, on a Mac, ruststore will be located at $(/usr/libexec/java_home/)/jre/lib/security/cacerts. It will be different on Linux.

$ mkdir /tmp/custom-trust-store
$ cp {path-to-cacerts} /tmp/custom-trust-store
$ keytool import -alias custom-ca -keystore /tmp/custom-trust-store/cacerts -file {your-internal-certificate}

For Golang services, make a copy of /etc/ssl/cert.pem and append the internal certificate to your copy of cert.pem. Note: If you do not have a copy of the internal certificate - you can run the following command to retrieve it manually: openssl s_client -showcerts -connect host:port |openssl x509 -outform PEM >mycertfile.pem Use kubectl to create a Secret from your copy of cacerts or cert.pem.

$ kubectl create secret generic -n {your-spinnaker-namespace} internal-trust-store --from-file /tmp/custom-trust-store/cacerts

Configure a Spinnaker service with the new trust/key store using volume mount. In this example we’ll be configuring Front50 with this new store. In Halyard Disclaimer The mountPath suggested should work for most cases but we did notice that this could be specific to the image used. (eg. when using Ubuntu, users will need to use /etc/ssl/certs for Golang services) # ~/.hal/default/service-settings/front50.yml

kubernetes:
volumes:
- id: internal-trust-store
mountPath: /etc/ssl/certs/java
type: secret

# ~/.hal/default/service-settings/dinghy.yml or other Golang based services kubernetes: 

kubernetes:
volumes:
- id: internal-trust-store
mountPath: /etc/ssl/
type: secret

In OperatorDisclaimer The mountPath suggested should work for most cases but we did notice that this could be specific to the image used. (eg. when using Ubuntu, users will need to use /etc/ssl/certs for Golang services) In the SpinnakerService.yml, in the spec.spinnakerConfig.service-settings section for each service based in Java (e.g. Front50) spec:

  spinnakerConfig:
service-settings:
front50:
kubernetes:
volumes:
- id: internal-trust-store
mountPath: /etc/ssl/certs/java
type: secret

In the SpinnakerService.yml, in the spec.spinnakerConfig.service-settings section for each service in Golang (e.g. Dinghy): 

spec:
spinnakerConfig:
service-settings:
dinghy:
kubernetes:
volumes:
- id: internal-trust-store
mountPath: /etc/ssl/
type: secret
  • Redeploy Spinnaker using hal deploy apply, or deploying the Operator Manifest The Spinnaker component for which you configured the volume mount should now be using the new trust/key store by default.