DEV Community

Cover image for Interpolating HashiCorp Vault Secrets into Jenkins X Helm Chart App
Oscar Medina
Oscar Medina

Posted on • Originally published at sharepointoscar.com

Interpolating HashiCorp Vault Secrets into Jenkins X Helm Chart App

Overview

If you have used Jenkins X, you know that HashiCorp Vault is installed by default in the CJXD (CloudBees Jenkins X Distro). However, there hasn't really been an example in the docs about how to use secrets stored in Vault when deploying an app that has the need for them.

In this guide, I walk you through deploying the Cars REST API a full-stack app with a backend in MongoDB. The repo branch titled Vault-Secrets is the one you want to look at.

TIP: With the recently announced tighter Vault integration with Kubernetes, there is actually a better way. We can inject Vault secrets directly into pods and make them available. My friend Nick Jackson explains how to do this on his post - Dynamic Database Credentials with Vault and Kubernetes

Nick and I will be showing you how to do this on Jenkins X very soon, so stay tuned!

Prerequisites

  1. Either the OSS or CJXD editions of Jenkins X working with Vault installed.
  2. Clone the Cars REST API app

1. Creating Vault Secret

The first thing you want to do is create the Vault Secret. Call it mongodb and add the following keys:

  • mongodb-username
  • mongodb-password
  • mongodb-root-password

Accessing HashiCorp Vault UI

To access the Vault instance in Jenkins X, you will need to first retrieve the configuration by executing the following:

> $ echo eval `jx get vault-config`

# copy the output to set env variables (yours are different of course)
export VAULT_ADDR=https://vault.cjxd.sharepointoscar.com export VAULT_TOKEN=r.4bbbbbbbX4jDB4QOKoHDCid4Sxtk5v
Enter fullscreen mode Exit fullscreen mode

What we are doing is retrieving the configuration. Then setting up Environment Variables (copy n paste them on your terminal). If you then execute env | grep VAULT you will see the variables are set.

From the UI, follow the instructions to create a secret. It should look something similar to the following:

Vault UI

2. Modify the Environment Repo (Staging)

NOTE
Though I am told that you can accomplish secret interpolation by setting this at the app level only, I have not tried it and so I want you to also include this on your target environment where the app is being deployed. In my case, it is Staging. Take a look at the actual file in my repo.

  • You will want to check out the file located at env/values.yaml (this file can be empty based on my experience, later gets populated again)

  • You will want to create a new file, name it env/values.tmpl.yaml. The file should look like the sample code below. At the bottom is where I add my app secrets and set them as environment variables for the Staging environment.


PipelineSecrets: {}
cleanup:
  Annotations:
    helm.sh/hook: pre-delete
    helm.sh/hook-delete-policy: hook-succeeded
  Args:
  - --cleanup
expose:
  Annotations:
    helm.sh/hook: post-install,post-upgrade
    helm.sh/hook-delete-policy: hook-succeeded
  Args:
  - --v
  - 4
  config:
    domain: cjxd.sharepointoscar.com
    exposer: Ingress
    http: "true"
    tlsacme: "false"
jenkins:
  Servers:
    Global: {}
prow: {}

cars-rest-api:
  env:
    MONGODB_USERNAME: vault:mongodb:mongodb-username
    MONGODB_PASSWORD: vault:mongodb:mongodb-password
    MONGODB_DATABASE: cars-rest-api
Enter fullscreen mode Exit fullscreen mode

3. Modify App Helm Charts

There are several files we need to modify for two charts, the main chart is named cars-rest-api and the Preview app helm chart. Here is the structure depicting the charts in question.


➜ tree charts -l 2
charts
├── cars-rest-api
│   ├── Chart.yaml
│   ├── Makefile
│   ├── README.md
│   ├── requirements.lock
│   ├── requirements.yaml
│   ├── templates
│   │   ├── NOTES.txt
│   │   ├── _helpers.tpl
│   │   ├── deployment.yaml
│   │   ├── ksvc.yaml
│   │   └── service.yaml
│   └── values.yaml
└── preview
    ├── Chart.yaml
    ├── Makefile
    ├── requirements.yaml
    └── values..yaml


Enter fullscreen mode Exit fullscreen mode

The requirements.yaml changes

First, we must add the dependencies to the main chart. There is nothing new here, we add the MongoDB dependency to our chart using Helm standard approach, which is by modifying the requirements.yaml as shown below.

dependencies:
- name: mongodb
  alias: cars-rest-api-db
  version: 7.6.5
  repository: https://kubernetes-charts.storage.googleapis.com
  condition: cars-rest-api-db.enabled

Enter fullscreen mode Exit fullscreen mode

