Vault
Hashicorp Vault — это инструмент для управления секретами, который помогает организациям безопасно управлять, хранить и получать доступ к конфиденциальной информации. Он позволяет хранить учетные данные, ключи шифрования, сертификаты и другую секретную информацию в безопасном и надежном месте, доступ к которому можно получить только с разрешения.
Vault предлагает несколько функций, которые делают его идеальным решением для управления секретной информацией:
Безопасность: Vault использует передовые методы шифрования и аутентификации для обеспечения безопасности хранимых секретов. Он также поддерживает многофакторную аутентификацию для дополнительного уровня защиты.
Управление доступом: Vault позволяет администраторам определять политики доступа, которые определяют, кто может получать доступ к секретам и на каких условиях. Это помогает обеспечить контроль над тем, кто имеет доступ к чувствительной информации.
Централизованное хранение: Vault хранит все секреты в одном месте, что упрощает управление и доступ к ним.
Автоматизация: Vault может быть интегрирован с другими инструментами Hashicorp, такими как Consul и Nomad, для автоматизации процессов управления секретами.
Гибкость: Vault может работать в различных окружениях, включая облачные платформы, такие как Amazon Web Services (AWS) и Microsoft Azure, и на локальных серверах.
Открытый исходный код: Hashicorp Vault распространяется под лицензией Apache 2.0, что позволяет пользователям свободно использовать, изменять и распространять его.
Масштабируемость: Vault масштабируется для поддержки больших объемов данных и большого числа пользователей.
В целом, Hashicorp Vault является надежным и безопасным решением для хранения и управления секретами в организации. Он обеспечивает гибкость, масштабируемость и открытый исходный код, что делает его привлекательным для многих предприятий.
Общая схема Vault:
Vault использует различные алгоритмы шифрования для защиты данных, хранящихся в нем. Процедура шифрования включает в себя следующие шаги:
Генерация ключа шифрования: Vault генерирует случайный ключ шифрования, который будет использоваться для защиты данных.
Шифрование данных: Vault использует этот ключ для шифрования всех данных, которые будут храниться в системе.
Хранение ключа шифрования: Ключ шифрования хранится в безопасном месте, доступном только для администраторов Vault.
Storage Backend
Это место, где Vault хранит секреты в зашифрованном виде. Это хранилище зашифровано мастер-ключом, этот мастер-ключ зашифрован root-ключом, и он тоже зашифрован другими ключами.
Само хранилище может представлять собой файл, который расположен на том же хосте, где функционирует Vault или, например, может использоваться удаленная база данных.
Главное, что надо знать, — что вот это хранилище зашифровано (и ключи шифрования также последовательно зашифрованы). И как раз с этим связаны понятия Seal и Unseal.
Seal/Unseal
Seal и Unseal — это запечатывание и распечатывание.
Sealed state — это запечатанное состояние Vault, при котором он имеет физический доступ к зашифрованным данным, но расшифровать их не способен, так как отсутствует доступ к ключу шифрования.
При любом рестарте Vault переходит в запечатанное состояние. И чтобы перевести Vault в рабочее (распечатанное) состояние, нужно дать ему Unseal-ключ, который по умолчанию разделяется на части по алгоритму Шамира.
Чтобы распечатать Vault, необходимо предоставить ему некоторое количество частей данного Unseal-ключа.
Если мы говорим про большие системы то существует механизм Auto Unseal. Что такое Auto Unseal? Вы поднимаете один транзитный узел с Vault (он так называется, поскольку внутри используется Secret Engine — transit).
В данном Vault хранится ключ для распечатывания узлов основного кластера.
В случае рестарта какого-либо узла из основного кластера, где, собственно, хранятся секреты, данный узел обращается к транзитной ноде.
Там он получает ключ от других ключей, который в итоге ему расшифрует хранилище. Это общепринятый способ.
Важно выполнять бэкапирование ключа, который распечатывает основные узлы, так как в случае потери транзитной ноды будет потерян ключ для распечатывания, а следовательно, доступ до секретов основного кластера Vault.
Так как основной кластер Vault авторизуется в транзитной ноде и получает себе ключ для распечатывания с помощью токена, а данный токен имеет свое время жизни, то необходимо его продлевать.
Для этого токен для получения Unseal-ключа должен быть создан с флагами -orphan и -periodic. Поясним, что это значит. Флаг Periodic нужен для того, чтобы токен продлевался на свой срок жизни при каждом использовании в Vault.
То есть основной кластер сходил к транзиту, авторизовался по данному токену и получил ключ, тогда срок его жизни сразу обновится.
Orphan — это понятие связано с тем, что в Vault все токены наследуются, и если вы под какой-то учетной записью выпустили токен, то он будет зависеть от токена той учетной записи, от которой вы его выпустили.
Если, допустим, токену владельца осталось жить три дня, а вот выпускаемому им токену вы задали время жизни месяц, то он проживет три дня. Orphan означает то, что он сирота, у него нет родительского токена, и он будет жить столько, сколько вы указали при его создании.
Не делайте взаимно распечатываемые кластеры, потому что запросто получите взаимозапечатываемые кластеры.
Vault Policy
Vault Policy — это набор правил и настроек, определяющих, как и какие операции могут выполняться в Hashicorp Vault. Они используются для определения того, какие роли и пользователи могут получить доступ к определенным секретам, ключам, подписывать запросы и выполнять другие действия в хранилище. Политики в Vault помогают контролировать доступ и авторизовать пользователей на основе их ролей и привилегий.
Политики могут быть как разрешающими, например ["create", "update", "patch", "read", "delete"]. Так и запрещающими, например ["deny"].
Политики имеют очень обширный функционал, позволяют использовать маски и переменные. Подобрее о политиках в Vault можно почитать на сайте в документации: https://developer.hashicorp.com/vault/docs/concepts/policies
Vault Engines
В Vault существует несколько типов движков (engines), каждый из которых предназначен для хранения и обработки определенного типа данных. Вот некоторые из них:
Auth Engine — используется для аутентификации пользователей в системе и управления их доступом к ресурсам.
Audit Engine — предназначен для сбора и анализа информации о действиях пользователей в системе.
Secrets Engine — служит для хранения и управления секретами, такими как пароли, ключи API и другая конфиденциальная информация.
Каждый из этих движков имеет свои особенности и преимущества, и выбор конкретного типа зависит от потребностей и требований конкретной организации.
Secrets Engines:
KV
Движок Key/Value имеет две разные версии: KV_v1 и KV_v2. Они имеют ряд ключевых отличий: например, поддержка версионирования и разные методы доступа через API.
Мы в своих примерах будем использовать только v2, т.к. v1 считается устаревшей. Тем не менее, поскольку v1 часто встречается в старых установках vault, следует помнить, что доступ к их объектам надо получать по разному.
Vault UI
Vault UI (User Interface) — это пользовательский интерфейс для системы управления паролями Vault. Он предоставляет пользователям простой и безопасный способ доступа к своим учетным данным, хранящимся в Vault.
Наш учебный Vault UI
Аутентификация через ODIC.
Интерфейс vault очень простой, имеет минимальный функционал для администрирования ключей и данных. Основная работа с vault осуществляется через интеграции, например rest или vault cli.
Хорошей практикой является создавать отдельные учетные записи для каждого инженера или, например, включить авторизацию через LDAP.
Оригинальные бинариники vault находятся на официальном сайте vault, но так как доступ с российских адресов ограничен компанией, мы возьмем копии этих бинарников с нашего репозитория
Распаковка vault бинарника
git clone git@git.devops-teta.ru:materials/vault.git && cd vault
sudo apt install -y unzip
unzip vault_1.15.2_linux_amd64.zip
sudo mv vault /usr/local/bin
Vault CLI
Самый простой метод авторизации запросов в Vault — это token. Токен для своего пользователя можно скопировать в веб-интерфейсе.
Если доступа к UI нет то токен можно получить через curl по логину и паролю (basic auth/LDAP):
curl --request POST https://vault.devops-teta.ru/v1/auth/userpass/login/<username> --data '{"password": "PASSWORD"}
В полученном JSON можно найти токен:
{"request_id":"96139453-389b-7581-686b-a1dee32381c6","lease_id":"","renewable":false,"lease_duration":0,"data":null,"wrap_info":null,"warnings":null,
"auth":{"client_token":"s.dsfdsfsdfsdfew543", "accessor":"dwwerewrwerew","policies":["default","user"],"token_policies":["default"],"identity_policies":["user"],"metadata":{"username":"user"},"lease_duration":2764800,"renewable":true,"entity_id":"861f20d9-a8f7-dabf-f081-321046ac74bd","token_type":"service","orphan":true}}
Для использования vault cli необходимо настроить подключение в vault, а именно экспортировать переменные окружения VAULT_ADDR и VAULT_TOKEN**.** Сделаем это:
export VAULT_ADDR=https://vault.devops-teta.ru
export VAULT_TOKEN=ВАШ_ТОКЕН
Обратите внимание, токен имеет время жизни. Этот параметр настраивается. В нашем vault он составляет 4 часа для пользователей аутентифицированных через gitlab.
Попробуем получить некоторые данные из Vault к которым имеем доступ. Также попробуем записать новые данные в Vault.
get — получение данных
$ vault kv get test/demo_project/repo1
======== Secret Path ========
test/data/demo_project/repo1
======= Metadata =======
Key Value
--- -----
created_time 2023-11-29T14:32:49.581309614Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 2
====== Data ======
Key Value
--- -----
password value1
get — получение данных
$ vault kv get -field password test/demo_project/repo1
value1
put — запись в vault
$ vault kv put -mount=test demo_project/repo2 key1=my-long-passcode
======== Secret Path ========
test/data/demo_project/repo2
======= Metadata =======
Key Value
--- -----
created_time 2023-11-29T16:48:31.818653008Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 1
Также доступ к данным vault можно получить с помощью rest запроса в API.
rest
$ curl -s --header "X-Vault-Token: $VAULT_TOKEN" https://vault.devops-teta.ru/v1/test/data/demo_project/repo1 | jq
{
"request_id": "168dde12-1b46-821d-7792-2598c39dae6f",
"lease_id": "",
"renewable": false,
"lease_duration": 0,
"data": {
"data": {
"password": "value1"
},
"metadata": {
"created_time": "2023-11-29T14:32:49.581309614Z",
"custom_metadata": null,
"deletion_time": "",
"destroyed": false,
"version": 2
}
},
"wrap_info": null,
"warnings": null,
"auth": null
}
Wrapping — unwrapping
Стоит отметить такой метод работы с секретами в Vault как wrapping.
Механизм wrapping-unwrapping позволяет хранить в скриптах развертывания не сам секрет, а токен, предоставляющий доступ к нему.
Это позволяет иметь доступ только к определенным данным, а не ко всему ресурсу плюс накладывает TTL, по истечении которого секрет становится невалидным.
Также нужно отметить, что в Vault есть такой термин как num_uses, то есть количество использований какого-либо секрета. Для wrapped токенов num_uses равно 1, то есть после однократного использования токен становится невалидным.
Есть команда rewrap, которая обновляет токен и выпускает новый токен (действует только для валидного токена). Для получения секрета из токена необходимо использовать команду unwrap.
Для получения wrap token, который будет использоваться при авторизации и запросе secret-id, выполните команду:
vault write -wrap-ttl=600s -tls-skip-verify -force auth/some/role/my-app-role/secret-id
Затем полученный файл необходимо поместить на файловую систему виртуальной машины, где запускается наше приложение. Этот путь должен совпадать с тем, который ожидает приложение.
Полученный токен может быть использован лишь один раз. После запуска токен будет прочитан и использован для получения secret-id. После получения secret-id приложение может запросить данные из секретного хранилища Vault, пока не истек TTL для secret_id.
Данный способ хорошо подходит в том случае, когда мы заполняем начальную конфигурацию приложения на этапе запуска.
Рекомендации гласят, что wrap token должен иметь время жизни равное времени деплоя приложения. В то же время secret-id могут иметь длинное время жизни, но это не рекомендуется разработчиком Vault в силу большого потребления памяти и нагрузке при очистке истекших токенов.
Лучшая рекомендация гласит, что нужно использовать короткое время жизни и постоянно продлевать его. Тем самым избегать дорогих операций авторизации и выдачи новых токенов.
Hashicorp Vault в Ansible
При использовании общих ролей и плейбуков ansible для управления инфраструктурой, очень удобно и безопасно хранить секретную информацию в корпоративном vault.
За интеграцию ansible c vault отвечает lookup плагин hashi_vault. Для его работы необходимо установить python библиотеку hvac.
### В случае с установленым pip
pip install hvac
### В случае отсутствия pip
sudo apt-get -y install python3-hvac
Напишем простой плейбук для демонстрации работы hashi_vault.
- hosts: localhost
vars_prompt:
- name: "vault_token"
prompt: "Enter vault token"
private: yes
vars:
vault_addr: https://vault.devops-teta.ru
user_backend_pass: "{\{ lookup('hashi_vault', 'secret=test/data/demo_postgres:backend token={\{ vault_token }} url={\{ vault_addr }}') }}"
tasks:
- name: Return all kv v2 secrets from a path
debug:
msg: "{\{ user_backend_pass }}"
Запустим плейбук и введем наш TOKEN и получим данные из Vault:
ok: [localhost] => {
"msg": "mysecurebackendpassword"
}
По данном примеру доработаем наш плейбук postgres для использования vault. Доработка заключается в добавлении в плейбук запроса токена и получение пароля из vault.
DIFF: https://git.devops-teta.ru/materials/ansible/-/commit/d3cf17748f1839ea992aad7e1670990c44bfecd8
### inventory/group_vars/postgres.yml
---
password: "{\{ user_backend_pass|default('mysecurebackendpassword') }}"
### postgres.yml
---
- hosts: postgres
become: true
vars_prompt:
- name: "vault_token"
prompt: "Enter vault token"
private: yes
vars:
vault_addr: https://vault.devops-teta.ru
user_backend_pass: "{\{ lookup('hashi_vault', 'secret=test/data/demo_postgres:backend token={\{ vault_token }} url={\{ vault_addr }}') }}"
roles:
- postgres
AppRole
Approle Authentication в Vault позволяет пользователям аутентифицироваться в системе с использованием ролей, а не обычных учетных данных (логин/пароль). Это обеспечивает более гибкую и масштабируемую систему авторизации, поскольку позволяет создавать и управлять большим количеством ролей, а также ограничивать доступ пользователей к определенным ресурсам на основе этих ролей.
Для интеграции с системами не следует использовать токены от личных учетных записей. В Vault есть несколько способов аутентификации, approle один из них.
Включим engine AppRole и настроим роль для работы.
export VAULT_ADDR=https://vault.devops-teta.ru
export VAULT_TOKEN=hvs.CAESIDXq84mt7ip85M0NZcShG8UM4mztieuYX3pGEmdZUuTjGh4KHGh2cy5zWjlkS0xVZTI3YWpOZExwUkNVWEF2Mlg
### Включим движок approle. (На нашем vault он скорее всего уже включен, и будет ошибка)
$ vault auth enable approle
### Создадим пример политики для нашей новой роли.
$ vault policy write demo-gitlab -<<EOF
# Read-only permission on secrets stored at 'test/data/demo_postgres'
path "test/data/demo_postgres" {
capabilities = [ "read" ]
}
EOF
### Создадим роль и привяжем нашу политику к ней.
$ vault write auth/approle/role/demo-gitlab token_policies="demo-gitlab" \
token_ttl=1h token_max_ttl=4h
### Проверим созданную роль
$ vault read auth/approle/role/demo-gitlab
### Для использование ролей, необходим ее ID. Получим его этой командой:
$ vault read auth/approle/role/demo-gitlab/role-id
Key Value
--- -----
role_id 108383ad-95f0-0c8e-b40f-186d383c53e8
### Сгенерируем секрет для доступа к роли.
$ vault write -force auth/approle/role/demo-gitlab/secret-id
Key Value
--- -----
secret_id 0200c6fc-1f43-377f-575a-c3f2cd0ac886
secret_id_accessor d3fb2ada-8955-caf3-9fc3-10b6fef69bae
secret_id_num_uses 0
secret_id_ttl 0s
Используя данные для нашей роли, напишем простой playbook в ansible, который будет использовать approle аутентификацию, вместо токена.
- hosts: localhost
vars_prompt:
- name: "secret_id"
prompt: "Enter vault secret_id"
private: yes
vars:
vault_addr: https://vault.devops-teta.ru
role_id: 108383ad-95f0-0c8e-b40f-186d383c53e8
user_backend_pass: "{\{ lookup('hashi_vault', 'secret=test/data/demo_postgres:backend auth_method=approle role_id={\{role_id}} secret_id={\{secret_id}} url={\{ vault_addr }}') }}"
tasks:
- name: Return all kv v2 secrets from a path
debug:
msg: "{\{ user_backend_pass }}"
JWT
JWT (JSON Web Token) Authentication в Vault используется для аутентификации пользователей с помощью токенов JWT. Этот тип аутентификации позволяет создавать токены, которые содержат информацию о пользователе, такую как его идентификатор, роли и срок действия токена. Затем эти токены передаются на сервер Vault для проверки подлинности пользователя.
JWT аутентификация используется для интеграции с gitlab. Настроим такую интеграцию в нашем gitlab и vault.
Создадим новый проект в gitlab и узнаем его ID:
В учебных целях будем использовать проект
JWT
export VAULT_ADDR=https://vault.devops-teta.ru
export VAULT_TOKEN=hvs.CAESIDXq84mt7ip85M0NZcShG8UM4mztieuYX3pGEmdZUuTjGh4KHGh2cy5zWjlkS0xVZTI3YWpOZExwUkNVWEF2Mlg
### Включаем engine JWT
$ vault auth enable jwt
Success! Enabled jwt auth method at: jwt/
### Добавляем конфигурацию для валидации токенов с нашего gitlab.
$ vault write auth/jwt/config \
jwks_url="https://git.devops-teta.ru/-/jwks" \
bound_issuer="git.devops-teta.ru"
Success! Data written to: auth/jwt/config
### Создадим политику для доступ к секрету
$ vault policy write demoproject-staging -<<EOF
# Read-only permission on secrets stored at 'test/data/demo_project/repo1'
path "test/data/demo_project/repo1" {
capabilities = [ "read" ]
}
EOF
### Создадим пример роли, которая будет использоваться для доступа к секретам из ветки main.
$ vault write auth/jwt/role/vault-jwt-demo-staging - <<EOF
{
"role_type": "jwt",
"policies": ["demoproject-staging"],
"token_explicit_max_ttl": 60,
"user_claim": "user_email",
"bound_claims": {
"project_id": "302",
"ref": "main",
"ref_type": "branch"
}
}
EOF
Success! Data written to: auth/jwt/role/vault-jwt-demo-staging
Теперь напишем простой pipeline, демонстрирующий работу JWT аутентификации в vault.
https://git.devops-teta.ru/materials/vault-jwt-demo/-/pipelines
.gitlab-ci.yml
job:
image:
vault:1.13.3
script:
- set -eu
# Проверяем имя ref джобы
- echo $CI_COMMIT_REF_NAME
# и является ли она protected
- echo $CI_COMMIT_REF_PROTECTED
# Адрес Vault может быть передан через переменную в CI
- export VAULT_ADDR=https://vault.devops-teta.ru
# Проходим аутентификацию и получаем токен. Время истечения жизни токена и другие
# его параметры можно задать при конфигурации
# JWT Auth - https://www.vaultproject.io/api/auth/jwt#parameters-1
- export VAULT_TOKEN="$(vault write -field=token auth/jwt/login role=vault-jwt-demo-staging jwt=$CI_JOB_JWT)"
# Теперь используем VAULT_TOKEN для чтения секретов и сохранения их в перемнных окружения
- export PASSWORD="$(vault kv get -field=password test/demo_project/repo1)"
# Используем секрет
- if [[ -z "$PASSWORD" ]]; then exit 1; else echo 'Password is '$PASSWORD; fi
Проверим ограничение роли, создав любую ветку отличную от main. Результатом работы CI такой ветки будет ошибка 403.
Vault agent (sidecar)
Vault Agent — это компонент системы управления секретами Hashicorp Vault, который обеспечивает безопасное хранение и управление секретами на стороне клиента. Он работает на стороне приложения или микросервиса и обеспечивает автоматическую синхронизацию секретов с сервером Hashicorp Vault. Это позволяет разработчикам сосредоточиться на разработке и не беспокоиться о управлении секретами.
Запустим экземпляр такого контейнера и посмотрим как его конфигурировать.
Для примера воспользуемся roleid и secretid которые мы сгенерировали на предыдущем шаге. Создадим два файла:
roleid
108383ad-95f0-0c8e-b40f-186d383c53e8
secretid
0200c6fc-1f43-377f-575a-c3f2cd0ac886
Напомню, что данная роль у нас привязана к политике demo-gitlab:
demo-gitlab
path "test/data/demo_postgres" {
capabilities = [ "read" ]
}
Создадим конфигурационный файл:
agent.hcl
vault {
address = "https://vault.devops-teta.ru"
retry {
num_retries = 3
}
}
auto_auth {
method {
type = "approle"
config = {
role_id_file_path = "/config/roleid"
secret_id_file_path = "/config/secretid"
remove_secret_id_file_after_reading = true
}
}
}
api_proxy {
use_auto_auth_token = true
}
listener "tcp" {
address = "0.0.0.0:8100"
tls_disable = true
}
Все файлы помести в папку config, которую примонтируем в контейнер в путь /config.
├── config
│ ├── agent.hcl
│ ├── roleid
│ ├── secretid
Запустим vault agent:
docker run --name vault-agent -d -p 127.0.0.1:8100:8100 -v `pwd`/config:/config vault:1.13.3 vault agent -config /config/agent.hcl
Агент предоставляет доступ к API vault, в данном случае без дополнительной аутентификации. Поэтому такой агент должен запускаться в доверенном окружении, обычно рядом с приложением в роли sidecar.
Код на стороне приложения ничего не знает про метод аутентификации в Vault. Не имеет ключевой информации для доступа в Vault. В нашем примере такое приложение — curl.
curl http://localhost:8100/v1/test/data/demo_postgres | jq
export pass=$(curl -s http://localhost:8100/v1/test/data/demo_postgres | jq -r '.data.data.backend')
echo $pass
Еще один вариант работы vault agent — шаблоны. Аналогично шаблонам в ansible, vault agent может сгенерировать требуемые файлы исходя из данных в vault.
Посмотрим такой пример, создадим шаблон генерирующий строку подключения к Postgres.
/config/template.ctmpl
{\{ with secret "test/demo_postgres" -}}
postgresql://{\{ .Data.data.user }}:{\{ .Data.data.password }}@{\{.Data.data.postgres_host}}:{\{.Data.data.postres_port}}/{\{.Data.data.db}}
{\{- end }}
Поместим шаблон в папку config и добавим в agent. hcl следующие строки:
template {
source = "/config/template.ctmpl"
destination = "/render/render.txt"
error_on_missing_key = true
}
Создадим папку render, выдадим ей права на запись.
mkdir render && sudo chown 100:100 render
Доработаем строку запуска контейнера, примонтировав новую папку, запустим агента и посмотрим результат рендера шаблона.
docker run --name vault-agent -d -p 127.0.0.1:8100:8100 -v `pwd`/config:/config -v `pwd`/render:/render vault:1.13.3 vault agent -config /config/agent.hcl
$ cat render/render.txt
postgresql://backend:mysecurebackendpassword@10.0.10.50:5432/backend
Итоговый вид файлов и каталогов:
├── config
│ ├── agent.hcl
│ ├── roleid
│ ├── secretid
│ └── template.ctmpl
└── render
└── render.txt
Итоговая самостоятельная работа
Дедлайн сдачи: 20 декабря
Рассмотрим audit-svc — игрушечный веб-сервис принимающий по HTTP события аудита (техническое описание смотрите в README.md репозитория). Это сервис на Python, использующий пакетный менеджер Poetry (аналогичный counter-backend, с которым мы работали на практиках ранее), но в отличии от counter-backend этому сервису для работы требуется подключение к БД PostgreSQL.
В рамках итоговой самостоятельной работы вам предстоит написать скрипты развертывания для этого сервиса, настроить хранение секретов и мониторинг.
Рассмотрим задачи детальнее.
Начнем с публикации проекта: требуется написать GitLab CI пайплайн упаковывающий сервис в Docker-образ и публикующий его на курсовой Harbor. Как пробросить настройки Harbor в пайплайн остается на ваше усмотрение: вы можете использовать интеграцию с Harbor, задать требуемые переменные вручную в настройках проекта, или же подтягивать их из курсового Vault.
После того, как вы опубликуете образ, вам предстоит развернуть сервис на ВМ2. Так как здесь мы развертываем один независимый сервис, то выносить развертывание в отдельный репозиторий необязательно. Используйте любую из рассмотренных нами технологий: Docker, Docker Compose, Ansible + коллекция community.docker.
Развертывание должно запускаться как задача в сборочном пайплайне при создании тега или по коммиту в репозиторий развертывания (задача с коммитом также должна запускаться из тега).
Рассмотрим состав развертывания:
- Сервису требуется подготовленная БД в PostgreSQL: саму БД и пользователя в ней создайте при помощи роли, рассмотренной на практике. Подготовку Б Д выполните при помощи скрипта migrate в репозитории сервиса;
- Параметры подключения к БД — это секреты и должны храниться соответствующе. В этой практике мы рассматривали HashiCorp Vault как хранилище секретов: используйте его, чтобы сохранить параметры подключения и отдать их сервису при развертывании.
Для передачи параметров в сам сервис используйте Vault Agent и его механизм генерации конфигов из шаблонов, который мы также рассматривали в этой практике. Чтобы автоматизировать перезагрузку сервиса при обновлении конфигурационного файла используйте опцию command, которая позволяет выполнить произвольную команду при обновлении сгенерированного файла (сервис перечитывает конфиг при вызове эндпоинта POST /reload).
Авторизацию Vault Agent в Vault также настройте аналогично этой практике — при помощи AppRole и политик, ограничивающих доступ до конкретного секрета.
- Разверните вместе с сервисом Nginx и организуйте доступ так, чтобы к сервису нельзя было обратиться напрямую из внутренней подсети МТС Cloud или интернета (только через Nginx). Также ограничьте доступ к эндпоинту /reload в конфигурации Nginx так, чтобы при вызове этого эндпоинта через Nginx запрос не пробрасывался в сервис, а вместо этого возвращался HTTP код ответа 404;
- Добавьте к развернутому Nginx официальный экспортер — nginx-exporter и настройте Nginx так, чтобы в экспортере была информация об развернутом инстансе (инструция по настройке есть в репозитории nginx-exporter).
В задании не требуется автоматизировать запуск миграций БД при каждом развертывании сервиса, но вы можете сделать это как дополнительное задание.
После того как вы развернете сервис требуется настроить сбор его метрик в инстанс Prometheus, развернутый ранее. Затем создайте в курсовой Grafana дэшборд, содержащий следующие метрики сервиса:
- Графики присланных событий в секунду в разбивке по приложениям;
- Графики распределения кодов ответа от сервиса (какой процент от всех ответов составляли ответы с кодом XXX в каждый момент времени);
- Статусный блок, показывающий запущен ли сервис (воспользуйтесь системной метрикой up);
Чтобы на дэшборде отображались не нули, сгенерируйте события аудита при помощи скрипта generate в репозитории сервиса.
- Затем скачайте дэшборд для мониторинга Nginx при помощи nginx-exporter и сохраните его в курсовую Grafana.
Для проверки предоставьте артефакты:
Репозиторий audit-svc, форкнутый в вашу подгруппу.
Ссылки на запуски пайплайнов сервиса:
- В ветке по-умолчанию (пайплайн должен содержать сборку проекта и публикацию Docker образа)
- В защищенном теге (пайплайн должен содержать либо задачу развертывания, либо запускать пайплайн развертывания);
- Если пайплайн развертывания вынесен отдельно, то ссылку на его успешный запуск.
Ссылки на скрипты развертывания в курсовом GitLab, которые демонстрируют:
- Запуск миграций при каждом развертывании (опционально);
- Настроенную синхронизацию конфига сервиса с Vault при помощи Vault Agent.
Ссылку на развернутый сервис в подсети МТС Cloud;
- Запросы к эндпоинту /reload не должны доходить до сервиса и должны возвращать HTTP код ответа 404;
- Ссылку на настроенный дэшборд сервиса.