CircleCI logo

Secrets in CircleCI

In CircleCI, secrets are usually stored as CI environment variables and injected into the pipeline. This simple approach has advantages, but also brings challenges of its own.

For starters, to run tests locally with this setup, secrets need to be manually synchronized between different developers and environments.

Moreover, any environment variables defined in the pipeline also need to be configured on the local workstation.

The CircleCI security checklist encourages regular rotation of secrets. This, however can be quite challenging without automating the fetching of secrets.

Secret management with SecretHub

SecretHub simplifies secret management by storing secrets securely in a central database and providing them automatically to all authenticated parties.

When using SecretHub, the secret to environment variable mapping will be moved to a secrethub.env file which can also be used for running the code in production or locally, from your IDE or the command line.

Before you begin

To follow along, you will need to:

Step 1: Write your secrets

First, write your secrets to SecretHub to have them provided to the CI pipeline or any development environment.

SecretHub organizes secrets in repositories. To create a repository for your secrets use the repo init command:

secrethub repo init your-username/repo-name

Now you can write the secrets that you want to have access to later with the write command:

secrethub write your-username/repo-name/password

Step 2: Add the secrethub.env file

To provide a mapping between environment variables and secrets, create a file named secrethub.env in your project’s root directory, similar to this one:

DB_HOST = localhost
DB_USER = test-user
DB_PASS = {{ your-username/repo-name/password }}

The path {{ your-username/repo-name/password }} references the secret defined in the previous step.

Step 3: Set up your CirceCI configuration

Now you can include SecretHub in your CircleCI pipeline. To do this, create the file .circleci/config.yml with the following content:

version: 2.0
jobs:
  build:
    docker:
      - image: node:alpine
    steps:
      - run: apk add --repository https://alpine.secrethub.io/alpine/edge/main --allow-untrusted secrethub-cli
      - checkout
      - run: secrethub run -- node test.js

Alternatively the installation can be included in a docker image. With this approach the SecretHub CLI will not be installed every time the pipeline is executed.

Note that we will use a Node.js application as an example throughout this guide, but the same approach works for other test commands as well.

The apk add command added as a first step installs the SecretHub CLI, so that you can use it later in the pipeline

In the third step of the pipeline, the command you usually run test with (in this case node test.js) is wrapped with the secrethub run command. This command fetches the secrets required by the application and injects them as environment variables according to the mapping specified in the secrethub.env file.

Step 4: Create a SecretHub service account

SecretHub uses service accounts to grant non-human parties (such as CIs) access to secrets. To create a service account, run the secrethub service init command:

secrethub service init --permission read your-username/repo-name

This command will output the generated account credential. Make sure to copy it as it will be needed in the next step.

The --permission read flag will grant the service read access to the specified repo.

Note that you can use the --clip flag to write the output of the command to your clipboard:

secrethub service init --clip --permission read your-username/repo-name

Step 5: Provide the credential to CircleCI

  1. Open the CircleCI web app and go to your project’s settings page
    Go to the settings page in the CircleCI web app
  2. Click on Environment Variables under Build Settings
    Go to Environment Variables under Build Settings
  3. Click on Add Variable
  4. Set the variable name to SECRETHUB_CREDENTIAL and paste the key from the previous step into the value field
    Fill in the dialog
  5. Click on Add Variable

You have successfully configured your CircleCI pipeline to automatically fetch secrets from the SecretHub API, while also simplifying secret provisioning in development and production environments. Moreover, you can now rotate your secrets and the pipeline will automatically use their latest version.

See also

Happy coding!