Введення в Hashicorp Consul's Kubernetes

Введення в Hashicorp Consul's Kubernetes

Все правильно, після релізу Hashicorp Consul 1.5.0 на початку травня 2019 року в Consul можна робити авторизацію додатків та служб, запущених у Kubernetes, нативно.

У цьому посібнику ми крок за кроком створимо POC (Перевірка концепції (Proof of concept, PoC — доказ [здійсненності] концепції — прим. перекл.), продемонструвавши цю нову функцію. Від вас очікуються базові знання про Kubernetes та Hashicorp's Consul. І хоча ви можете використовувати будь-яку хмарну платформу чи локальне середовище, у цьому посібнику ми будемо використовувати Google Cloud Platform.

Огляд

Якщо ми перейдемо до документації Consul за його методом авторизації, ми отримаємо короткий огляд його призначення та варіанти використання, а також деякі технічні деталі та загальний огляд логіки. Я настійно рекомендую прочитати її принаймні один раз, перш ніж продовжити, тому що зараз я все це пояснюватиму і розжовуватиму.

Введення в Hashicorp Consul's Kubernetes

Схема 1: Офіційний огляд методу авторизації Consul

Давайте подивимося в документацію для конкретного методу авторизації Kubernetes.

Звичайно, там є корисна інформація, але немає посібника про те, як насправді все це використовувати. Тому, як будь-яка розсудлива людина, ви прочісує Інтернет у пошуках керівництва. А потім... Зазнайте поразки. Так буває. Давайте це виправимо.

Перш ніж ми перейдемо до створення нашого POC, повернімося до огляду методів авторизації Consul (Схема 1) і уточнимо його в контексті Kubernetes.

Архітектура

У цьому посібнику ми будемо створювати Consul-сервер на окремій машині, яка буде взаємодіяти з кластером Kubernetes із встановленим клієнтом Consul. Потім ми створимо наш фіктивний додаток у поді та використовуємо наш налаштований метод авторизації для читання з нашого Consul key/value сховища.

Схема нижче детально показує архітектуру, яку ми створюємо в цьому посібнику, а також логіку методу авторизації, яка буде пояснена пізніше.

Введення в Hashicorp Consul's Kubernetes

Схема 2: Огляд методу авторизації в Kubernetes

Невелике зауваження: Consul-серверу не потрібно жити поза межами кластера Kubernetes, щоб це працювало. Але так, він може і так і сяк.

Отже, взявши оглядову схему Consul (Схема 1) і застосувавши Kubernetes до неї, ми отримуємо схему вище (Схема 2), і тут логіка буде наступна:

  1. До кожного поду буде прикріплено службовий обліковий запис, що містить токен JWT, згенерований та відомий Kubernetes. Цей токен також вставляється в під за замовчуванням.
  2. Наша програма або сервіс всередині пода ініціює команду входу в наш Consul-клієнт. У запиті на вхід до системи також буде вказано наш токен та вказано ім'я спеціально створеного методу авторизації (типу Kubernetes). Цей крок № 2 відповідає кроці 1 схеми Consul (Схема 1).
  3. Наш Consul-клієнт потім надішле цей запит на наш Consul-сервер.
  4. МАГІЯ! Саме тут Consul-сервер перевіряє справжність запиту, збирає відомості про ідентичність запиту та порівнює їх із якими-небудь асоційованими визначеними правилами. Нижче буде інша схема, щоби це проілюструвати. Цей крок відповідає крокам 3, 4 та 5 оглядової схеми Consul (Схема 1).
  5. Наш Consul-сервер генерує Consul токен з дозволами відповідно до вказаних нами правил методу авторизації (які ми визначили) щодо особи запитуючого. Потім він відправить цей токен назад. Це відповідає кроці 6 схеми Consul (Схема 1).
  6. Наш Consul-клієнт перенаправляє токен додатку або сервісу, що запитує.

Наша програма або сервіс тепер можуть використовувати цей Consul токен для зв'язку з нашими даними Consul, як було визначено привілеями токена.

Чари розкриті!

Для тих з вас, хто не задоволений лише кроликом з капелюха і хоче знати, як це працює… дозвольте мені «показати вам, наскільки глибока кроляча нора».

Як згадувалося раніше, наш «магічний» крок (Схема 2: Крок 4) полягає в тому, що Consul-сервер перевіряє справжність запиту, збирає відомості про запит та порівнює їх із будь-якими асоційованими визначеними правилами. Цей крок відповідає крокам 3, 4 та 5 оглядової схеми Consul (Схема 1). Нижче наведено схему (Схема 3), мета якої наочно показати, що насправді відбувається під капотом конкретний метод авторизації Kubernetes.

Введення в Hashicorp Consul's Kubernetes

Схема 3: Чари розкриті!

  1. Як відправна точка, наш Consul-клієнт перенаправляє запит на вхід на наш Consul-сервер з токеном облікового запису Kubernetes і конкретним ім'ям інстансу методу авторизації, який був створений раніше. Цей крок відповідає кроці 3 у попередньому поясненні схеми.
  2. Тепер Consul-сервер (або лідер) необхідно перевірити справжність отриманого токена. Тому він проконсультується з кластером Kubernetes (через Consul-клієнт) і, за наявності відповідних дозволів, ми з'ясуємо, чи токен є справжнім, і кому він належить.
  3. Потім перевірений запит повертається до Consul-лідера, і на сервері Consul виконується пошук інстансу методу авторизації із зазначеним ім'ям із запиту на вхід до системи (та типу Kubernetes).
  4. Consul-лідер визначає зазначений інстанс методу авторизації (якщо його знайдено) і читає набір правил прив'язки, які до нього прикріплені. Потім він читає ці правила і порівнює їх із перевіреними атрибутами ідентичності.
  5. Та да! Переходимо до кроку 5 попередньому поясненні схеми.

Запустіть Consul-server на звичайній віртуальній машині

З цього моменту я в основному даватиму інструкції щодо створення цього POC, часто в пунктах, без пояснювальних цілих пропозицій. Також, як зазначалося раніше, я використовуватиму GCP для створення всієї інфраструктури, але ви можете створити таку ж інфраструктуру в будь-якому іншому місці.

  • Запустіть віртуальну машину (інстанс/сервер).

Введення в Hashicorp Consul's Kubernetes

  • Створіть правило для firewall (група безпеки в AWS):
  • Мені подобається присвоювати те саме ім'я машини правилу і мережному тегу, в даному випадку це «skywiz-consul-server-poc».
  • Знайдіть IP-адресу вашого локального комп'ютера і додайте її до списку вихідних IP-адрес, щоб отримати доступ до інтерфейсу користувача (UI).
  • Відкрийте порт 8500 для UI. Натисніть Create (Створити). Ми незабаром знову змінимо цей firewall [посилання].
  • Додайте правило для firewall до інстансу. Поверніться на панель моніторингу VM на сервері Consul і додайте «skywiz-consul-server-poc» у поле мережевих тегів. Натисніть Save (Зберегти).

Введення в Hashicorp Consul's Kubernetes

  • Встановіть Consul на віртуальну машину, перевірте тут. Пам'ятайте, що вам потрібна версія Consul ≥ 1.5 [посилання]
  • Створимо single node Consul - наступна конфігурація.

groupadd --system consul
useradd -s /sbin/nologin --system -g consul consul
mkdir -p /var/lib/consul
chown -R consul:consul /var/lib/consul
chmod -R 775 /var/lib/consul
mkdir /etc/consul.d
chown -R consul:consul /etc/consul.d

  • Докладніше посібник зі встановлення Consul та налаштування кластера з 3 нід див. тут.
  • Створіть файл /etc/consul.d/agent.json так [посилання]:

### /etc/consul.d/agent.json
{
 "acl" : {
 "enabled": true,
 "default_policy": "deny",
 "enable_token_persistence": true
 }
}

  • Запустіть наш Consul-сервер:

consul agent 
-server 
-ui 
-client 0.0.0.0 
-data-dir=/var/lib/consul 
-bootstrap-expect=1 
-config-dir=/etc/consul.d

  • Ви повинні побачити купу вихідних даних і зрештою “… update blocked by ACLs”.
  • Знайдіть зовнішню IP-адресу Consul-сервера та відкрийте браузер із цією IP-адресою на порту 8500. Переконайтеся, що відкривається UI.
  • Спробуйте додати пару ключ/значення. Має бути помилка. Це тому, що ми завантажили сервер Consul за допомогою ACL і заборонили всі правила.
  • Поверніться до своєї оболонки на Consul-сервері і запустіть процес у фоновому режимі або іншим способом, щоб він працював, і введіть наступне:

consul acl bootstrap

  • Знайдіть значення "SecretID" і поверніться до UI. На вкладці ACL введіть секретний ідентифікатор токена, який ви тільки що скопіювали. Скопіюйте SecretID ще кудись, він знадобиться нам пізніше.
  • Тепер додайте пару ключ/значення. Для цього POC додамо таке: ключ: "custom-ns/test_key", значення: "I'm in the custom-ns folder!"

Запуск Kubernetes-кластера для нашої програми з Consul-клієнтом як Daemonset

  • Створіть кластер K8s (Kubernetes). Ми створимо його в тій же зоні, що й сервер, для більш швидкого доступу, і тому ми можемо використовувати ту саму підмережу для простого підключення з внутрішніми IP-адресами. Ми назвемо його "skywiz-app-with-consul-client-poc".

Введення в Hashicorp Consul's Kubernetes

  • Як примітка, ось хороший посібник, з яким я зіткнувся при налаштуванні POC Consul-кластера з Consul Connect.
  • Ми також будемо використовувати Hashicorp helm chart із розширеним файлом значень.
  • Встановіть та налаштуйте Helm. Кроки конфігурації:

kubectl create serviceaccount tiller --namespace kube-system
kubectl create clusterrolebinding tiller-admin-binding 
   --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
./helm init --service-account=tiller
./helm update

### poc-helm-consul-values.yaml
global:
 enabled: false
 image: "consul:latest"
# Expose the Consul UI through this LoadBalancer
ui:
 enabled: false
# Allow Consul to inject the Connect proxy into Kubernetes containers
connectInject:
 enabled: false
# Configure a Consul client on Kubernetes nodes. GRPC listener is required for Connect.
client:
 enabled: true
 join: ["<PRIVATE_IP_CONSUL_SERVER>"]
 extraConfig: |
{
  "acl" : {
 "enabled": true,   
 "default_policy": "deny",   
 "enable_token_persistence": true 
  }
}
# Minimal Consul configuration. Not suitable for production.
server:
 enabled: false
# Sync Kubernetes and Consul services
syncCatalog:
 enabled: false

  • Застосуйте helm chart:

./helm install -f poc-helm-consul-values.yaml ./consul-helm - name skywiz-app-with-consul-client-poc

  • При спробі запуску йому знадобляться дозволи для Consul-сервера, так що давайте додамо їх.
  • Зверніть увагу на «діапазон адрес Pod», розташований на панелі приладів кластера, і поверніться до нашого правила для firewall «skywiz-consul-server-poc».
  • Додайте діапазон адрес для подавання до списку IP-адрес та відкрийте порти 8301 та 8300.

Введення в Hashicorp Consul's Kubernetes

  • Перейдіть до Consul UI, і за кілька хвилин ви побачите, що наш кластер з'явиться на вкладці нод.

Введення в Hashicorp Consul's Kubernetes

Налаштування методу авторизації шляхом інтеграції Consul з Kubernetes

  • Поверніться в оболонку Consul-сервера та експортуйте токен, який ви зберегли раніше:

export CONSUL_HTTP_TOKEN=<SecretID>

  • Нам знадобиться інформація з нашого Kubernetes-кластера, щоб створити інстанс методу auth:
  • kubernetes-host

kubectl get endpoints | grep kubernetes

  • kubernetes-service-account-jwt

kubectl get sa <helm_deployment_name>-consul-client -o yaml | grep "- name:"
kubectl get secret <secret_name_from_prev_command> -o yaml | grep token:

  • Токен закодований в base64, тому розшифруйте його за допомогою вашого улюбленого інструменту [посилання]
  • kubernetes-ca-cert

kubectl get secret <secret_name_from_prev_command> -o yaml | grep ca.crt:

  • Візьміть сертифікат ca.crt (після декодування з base64) і впишіть його у файл ca.crt.
  • Тепер створіть інстанс методу auth, замінивши місцеholders на значення, які ви тільки що отримали.

consul acl auth-method create 
-type "kubernetes" 
-name "auth-method-skywiz-consul-poc" 
-description "This is an auth method using kubernetes for the cluster skywiz-app-with-consul-client-poc" 
-kubernetes-host "<k8s_endpoint_retrieved earlier>" 
[email protected] 
-kubernetes-service-account-
jwt="<decoded_token_retrieved_earlier>"

  • Далі ми маємо створити правило та прикріпити його до нової ролі. Для цієї частини можна використовувати Consul UI, але ми будемо використовувати командний рядок.
  • Напишіть правило

### kv-custom-ns-policy.hcl
key_prefix "custom-ns/" {
 policy = "write"
}

  • Застосуйте правило

consul acl policy create 
-name kv-custom-ns-policy 
-description "This is an example policy for kv at custom-ns/" 
-rules @kv-custom-ns-policy.hcl

  • Знайдіть ідентифікатор правила, яке ви щойно створили з вихідних даних.
  • Створіть роль із новим правилом.

consul acl role create 
-name "custom-ns-role" 
-description "This is an example role for custom-ns namespace" 
-policy-id <policy_id>

consul acl binding-rule create 
-method=auth-method-skywiz-consul-poc 
-bind-type=role 
-bind-name='custom-ns-role' 
-selector='serviceaccount.namespace=="custom-ns"'

Зміни насамкінець

Права доступу

  • Створіть права доступу. Нам потрібно надати дозвіл Consul на перевірку та ідентифікацію посвідчення токена облікового запису служби K8s.
  • Запишіть у файл наступне [посилання]:

###skywiz-poc-consul-server_rbac.yaml
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
 name: review-tokens
 namespace: default
subjects:
- kind: ServiceAccount
 name: skywiz-app-with-consul-client-poc-consul-client
 namespace: default
roleRef:
 kind: ClusterRole
 name: system:auth-delegator
 apiGroup: rbac.authorization.k8s.io
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
 name: service-account-getter
 namespace: default
rules:
- apiGroups: [""]
 resources: ["serviceaccounts"]
 verbs: ["get"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
 name: get-service-accounts
 namespace: default
subjects:
- kind: ServiceAccount
 name: skywiz-app-with-consul-client-poc-consul-client
 namespace: default
roleRef:
 kind: ClusterRole
 name: service-account-getter
 apiGroup: rbac.authorization.k8s.io

  • Створимо права доступу

kubectl create -f skywiz-poc-consul-server_rbac.yaml

Підключення до Consul Client

  • Як зазначалося тут, є кілька опцій для підключення до daemonset, але ми перейдемо до наступного простого рішення:
  • Застосуйте наступний файл [посилання].

### poc-consul-client-ds-svc.yaml
apiVersion: v1
kind: Service
metadata:
 name: consul-ds-client
spec:
 selector:
   app: consul
   chart: consul-helm
   component: client
   hasDNS: "true"
   release: skywiz-app-with-consul-client-poc
 ports:
 - protocol: TCP
   port: 80
   targetPort: 8500

  • Потім застосуйте наступну вбудовану команду для створення configmap [посилання]. Зверніть увагу, що ми посилаємось на назву нашого сервісу, замініть його за потреби.

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
 labels:
   addonmanager.kubernetes.io/mode: EnsureExists
 name: kube-dns
 namespace: kube-system
data:
 stubDomains: |
   {"consul": ["$(kubectl get svc consul-ds-client -o jsonpath='{.spec.clusterIP}')"]}
EOF

Тестування auth-методу

Тепер давайте подивимося на магію у дії!

  • Створіть ще кілька ключових папок із тим самим ключем верхнього рівня (тобто. /sample_key) і значенням на ваш вибір. Створіть відповідні політики та ролі для нових ключових шляхів. Ми зробимо прив'язки пізніше.

Введення в Hashicorp Consul's Kubernetes

Користувальницький тест простору імен:

  • Створимо наш власний простір імен:

kubectl create namespace custom-ns

  • Створимо під нашому новому просторі імен. Напишіть конфігурацію для подавання.

###poc-ubuntu-custom-ns.yaml
apiVersion: v1
kind: Pod
metadata:
 name: poc-ubuntu-custom-ns
 namespace: custom-ns
spec:
 containers:
 - name: poc-ubuntu-custom-ns
   image: ubuntu
   command: ["/bin/bash", "-ec", "sleep infinity"]
 restartPolicy: Never

  • Створіть під:

kubectl create -f poc-ubuntu-custom-ns.yaml

  • Як тільки контейнер запуститься, зайдіть туди та встановіть curl.

kubectl exec poc-ubuntu-custom-ns -n custom-ns -it /bin/bash
apt-get update && apt-get install curl -y

  • Тепер ми надішлемо запит на вхід у Consul, використовуючи метод авторизації, який ми створили раніше [посилання].
  • Щоб переглянути введений токен зі свого облікового запису служби:

cat /run/secrets/kubernetes.io/serviceaccount/token

  • Напишіть наступне у файлі всередині контейнера:

### payload.json
{
 "AuthMethod": "auth-method-test",
 "BearerToken": "<jwt_token>"
}

  • Увійти!

curl 
--request POST 
--data @payload.json 
consul-ds-client.default.svc.cluster.local/v1/acl/login

  • Щоб виконати вищезгадані кроки в одному рядку (оскільки ми будемо виконувати кілька тестів), ви можете зробити таке:

echo "{ 
"AuthMethod": "auth-method-skywiz-consul-poc", 
"BearerToken": "$(cat /run/secrets/kubernetes.io/serviceaccount/token)" 
}" 
| curl 
--request POST 
--data @- 
consul-ds-client.default.svc.cluster.local/v1/acl/login

  • Працює! Мабуть, принаймні. Тепер візьміть SecretID і спробуйте отримати доступ до ключа/значення, до якого має бути доступ.

curl 
consul-ds-client.default.svc.cluster.local/v1/kv/custom-ns/test_key --header “X-Consul-Token: <SecretID_from_prev_response>”

  • Ви можете декодувати "Value" base64 і побачити, що воно відповідає значенню в custom-ns/test_key в UI. Якщо ви використовували те саме значення, наведене вище в цьому посібнику, ваше кодоване значення буде IkknbSBpbiB0aGUgY3VzdG9tLW5zIGZvbGRlciEi.

Тест облікового запису користувальницької служби:

  • Створіть користувальницький ServiceAccount за допомогою наступної команди [посилання].

kubectl apply -f - <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
 name: custom-sa
EOF

  • Створіть новий конфігураційний файл для подавання. Зверніть увагу, що я ввімкнув установку curl для економії праці 🙂

###poc-ubuntu-custom-sa.yaml
apiVersion: v1
kind: Pod
metadata:
 name: poc-ubuntu-custom-sa
 namespace: default
spec:
 serviceAccountName: custom-sa
 containers:
 - name: poc-ubuntu-custom-sa
   image: ubuntu
   command: ["/bin/bash","-ec"]
   args: ["apt-get update && apt-get install curl -y; sleep infinity"]
 restartPolicy: Never

  • Після цього запустіть оболонку усередині контейнера.

kubectl exec -it poc-ubuntu-custom-sa /bin/bash

  • Увійти!

echo "{ 
"AuthMethod": "auth-method-skywiz-consul-poc", 
"BearerToken": "$(cat /run/secrets/kubernetes.io/serviceaccount/token)" 
}" 
| curl 
--request POST 
--data @- 
consul-ds-client.default.svc.cluster.local/v1/acl/login

  • Прихильність знижена. О, ми забули додати нову прив'язку правил із відповідними дозволами, давайте зробимо це зараз.

