Good day, reader!
On April 22, GitLab released the 12.10 release and announced that now the CI process can authorize in Hashicorp's Vault via the JSON Web Token (JWT), and for authorization there is no need to store the token to access the required policies in environment variables (or anywhere yet).
This feature seemed useful to us, so we offer a translation of the corresponding tutorial from the official GitLab documentation:
This tutorial demonstrates an example of authentication, configuration and reading secrets from HashiCorp's Vault via GitLab CI / CD.
Requirements
This tutorial assumes that you are familiar with GitLab CI / CD and Vault.
To follow it, you will need:
- GItLab account
- Running Vault server and access to configure authentication and create roles and policies.
: URL vault.example.com URL Vault gitlab.example.com GitLab .
(job) JSON Web Token (JWT), CI_JOB_JWT
. JWT Vault JWT Auth.
, JWT :
{
"jti": "c82eeb0c-5c6f-4a33-abf5-4c474b92b558", #
"iss": "gitlab.example.com", # Issuer, .. GitLab
"iat": 1585710286, #
"nbf": 1585798372, #
"exp": 1585713886, #
"sub": "22", # Subject (project id)
"namespace_id": "1",
"namespace_path": "mygroup",
"project_id": "22",
"project_path": "mygroup/myproject",
"user_id": "42",
"user_login": "myuser",
"user_email": "myuser@example.com"
"pipeline_id": "1212",
"job_id": "1212",
"ref": "auto-deploy-2020-04-01", # Git-refs
"ref_type": "branch", # Git-refs, (branch) (tag)
"ref_protected": "true" # true, protected, false
}
RS256 OpenID Connect GitLab , . , , c JWT . , , 5 .
JWT- URL (https://gitlab.example.com/-/jwks) JWKS Vault , JWT-.
Vault, bound_claims JWT , , , CI .
Vault CLI, API ( curl ).
, , production staging Vault, http://vault.example.com:8200. stage pa$$w0rd
real-pa$$w0rd
prod:
$ vault kv get -field=password secret/myproject/staging/db
pa$$w0rd
$ vault kv get -field=password secret/myproject/production/db
real-pa$$w0rd
Vault- JWT:
$ vault auth enable jwt
Success! Enabled jwt auth method at: jwt/
policy, :
$ 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" ]
}
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" ]
}
EOF
Success! Uploaded policy: myproject-production
, JWT-.
stage myproject-staging
:
$ 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": "22",
"ref": "master",
"ref_type": "branch"
}
}
EOF
production myproject-production
:
$ 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": "22",
"ref_protected": "true",
"ref_type": "branch",
"ref": "auto-deploy-*"
}
}
EOF
bound_claims , JWT- .
GitLab protected branches, , .
Token_explicit_max_ttl , Vault , 60 .
User_claim , Vault . (. — "user_claim" = "user_email", user_email JWT-. ( GitLab) email , .)
bound_claims_type bound_claims
. “glob”, glob
*
. (. — “string”, *
*
.)
Vault’s Create Role documentation.
: project_id
namespace_id
, , GitLab, .
JWT:
$ vault write auth/jwt/config \
jwks_url="https://gitlab.example.com/-/jwks" \
bound_issuer="gitlab.example.com"
bound_issuer , , gitlab.example.com
(iss
claim) , JWKS https://gitlab.example.com/-/jwks .
master-, secret/myproject/staging/
, secret/myproject/production/
:
read_secrets:
script:
# ref
- echo $CI_COMMIT_REF_NAME
# protected
- echo $CI_COMMIT_REF_PROTECTED
# Vault CI
- export VAULT_ADDR=http://vault.example.com:8200
# .
#
# JWT Auth - https://www.vaultproject.io/api/auth/jwt#parameters-1
- export VAULT_TOKEN="$(vault write -field=token auth/jwt/login role=myproject-staging jwt=$CI_JOB_JWT)"
# VAULT_TOKEN
- export PASSWORD="$(vault kv get -field=password secret/myproject/staging/db)"
#
- echo $PASSWORD
# , myproject-staging
# secret/myproject/production/*
- export PASSWORD="$(vault kv get -field=password secret/myproject/production/db)"
myproject-production
/secret/myproject/production/
:
read_secrets:
script:
# ref
- echo $CI_COMMIT_REF_NAME
# protected
- echo $CI_COMMIT_REF_PROTECTED
# Vault CI
- export VAULT_ADDR=http://vault.example.com:8200
# .
#
# JWT Auth - https://www.vaultproject.io/api/auth/jwt#parameters-1
- export VAULT_TOKEN="$(vault write -field=token auth/jwt/login role=myproject-production jwt=$CI_JOB_JWT)"
# VAULT_TOKEN
- export PASSWORD="$(vault kv get -field=password secret/myproject/production/db)"
#
- echo $PASSWORD
, !
GitLab, Vault GitLab 13.4, 22 2020.