Vault with k8s: различия между версиями
Sirmax (обсуждение | вклад) |
Sirmax (обсуждение | вклад) |
||
| Строка 176: | Строка 176: | ||
Создать привязку |
Создать привязку |
||
<PRE> |
<PRE> |
||
| + | vault \ |
||
| − | ${VAULT} \ |
||
write \ |
write \ |
||
auth/kubernetes/role/${VAULT_K8S_ROLE} \ |
auth/kubernetes/role/${VAULT_K8S_ROLE} \ |
||
Версия 14:03, 1 февраля 2019
Авторизация контейнеров/PODов в Hashicorp Vault
Задача - использовать сервисные аккаунты кубернетиса для авторизации а Hashicorp Vault
Схема работы
1. Создается сервисный аккаунт
2. Запускается POD с этим сервисным аккаунтом
3. POD получает адрес Vault каким-то способом (в моем случае - вычитывает из Consul но это не принципиально, можно через переменную окружения или еще как-то)
4. Авторизуется в Vault под определенной ролью используя JWT
5 Vault возвращает токен с политиками назначенными на роль
5. POD читает из Vault используя полученный токен
+-------------------------------------------------------------------------------------------------------------------------------+ | Google Cloud Engine | | | | | | +-----------------------------------------------------------+ | | | K8S Cluster (in GKE) | | | | | | | | | | | | +---------------------------------------------------+ | | | | | POD | | | | | | spec: | | | | | | serviceAccountName: k8s-test-service-account | | | | | | ... | | | | | | containers: | | | | | | - name: container-name | | | | | | image: ... | | +-------------------+ | | | | imagePullPolicy: Always | | | VM Instance | | | | | env: | | | | | | | | - name: VAULT_K8S_ROLE | | | +------------+ | | | | | value: k8s-test-role | ---|-->---> Token Request for role ->-->-->---| | Vault | | | | | +---------------------------------------------------+ | * POD's SA JWT | | Process | | | | | | * Role Name | | | | | | | | | | | | | | | +--------------------+ | Verify POS's Service Account JWT | | | | | | | | K8S API Endpoint |<--------<--------<----------------|-( auth with Vault's Service Account )-<--| | | | | | | +--------------------+ | | +------------+ | | | | | | | | | +-----------------------------------------------------------+ +-------------------+ | | | +-------------------------------------------------------------------------------------------------------------------------------+
Настройка
k8s
Сервисный аккаунт
Это аккаунт с которым Vault подключается к API k8s для валидации JWT
--- apiVersion: v1 kind: ServiceAccount metadata: name: vault-tokenreview-service-account namespace: test-namespace
Права сервисного аккаунта
Для того что б аккаунт мог проверить JWT у других сервисных аккаунтов ему назначается
ClusterRole system:auth-delegator
Важно: Назначить права нужно в 2 неймспейсах - если назначить только в test-namespace то прав для проверки JWT недостаточно (что совершенно не очевидно из конфигурации)
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: vault-tokenreview-service-account-role-binding namespace: test-namespace roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: system:auth-delegator subjects: - kind: ServiceAccount name: vault-tokenreview-service-account namespace: test-namespace --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: vault-tokenreview-service-account-role-binding-2 namespace: default roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: system:auth-delegator subjects: - kind: ServiceAccount name: vault-tokenreview-service-account namespace: test-namespace
Vault
Для настройки Vault потребуется токен с рутовыми правами адрес Vault дан для примера. В моем случае он вычитывается из Consul.
export VAULT_TOKEN="<ROOT_TOKEN>" export VAULT_ADDR="http://192.168.1.4:8200"
Включить поддержку k8s в Vault
vault auth-enable kubernetes
Получение необходимых секретов из K8S
Так-как в моем случае все PODы находятся в отдельном namespace то:
export NAMESPACE="my-namespace-name"
Получить имя "секрета" для сервисного аккаунта vault-tokenreview-service-accoun (аккаунт под которым Vault работает с K8S API)
export SECRET_NAME=$( \
kubectl \
--namespace ${NAMESPACE} \
get \
serviceaccount \
vault-tokenreview-service-account \
-o jsonpath='{.secrets[0].name}' )
Зная имя секрета можно получить его токен:
export ACCOUNT_TOKEN=$( \
kubectl \
--namespace ${NAMESPACE} \
get \
secret ${SECRET_NAME} \
-o jsonpath='{.data.token}' \
| base64 --decode )
В том же секрете содержится сертификат СА:
export SERVICE_ACCOUNT_CA_CRT=$( \
kubectl \
--namespace ${NAMESPACE} \
get \
secret ${SECRET_NAME} \
-o jsonpath="{.data['ca\.crt']}" \
| base64 --decode; echo )
====Настройка доступа Vault в K8S====
Настроить vault (адрес API можно взять из конфигурации kubectl)
<PRE>
vault \
write \
auth/kubernetes/config \
kubernetes_host="https://192.168.191.2:443" \
kubernetes_ca_cert="${SERVICE_ACCOUNT_CA_CRT}" \
token_reviewer_jwt="${ACCOUNT_TOKEN}"
Обратить внимание:
- Service Account - это аккаунт с которым будет деплоиться POD. Это аккаунт в k8s а не в Vault.
- Роль существует только в пределах Vault (а не в K8S)
- При авторизации POD запрашивает токен для роли
- На токен будут назначены политики из привязки
Привязка сервисных аккаунтов K8S к ролям Vault
export VAULT_K8S_SERVICE_ACCOUNT="k8s-test-service-account" export VAULT_K8S_ROLE="k8s-test-role"
Создать привязку
vault \
write \
auth/kubernetes/role/${VAULT_K8S_ROLE} \
bound_service_account_names=${VAULT_K8S_SERVICE_ACCOUNT} \
bound_service_account_namespaces=${NAMESPACE} \
policies=policy1,policy2,default \
ttl=1h
Обратить внимание - политики policy1,policy2 уже существуют (созданы до этого). Если политик нет их необходимо создать.
Деплоймент в K8S
Примерная конфигурация PODа export VAULT_K8S_SERVICE_ACCOUNT="k8s-test-service-account" export VAULT_K8S_ROLE="k8s-test-role"
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: my-deployment
spec:
replicas: 1
selector:
matchLabels:
app: my-deployment-pod
template:
metadata:
labels:
app: my-deployment-pod
spec:
serviceAccountName: "k8s-test-service-account"
containers:
- name: my-container-name
image: ...
imagePullPolicy: Always
args: ...
env:
- name: VAULT_K8S_ROLE
value: "k8s-test-role"
Получение токена
Адрес Vault известен (через переменную окружения или из Consul)
Токен сервисного аккаунта монтируется как вольюм
Изнутри контейнера:
export VAULT_ADDR="http://192.168.1.4:8200" export JWT="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"
Авторизация используя утилиту vault
vault write auth/kubernetes/login role=k8s-test-role jwt=${JWT}
Key Value --- ----- token s.SyMDLTmAYLtEA13vBVfjqyfq token_accessor 3pQbarDfUWChuIgWZRnnKMMB token_duration 1h token_renewable true token_policies ["policy1" "policy2" "default" ] identity_policies [] policies token_policies ["policy1" "policy2" "default" ] token_meta_service_account_name k8s-test-service-account token_meta_service_account_namespace test-namespace token_meta_service_account_secret_name k8s-test-service-account-token-klp4w token_meta_service_account_uid fe7fc17f-2305-11e9-b347-4201c0a8bf08 token_meta_role k8s-testi-role
Авторизация через Curl
curl \
--request POST \
--data '{"jwt": "'"${JWT}"'", "role": "k8s-test-role"}' \
${VAULT_ADDR}/v1/auth/kubernetes/login
{
"request_id": "8d524407-ee6b-a6c2-b011-d02572ae2ce9",
"lease_id": "",
"renewable": false,
"lease_duration": 0,
"data": null,
"wrap_info": null,
"warnings": null,
"auth": {
"client_token": "s.3YsrjrkBZLOXF5sAmR2ceqrs",
"accessor": "I532wSMIIXYSiAocKcShEhe7",
"policies": [
"policy1",
"policy2",
"default"
],
"token_policies": [
"policy1",
"policy2",
"default"
],
"metadata": {
"role": "k8s-test-role",
"service_account_name": "k8s-test-service-account",
"service_account_namespace": "test-namespace",
"service_account_secret_name": "k8s-test-service-account-token-klp4w",
"service_account_uid": "fe7fc17f-2305-11e9-b347-4201c0a8bf08"
},
"lease_duration": 3600,
"renewable": true,
"entity_id": "5d4ec129-0298-54a6-bf03-a51dbda0a917",
"token_type": "service"
}
}
Ссылки
- https://coreos.com/tectonic/docs/latest/vault-operator/user/kubernetes-auth-backend.html
- https://medium.com/@gmaliar/dynamic-secrets-on-kubernetes-pods-using-vault-35d9094d169
- https://blog.openshift.com/vault-integration-using-kubernetes-authentication-method/
- https://www.vaultproject.io/docs/auth/kubernetes.html