Vault with k8s v2: различия между версиями

Материал из noname.com.ua
Перейти к навигацииПерейти к поиску
 
(не показана 61 промежуточная версия этого же участника)
Строка 1: Строка 1:
  +
[[Категория:Hashicorp]]
  +
[[Категория:Linux]]
  +
[[Категория:Vault]]
  +
[[Категория:K8s]]
 
=Авторизация K8S POD в Vault=
 
=Авторизация K8S POD в Vault=
   
Строка 23: Строка 27:
 
# После успешной авторизации POD может читать "секреты" из VAULT согласно политик которые привязаны к роле (политики и роли тут - это объекты в Vault)
 
# После успешной авторизации POD может читать "секреты" из VAULT согласно политик которые привязаны к роле (политики и роли тут - это объекты в Vault)
   
  +
<BR><BR>
  +
'''
  +
<big>
  +
Другими словами в качестве пары логин/пароль выступает роль <BR>
  +
(которую POD "знает" из переменных окружения, и которая не является "секретом") <BR>
  +
и токен сервисного аккаунта (к которому имеет доступ только POD запущенный с правами этого сервисного аккаунта)<BR>
  +
</big>
  +
'''
   
=Настройка Vault=
+
=Настройка со стороны k8s=
==Настройка со стороны k8s==
+
Настройка K8S состоит из следующих шагов:
  +
* Создать отдельное пространство имен (опционально: можно использовать default)
===Namespace===
 
  +
* Создать сервисные аккаунт для проверки токенов и назначить ему права
  +
* Создать сервисные аккаунты для запуска POD-ов
  +
==Namespace==
 
* Создать пространство (имен если не создано)
 
* Создать пространство (имен если не создано)
 
* Имя пространства имен выбрано произвольно ('''kilda''' в этом примере)
 
* Имя пространства имен выбрано произвольно ('''kilda''' в этом примере)
Строка 49: Строка 64:
 
</PRE>
 
</PRE>
   
===Сервисный аккаунт===
+
==Сервисный аккаунт для проверки токенов==
   
 
* Это аккаунт с которым Vault подключается к API k8s для валидации JWT
 
* Это аккаунт с которым Vault подключается к API k8s для валидации JWT
Строка 72: Строка 87:
 
</PRE>
 
</PRE>
   
===Права сервисного аккаунта===
+
==Права сервисного аккаунта==
 
* Для того что б аккаунт мог проверить JWT у других сервисных аккаунтов ему назначается '''ClusterRole system:auth-delegator'''
 
* Для того что б аккаунт мог проверить JWT у других сервисных аккаунтов ему назначается '''ClusterRole system:auth-delegator'''
   
Строка 78: Строка 93:
 
Если назначить только в '''kilda-namespace''' то прав для проверки JWT '''<big>недостаточно</big>''' (что совершенно не очевидно из конфигурации)<BR>
 
Если назначить только в '''kilda-namespace''' то прав для проверки JWT '''<big>недостаточно</big>''' (что совершенно не очевидно из конфигурации)<BR>
   
====kilda-namespace====
+
===kilda-namespace===
 
* Права назначаются на аккаунт созданный ранее: '''kilda-vault-token-review-service-account''' в ''' kilda-namespace'''
 
* Права назначаются на аккаунт созданный ранее: '''kilda-vault-token-review-service-account''' в ''' kilda-namespace'''
 
* '''kubectl apply -f kilda-vault-token-review-service-account-role-binding-in-kilda-namespace.yaml'''
 
* '''kubectl apply -f kilda-vault-token-review-service-account-role-binding-in-kilda-namespace.yaml'''
Строка 100: Строка 115:
   
   
====default-namespace====
+
===default-namespace===
 
* Права назначаются на аккаунт созданный ранее: '''kilda-vault-token-review-service-account''' в ''' default-namespace'''
 
* Права назначаются на аккаунт созданный ранее: '''kilda-vault-token-review-service-account''' в ''' default-namespace'''
 
* '''kubectl apply -f kilda-vault-token-review-service-account-role-binding-in-default-namespace.yaml'''
 
* '''kubectl apply -f kilda-vault-token-review-service-account-role-binding-in-default-namespace.yaml'''
 
* Содержимое файла '''kilda-vault-token-review-service-account-role-binding-in-default-namespace.yaml''':
 
* Содержимое файла '''kilda-vault-token-review-service-account-role-binding-in-default-namespace.yaml''':
 
 
 
<PRE>
 
<PRE>
 
---
 
---
Строка 122: Строка 135:
 
namespace: kilda-namespace
 
namespace: kilda-namespace
 
</PRE>
 
</PRE>
  +
===Проверка===
 
====Проверка====
 
 
* Проверить: '''kubectl get clusterRoleBinding'''
 
* Проверить: '''kubectl get clusterRoleBinding'''
 
<PRE>
 
<PRE>
Строка 132: Строка 144:
 
...
 
...
 
</PRE>
 
</PRE>
  +
==Сервисные аккаунты для POD==
 
  +
* Это сервисные аккаунты предназначенные для запуска POD
==Собственно настройка Vault==
 
  +
* Аккаунты будут смаплены на разные политики Vault и иметь разные права доступа (могут читать разные ветки в key/values storage)
 
  +
* Два аккаунта = '''common-service-account''' и '''kilda-service-account''' (имена могут быть любые)
===Доступ к Vault===
 
  +
===common-service-account===
Для настройки Vault потребуется токен с рутовыми правами.
 
  +
* '''kubectl apply -f common-service-account.yaml'''
* Токен для примера (отличается для каждой инсталляции Vault)
 
* В случае https - требуется добавить CA в доверенные (если не добавлен до того)
 
 
<PRE>
 
<PRE>
  +
---
export VAULT_TOKEN="s.pRFenxR9CANXqLtGI0b6fvy3"
 
  +
apiVersion: v1
export VAULT_ADDR="https://vault.domain.tld:8200"
 
  +
kind: ServiceAccount
  +
metadata:
  +
name: common-service-account
  +
namespace: kilda
 
</PRE>
 
</PRE>
  +
===kilda-service-account===
 
  +
* '''kubectl apply -f kilda-service-account.yaml'''
===Включить поддержку k8s в Vault===
 
* Предполагается использование нескольких кластеров с одним Vault, для этого указывается отдельный путь '''-path kilda-fred''' для каждого кластера kubernetes.
 
* Имя пути (в примере '''kilda-fred''') может быть выбрано произвольно
 
 
<PRE>
 
<PRE>
  +
---
vault auth enable -path kilda-fred kubernetes
 
  +
apiVersion: v1
Success! Enabled kubernetes auth method at: kilda-fred/
 
  +
kind: ServiceAccount
  +
metadata:
  +
name: kilda-service-account
  +
namespace: kilda
 
</PRE>
 
</PRE>
  +
* проверка
 
  +
  +
  +
===Провека===
  +
'''kubectl get serviceAccount --namespace kilda'''
 
<PRE>
 
<PRE>
  +
NAME SECRETS AGE
vault auth list
 
Path Type Accessor Description
+
common-service-account 1 15s
---- ---- -------- -----------
+
default 1 160m
  +
kilda-service-account 1 23s
kilda-fred/ kubernetes auth_kubernetes_34db5104 n/a
 
  +
