Hashicorp Vault with GitLab

The best way to protect our secrets is using a proper Vault for that, here we gonna see how we can integrate GitLab with Hashicorp Vault and retrieve secrets using JWT method.

For testing purposes, I used the Hashicorp Vault managed solution, which means the enterprise version.
The enterprise version has a very interesting feature called Namespaces where you can configure and isolate different teams.

This is the area to manage the vault in the Hashicorp portal
This is how the vault GUI looks like

If you go with the Hashicorp managed solution, keep in mind that you will need an AWS account to create a network peering in order to use a private endpoint, otherwise, you only have the public endpoint as an option.

Once you have the vault created you need to perform a few steps:

Enable JWT authentication

➜ vault auth enable jwt
Success! Enabled jwt auth method at: jwt/
➜ vault write auth/jwt/config \
    jwks_url="https://gitlab.com/-/jwks" \
    bound_issuer="gitlab.com"
Success! Data written to: auth/jwt/config

Create the policies

➜ vault policy write myproject-staging - <<EOF
# Policy name: myproject-staging
#
# Read-only permission on 'secret/data/myproject/staging/*' path
path "secret/data/myproject/staging/*" {
  capabilities = [ "read", "list" ]
}
EOF
Success! Uploaded policy: myproject-staging
➜ vault policy write myproject-production - <<EOF
# Policy name: myproject-production
#
# Read-only permission on 'secret/data/myproject/production/*' path
path "secret/data/myproject/production/*" {
  capabilities = [ "read", "list" ]
}
EOF
Success! Uploaded policy: myproject-production

We also need roles to be linked to the policies

➜ vault write auth/jwt/role/myproject-staging - <<EOF
{
  "role_type": "jwt",
  "policies": ["myproject-staging"],
  "token_explicit_max_ttl": 60,
  "user_claim": "user_email",
  "bound_claims": {
    "project_id": "32967301"
  }
}
EOF
➜ vault write auth/jwt/role/myproject-production - <<EOF
{
  "role_type": "jwt",
  "policies": ["myproject-production"],
  "token_explicit_max_ttl": 60,
  "user_claim": "user_email",
  "bound_claims_type": "glob",
  "bound_claims": {
    "project_id": "32967301"
  }
}
EOF

In these case the project_id needs to match with project id from the gitlab repository:

We need to configure the following pipeline .gitlab-ci.yml

default:
  image: vault:latest

read_secrets:
  script:
    # when configuring JWT Auth - https://www.vaultproject.io/api/auth/jwt#parameters-1
    - export VAULT_TOKEN="$(vault write -field=token admin/auth/jwt/login role=myproject-staging jwt=$CI_JOB_JWT)"
    # Now use the VAULT_TOKEN to read the secret and store it in an environment variable
    - export PASSWORD="$(vault kv get -field=password admin/secret/myproject/staging/db)"
    # Use the secret
    - echo $PASSWORD
    # This will fail because the role myproject-staging can not read secrets from secret/myproject/production/*
    - export PASSWORD="$(vault kv get -field=password secret/myproject/production/db)"

And configure only a few variables in gitlab

Pipeline result
https://gitlab.com/carlospcastro/gitops/-/jobs/2025444111

That’s it folks, hope this could help you somehow and if you have any question just reach out here.

Gitlab repo: https://gitlab.com/carlospcastro/gitops

Reference:
https://docs.gitlab.com/ee/ci/examples/authenticating-with-hashicorp-vault/
https://www.vaultproject.io/docs/auth/jwt#jwt-authentication

Related Post

2 thoughts on “Hashicorp Vault with GitLab

  1. You have an error in the ci-cd:
    “`
    export VAULT_TOKEN=”$(vault write -field=token admin/auth/jwt/login role=myproject-staging jwt=$CI_JOB_JWT)”
    “`
    should be
    “`
    export VAULT_TOKEN=”$(vault write -field=token auth/jwt/login role=myproject-staging jwt=$CI_JOB_JWT)”
    “`

    1. Hello promzeus, thanks for you comment.
      In fact if you using Vault managed solution, the path should start with admin, otherwise is not going to work, keep in mind that applies only for managed solution, if you have your own installation you don’t need to fallow this pattern.

      Hope that helps
      Take care.

Comments are closed.