jenkins – інтеграція з hashicorp vault


Розглянемо процес налаштування інтеграції з HashiCorpVAULT.
Для інтеграції типу “app to app” рекомендується використовувати метод аутентифікації AppRole.

Рекомендується ознайомитись з кращими практиками approle-best-practices та впроваджувати їх.

Що таке AppRole?
Це один з методів аутентифікації, який дозволяє додаткам, хостам аутентифікуватися за допомогою визначених ролей в VAULT. В нашому випадку за допомогою встановленого та налаштованого плагіну HashicorpVault, Jenkins зможе отримувати VAULT_TOKEN з відповідними політиками, які надають доступ до вказаних шляхів.


Як працює AppRole?

Кожна створена approle має унікальний ідентифікатор role_id який захищений за допомогою secret_id (можемо вважати це логіном та паролем). Коли отримали обидва ці значення, можемо запросити в Vault токен, який буде використаний для доступу до сховища, вказаних шляхів які ми описуємо в політиках VAULT.


Для чого це потрібно?

В першу чергу для безпеки, щоб не зберігати критичні дані в “Jenkins Credentials Storage” та не вказувати в “job parameters”, а отримувати їх з централізованого сховища.


Як будемо реалізовувати?
Сам процес розділимо на декілька етапів:

  • роботи з VAULT (налаштування, створення політики, ролі)
  • роботи з Jenkins (встановлення/налаштування плагіну, тестування)

Підготовка VAULT

Дані маніпуляції можна проводити на сервері VAULT або з локальної машини (наш варіант), для цього потрібно щоб у вас був встановлений пакет vault або виконувати запити за допомогою curl(варіант з curl описаний в документації).

Налаштовуємо доступ, експортуємо дані:

export VAULT_ADDR=https://vault.example.com
export VAULT_TOKEN=s.3**23*********fs42

Вмикаємо метод авторизації approle:

vault auth enable approle
Success! Enabled approle auth method at: approle/

Створюємо політику доступу з назвою “jenkins”, в якій вказуємо шлях до якого потрібен доступ:

vault policy write jenkins -<<EOF
path "service/data/jenkins/credentials" {
  capabilities = [ "read" ]
}EOF

де:

  • path “service/data/jenkins/credentials”шлях з якого ми хочемо зчитувати ключ-значення;
  • capabilities = [ “read” ] – вказуємо що дозволено виконувати, а що ні, в такому випадку дозволено тільки читати записи;

Переходимо до створення ролі, назвемо її “jenkins-role”:

vault write auth/approle/role/jenkins \
  secret_id_bound_cidrs="*43.*.*.*/32","**9.*.*.*/32","*1.*.*.*/32","127.0.0.1/32" \
  secret_id_num_uses=0 \
  enable_local_secret_ids=false \
  token_bound_cidrs="*43.*.*.*/32","**9.*.*.*/32","*1.*.*.*/32","127.0.0.1/32" \
  token_num_uses=0 \
  token_ttl=1h \
  token_max_ttl=3h \
  token_type=default \
  period="" \
  policies="default","jenkins"

де:

  • secret_id_bound_cidrs – дозволені ip-адреси які можуть виконувати логін;
  • secret_id_num_uses – кількість разів коли певний SecretID може отримати токен з AppRole, після чого дія SecretID закінчується. Якщо потрібно необмежене використання встановлюємо 0. За бажанням цей параметр можна змінити полем «num_uses» при генерації SecretID;
  • enable_local_secret_ids – не створювати local_secret_ids;
  • token_num_uses – максимальна кількість разів, коли згенерований токен може бути використаний (протягом встановленого терміну служби). 0 – означає необмежений.
  • token_ttl – час життя токена після якого він буде поновлюватись;
  • token_max_ttl – максимальний термін служби згенерованих токенів;
  • token_typeтип токена який буде генеруватися;
  • token_bound_cidrs – список ір-адрес яким дозволено аутентифікуватися за допомогою токена;
  • policies=”jenkins”додаємо створено політику “jenkins” до ролі;

 

Отримуємо role_id:

vault read auth/approle/role/jenkins-role/role-id
Key        Value
---        -----
role_id    8f******-****-d236-****-7*******67

де:

  • role_id – ідентифікатор (унікальними UUID) який призначається для approle (можна вважати це логіном).


Генеруємо secret_id:

vault write -f auth/approle/role/jenkins-role/secret-id
Key                   Value
---                   -----
secret_id             b*******-5**c-*c**-8***-**********50

де:

  • secret_id – якщо коротко, це облікові дані які використовуються для будь-якого входу (можна вважати це паролем).