kilda-vault-token-review-service-account 1 155m
...
 
 
</PRE>
 
</PRE>
   
===Получение необходимых секретов из K8S===
+
=Получение необходимых секретов из K8S=
 
* В примере все объекты находятся в отдельном пространстве имен - '''kilda'''
 
* В примере все объекты находятся в отдельном пространстве имен - '''kilda'''
  +
* Токен сервисного аккаунта (нужен для того что бы Vault мог авторизоваться в кластере K8S)
  +
* CA кластера нужен для установки '''https''' соединения (СА может быть получен и из конфига kubecl)
   
====Получение имени "секрета"====
+
==Получение имени "секрета"==
 
* Получить имя "секрета" для сервисного аккаунта '''kilda-vault-token-review-service-account'''
 
* Получить имя "секрета" для сервисного аккаунта '''kilda-vault-token-review-service-account'''
 
* '''kilda-vault-token-review-service-account''' это аккаунт с которым Vault подключается к API k8s для валидации JWT (создан выше)
 
* '''kilda-vault-token-review-service-account''' это аккаунт с которым Vault подключается к API k8s для валидации JWT (создан выше)
Строка 207: Строка 230:
   
   
====Получение данных из "секрета"====
+
==Получение данных из "секрета"==
 
* имя секрета получено на предыдущем шаге - '''kilda-vault-token-review-service-account-token-sdz49'''
 
* имя секрета получено на предыдущем шаге - '''kilda-vault-token-review-service-account-token-sdz49'''
 
* не забывать что используется отдельное пространство имен - '''kilda'''
 
* не забывать что используется отдельное пространство имен - '''kilda'''
=====Токен=====
+
===Токен===
 
Зная имя секрета можно получить его токен:
 
Зная имя секрета можно получить его токен:
 
<PRE>
 
<PRE>
Строка 252: Строка 275:
 
eyJhbGciOiJSU <тут вырезано >MT3cuTbiL7rZr8oiBM331iCpZ6BK-nybCpptg3lnKOnjJbs26HoMGIY2_DvunNo_TiHRzq03h3z344F5SAqgEe27LWtaiGD1xA
 
eyJhbGciOiJSU <тут вырезано >MT3cuTbiL7rZr8oiBM331iCpZ6BK-nybCpptg3lnKOnjJbs26HoMGIY2_DvunNo_TiHRzq03h3z344F5SAqgEe27LWtaiGD1xA
 
</PRE>
 
</PRE>
===== CA =====
+
=== CA ===
 
* В том же секрете содержится сертификат СА
 
* В том же секрете содержится сертификат СА
 
* Этот же сертификат содержится в конфиге kubectl
 
* Этот же сертификат содержится в конфиге kubectl
Строка 273: Строка 296:
 
</PRE>
 
</PRE>
   
===Настройка доступа Vault в K8S===
+
=Настройка Vault=
  +
* настроить доступ к Vault (авторизация требует рутовых прав)
  +
* создать политики доступа
  +
* включить авторизацию через k8s
  +
  +
==Доступ к Vault==
  +
Для настройки Vault потребуется токен с рутовыми правами.
  +
* Токен для примера (отличается для каждой инсталляции Vault)
  +
* В случае https - требуется добавить CA в доверенные (если не добавлен до того)
  +
<PRE>
  +
export VAULT_TOKEN="s.pRFenxR9CANXqLtGI0b6fvy3"
  +
export VAULT_ADDR="https://vault.domain.tld:8200"
  +
</PRE>
  +
  +
==Создание политик доступа==
  +
* Cоздаем 2 политики:
  +
** kilda-policy для аккаунта kilda-service-account
  +
** kv-common-policy для аккаунта common-service-account
  +
===kilda-policy===
  +
Используем предсозданнную политику - https://noname.com.ua/mediawiki/index.php/Vault_Basic_Setup#.D0.9F.D0.BE.D0.BB.D0.B8.D1.82.D0.B8.D0.BA.D0.B8_.D0.B4.D0.BB.D1.8F_KV
  +
===kv-common-policy===
  +
Аналогично
  +
<PRE>
  +
path "kv/data/common/*" {
  +
capabilities = ["read", "list", "create", "update"]
  +
}
  +
  +
path "kv/data/common/readonly/*" {
  +
capabilities = ["read"]
  +
}
  +
  +
path "kv/data/common/readonly" {
  +
capabilities = ["read"]
  +
}
  +
  +
path "kv/data/common/read_and_update/*" {
  +
capabilities = ["read", "update"]
  +
}
  +
  +
path "kv/data/common/read_and_update" {
  +
capabilities = ["read", "update"]
  +
}
  +
  +
path "kv/data/common/noaccess" {
  +
capabilities = ["deny"]
  +
}
  +
</PRE>
  +
===Просмотр политик===
  +
<PRE>
  +
vault policy list
  +
</PRE>
  +
<PRE>
  +
default
  +
kilda-policy
  +
kv-common-policy
  +
root
  +
</PRE>
  +
  +
<PRE>
  +
vault policy read kilda-policy
  +
</PRE>
  +
<PRE>
  +
path "kv/data/kilda/*" {
  +
capabilities = ["read", "list", "create", "update"]
  +
}
  +
  +
  +
path "kv/data/kilda/readonly/*" {
  +
capabilities = ["read"]
  +
}
  +
  +
path "kv/data/kilda/read_and_update/*" {
  +
capabilities = ["read", "update"]
  +
}
  +
  +
path "kv/data/kilda/read_and_update" {
  +
capabilities = ["read", "update"]
  +
}
  +
  +
  +
path "kv/data/kilda/noaccess" {
  +
capabilities = ["deny"]
  +
}
  +
</PRE>
  +
  +
==Включить поддержку k8s в Vault==
  +
* Предполагается использование нескольких кластеров с одним Vault, для этого указывается отдельный путь '''-path kilda-fred''' для каждого кластера kubernetes.
  +
* Имя пути (в примере '''kilda-fred''') может быть выбрано произвольно
  +
<PRE>
  +
vault auth enable -path kilda-fred kubernetes
  +
Success! Enabled kubernetes auth method at: kilda-fred/
  +
</PRE>
  +
* проверка
  +
<PRE>
  +
vault auth list
  +
Path Type Accessor Description
  +
---- ---- -------- -----------
  +
kilda-fred/ kubernetes auth_kubernetes_34db5104 n/a
  +
...
  +
</PRE>
  +
  +
==Настройка доступа Vault в K8S==
  +
  +
На этом шаге указывается к какому кластеру "ходить" за проверкой, и с каким токеном авторизоваться в этом кластере
   
 
* ACCOUNT_TOKEN - получен на предыдущем шаге
 
* ACCOUNT_TOKEN - получен на предыдущем шаге
Строка 305: Строка 431:
 
</PRE>
 
</PRE>
   
  +
==Назначение политик Vault для сервисных аккаунтов==
======11111======
 
  +
* назначаются политики на 2 сервисных аккауната '''kilda-service-account''' и '''common-service-account '''
Обратить внимание:
 
