Utiliser GitLab CI/CD avec HashiCorp Vault

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/

 

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.