Vault with k8s: различия между версиями
Sirmax (обсуждение | вклад) (→Ссылки) |
Sirmax (обсуждение | вклад) |
||
| Строка 186: | Строка 186: | ||
Обратить внимание - политики <B>policy1,policy2</B> уже существуют (созданы до этого). Если политик нет их необходимо создать. |
Обратить внимание - политики <B>policy1,policy2</B> уже существуют (созданы до этого). Если политик нет их необходимо создать. |
||
| + | ==Деплоймент в K8S== |
||
| + | <PRE> |
||
| + | apiVersion: extensions/v1beta1 |
||
| + | kind: Deployment |
||
| + | metadata: |
||
| + | name: {{ template "mosaicName" . }} |
||
| + | spec: |
||
| + | replicas: 1 |
||
| + | selector: |
||
| + | matchLabels: |
||
| + | app: {{ template "mosaicName" . }}-pod |
||
| + | template: |
||
| + | metadata: |
||
| + | labels: |
||
| + | app: {{ template "mosaicName" . }}-pod |
||
| + | spec: |
||
| + | serviceAccountName: {{ .Values.serviceAccount }} |
||
| + | volumes: |
||
| + | - name: {{ template "mosaicName" . }}-super-ca-volume |
||
| + | secret: |
||
| + | secretName: {{ template "mosaicName" . }}-super-ca-secret |
||
| + | containers: |
||
| + | - name: {{ template "mosaicName" . }}-container-consul |
||
| + | image: gcr.io/kohls-kos-cicd/kos/snb-ui-svc:{{ .Values.artifactVersion }} |
||
| + | imagePullPolicy: Always |
||
| + | args: ["/bin/bash", "/opt/hashicorp/consul/bin/start-consul.sh"] |
||
| + | volumeMounts: |
||
| + | - name: {{ template "mosaicName" . }}-super-ca-volume |
||
| + | mountPath: /tmp/superCA |
||
| + | env: |
||
| + | - name: CONSUL_TOKEN |
||
| + | value: {{ .Values.consulToken | quote }} |
||
| + | - name: CONSUL_KEY |
||
| + | value: {{ .Values.consulKey | quote }} |
||
| + | - name: CONSUL_SCHEME |
||
| + | value: {{ .Values.consulScheme | quote }} |
||
| + | - name: CONSUL_HTTP_ADDR |
||
| + | value: {{ .Values.consulHttpAddr | quote }} |
||
| + | - name: CA_PATH |
||
| + | value: {{ .Values.caPath | quote }} |
||
| + | - name: LOCAL_IP |
||
| + | valueFrom: |
||
| + | fieldRef: |
||
| + | fieldPath: status.podIP |
||
| + | - name: DEPLOYMENT_DATACENTER |
||
| + | value: {{ .Values.deploymentDatacenter | quote }} |
||
| + | - name: DEPLOYMENT_CHANNEL |
||
| + | value: {{ .Values.deploymentChannel | quote }} |
||
| + | - name: DEPLOYMENT_ENV |
||
| + | value: {{ .Values.deploymentEnv | quote }} |
||
| + | - name: SECRETS_BACKEND |
||
| + | value: {{ .Values.secretsBackend | quote }} |
||
| + | - name: PROFILE |
||
| + | value: {{ .Values.profile | quote }} |
||
| + | - name: VAULT_K8S_ROLE |
||
| + | value: {{ .Values.vaultK8sRole | quote }} |
||
| + | </PRE> |
||
==Получение токена== |
==Получение токена== |
||
Версия 16:31, 30 января 2019
Авторизация контейнеров/PODов в Hashicorp Vault
Задача - использовать сервисные аккаунты кубернетиса для авторизации а Hashicorp Vault
Схема работы
1. Создается сервисный аккаунт
2. Запускается POD с этим сервисным аккаунтом
3. Под получает адрес 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"
Получить имя "секрета"
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
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: {{ template "mosaicName" . }}
spec:
replicas: 1
selector:
matchLabels:
app: {{ template "mosaicName" . }}-pod
template:
metadata:
labels:
app: {{ template "mosaicName" . }}-pod
spec:
serviceAccountName: {{ .Values.serviceAccount }}
volumes:
- name: {{ template "mosaicName" . }}-super-ca-volume
secret:
secretName: {{ template "mosaicName" . }}-super-ca-secret
containers:
- name: {{ template "mosaicName" . }}-container-consul
image: gcr.io/kohls-kos-cicd/kos/snb-ui-svc:{{ .Values.artifactVersion }}
imagePullPolicy: Always
args: ["/bin/bash", "/opt/hashicorp/consul/bin/start-consul.sh"]
volumeMounts:
- name: {{ template "mosaicName" . }}-super-ca-volume
mountPath: /tmp/superCA
env:
- name: CONSUL_TOKEN
value: {{ .Values.consulToken | quote }}
- name: CONSUL_KEY
value: {{ .Values.consulKey | quote }}
- name: CONSUL_SCHEME
value: {{ .Values.consulScheme | quote }}
- name: CONSUL_HTTP_ADDR
value: {{ .Values.consulHttpAddr | quote }}
- name: CA_PATH
value: {{ .Values.caPath | quote }}
- name: LOCAL_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: DEPLOYMENT_DATACENTER
value: {{ .Values.deploymentDatacenter | quote }}
- name: DEPLOYMENT_CHANNEL
value: {{ .Values.deploymentChannel | quote }}
- name: DEPLOYMENT_ENV
value: {{ .Values.deploymentEnv | quote }}
- name: SECRETS_BACKEND
value: {{ .Values.secretsBackend | quote }}
- name: PROFILE
value: {{ .Values.profile | quote }}
- name: VAULT_K8S_ROLE
value: {{ .Values.vaultK8sRole | quote }}