Service Account - это аккаунт с которым будет деплоиться POD. Это аккаунт в k8s а не в Vault.
+
* Service Account - это аккаунт с которым будет деплоиться POD. Это аккаунт в k8s а не в Vault. (созданы при настройке k8s выше)
Роль существует только в пределах Vault (а не в K8S)
+
* Роль существует только в пределах Vault (а не в K8S)
При авторизации POD запрашивает токен для роли
+
* При авторизации POD запрашивает '''токен Vault''' для роли используя для авторизации '''токен service account из k8s'''
На токен будут назначены политики из привязки
+
* На '''токен vault ''' будут назначены политики vault из роли
  +
Привязка сервисных аккаунтов K8S к ролям Vault[править]
 
  +
export VAULT_K8S_SERVICE_ACCOUNT="k8s-test-service-account"
 
  +
export VAULT_K8S_ROLE="k8s-test-role"
 
  +
'''Другими словами в качестве пары логин/пароль выступает роль (которую POD "знает" из переменных окружения, и которая не является "секретом") и токен сервисного аккаунта (к которому имеет доступ только POD запущенный с правами этого сервисного аккаунта)'''
Здесь VAULT_K8S_SERVICE_ACCOUNT - это сервисный аккаунт в k8s который можно создать например так:
 
  +
===kilda-service-account===
---
 
  +
Назначаются 3 политики vault : kilda-policy,kv-common-policy,default
apiVersion: v1
 
  +
<PRE>
kind: ServiceAccount
 
  +
export NAMESPACE="kilda"
metadata:
 
name: k8s-service-account
+
export VAULT_K8S_SERVICE_ACCOUNT="kilda-service-account"
  +
export VAULT_K8S_ROLE="kilda-role"
namespace: my-namespace-name
 
  +
export POLICIES="kilda-policy,kv-common-policy,default"
Важно: Это сервисный аккаунт для запуска PODов, и это НЕ ТОТ сервисный аккаунт который используется Vault
 
  +
Создать привязку
 
 
vault \
 
vault \
 
write \
 
write \
auth/kubernetes/role/${VAULT_K8S_ROLE} \
+
auth/kilda-fred/role/${VAULT_K8S_ROLE} \
 
bound_service_account_names=${VAULT_K8S_SERVICE_ACCOUNT} \
 
bound_service_account_names=${VAULT_K8S_SERVICE_ACCOUNT} \
 
bound_service_account_namespaces=${NAMESPACE} \
 
bound_service_account_namespaces=${NAMESPACE} \
policies=policy1,policy2,default \
+
policies=kilda-policy,kv-common-policy,default \
  +
</PRE>
ttl=1h
 
Обратить внимание - политики policy1,policy2 уже существуют (созданы до этого). Если политик нет их необходимо создать.
 
   
  +
===common-service-account===
 
=111=
 
 
<PRE>
 
<PRE>
  +
export NAMESPACE="kilda"
---
 
  +
export VAULT_K8S_SERVICE_ACCOUNT="common-service-account"
apiVersion: v1
 
  +
export VAULT_K8S_ROLE="common-role"
kind: ServiceAccount
 
  +
export POLICIES="kv-common-policy,default"
metadata:
 
  +
name: kilda-service-account
 
  +
vault \
namespace: kilda
 
  +
write \
</PRE>
 
  +
auth/kilda-fred/role/${VAULT_K8S_ROLE} \
  +
bound_service_account_names=${VAULT_K8S_SERVICE_ACCOUNT} \
  +
bound_service_account_namespaces=${NAMESPACE} \
  +
policies=kv-common-policy,default \
  +
ttl=1h
   
<PRE>
 
---
 
apiVersion: v1
 
kind: ServiceAccount
 
metadata:
 
name: common-service-account
 
namespace: kilda
 
 
</PRE>
 
</PRE>
   
  +
=Тестирование=
  +
==План тестирования==
   
  +
# запустить POD в сервисном аккаунте kilda-service-account
<PRE>
 
  +
# авторизоваться в Vault используя токен сервисного аккаунта
  +
# Проверить возможность чтения из разрешенных путей key/value
  +
# Проверить невозможность чтения из запрещенных путей key/value
   
  +
# запустить POD в сервисном аккаунте common-service-account
kubectl apply -f kilda-service-account.yaml
 
  +
# авторизоваться в Vault используя токен сервисного аккаунта
serviceaccount/kilda-service-account created
 
  +
# Проверить возможность чтения из разрешенных путей key/value
  +
# Проверить невозможность чтения из запрещенных путей key/value
   
kubectl apply -f common-service-account.yaml
 
serviceaccount/common-service-account created
 
   
kubectl get serviceAccount --namespace kilda
 
NAME SECRETS AGE
 
common-service-account 1 15s
 
default 1 160m
 
kilda-service-account 1 23s
 
kilda-vault-token-review-service-account 1 155m
 
</PRE>
 
 
=Тестирование=
 
 
<PRE>
 
<PRE>
 
vault kv put kv/common/somepath commonkey=commonvalue
 
vault kv put kv/common/somepath commonkey=commonvalue
Строка 380: Строка 498:
 
</PRE>
 
</PRE>
   
  +
==Проверка kilda-service-account==
==Создание POD==
 
  +
===Создание POD===
 
  +
'''kubectl apply -f pod-kilda-service-account.yaml'''
 
 
<PRE>
 
<PRE>
 
apiVersion: v1
 
apiVersion: v1
Строка 393: Строка 511:
 
spec:
 
spec:
 
serviceAccountName: "kilda-service-account"
 
serviceAccountName: "kilda-service-account"
  +
hostAliases:
  +
- ip: "10.14.15.201"
  +
hostnames:
  +
- "vault.domain.tld.com"
 
containers:
 
containers:
 
- name: web
 
- name: web
Строка 400: Строка 522:
 
env:
 
env:
 
- name: VAULT_K8S_ROLE
 
- name: VAULT_K8S_ROLE
value: "kilda-role"
+
value: "common-role"
 
- name: VAULT_ADDR
 
- name: VAULT_ADDR
 
value: "https://vault.domain.tld:8200"
 
value: "https://vault.domain.tld:8200"
  +
- name: VAULT_AUTH_PATH
  +
value: "kilda-fred"
 
</PRE>
 
</PRE>
   
  +
===Авторизация в Vault===
 
  +
* Все действия из контейнера
 
 
 
<PRE>
 
<PRE>
kubectl apply -f pod-kilda-service-account.yaml
+
kubectl --namespace kilda exec -ti test-kilda-service-acc -- bash
pod/test-kilda-service-acc created
 
 
</PRE>
 
</PRE>
  +
* Получение токена '''сервисного аккаунта k8'''
 
  +
<PRE>
 
  +
export JWT="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"
kubectl --namespace kilda exec -ti test-kilda-service-acc -- bash
 
  +
</PRE>
 
  +
* Просмотре переменных окружения
 
  +
<PRE>
env | grep VAULT
 
  +
env | grep VAULT
 
VAULT_K8S_ROLE=kilda-role
 
VAULT_K8S_ROLE=kilda-role
 
VAULT_ADDR=https://vault.domain.tld:8200
 
VAULT_ADDR=https://vault.domain.tld:8200
  +
VAULT_K8S_ROLE=kilda-role
  +
VAULT_AUTH_PATH=kilda-fred
  +
</PRE>
   
  +
* Авторизация в Vault используя роль и токен сервисного аккаунта: получение токена
   
  +
'''vault write auth/kilda-fred/login role=${VAULT_K8S_ROLE} jwt=${JWT}'''
 
 
<PRE>
 