Повторіть попередні кроки вище:
а) Створіть ідентичну Політику префіксу «custom-sa/».
б) Створіть Role, назвіть її «custom-sa-role»
в) Прикріпіть Політику до Role.

  • Створіть Rule-Binding (можливо лише з cli/api). Зверніть увагу на інше значення селекторного прапора.

consul acl binding-rule create 
-method=auth-method-skywiz-consul-poc 
-bind-type=role 
-bind-name='custom-sa-role' 
-selector='serviceaccount.name=="custom-sa"'

  • Повторіть вхід у систему із контейнера «poc-ubuntu-custom-sa». Success!
  • Перевірте наш доступ до ключового шляху custom-sa/.

curl 
consul-ds-client.default.svc.cluster.local/v1/kv/custom-sa/test_key --header “X-Consul-Token: <SecretID>”

  • Ви також можете переконатися, що цей токен не надає доступу kv у «custom-ns/». Просто повторіть наведену вище команду після заміни custom-sa на префікс custom-ns.
    У дозволі відмовлено.

Приклад свердління:

  • Всі порівняння rule-binding будуть додані в токен з цими правами.
  • Наш контейнер «poc-ubuntu-custom-sa» знаходиться в просторі стандартних імен — так що давайте використовувати його для іншої rule-binding.
  • Повторіть попередні кроки:
    а) Створіть ідентичну Політику префіксу ключа «default/».
    б) Створіть Role, назвіть її "default-ns-role"
    в) Прикріпіть Політику до Role.
  • Створіть Rule-Binding (можливо тільки з cli/api)

