Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best way to use Hashicorp Vault with GitLab pipelines?

Let's say I want to make a variable with the value from Vault.

variables:
  $SSH_PRIVATE_KEY: `vault kv get -field=private_key project/production`
before_script:
  - echo "$SSH_PRIVATE_KEY"

Is it possible?

Is there another way to use Vault secrets inside pipelines?

like image 842
Gregory Avatar asked Jul 07 '19 01:07

Gregory


2 Answers

Original answer Jul 2019:

You can see it used in before/after script steps, with a revoked token at the end.
See gitlab.eng.cleardata.com pub/pipelines/gcp-ci.yml as an example:

# Obtains credentials via vault (the gitlab-runner authenticates to vault using its AWS credentials)
# Configures the `gcloud` sdk and `kubectl` to authenticate to our *production* cluster
#
# Note: Do not override the before_script or the after_script in your job
#
.auth-prod: &auth-prod
  image: cleardata/bionic
  before_script:
    - |
      export CLUSTER_NAME=production
      export CLUSTER_LOCATION=us-central1
      export CLUSTER_PROJECT_ID=cleardata-production-cluster
    - vault login -method=aws -path=gitlab-ci -no-print header_value=gitlab.eng.cleardata.com
    - GCP_CREDS=$(vault read -field=private_key_data gitlab-ci/gcp/cleardata-production-cluster/key/deployment-key)
    - gcloud auth activate-service-account --key-file=<(base64 -d <<<$GCP_CREDS)
    - gcloud auth configure-docker
    - gcloud beta container clusters get-credentials $CLUSTER_NAME --region $CLUSTER_LOCATION --project $CLUSTER_PROJECT_ID
  after_script:
    - vault token revoke -self

Update March 2020: This is supported with GitLab 12.9

HashiCorp Vault GitLab CI/CD Managed Application

GitLab wants to make it easy for users to have modern secrets management. We are now offering users the ability to install Vault within a Kubernetes cluster as part of the GitLab CI managed application process.
This will support the secure management of keys, tokens, and other secrets at the project level in a Helm chart installation.

See documentation and issue.


April 2020: GitLab 12.10:

Retrieve CI/CD secrets from HashiCorp Vault

In this release, GitLab adds support for lightweight JSON Web Token (JWT) authentication to integrate with your existing HashiCorp Vault.

Now, you can seamlessly provide secrets to CI/CD jobs by taking advantage of HashiCorp’s JWT authentication method rather than manually having to provide secrets as a variable in GitLab.

See documentation and issue.


See GitLab 13.4 (September 2020)

For Premium/Silver only:

Use HashiCorp Vault secrets in CI jobs

In GitLab 12.10, GitLab introduced functionality for GitLab Runner to fetch and inject secrets into CI jobs. GitLab is now expanding the JWT Vault Authentication method by building a new secrets syntax in the .gitlab-ci.yml file. This makes it easier for you to configure and use HashiCorp Vault with GitLab.

https://about.gitlab.com/images/13_4/vault_ci.png -- Use HashiCorp Vault secrets in CI jobs

See Documentation and Issue.


See GitLab 13.9 (February 2021)

Vault JWT (JSON Web Token) supports GitLab environments.

To simplify integrations with HashiCorp Vault, we’ve shipped Vault JWT token support. From the launch, you could restrict access based on data in the JWT. This release gives you a new dimension for restricting access to credentials: the environment a job targets.

This release extends the existing Vault JWT token to support environment-based restrictions too. As the environment name could be supplied by the user running the pipeline, we recommend you use the new environment-based restrictions with the already-existing ref_type values for maximum security.

See Documentation and Issue.

like image 126
VonC Avatar answered Oct 04 '22 03:10

VonC


We have a helper script baked into our builder images that can convert GitLab CI/CD job variables pointing to secrets into job env vars containing Vault secrets. In our case, we're also using the appRole auth method to limit the validity of the temporary Vault access token.

An example use case would be:

I want a job env var "MY_SECRET_TOKEN" with a value from a Vault secret.
So I add a CI/CD variable called V_MY_SECRET_TOKEN="secret/<path>/<key>"
Then I insert a job step to retrieve the secret value and populate
  the MY_SECRET_TOKEN with the value associated with the key.

Variables added to the CICD job setup in GitLab.

VAULT_ADDR=https://vault.example.com:8200
VAULT_ROLE_ID=db02de05-fa39-4855-059b-67221c5c2f63
VAULT_SECRET_ID=6a174c20-f6de-a53c-74d2-6018fcceff64
VAULT_VAR_FILE=/var/tmp/vault-vars.sh

Steps added to the .gitlab-ci.yml job definition.

script:
  - get-vault-secrets-by-approle > ${VAULT_VAR_FILE}
  - source ${VAULT_VAR_FILE} && rm ${VAULT_VAR_FILE}

Here is a reference to the get-vault-secrets-by-approle helper script we use.
Here is a writeup of the thinking behind the design.

The 'before_script' option didn't fit our workflows as we define a combination of privileged and non-privledged stages in our gitlab-ci.yml definition. The non-privileged jobs build and QA code while the privileged jobs package and release code. The VAULT_ROLE_ID and VAULT_SECRET_ID job variables should only be visible to the privileged package and release jobs.

I also experimented with using include's, extend's, and yaml anchors but I wanted to merge items into existing yaml maps (script: {} or before_script: {}) as opposed to replacing all the items in a map with the template.

like image 31
Chris Ottinger Avatar answered Oct 04 '22 02:10

Chris Ottinger