<PRE>
root@test-kilda-service-acc:~# vault write auth/kilda-fred/login role=${VAULT_K8S_ROLE} jwt=${JWT}
 
 
Key Value
 
Key Value
 
--- -----
 
--- -----
Строка 439: Строка 565:
 
token_meta_service_account_secret_name n/a
 
token_meta_service_account_secret_name n/a
 
token_meta_service_account_uid 50b15622-38d9-4725-96b1-1c56f4ca0da1
 
token_meta_service_account_uid 50b15622-38d9-4725-96b1-1c56f4ca0da1
  +
</PRE>
root@test-kilda-service-acc:~# vault token lookup
 
  +
* логин с использованием токена
Error looking up token: Error making API request.
 
 
URL: GET https://vault.fred.in.pn.telstra.com:8200/v1/auth/token/lookup-self
 
Code: 400. Errors:
 
 
* missing client token
 
root@test-kilda-service-acc:~# vault login s.vGsxWHAW9xHzdryEHolw3Xw1
 
Success! You are now authenticated. The token information displayed below
 
is already stored in the token helper. You do NOT need to run "vault login"
 
again. Future Vault requests will automatically use this token.
 
   
  +
'''vault login s.vGsxWHAW9xHzdryEHolw3Xw1'''
  +
<PRE>
 
Key Value
 
Key Value
 
--- -----
 
--- -----
Строка 465: Строка 584:
 
token_meta_service_account_secret_name n/a
 
token_meta_service_account_secret_name n/a
 
token_meta_service_account_uid 50b15622-38d9-4725-96b1-1c56f4ca0da1
 
token_meta_service_account_uid 50b15622-38d9-4725-96b1-1c56f4ca0da1
  +
</PRE>
root@test-kilda-service-acc:~# vault token lookup
 
  +
* Просмотр токена и его прав ( в том числе политик)
  +
* результат соответсвует ожидаемому: '''policies [default kilda-policy kv-common-policy]'''
  +
  +
'''vault token lookup'''
  +
<PRE>
 
Key Value
 
Key Value
 
--- -----
 
--- -----
Строка 485: Строка 609:
 
ttl 59m21s
 
ttl 59m21s
 
type service
 
type service
  +
</PRE>
root@test-kilda-service-acc:~# vault vault kv get kv/kilda/subpath^C
 
  +
root@test-kilda-service-acc:~# vault kv get kv/kilda/subpath
 
  +
===Проверить возможность чтения из разрешенных путей key/value===
  +
'''vault kv get kv/kilda/subpath''' (чтение возможно - результат соответсвует ожиданием)
  +
<PRE>
 
======= Metadata =======
 
======= Metadata =======
 
Key Value
 
Key Value
Строка 500: Строка 627:
 
--- -----
 
--- -----
 
somekey somedata
 
somekey somedata
  +
</PRE>
root@test-kilda-service-acc:~# vault kv get kv/common/somepath
 
  +
  +
'''vault kv get kv/common/somepath''' (чтение возможно - результат соответсвует ожиданием)
  +
<PRE>
 
======= Metadata =======
 
======= Metadata =======
 
Key Value
 
Key Value
Строка 515: Строка 645:
 
commonkey commonvalue
 
commonkey commonvalue
 
</PRE>
 
</PRE>
  +
  +
===Проверить невозможность чтения из запрещенных путей key/value===
  +
'''vault kv get kv/kilda/noaccess''' (чтение '''НЕ''' возможно - результат соответсвует ожиданием)
  +
<PRE>
  +
Error reading kv/data/kilda/noaccess: Error making API request.
  +
  +
URL: GET https://vault.domain.tld:8200/v1/kv/data/kilda/noaccess
  +
Code: 403. Errors:
  +
  +
* 1 error occurred:
  +
* permission denied
  +
</PRE>
  +
  +
==Проверка common-service-account==
  +
===Создание POD===
  +
'''kubectl apply -f pod-common-service-account.yaml'''
  +
<PRE>
  +
apiVersion: v1
  +
kind: Pod
  +
metadata:
  +
name: test-common-service-acc
  +
namespace: kilda
  +
labels:
  +
role: test
  +
spec:
  +
serviceAccountName: "common-service-account"
  +
hostAliases:
  +
- ip: "10.14.15.201"
  +
hostnames:
  +
- "vault.domain.tld"
  +
containers:
  +
- name: web
  +
image: ubuntu:20.04
  +
imagePullPolicy: Always
  +
command: ["sleep", "3600000"]
  +
env:
  +
- name: VAULT_K8S_ROLE
  +
value: "common-role"
  +
- name: VAULT_ADDR
  +
value: "https://vault.domain.tld:8200"
  +
- name: VAULT_AUTH_PATH
  +
value: "kilda-fred"
  +
</PRE>
  +
  +
===Авторизация в Vault===
  +
* Все действия из контейнера
  +
<PRE>
  +
kubectl --namespace kilda exec -ti test-common-service-acc -- bash
  +
</PRE>
  +
* Получение токена '''сервисного аккаунта k8'''
  +
<PRE>
  +
export JWT="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"
  +
</PRE>
  +
* Просмотре переменных окружения
  +
<PRE>
  +
env | grep VAULT
  +
VAULT_K8S_ROLE=common-role
  +
VAULT_ADDR=https://vault.domain.tld:8200
  +
VAULT_AUTH_PATH=kilda-fred
  +
</PRE>
  +
  +
* Авторизация в Vault используя роль и токен сервисного аккаунта: получение токена
  +
  +
'''vault write auth/kilda-fred/login role=${VAULT_K8S_ROLE} jwt=${JWT}'''
  +
<PRE>
  +
Key Value
  +
--- -----
  +
token s.fj4OxBwSn3jJjZ1FECwxSS6D
  +
token_accessor 7TOZSFyiCRnTeAydmUxlKdLb
  +
token_duration 1h
  +
token_renewable true
  +
token_policies ["default" "kv-common-policy"]
  +
identity_policies []
  +
policies ["default" "kv-common-policy"]
  +
token_meta_service_account_name common-service-account
  +
token_meta_service_account_namespace kilda
  +
token_meta_service_account_secret_name n/a
  +
token_meta_service_account_uid 70f30a0a-4efb-4356-b90d-be9210f47117
  +
token_meta_role common-role
  +
</PRE>
  +
* логин с использованием токена
  +
  +
'''vault login s.fj4OxBwSn3jJjZ1FECwxSS6D'''
  +
<PRE>
  +
Key Value
  +
--- -----
  +
token s.fj4OxBwSn3jJjZ1FECwxSS6D
  +
token_accessor 7TOZSFyiCRnTeAydmUxlKdLb
  +
token_duration 59m18s
  +
token_renewable true
  +
token_policies ["default" "kv-common-policy"]
  +
identity_policies []
  +
policies ["default" "kv-common-policy"]
  +
token_meta_service_account_secret_name n/a
  +
token_meta_service_account_uid 70f30a0a-4efb-4356-b90d-be9210f47117
  +
token_meta_role common-role
  +
token_meta_service_account_name common-service-account
  +
token_meta_service_account_namespace kilda
  +
  +
</PRE>
  +
* Просмотр токена и его прав ( в том числе политик)
  +
* результат соответсвует ожидаемому: '''policies [default kilda-policy kv-common-policy]'''
  +
  +