consul acl binding-rule create 
-method=auth-method-skywiz-consul-poc 
-bind-type=role 
-bind-name='default-ns-role' 
-selector='serviceaccount.namespace=="default"'

  • Поверніться до нашого контейнера «poc-ubuntu-custom-sa» і спробуйте отримати доступ до «default/» kv.
  • У дозволі відмовлено.
    Ви можете переглянути облікові дані для кожного токена в UI в розділі ACL > Tokens. Як бачите, до нашого поточного токену прикріплена лише одна «custom-sa-role». Токен, який ми використовуємо в даний час, був згенерований, коли ми увійшли в систему, і тоді була тільки одна rule-binding, яка тоді відповідала. Нам потрібно знову увійти до системи та використовувати новий токен.
  • Переконайтеся, що ви можете читати як зі шляхів «custom-sa/», так і «default/» kv.
    Успіх!
    Це пов'язано з тим, що наш «poc-ubuntu-custom-sa» відповідає прив'язкам правил «custom-sa» та «default-ns».

Висновок

TTL token mgmt?

На момент написання цієї статті немає інтегрованого способу визначення TTL для токенів, згенерованих цим методом авторизації. Це була б фантастична можливість забезпечити безпечну автоматизацію авторизації Consul.

Існує можливість вручну створити токен з TTL:

Сподіваюся, найближчим часом ми зможемо контролювати, як генеруються токени (для кожного правила чи методу авторизації), та додавати TTL.

До того часу пропонується використовувати у своїй логіці кінцеву точку виходу із системи.

Також читайте інші статті у нашому блозі:

Джерело: habr.com

Додати коментар або відгук