Перед використанням в Jenkins перевіримо доступ за допомогою ролі з локальної робочої станції (вашого ПК). Виконаємо логін за допомогою approle:

vault write auth/approle/login role_id="******7-cf**-****-***f-**ec*****ea" secret_id="ed******-****f-****-***f-********5f29"
Key                     Value
---                     -----
token                   s.ncE******************5h
token_accessor          gIQF*******************nQu
token_duration          1h
token_renewable         true
token_policies          ["default" "jenkins"]
identity_policies       []
policies                ["default" "jenkins"]
token_meta_role_name    jenkins

У виводі отримали певну інформацію, з якої беремо токен та експортуємо його:

export APP_TOKEN="s.ncE******************5h"
export VAULT_TOKEN=$APP_TOKEN

перевіряємо доступ за шляхом  service/jenkins/credentials:

vault kv get service/jenkins/credentials
========= Secret Path =========
service/data/jenkins/credentials
 
====== Metadata ======
Key Value
--- -----
created_time *************
deletion_time n/a
destroyed false
version 1
 
=========== Data ===========
Key Value
--- -----
jenkins_pass *************************
jenkins_token ********************
jenkins_user ********************

тепер спробуємо вказати інший шлях, приклад service/gitlab:

vault kv get service/gitlab/
Error making API request.
 
URL: GET https://vault.example.com/v1/sys/internal/ui/mounts/service/gitlab
Code: 403. Errors:
 
* preflight capability check returned 403, please ensure client's policies grant access to path "service/gitlab/"

отримали 403, оскільки в політиці доступу даний шлях не вказаний. Таким чином ми перевірили доступ за допомогою approle, переконалися що з політика налаштована вірно, переходимо до встановлення та налаштування плагіну з боку Jenkins.

Встановлення

Логінимось в Jenkins, переходимо в Manage Jenkins > Manage Plugins > Avealible Plugins, обираємо HashiCorp Vault та встановлюємо:


Створимо запис для доступу в Vault, переходимо Manage Jenkins > Credentiasl > System > Global credentials > Add credentials, назвемо його vault-role-jenkins:


де:

  • Kind “VAULT App role Credentials” – тип запису для AppRole;
  • Role ID – унікальний ідентифікатор ролі;
  • Secret ID – таємний ключ для ролі;
  • ID – назва запису;

Налаштування Плагіну

Переходимо в Manage Jenkins > Configure System знаходимо розділ Vault Plugin:

де:

  • Vautl URL – посилання на Ваш сервер;
  • Vault Credential – створений запис для доступу;

Заповнюємо та зберігаємо зміни, перевіряємо роботу плагіну.

Використання

Створимо тестове завдання, в якому будемо витягувати записи з VAULT. Приклад пайплайну взято з офіційної сторінки плагіну, використовуємо groovy:

node {
def configuration = [vaultUrl: 'https://vault.example.com', vaultCredentialId: 'vault-role-jenkins', engineVersion: 2]
def secrets = [
        [path: 'service/jenkins/credentials', engineVersion: 2, secretValues: [
            [vaultKey: 'jenkins_user']]]
    ]
    withVault([configuration: configuration, vaultSecrets: secrets]) {
        sh 'echo $jenkins_user >> test.txt'
    }
}

де:

  • def configuration – функція в якій описуємо конфігурацію для доступу до VAULT;
  • def secrets – вказуємо шлях до ключів та значень і ключ, значення якого хочемо отримати;

Запустимо завдання, переглянемо вивід:

Started by user geek
[Pipeline] Start of Pipeline
[Pipeline] node
Running on runner in /opt/jenkins/workspace/TEST/VAULT_TEST
[Pipeline] {
[Pipeline] withVault
Retrieving secret: service/jenkins/credentials
[Pipeline] {
[Pipeline] sh
+ echo ****
[Pipeline] // withVault
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS

Оскільки плагін за замовчуванням маскує вивід критичних даних в output переглянути вміст не вийде. Щоб переконатися що отримане значення вірне, можемо вивід ключа перенаправити в файл, потім прочитати значення з файлу (безпосередньо на сервері або агенті jenkins). Інтеграцію налаштовано.

Корисні посилання

  • https://developer.hashicorp.com/vault/docs/auth/approle
  • https://developer.hashicorp.com/vault/tutorials/auth-methods/approle
  • https://developer.hashicorp.com/vault/api-docs/auth/approle
  • https://plugins.jenkins.io/hashicorp-vault-plugin
Click to rate this post!
[Total: 2 Average: 5]