Аутентификация и чтение секретов в Vault через Gitflic CI
Функционал доступен в Enterprise версии
Введение
Vault - это система управления секретами. Она предоставляет способы шифрования, которые защищены методами аутентификации и авторизации, для обеспечения безопасного, проверяемого и ограниченного доступа к секретам. Под секретом может пониматься все, доступ к чему вы хотите контролировать, например, токены, ключи API, пароли, ключи шифрования или сертификаты
Предусловия
Для работы с Vault необходимо иметь
- аккаунт на GitFlic
- доступ к работающему серверу Vault (версии 1.2.0 и выше) для настройки аутентификации, а также для создания ролей и политик
Работа с Vault
JSON Web Tokens (JWTs) используется для OIDC аутентификации со сторонними службами. Если для задачи определен хотя бы один JWTs, то секрет автоматически использует этот токен для аутентификации в Vault.
В JWTs включены следующие параметры:
Параметр | Наличие | Описание |
---|---|---|
iss |
Обязательно | Домен сервиса gitflic |
project_visibility |
Обязательно | Приватность проекта |
ref_name |
Обязательно | Имя ветки |
commit_sha |
Обязательно | Хэш коммита |
project_path |
Обязательно | Путь проекта |
project_name |
Обязательно | Псевдоним проекта |
project_title |
Обязательно | Название проекта |
pipeline_source |
Обязательно | Источник конвейера |
pipeline_id |
Обязательно | ID конвейера |
sub |
Обязательно | ID задачи |
user_login |
Обязательно | Имя пользователя, запускающего задачу |
default_branch |
Обязательно | Стандартная ветка проекта |
iat |
Обязательно | Дата создания |
exp |
Обязательно | Дата окончания действия |
aud |
Не обязательно | Адрес Vault |
Пример JWTs:
{
"iss": "gitflic.ru/vault",
"project_visibility": "private"
"ref_name": "master",
"commit_sha": "812194e1724d03aaaaaaaaaaaa9adec3ec71f7c2",
"project_path": "mygroup/myproject",
"project_name": "myproject",
"project_title": "myproject",
"pipeline_source": "web",
"pipeline_id": "1212",
"sub": "1546"
"user_login": "myuser",
"default_branch": "master"
"iat": 1585710286,
"exp": 1585713886,
"aud": "https://gitflic.ru/vault"
}
JWT кодируется с использованием RS256 и подписывается специальным приватным ключом. Срок действия токена равен тайм-ауту задачи, если он указан, или 5 минутам, если он не указан. Ключ, используемый для подписи этого токена, может быть изменен без предварительного уведомления. В таком случае, при повторной попытке задания, создается новый JWT с использованием текущего ключа подписи.
Этот JWT можно использовать для аутентификации на сервере Vault, который настроен на использование метода аутентификации JWT. Для этого необходимо указать базовый URL-адрес GitFlic (например, https://gitflic.ru/vault) на сервере Vault в качестве oidc_discovery_url. Затем сервер сможет получить ключи для проверки вашего токена.
При настройке ролей в Vault, вы можете использовать JWT для ограничения доступа к секретам для каждой задачи CI/CD.
Для взаимодействия с Vault вы можете использовать его клиент CLI, либо выполнять API запросы (с помощью Curl или другого клиента).
Пример работы
Допустим, у вас есть пароли для промежуточной и рабочей баз данных, хранящиеся на сервере Vault, работающем по адресу http://vault.example.com:8200. Ваш промежуточный пароль — pa$$w0rd, а рабочий пароль — real-pa$$w0rd.
$ 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/
Затем создайте политики, которые позволят вам читать эти секреты (по одному для каждого секрета):
$ vault policy write myproject-staging - <<EOF
# Policy name: myproject-staging
#
# Read-only permission on 'secret/myproject/staging/*' path
path "secret/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/myproject/production/*' path
path "secret/myproject/production/*" {
capabilities = [ "read" ]
}
EOF
Success! Uploaded policy: myproject-production
Вам также нужны роли, которые связывают JWT с этими политиками.
Одна для промежуточной базы данных с именем 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": {
"user_login": "myuser"
}
}
EOF
Вторая для рабочей базы данных с именем 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": {
"user_login": "myuser"
}
}
EOF
В данном примере используются связанные требования для указания того, что аутентификация JWT разрешена только с соответствующими значениями для указанных требований.
В сочетании с защищенными ветками вы можете ограничить круг лиц, которые могут аутентифицироваться или читать секреты.
Любое из требований, включенное в JWT, может быть сопоставлено со списком значений в связанных требованиях. Например:
"bound_claims": {
"user_login": ["alice", "bob", "mallory"]
}
"bound_claims": {
"ref_name": ["main", "develop", "test"]
}
-
token_explicit_max_ttl
указывает, что токен, выдаваемый Vault после успешной аутентификации, имеет срок действия в 60 секунд. -
user_claim
указывает псевдоним, созданного Vault при успешном входе в систему.
Ознакомиться с полным списком настроек можно здесь.
Настройка метода аутентификации JWT:
vault write auth/jwt/config \
oidc_discovery_url="http://localhost:8044/vault" \
bound_issuer="http://localhost:8044""
Ознакомиться с полным списком настроек можно в документации для API Vault'a.
В GitFlic создайте следующие переменные CI/CD, чтобы предоставить подробную информацию о вашем сервере Vault:
VAULT_SERVER_URL
— URL-адрес вашего сервера Vault, например https://vault.example.com:8200.VAULT_AUTH_ROLE
— Роль, используемая при попытке аутентификации. Необязательная переменная. Если роль не указана, Vault использует роль по умолчанию, указанную при настройке метода аутентификации.VAULT_AUTH_PATH
— Путь, по которому смонтирован метод аутентификации. Необязательная переменная. По умолчанию —jwt
VAULT_NAMESPACE
– Пространство имен Vault Enterprise, которое будет использоваться для чтения секретов и аутентификации. Необязательная переменная. Если пространство имен не указано, Vault использует корневое пространство имен (/). Этот параметр игнорируется Vault Open Source.
Задача, приведенная ниже, запущенная для ветки по умолчанию, может читать секреты в secret/myproject/staging/
, но не секреты в secret/myproject/production/
:
job_with_secrets:
id_tokens:
VAULT_ID_TOKEN:
aud: https://example.vault.com
secrets:
STAGING_DB_PASSWORD:
vault: secret/myproject/staging/db/password@secrets # авторизация с помощью $VAULT_ID_TOKEN
script:
- access-staging-db.sh --token $STAGING_DB_PASSWORD
В этом примере:
@secrets
— имя хранилища, в котором включены механизмы защиты.secret/myproject/staging/db
— путь к секрету в Vault.password
- поле, которое необходимо получить из указанного секрета.
Ограничения токенов доступа к секретам в Vault
Вы можете контролировать уровень доступа токенов к секретам Vault, используя средства защиты Vault и функции GitFlic. Примеры возможных ограничений:
- Использование
Vault bound claims
для определенных групп с помощьюgroup_claim
. - Жесткое кодирования для
Vault bound claims
, на основеuser_login
иuser_email
конкретных пользователей. - Установка ограничения времени Vault для TTL токена, с помощью
token_explicit_max_ttl
. - Комбинация JWT и функции защиты веток для ограничить круга лиц, которые могут аутентифицироваться или читать секреты.