'''vault token lookup'''
  +
<PRE>
  +
Key Value
  +
--- -----
  +
accessor 7TOZSFyiCRnTeAydmUxlKdLb
  +
creation_time 1644506420
  +
creation_ttl 1h
  +
display_name kilda-fred-kilda-common-service-account
  +
entity_id 522a6514-5e13-44d8-0377-c213154e0d44
  +
expire_time 2022-02-10T16:20:20.254743135Z
  +
explicit_max_ttl 0s
  +
id s.fj4OxBwSn3jJjZ1FECwxSS6D
  +
issue_time 2022-02-10T15:20:20.254757455Z
  +
meta map[role:common-role service_account_name:common-service-account service_account_namespace:kilda service_account_secret_name: service_account_uid:70f30a0a-4efb-4356-b90d-be9210f47117]
  +
num_uses 0
  +
orphan true
  +
path auth/kilda-fred/login
  +
policies [default kv-common-policy]
  +
renewable true
  +
ttl 58m33s
  +
type service
  +
</PRE>
  +
  +
===Проверить возможность чтения из разрешенных путей key/value===
  +
  +
'''vault kv get kv/common/somepath''' (чтение возможно - результат соответсвует ожиданием)
  +
<PRE>
  +
======= Metadata =======
  +
Key Value
  +
--- -----
  +
created_time 2022-02-09T14:23:30.169927438Z
  +
custom_metadata <nil>
  +
deletion_time n/a
  +
destroyed false
  +
version 1
  +
  +
====== Data ======
  +
Key Value
  +
--- -----
  +
commonkey commonvalue
  +
</PRE>
  +
  +
===Проверить невозможность чтения из запрещенных путей key/value===
  +
'''vault kv get kv/kilda/subpath'''
  +
(чтение '''НЕ''' возможно - результат соответсвует ожиданием)
  +
<PRE>
  +
  +
Error reading kv/data/kilda/subpath: Error making API request.
  +
  +
URL: GET https://vault.domain.tld:8200/v1/kv/data/kilda/subpath
  +
Code: 403. Errors:
  +
* 1 error occurred:
  +
* permission denied
  +
</PRE>
  +
  +
=Выводы=
  +
  +
* Сервисный аккаунт kilda-service-account имеет доступ к k/v '''kv/kilda/*''' и '''kv/common/*'''
  +