Next, we modify values.yaml and add to the env: variables as well as the mongoDB dependency, which I've aliased as cars-rest-api-db (shown on requirements.yaml above)

NOTE: It is important to notice that the reference to the Vault keys within the MongoDB chart parameters is within double-quotes. Took me 4 full days to realize this issue and I grew more gray hair for sure.

The values.yaml changes

The values.yaml file should look like this.

 .....
env:
  MONGDB_USERNAME: vault:mongodb:mongodb-username
  MONGDB_PASSWORD: vault:mongodb:mongodb-password
  MONGDB_ROOT_PASSWORD: vault:mongodb:mongodb-root-password
....

# MongoDB Configuration
cars-rest-api-db:
  ## Whether to deploy a mongodb server to satisfy the application database requirements.
  ## To use an external database set this to false and configure the externaldb parameters
  enabled: true

  ## Enable authentication
  ## ref: https://docs.mongodb.com/manual/tutorial/enable-authentication/
  #
  usePassword: true
  # existingSecret: jx-auth

  ## MongoDB custom user and database
  ## ref: https://github.com/bitnami/bitnami-docker-mongodb/blob/master/README.md#creating-a-user-and-database-on-first-run
  ##
  mongodbUsername: "vault:mongodb:mongodb-username"
  mongodbDatabase: "cars_rest_api"
  mongodbPassword: "vault:mongodb:mongodb-password"

  ## MongoDB admin password
  ## ref: https://github.com/bitnami/bitnami-docker-mongodb/blob/master/README.md#setting-the-root-password-on-first-run
  ##
  mongodbRootPassword: "vault:mongodb:mongodb-root-password"
  ...

Enter fullscreen mode Exit fullscreen mode

The Preview Chart Changes

For the Preview chart, we modify two files. The values.yaml and the requirements.yaml, very similar changes. However, we name things differently.

On the requirements.yaml we alias the MongoDB as preview-db and make sure we add it below the existing dependencies, BUT before the preview chart definition as shown below.

 dependencies:
- alias: expose
  name: exposecontroller
  repository: http://chartmuseum.jenkins-x.io
  version: 2.3.92
- alias: cleanup
  name: exposecontroller
  repository: http://chartmuseum.jenkins-x.io
  version: 2.3.92

- name: mongodb
  alias: preview-db
  version: 5.3.0
  repository: https://kubernetes-charts.storage.googleapis.com

    # !! "alias: preview" must be last entry in dependencies array !!
  # !! Place custom dependencies above !!
- alias: preview
  name: cars-rest-api
  repository: file://../cars-rest-api
Enter fullscreen mode Exit fullscreen mode

The values.yaml file contains the same environment variables as the main chart.

NOTE: It is important to notice that the reference to the Vault keys within the MongoDB chart parameters is within double-quotes. Took me 4 full days to realize this issue and I grew more gray hair for sure.

 .....
  env:
    MONGODB_USERNAME: vault:mongodb:mongodb-username
    MONGODB_PASSWORD: vault:mongodb:mongodb-password
    MONGODB_DATABASE: cars-rest-api
    MONGODB_ROOT_PASSWORD: vault:mongodb:mongodb-root-password
## MongoDB chart configuration
## ref: https://github.com/helm/charts/blob/master/stable/mongodb/values.yaml
##
preview-db:
  ## Whether to deploy a mongodb server to satisfy the applications database requirements.
  ## To use an external database set this to false and configure the externaldb parameters
  enabled: true

  ## Enable authentication
  ## ref: https://docs.mongodb.com/manual/tutorial/enable-authentication/
  # NOTE: make sure this secret is in 
  usePassword: true
  #existingSecret: preview-auth

  ## MongoDB custom user and database
  ## ref: https://github.com/bitnami/bitnami-docker-mongodb/blob/master/README.md#creating-a-user-and-database-on-first-run
  ##
  mongodbUsername: "vault:mongodb:mongodb-username"
  mongodbDatabase: "cars_rest_api"
  mongodbPassword: "vault:mongodb:mongodb-password"

    ## MongoDB admin password
  ## ref: https://github.com/bitnami/bitnami-docker-mongodb/blob/master/README.md#setting-the-root-password-on-first-run
  ##
  mongodbRootPassword: "vault:mongodb:mongodb-root-password"
.....

Enter fullscreen mode Exit fullscreen mode

Summary

On this post, we walked through the required steps to ensure you are able to retrieve and interpolate Vault secrets within your custom app being put through CI/CD in Jenkins X.

Here is the video of the webinar session where I show it in action.

https://www.youtube.com/embed/LRj_yHKxG80

Cheers,

@SharePointOscar

Top comments (0)