Skip to content

IDToken - HashiCorp Vault

You can use JWTs to authenticate with HashiCorp Vault. This way your pipelines can directly communicate with Vault and use all of its features, beyond what Concourse's native Vault-integration offers.

First enable the JWT auth method in your Vault Server:

vault auth enable jwt

Now configure the JWT auth method to accept JWTs issued by your Concourse (use your --oidc-issuer-url if configured, otherwise your external URL - see Configuring a Separate OIDC Issuer):

vault write auth/jwt/config \
  oidc_discovery_url="https://<external_url_or_oidc_issuer_url>" \
  default_role="demo"

Lastly, configure a role for JWT auth. Make sure to use the same value in your pipeline that you used for bound_audiences (the best would be the URL of your Vault). bound_subject must be the sub-claim value of your JWT, if you use the subject_scope setting to change the contents of your sub-claim, adapt this accordingly!

vault write auth/jwt/role/demo \
  role_type="jwt"\
  user_claim="sub" \
  bound_subject="main/your-pipeline" \
  bound_audiences="my-vault-server.com" \
  policies=webapps \
  ttl=1h

This role will allow the holder of a JWT with aud: "my-vault-server.com" and sub: "main/your-pipeline" to get a Vault token with the Vault-policy webapps. If the policy you want to assign has a different name, simply change it in the above example. Make sure to adapt the value for bound_subject according to your team and pipeline name.

Pipelines can now do the following:

var_sources:
  - name: vaulttoken
    type: idtoken
    config:
      audience: [ "my-vault-server.com" ]

jobs:
  - name: vault-login
    plan:
      - task: login
        config:
          platform: linux
          image_resource:
            type: registry-image
            source: { repository: hashicorp/vault }
          run:
            path: sh
            args:
              - -e
              - -c
              - |
                export VAULT_ADDR=https://my-vault-server.com
                vault write auth/jwt/login \
                  role=demo \
                  jwt=((vaulttoken:token)) \
                  --format=json > vault-response.json
                echo "Now do something with the token in vault-response.json"

You don't have to create a role and a policy for every single of your pipelines! You can use claims from the JWT with Vault's policy templating feature. This way you can define a policy that allows a pipeline read to all the secrets it would usually have access to using Concourse's native Vault-integration:

path "concourse/metadata/{{ identity.entity.aliases.<JWT_ACCESSOR>.metadata.team }}" {
  capabilities = ["list"]
}

path "concourse/data/{{ identity.entity.aliases.<JWT_ACCESSOR>.metadata.team }}/+" {
  capabilities = ["read"]
}

path "concourse/metadata/{{ identity.entity.aliases.<JWT_ACCESSOR>.metadata.team }}/{{ identity.entity.aliases.<JWT_ACCESSOR>.metadata.pipeline }}" {
  capabilities = ["list"]
}

path "concourse/metadata/{{ identity.entity.aliases.<JWT_ACCESSOR>.metadata.team }}/{{ identity.entity.aliases.<JWT_ACCESSOR>.metadata.pipeline }}/*" {
  capabilities = ["read", "list"]
}

path "concourse/data/{{ identity.entity.aliases.<JWT_ACCESSOR>.metadata.team }}/{{ identity.entity.aliases.<JWT_ACCESSOR>.metadata.pipeline }}/*" {
  capabilities = ["read", "list"]
}

Note

Make sure to set <JWT_ACCESSOR> to the actual mount-accessor value of your JWT Auth method! You can use vault auth list --format=json | jq -r '."jwt/".accessor' to get the accessor for your jwt auth method.

With a policy like this you don't need to configure bound_subject in your JWT auth role. Every single pipeline can simply use the same role and the policy will take care that they can only access secrets meant for them. However, you need to explicitly configure claim to metadata mapping:

vault write auth/jwt/role/demo \
  role_type="jwt"\
  user_claim="sub" \
  bound_subject= \
  bound_audiences="my-vault-server.com" \
  policies=pipeline-new \
  claim_mappings='team=team' \
  claim_mappings='pipeline=pipeline' \
  ttl=1h