* Сервисный аккаунт common-service-account имеет доступ к k/v ''kv/common/*''' и не имеет доступа к '''k/v '''kv/kilda/*'''
  +
* те все работает так как должно

Текущая версия на 08:41, 30 октября 2023

Авторизация K8S POD в Vault

Постановка задачи

  • Получать "секреты" из Vault при этом не передавая в POD пароли, токены или другую секретную информацию

Предварительны условия

  • Установлен и настроен Vault

(базовая настройка - https://noname.com.ua/mediawiki/index.php/Vault_Basic_Setup)

  • кластер Kubernetes установлен и настроен
  • kubectl настроен для работы с кластером

Принципы работы

  1. Создается один или несколько Service Account
  2. POD запускается в определенном Service Account
  3. POD может воспользоваться токеном этого Service Account
  4. В качестве входных данных POD получает НЕ СЕКРЕТНУЮ информацию
    1. Адрес Vault в переменной окружения VAULT_ADDR
    2. Имя роли в переменной окружения VAULT_K8S_ROLE
  5. POD авторизуется в VAULT под ролью переданной в переменной VAULT_K8S_ROLE используя для этого JWT принадлежащий Service Account
  6. Vault настроен на проверку прав токена PODs в API K8S (Сам процесс VAULT использует ДРУГОЙ сервисный аккаунт, отличный от того под которым запускается POD для проверки токена PODa)
  7. После успешной авторизации POD может читать "секреты" из VAULT согласно политик которые привязаны к роле (политики и роли тут - это объекты в Vault)



Другими словами в качестве пары логин/пароль выступает роль
(которую POD "знает" из переменных окружения, и которая не является "секретом")
и токен сервисного аккаунта (к которому имеет доступ только POD запущенный с правами этого сервисного аккаунта)

Настройка со стороны k8s

Настройка K8S состоит из следующих шагов:

  • Создать отдельное пространство имен (опционально: можно использовать default)
  • Создать сервисные аккаунт для проверки токенов и назначить ему права
  • Создать сервисные аккаунты для запуска POD-ов

Namespace

  • Создать пространство (имен если не создано)
  • Имя пространства имен выбрано произвольно (kilda в этом примере)
  • kubectl apply -f kilda-namespace.yaml
  • Содержимое kilda-namespace.yaml:
---
apiVersion: v1
kind: Namespace
metadata:
  name: kilda
  • проверка: kubectl get namespaces
NAME              STATUS   AGE
default           Active   56d
kilda             Active   7s
kube-public       Active   56d
kube-system       Active   56d
metallb-system    Active   56d
...

Сервисный аккаунт для проверки токенов

  • Это аккаунт с которым Vault подключается к API k8s для валидации JWT
  • Этот аккаунт отличается от того который используется для запуска POD
  • Создается в правильном пространстве имен (в частном случае может использоваться default)
  • Имя аккаунта выбрано произвольно
  • kubectl apply -f kilda-vault-token-review-service-account.yaml
  • Содержимое файла kilda-vault-token-review-service-account.yaml:
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: kilda-vault-token-review-service-account
  namespace: kilda
  • Проверка: kubectl get serviceAccount --namespace kilda
NAME                                       SECRETS   AGE
default                                    1         9m12s
kilda-vault-token-review-service-account   1         3m37s

Права сервисного аккаунта

  • Для того что б аккаунт мог проверить JWT у других сервисных аккаунтов ему назначается ClusterRole system:auth-delegator

Важно: Назначить права нужно в 2 пространствах имен
Если назначить только в kilda-namespace то прав для проверки JWT недостаточно (что совершенно не очевидно из конфигурации)

kilda-namespace

  • Права назначаются на аккаунт созданный ранее: kilda-vault-token-review-service-account в kilda-namespace
  • kubectl apply -f kilda-vault-token-review-service-account-role-binding-in-kilda-namespace.yaml
  • Содержимое файла kilda-vault-token-review-service-account-role-binding-in-kilda-namespace.yaml:
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kilda-vault-token-review-service-account-role-binding-in-kilda-namespace
  namespace: kilda
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:auth-delegator
subjects:
- kind: ServiceAccount
  name: kilda-vault-token-review-service-account
  namespace: kilda


default-namespace

  • Права назначаются на аккаунт созданный ранее: kilda-vault-token-review-service-account в default-namespace
  • kubectl apply -f kilda-vault-token-review-service-account-role-binding-in-default-namespace.yaml
  • Содержимое файла kilda-vault-token-review-service-account-role-binding-in-default-namespace.yaml:
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kilda-vault-token-review-service-account-role-binding-in-default-namespace
  namespace: default
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:auth-delegator
subjects:
- kind: ServiceAccount
  name: kilda-vault-token-review-service-account
  namespace: kilda-namespace

Проверка

  • Проверить: kubectl get clusterRoleBinding
NAME                                                                         ROLE
...
kilda-vault-token-review-service-account-role-binding-in-default-namespace   ClusterRole/system:auth-delegator
kilda-vault-token-review-service-account-role-binding-in-kilda-namespace     ClusterRole/system:auth-delegator
...

Сервисные аккаунты для POD

  • Это сервисные аккаунты предназначенные для запуска POD
  • Аккаунты будут смаплены на разные политики Vault и иметь разные права доступа (могут читать разные ветки в key/values storage)
  • Два аккаунта = common-service-account и kilda-service-account (имена могут быть любые)

common-service-account

  • kubectl apply -f common-service-account.yaml
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: common-service-account
  namespace: kilda

kilda-service-account

  • kubectl apply -f kilda-service-account.yaml
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: kilda-service-account
  namespace: kilda


Провека

kubectl get serviceAccount --namespace kilda

NAME                                       SECRETS   AGE
common-service-account                     1         15s
default                                    1         160m
kilda-service-account                      1         23s
kilda-vault-token-review-service-account   1         155m

Получение необходимых секретов из K8S

  • В примере все объекты находятся в отдельном пространстве имен - kilda
  • Токен сервисного аккаунта (нужен для того что бы Vault мог авторизоваться в кластере K8S)
  • CA кластера нужен для установки https соединения (СА может быть получен и из конфига kubecl)

Получение имени "секрета"

  • Получить имя "секрета" для сервисного аккаунта kilda-vault-token-review-service-account
  • kilda-vault-token-review-service-account это аккаунт с которым Vault подключается к API k8s для валидации JWT (создан выше)
kubectl \
    --namespace kilda \
    get \
    serviceaccount \
    kilda-vault-token-review-service-account \
   -o json
{
  "apiVersion": "v1",
  "kind": "ServiceAccount",
  "metadata": {
    "annotations": {
      "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"ServiceAccount\",\"metadata\":{\"annotations\":{},\"name\":\"kilda-vault-token-review-service-account\",\"namespace\":\"kilda\"}}\n"
    },
    "creationTimestamp": "2022-02-09T10:17:40Z",
    "name": "kilda-vault-token-review-service-account",
    "namespace": "kilda",
    "resourceVersion": "8768345",
    "uid": "33b39f30-ba7e-4ef3-a12d-59e0cee9abee"
  },
  "secrets": [
    {
      "name": "kilda-vault-token-review-service-account-token-sdz49"
    }
  ]
}

Тут имя секрета =.secrets[0].name, его можно получить одной командой непосредственно используя jq или встроенную в kubectl фильтрацию

kubectl \
    --namespace kilda \
    get \
    serviceaccount \
    kilda-vault-token-review-service-account \
   -o jsonpath='{.secrets[0].name}'

Результат - kilda-vault-token-review-service-account-token-sdz49


Получение данных из "секрета"

  • имя секрета получено на предыдущем шаге - kilda-vault-token-review-service-account-token-sdz49
  • не забывать что используется отдельное пространство имен - kilda

Токен

Зная имя секрета можно получить его токен:

kubectl \
    --namespace kilda  \
    get \
    secret kilda-vault-token-review-service-account-token-sdz49 \
    -o json
  • Пример вывода (длинные поля заменены описанием для простоты):
{
  "apiVersion": "v1",
  "data": {
    "ca.crt": "<тут base64-encoded CA>=",
    "namespace": "a2lsZGE=",
    "token": "<тут тут base64-encoded tocken>"
  },
  "kind": "Secret",
  "metadata": {
    "annotations": {
      "kubernetes.io/service-account.name": "kilda-vault-token-review-service-account",
      "kubernetes.io/service-account.uid": "33b39f30-ba7e-4ef3-a12d-59e0cee9abee"
    },
    "creationTimestamp": "2022-02-09T10:17:40Z",
    "name": "kilda-vault-token-review-service-account-token-sdz49",
    "namespace": "kilda",
    "resourceVersion": "8768344",
    "uid": "e509252c-3e36-4344-930f-9e988156442c"
  },
  "type": "kubernetes.io/service-account-token"
}

Здесь интересует поле .data - можно получить одной командой, не сохраняя промежуточные данные

kubectl --namespace kilda get secret kilda-vault-token-review-service-account-token-sdz49 -o jsonpath='{.data.token}' | base64 -d

Токен выглядит примерно так:

eyJhbGciOiJSU <тут вырезано >MT3cuTbiL7rZr8oiBM331iCpZ6BK-nybCpptg3lnKOnjJbs26HoMGIY2_DvunNo_TiHRzq03h3z344F5SAqgEe27LWtaiGD1xA

CA

  • В том же секрете содержится сертификат СА
  • Этот же сертификат содержится в конфиге kubectl
kubectl \
    --namespace kilda \
    get \
    secret kilda-vault-token-review-service-account-token-sdz49 \
    -o jsonpath="{.data['ca\.crt']}" \
    | base64 --decode;
-----BEGIN CERTIFICATE-----
MIIDADCCAeigAwIBAgIUXvcRvJKO5x/sOIXOxVD2VIQXY3QwDQYJKoZIhvcNAQEL
BQAwGDEWMBQGA1UEAxMNa3ViZXJuZXRlcy1jYTAeFw0yMTEyMTQxNjQ5MDBaFw0z
<skipped>
eTh8bGZMYcccstj+sPLyprG8bueXzo6hDgaKkz4NXKlgP/b1gB/uycVKuS351mxF
qOY4fQ==
-----END CERTIFICATE-----

Настройка Vault

  • настроить доступ к Vault (авторизация требует рутовых прав)
  • создать политики доступа
  • включить авторизацию через k8s

Доступ к Vault

Для настройки Vault потребуется токен с рутовыми правами.

  • Токен для примера (отличается для каждой инсталляции Vault)
  • В случае https - требуется добавить CA в доверенные (если не добавлен до того)
export VAULT_TOKEN="s.pRFenxR9CANXqLtGI0b6fvy3"
export VAULT_ADDR="https://vault.domain.tld:8200"

Создание политик доступа

  • Cоздаем 2 политики:
    • kilda-policy для аккаунта kilda-service-account
    • kv-common-policy для аккаунта common-service-account

kilda-policy

Используем предсозданнную политику - https://noname.com.ua/mediawiki/index.php/Vault_Basic_Setup#.D0.9F.D0.BE.D0.BB.D0.B8.D1.82.D0.B8.D0.BA.D0.B8_.D0.B4.D0.BB.D1.8F_KV

kv-common-policy

Аналогично

path "kv/data/common/*" {
  capabilities = ["read", "list", "create", "update"]
}

path "kv/data/common/readonly/*" {
  capabilities = ["read"]
}

path "kv/data/common/readonly" {
  capabilities = ["read"]
}

path "kv/data/common/read_and_update/*" {
  capabilities = ["read", "update"]
}

path "kv/data/common/read_and_update" {
  capabilities = ["read", "update"]
}

path "kv/data/common/noaccess" {
 capabilities = ["deny"]
}

Просмотр политик

vault policy list
default
kilda-policy
kv-common-policy
root
vault policy read kilda-policy
path "kv/data/kilda/*" {
  capabilities = ["read", "list", "create", "update"]
}


path "kv/data/kilda/readonly/*" {
  capabilities = ["read"]
}

path "kv/data/kilda/read_and_update/*" {
  capabilities = ["read", "update"]
}

path "kv/data/kilda/read_and_update" {
  capabilities = ["read", "update"]
}


path "kv/data/kilda/noaccess" {
 capabilities = ["deny"]
}

Включить поддержку k8s в Vault

  • Предполагается использование нескольких кластеров с одним Vault, для этого указывается отдельный путь -path kilda-fred для каждого кластера kubernetes.
  • Имя пути (в примере kilda-fred) может быть выбрано произвольно
vault auth enable -path kilda-fred  kubernetes
Success! Enabled kubernetes auth method at: kilda-fred/
  • проверка
vault auth list
Path           Type          Accessor                    Description
----           ----          --------                    -----------
kilda-fred/    kubernetes    auth_kubernetes_34db5104    n/a
...

Настройка доступа Vault в K8S

На этом шаге указывается к какому кластеру "ходить" за проверкой, и с каким токеном авторизоваться в этом кластере

  • ACCOUNT_TOKEN - получен на предыдущем шаге
  • API - адрес API kubernetes
  • SERVICE_ACCOUNT_CA_CRT - CA (получен на предыдущем шаге или взят из конфигурации kubectl - это один и тот же CA)
  • kilda-fred - это путь указаный ранее
#!/bin/bash

ACCOUNT_TOKEN="eyJhbGci<skipped>uZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImtpbGRhLXZhd
API="https://https://vault.domain.tld::6443"

SERVICE_ACCOUNT_CA_CRT="-----BEGIN CERTIFICATE-----
MIIDADCCAeigAwIBAgIUXvcRvJKO5x/sOIXOxVD2VIQXY3QwDQYJKoZIhvcNAQEL
<Skipped>
PVGSuNobYcdns4Z+E1O2QLYbnoDsLd+sqf0r9aaFSZQZry8bP783VCuBXg6Zy0BR
eTh8bGZMYcccstj+sPLyprG8bueXzo6hDgaKkz4NXKlgP/b1gB/uycVKuS351mxF
qOY4fQ==
-----END CERTIFICATE-----
"

vault \
    write \
    auth/kilda-fred/config \
    kubernetes_host="${API}" \
    kubernetes_ca_cert="${SERVICE_ACCOUNT_CA_CRT}" \
    token_reviewer_jwt="${ACCOUNT_TOKEN}"
Success! Data written to: auth/kilda-fred/config

Назначение политик Vault для сервисных аккаунтов

  • назначаются политики на 2 сервисных аккауната kilda-service-account и common-service-account
  • Service Account - это аккаунт с которым будет деплоиться POD. Это аккаунт в k8s а не в Vault. (созданы при настройке k8s выше)
  • Роль существует только в пределах Vault (а не в K8S)
  • При авторизации POD запрашивает токен Vault для роли используя для авторизации токен service account из k8s
  • На токен vault будут назначены политики vault из роли


Другими словами в качестве пары логин/пароль выступает роль (которую POD "знает" из переменных окружения, и которая не является "секретом") и токен сервисного аккаунта (к которому имеет доступ только POD запущенный с правами этого сервисного аккаунта)

kilda-service-account

Назначаются 3 политики vault : kilda-policy,kv-common-policy,default

export NAMESPACE="kilda"
export VAULT_K8S_SERVICE_ACCOUNT="kilda-service-account"
export VAULT_K8S_ROLE="kilda-role"
export POLICIES="kilda-policy,kv-common-policy,default"

vault \
    write \
    auth/kilda-fred/role/${VAULT_K8S_ROLE} \
    bound_service_account_names=${VAULT_K8S_SERVICE_ACCOUNT} \
    bound_service_account_namespaces=${NAMESPACE} \
    policies=kilda-policy,kv-common-policy,default \

common-service-account

export NAMESPACE="kilda"
export VAULT_K8S_SERVICE_ACCOUNT="common-service-account"
export VAULT_K8S_ROLE="common-role"
export POLICIES="kv-common-policy,default"

vault \
    write \
    auth/kilda-fred/role/${VAULT_K8S_ROLE} \
    bound_service_account_names=${VAULT_K8S_SERVICE_ACCOUNT} \
    bound_service_account_namespaces=${NAMESPACE} \
    policies=kv-common-policy,default \
    ttl=1h

Тестирование

План тестирования

  1. запустить POD в сервисном аккаунте kilda-service-account
  2. авторизоваться в Vault используя токен сервисного аккаунта
  3. Проверить возможность чтения из разрешенных путей key/value
  4. Проверить невозможность чтения из запрещенных путей key/value
  1. запустить POD в сервисном аккаунте common-service-account
  2. авторизоваться в Vault используя токен сервисного аккаунта
  3. Проверить возможность чтения из разрешенных путей key/value
  4. Проверить невозможность чтения из запрещенных путей key/value


vault kv put kv/common/somepath  commonkey=commonvalue
Key                Value
---                -----
created_time       2022-02-09T14:23:30.169927438Z
custom_metadata    <nil>
deletion_time      n/a
destroyed          false

Проверка kilda-service-account

Создание POD

kubectl apply -f pod-kilda-service-account.yaml

apiVersion: v1
kind: Pod
metadata:
  name: test-kilda-service-acc
  namespace: kilda
  labels:
    role: test
spec:
  serviceAccountName: "kilda-service-account"
  hostAliases:
  - ip: "10.14.15.201"
    hostnames:
    - "vault.domain.tld.com"
  containers:
    - name: web
      image: ubuntu:20.04
      imagePullPolicy: Always
      command: ["sleep", "3600000"]
      env:
      - name: VAULT_K8S_ROLE
        value: "common-role"
      - name: VAULT_ADDR
        value: "https://vault.domain.tld:8200"
      - name: VAULT_AUTH_PATH
        value: "kilda-fred"

Авторизация в Vault

  • Все действия из контейнера
kubectl --namespace kilda exec -ti  test-kilda-service-acc -- bash
  • Получение токена сервисного аккаунта k8
export JWT="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"
  • Просмотре переменных окружения
env | grep VAULT
VAULT_K8S_ROLE=kilda-role
VAULT_ADDR=https://vault.domain.tld:8200
VAULT_K8S_ROLE=kilda-role
VAULT_AUTH_PATH=kilda-fred
  • Авторизация в Vault используя роль и токен сервисного аккаунта: получение токена

vault write auth/kilda-fred/login role=${VAULT_K8S_ROLE} jwt=${JWT}

Key                                       Value
---                                       -----
token                                     s.vGsxWHAW9xHzdryEHolw3Xw1
token_accessor                            x4JGArK99k6wkh9QqgPE6dwF
token_duration                            1h
token_renewable                           true
token_policies                            ["default" "kilda-policy" "kv-common-policy"]
identity_policies                         []
policies                                  ["default" "kilda-policy" "kv-common-policy"]
token_meta_role                           kilda-role
token_meta_service_account_name           kilda-service-account
token_meta_service_account_namespace      kilda
token_meta_service_account_secret_name    n/a
token_meta_service_account_uid            50b15622-38d9-4725-96b1-1c56f4ca0da1
  • логин с использованием токена

vault login s.vGsxWHAW9xHzdryEHolw3Xw1

Key                                       Value
---                                       -----
token                                     s.vGsxWHAW9xHzdryEHolw3Xw1
token_accessor                            x4JGArK99k6wkh9QqgPE6dwF
token_duration                            59m26s
token_renewable                           true
token_policies                            ["default" "kilda-policy" "kv-common-policy"]
identity_policies                         []
policies                                  ["default" "kilda-policy" "kv-common-policy"]
token_meta_role                           kilda-role
token_meta_service_account_name           kilda-service-account
token_meta_service_account_namespace      kilda
token_meta_service_account_secret_name    n/a
token_meta_service_account_uid            50b15622-38d9-4725-96b1-1c56f4ca0da1
  • Просмотр токена и его прав ( в том числе политик)
  • результат соответсвует ожидаемому: policies [default kilda-policy kv-common-policy]

vault token lookup

Key                 Value
---                 -----
accessor            x4JGArK99k6wkh9QqgPE6dwF
creation_time       1644416277
creation_ttl        1h
display_name        kilda-fred-kilda-kilda-service-account
entity_id           ab9837eb-ff5c-71e4-cb78-16065ef5a7eb
expire_time         2022-02-09T15:17:57.790015655Z
explicit_max_ttl    0s
id                  s.vGsxWHAW9xHzdryEHolw3Xw1
issue_time          2022-02-09T14:17:57.79003263Z
meta                map[role:kilda-role service_account_name:kilda-service-account service_account_namespace:kilda service_account_secret_name: service_account_uid:50b15622-38d9-4725-96b1-1c56f4ca0da1]
num_uses            0
orphan              true
path                auth/kilda-fred/login
policies            [default kilda-policy kv-common-policy]
renewable           true
ttl                 59m21s
type                service

Проверить возможность чтения из разрешенных путей key/value

vault kv get kv/kilda/subpath (чтение возможно - результат соответсвует ожиданием)

======= Metadata =======
Key                Value
---                -----
created_time       2022-02-08T14:59:04.275447933Z
custom_metadata    <nil>
deletion_time      n/a
destroyed          false
version            1

===== Data =====
Key        Value
---        -----
somekey    somedata

vault kv get kv/common/somepath (чтение возможно - результат соответсвует ожиданием)

======= Metadata =======
Key                Value
---                -----
created_time       2022-02-09T14:23:30.169927438Z
custom_metadata    <nil>
deletion_time      n/a
destroyed          false
version            1

====== Data ======
Key          Value
---          -----
commonkey    commonvalue

Проверить невозможность чтения из запрещенных путей key/value

vault kv get kv/kilda/noaccess (чтение НЕ возможно - результат соответсвует ожиданием)

Error reading kv/data/kilda/noaccess: Error making API request.

URL: GET https://vault.domain.tld:8200/v1/kv/data/kilda/noaccess
Code: 403. Errors:

* 1 error occurred:
	* permission denied

Проверка common-service-account

Создание POD

kubectl apply -f pod-common-service-account.yaml

apiVersion: v1
kind: Pod
metadata:
  name: test-common-service-acc
  namespace: kilda
  labels:
    role: test
spec:
  serviceAccountName: "common-service-account"
  hostAliases:
  - ip: "10.14.15.201"
    hostnames:
    - "vault.domain.tld"
  containers:
    - name: web
      image: ubuntu:20.04
      imagePullPolicy: Always
      command: ["sleep", "3600000"]
      env:
      - name: VAULT_K8S_ROLE
        value: "common-role"
      - name: VAULT_ADDR
        value: "https://vault.domain.tld:8200"
      - name: VAULT_AUTH_PATH
        value: "kilda-fred"

Авторизация в Vault

  • Все действия из контейнера
kubectl --namespace kilda exec -ti  test-common-service-acc -- bash
  • Получение токена сервисного аккаунта k8
export JWT="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"
  • Просмотре переменных окружения
env | grep VAULT
VAULT_K8S_ROLE=common-role
VAULT_ADDR=https://vault.domain.tld:8200
VAULT_AUTH_PATH=kilda-fred
  • Авторизация в Vault используя роль и токен сервисного аккаунта: получение токена

vault write auth/kilda-fred/login role=${VAULT_K8S_ROLE} jwt=${JWT}

Key                                       Value
---                                       -----
token                                     s.fj4OxBwSn3jJjZ1FECwxSS6D
token_accessor                            7TOZSFyiCRnTeAydmUxlKdLb
token_duration                            1h
token_renewable                           true
token_policies                            ["default" "kv-common-policy"]
identity_policies                         []
policies                                  ["default" "kv-common-policy"]
token_meta_service_account_name           common-service-account
token_meta_service_account_namespace      kilda
token_meta_service_account_secret_name    n/a
token_meta_service_account_uid            70f30a0a-4efb-4356-b90d-be9210f47117
token_meta_role                           common-role
  • логин с использованием токена

vault login s.fj4OxBwSn3jJjZ1FECwxSS6D

Key                                       Value
---                                       -----
token                                     s.fj4OxBwSn3jJjZ1FECwxSS6D
token_accessor                            7TOZSFyiCRnTeAydmUxlKdLb
token_duration                            59m18s
token_renewable                           true
token_policies                            ["default" "kv-common-policy"]
identity_policies                         []
policies                                  ["default" "kv-common-policy"]
token_meta_service_account_secret_name    n/a
token_meta_service_account_uid            70f30a0a-4efb-4356-b90d-be9210f47117
token_meta_role                           common-role
token_meta_service_account_name           common-service-account
token_meta_service_account_namespace      kilda

  • Просмотр токена и его прав ( в том числе политик)
  • результат соответсвует ожидаемому: policies [default kilda-policy kv-common-policy]

vault token lookup

Key                 Value
---                 -----
accessor            7TOZSFyiCRnTeAydmUxlKdLb
creation_time       1644506420
creation_ttl        1h
display_name        kilda-fred-kilda-common-service-account
entity_id           522a6514-5e13-44d8-0377-c213154e0d44
expire_time         2022-02-10T16:20:20.254743135Z
explicit_max_ttl    0s
id                  s.fj4OxBwSn3jJjZ1FECwxSS6D
issue_time          2022-02-10T15:20:20.254757455Z
meta                map[role:common-role service_account_name:common-service-account service_account_namespace:kilda service_account_secret_name: service_account_uid:70f30a0a-4efb-4356-b90d-be9210f47117]
num_uses            0
orphan              true
path                auth/kilda-fred/login
policies            [default kv-common-policy]
renewable           true
ttl                 58m33s
type                service

Проверить возможность чтения из разрешенных путей key/value

vault kv get kv/common/somepath (чтение возможно - результат соответсвует ожиданием)

======= Metadata =======
Key                Value
---                -----
created_time       2022-02-09T14:23:30.169927438Z
custom_metadata    <nil>
deletion_time      n/a
destroyed          false
version            1

====== Data ======
Key          Value
---          -----
commonkey    commonvalue

Проверить невозможность чтения из запрещенных путей key/value

vault kv get kv/kilda/subpath (чтение НЕ возможно - результат соответсвует ожиданием)


Error reading kv/data/kilda/subpath: Error making API request.

URL: GET https://vault.domain.tld:8200/v1/kv/data/kilda/subpath
Code: 403. Errors:
* 1 error occurred:
	* permission denied

Выводы

  • Сервисный аккаунт kilda-service-account имеет доступ к k/v kv/kilda/* и kv/common/*
  • Сервисный аккаунт common-service-account имеет доступ к k/v kv/common/* и не имеет доступа к k/v kv/kilda/*
  • те все работает так как должно