Dans cet article, nous allons voir comment utiliser GitLab CI/CD avec la solution HashiCorp Vault. Cela va nous permettre de stocker aucun mot de passe dans nos pipelines. Nous verrons également comment utiliser différents secrets en fonction des branches GIT utilisées.
Prérequis
Il est nécessaire d'avoir une plateforme GitLab CI/CD fonctionnelle ainsi qu'une plateforme HashiCorp Vault.
Contexte
Mon serveur Vault : https://vault.adminmalin.fr
Mon serveur GitLab: https://gitlab.adminmalin.fr
Pour mon exemple, je souhaite avoir deux arborescences de secrets :
- Une pour le développement
- Une pour la production
Cela ressemble à ceci :
GITLAB/dev/centreon :
- centreon_username = admin
- centreon_password = password-dev
GITLAB/production/centreon :
- centreon_username = admin
- centreon_password = password-prd
En fonction de la branche GIT qui appellera le pipeline, les secrets récupérés seront différents.
Configuration HashiCorp Vault
1) En SSH sur une machine pouvant communiquer avec l'interface WEB de Vault, exporter les variables nécessaires :
# export VAULT_ADDR=https://vault.adminmalin.fr # export VAULT_TOKEN=s.JKyBgKImhphr0AdV1kzdEfTg
2) Vérifier l'arborescence de vos secrets (facultatif) :
# vault kv get --field=centreon_user GITLAB/dev/centreon admin # vault kv get --field=centreon_password GITLAB/dev/centreon password-dev # vault kv get --field=centreon_user GITLAB/production/centreon admin # vault kv get --field=centreon_password GITLAB/production/centreon password-prod
3) Activation de l'authentification JWT utilisé par GitLab :
# vault auth enable jwt
4) Configuration JWT pour GitLab :
# vault write auth/jwt/config jwks_url="https://gitlab.adminmalin.fr/-/jwks" bound_issuer="gitlab.adminmalin.fr"
5) Création de deux règles Vault (policy), une pour le développement et une pour la production :
# vault policy write gitlab-production - <<EOF # Policy name: gitlab-dev # # Read-only permission on 'GITLAB/data/production/*' path path "GITLAB/data/production/*" { capabilities = [ "read" ] } EOF
# vault policy write gitlab-dev - <<EOF # Policy name: gitlab-dev # # Read-only permission on 'GITLAB/data/dev/*' path path "GITLAB/data/dev/*" { capabilities = [ "read" ] } EOF
Pour afficher les règles, saisir la commande suivante :
# vault policy list
Pour lire les paramètres d'une policy, utiliser la commande suivante :
# vault policy read gitlab-dev
6) Pour finir, nous allons créer deux rôles qui seront affectés à chaque règle :
# vault write auth/jwt/role/gitlab-dev - <<EOF
{
"role_type": "jwt",
"policies": ["gitlab-dev"],
"token_explicit_max_ttl": 60,
"user_claim": "user_email",
"bound_claims_type": "glob",
"bound_claims": {
"ref_type": "branch",
"ref": "deploy-*"
}
}
EOF
# vault write auth/jwt/role/gitlab-production - <<EOF
{
"role_type": "jwt",
"policies": ["gitlab-production"],
"token_explicit_max_ttl": 60,
"user_claim": "user_email",
"bound_claims_type": "glob",
"bound_claims": {
"ref": "master",
"ref_type": "branch"
}
}
EOF
Il est possible de définir d'autres règles d'authentification tel que le project ID GitLab. Pour cela ajouter dans la liste des paramètres bound_claims la directive suivante par exemple :
"project_id": "42",
Pour afficher les rôles saisir la commande suivante :
# vault list auth/jwt/role
Pour afficher le détails d'un rôle utiliser la commande suivante :
# vault read auth/jwt/role/gitlab-dev
Test avec GitLab CI/CD
1) Créer un fichier .gitlab-ci.yml à la racine de votre projet avec le contenu suivant :
stages:
- build_env
- execute
get_var_prod:
stage: build_env
image: vault
script:
- echo $CI_COMMIT_REF_NAME
- echo $CI_COMMIT_REF_PROTECTED
- export VAULT_ADDR=https://vault.adminmalin.fr
- export VAULT_TOKEN="$(vault write -field=token auth/jwt/login role=gitlab-production jwt=$CI_JOB_JWT)"
- |
cat <<EOF > vault.env
TOKEN=$VAULT_TOKEN
centreon_username=`vault kv get --field=centreon_user GITLAB/production/centreon`
centreon_password=`vault kv get --field=centreon_password GITLAB/production/centreon`
EOF
artifacts:
reports:
dotenv: vault.env
expire_in: 1 hour
only:
- master
get_var_dev:
stage: build_env
image: vault
script:
- echo $CI_COMMIT_REF_NAME
- echo $CI_COMMIT_REF_PROTECTED
- export VAULT_ADDR=https://vault.adminmalin.fr
- export VAULT_TOKEN="$(vault write -field=token auth/jwt/login role=gitlab-dev jwt=$CI_JOB_JWT)"
- |
cat <<EOF > vault.env
TOKEN=$VAULT_TOKEN
centreon_username=`vault kv get --field=centreon_user GITLAB/dev/centreon`
centreon_password=`vault kv get --field=centreon_password GITLAB/dev/centreon`
EOF
artifacts:
reports:
dotenv: vault.env
expire_in: 1 hour
only:
- /^deploy-.*$/
echo_var:
stage: execute
script:
- echo $TOKEN
- echo $centreon_username
- echo $centreon_password
2) Vérifier le résultat :
Pour la branche master :
Pour la branche deploy-dev :
Liens des solutions utilisées
GitLab édition Community 14.0.5 : https://about.gitlab.com/
HashiCorp Vault Open source 1.7.3 : https://www.vaultproject.io/