
Всичко е вярно, след излизането в началото на май 2019 година в Consul можем да правим авторизация на приложения и услуги, стартирани в Kubernetes, нативно.
В това ръководство стъпка по стъпка ще създадем (Проверка на концепцията (Proof of concept, PoC — доказателство [осъществимост] на концепцията — бел. прев.), демонстрирайки тази нова функция. Очакват се основни знания за Kubernetes и Hashicorp’s Consul. И макар че можете да използвате всяка облачна платформа или локална среда, в това ръководство ще използваме Google’s Cloud Platform.
Преглед
Ако преминем към , ще получим кратък преглед на целта и вариантите на използване, както и някои технически подробности и общ преглед на логиката. Настоятелно препоръчвам да я прочетете поне веднъж, преди да продължите, тъй като сега ще обяснявам и разглеждам всичко.

Схема 1: Официален преглед на метода за авторизация на Consul
Нека да погледнем в .
Разбира се, там има полезна информация, но няма ръководство за това как всъщност да се използва всичко това. Затова, като всеки разумен човек, вие преровявате Интернет в търсене на ръководство. А после… Ами, неуспех. Така става. Нека да го коригираме.
Преди да преминем към създаването на нашия POC, нека се върнем към прегледа на методите за авторизация на Consul (Схема 1) и да го уточним в контекста на Kubernetes.
Архитектура
В това ръководство ще създадем Consul-сървър на отделна машина, който ще взаимодействат с кластера Kubernetes с инсталиран клиент Consul. След това ще създадем нашето фиктивно приложение в пода и ще използваме нашия настроен метод за авторизация, за да четем от нашето Consul key/value хранилище.
Схемата по-долу подробно показва архитектурата, която създаваме в това ръководство, както и логиката на метода за авторизация, която ще бъде обяснена по-късно.

Схема 2: Преглед на метода за авторизация в Kubernetes
Небольшо уточнение: Consul-сървърът не е необходимо да бъде извън кластера Kubernetes, за да работи. Но да, той може както да бъде, така и да не бъде.
Така че, взимайки схемата на Consul (Схема 1) и прилагаща я към Kubernetes, получаваме схемата по-горе (Схема 2), и логиката ще бъде следната:
- Към всеки под ще бъде прикрепен служебен акаунт, съдържащ JWT токен, генериран и известен на Kubernetes. Този токен също се вмъква в пода по подразбиране.
- Нашето приложение или услуга в пода инициира команда за вход в нашия Consul клиент. В заявката за вход ще бъде посочен нашият токен и името на специално създаденото метод на авторизация (тип Kubernetes). Тази стъпка № 2 отговаря на стъпка 1 от схемата на Consul (Схема 1).
- Нашият Consul клиент след това ще изпрати тази заявка на нашия Consul сървър.
- МАГИЯ! Именно тук Consul сървърът проверява автентичността на заявката, събира информация за идентичността и я сравнява с каквито и да било свързани предварително зададени правила. По-долу ще има друга схема, за да илюстрира това. Тази стъпка отговаря на стъпки 3, 4 и 5 от прегледната схема на Consul (Схема 1).
- Нашият Consul сървър генерира Consul токен с разрешения в съответствие с посочените от нас правила на метода на авторизация (които сме задали) спрямо идентичността на запитващия. След това той ще изпрати този токен обратно. Това отговаря на стъпка 6 от схемата на Consul (Схема 1).
- Нашият Consul клиент пренасочва токена към запитващото приложение или услуга.
Нашето приложение или услуга сега могат да използват този Consul токен, за да взаимодействат с нашите данни от Consul, както е определено от разрешенията на токена.
Магията е разкрита!
За тези от вас, които не се задоволяват само с заек из шапка и искат да знаят как работи… позволете ми да "покажа колко дълбока е заячата дупка».
Както беше споменато по-рано, нашата "магическа" стъпка (Схема 2: Стъпка 4) е, че Consul сървърът проверява автентичността на заявката, събира информация и я сравнява с каквито и да било свързани предварително зададени правила. Тази стъпка отговаря на стъпки 3, 4 и 5 от прегледната схема на Consul (Схема 1). По-долу е схема (Схема 3), чиято цел е наглядно да покаже какво всъщност се случва под капака на конкретния метод на авторизация Kubernetes.

Схема 3: Магията разкрита!
- Като отправна точка, нашият Consul клиент пренасочва заявката за вход към нашия Consul сървър с токена на акаунта в Kubernetes и конкретното име на инстанцията на метода на авторизация, който е бил създаден по-рано. Тази стъпка отговаря на стъпка 3 от предишното обяснение на схемата.
- Сега на Consul-сервера (или лидера) е необходимо да провери автентичността на полученото токен. Затова той ще се консултира с кластер Kubernetes (чрез клиента Consul) и, при наличието на съответни разрешения, ние ще установим дали токенът е автентичен и на кого принадлежи.
- След това проверената заявка се връща към Consul-лидера и на сървера Consul се извършва търсене на инстанция на метода за удостоверяване с посоченото име от заявката за вход в системата (и тип Kubernetes).
- Consul-лидерът определя посочената инстанция на метода за удостоверяване (ако е намерена) и прочита набора от правила, които са прикрепени към нея. След това той чете тези правила и ги сравнява с проверените атрибути на идентичността.
- Ура! Преминаваме към стъпка 5 от предишното обяснение на схемата.
Стартирайте Consul-сървера на обикновена виртуална машина.
От този момент нататък основно ще давам инструкции за създаване на този POC, често в точки, без обяснителни цели изречения. Както беше отбелязано по-рано, ще използвам GCP за създаване на цялата инфраструктура, но можете да създадете същата инфраструктура и на друго място.
- Стартирайте виртуалната машина (инстанция / сървър).

- Създайте правило за firewall (група за сигурност в AWS):
- Обичам да присвоявам същото име на машината и на правилото и мрежовия таг, в този случай „skywiz-consul-server-poc“.
- Намерете IP адреса на локалния си компютър и го добавете в списъка с изходящи IP адреси, за да можем да получим достъп до интерфейса на потребителя (UI).
- Отворете порт 8500 за UI. Натиснете Create (Създаване). Скоро ще променим отново този firewall [].
- Добавете правило за firewall към инстанцията. Върнете се на таблото за управление на VM на Consul-сървера и добавете „skywiz-consul-server-poc“ в полето за мрежови тагове. Натиснете Save (Записване).

- Инсталирайте 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- Трябва да видите много изходни данни и в крайна сметка „… актуализация блокирана от ACLs“.
- Намерете външния IP адрес на Consul сървъра и отворете браузър с този IP адрес на порт 8500. Убедете се, че UI се отваря.
- Опитайте да добавите няколко ключ/стойност. Трябва да получите грешка. Това е, защото сме заредили Consul сървъра с ACL и сме забранили всички правила.
- Върнете се в терминала на Consul сървъра и стартирайте процеса на заден план или по друг начин, за да работи, и въведете следното:
consul acl bootstrap- Намерете стойността „SecretID“ и се върнете в UI. На раздела „ACL“ въведете секретния идентификатор на токена, който току-що копирахте. Копирайте SecretID още някъде, той ще ни бъде нужен по-късно.
- Сега добавете двойка ключ/стойност. За този POC ще добавим следното: ключ: „custom-ns/test_key“, стойност: „Аз съм в папката custom-ns!“
Стартиране на Kubernetes клъстер за нашето приложение с Consul клиент като Daemonset
- Създайте K8s (Kubernetes) клъстер. Ще го създадем в същата зона като сървера, за по-бърз достъп, и затова можем да използваме същата подсет, за да се свържем с вътрешни IP адреси. Ще го наречем „skywiz-app-with-consul-client-poc“.

- Като забележка, ето хубаво ръководство, с което се сблъсках, когато настройвах 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- helm chart:
- Използвайте следния файл за стойности (обърнете внимание, че повечето от тях деактивирах):
### 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“, разположен на таблото на клъстера, и се върнете към нашето правило за защитна стена „skywiz-consul-server-poc“.
- Добавете диапазона от адреси за пода в списъка с IP адреси и отворете портове 8301 и 8300.

- Отидете на Consul UI и след няколко минути ще видите, че нашият клъстер ще се появи на раздела с възли.

Настройка на метода за удостоверяване чрез интеграция на Consul с Kubernetes
- Върнете се в терминала на Consul сървъра и експортирайте токена, който запазихте по-рано:
export CONSUL_HTTP_TOKEN=- Ще ни е необходима информация от нашия Kubernetes клъстър, за да създадем инстанция на метода за удостоверяване:
- kubernetes-host
kubectl get endpoints | grep kubernetes- kubernetes-service-account-jwt
kubectl get sa -consul-client -o yaml | grep "- name:"
kubectl get secret -o yaml | grep token:- Токенът е кодирана в base64, затова го разкодирайте с любимия си инструмент []
- kubernetes-ca-cert
kubectl get secret -o yaml | grep ca.crt:- Вземете сертификата “ca.crt” (след разкодиране с base64) и го запишете във файла “ca.crt”.
- Сега създайте инстанция на метода за удостоверяване, заменяйки плейсхолдерите с получените по-рано стойности.
consul acl auth-method create
-type "kubernetes"
-name "auth-method-skywiz-consul-poc"
-description "Това е метод за удостоверяване, използващ kubernetes за клъстера skywiz-app-with-consul-client-poc"
-kubernetes-host ""
-kubernetes-ca-cert=@ca.crt
-kubernetes-service-account-
jwt=""- След това трябва да създадем правило и да го присъединим към новата роля. За тази част можете да използвате Consul UI, но ще използваме командния ред.
- Напишете правило
### kv-custom-ns-policy.hcl
key_prefix "custom-ns/" {
policy = "write"
}- Прилагане на правилото
consul acl policy create
-name kv-custom-ns-policy
-description "Това е примерен политика за kv на custom-ns/"
-rules @kv-custom-ns-policy.hcl- Намерете идентификатора на правилото, което току-що създадохте, от изходните данни.
- Създайте роля с новото правило.
consul acl role create
-name "custom-ns-role"
-description "Това е примерна роля за namespace custom-ns"
-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) и стойност по ваш избор. Създайте съответни политики и роли за новите ключови пътища. Ще направим връзките по-късно.

Пользовательски тест на пространството имен:
- Нека създадем свое собствено пространство имен:
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: ”- Можете да декодирате стойността 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". Успех!
- Проверете нашия достъп до ключовия път custom-sa/.
curl
consul-ds-client.default.svc.cluster.local/v1/kv/custom-sa/test_key --header “X-Consul-Token: ”- Можете също така да се уверите, че този токен не предоставя достъп до kv в "custom-ns/". Просто повторете горепосочената команда, след като замените "custom-sa" с приставката "custom-ns".
Достъп отказан.
Пример за оверлей:
- Следва да се отбележи, че всички свързвания за правила ще бъдат добавени към токена с тези права.
- Нашият контейнер "poc-ubuntu-custom-sa" се намира в пространството на имена по подразбиране — затова нека го използваме за друго свързване на правила.
- Повторете предишните стъпки:
а) Създайте идентична Политика за приставката на ключа "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". Токенът, който в момента използваме, е генериран, когато влязохме в системата, и тогава имаше само едно свързване на правила, което отговаряше. Трябва да влезем отново в системата и да използваме нов токен. - Уверете се, че можете да четете както от пътищата "custom-sa/", така и от "default/" kv.
Успех!
Това е, защото нашият "poc-ubuntu-custom-sa" отговаря на свързванията на правила "custom-sa" и "default-ns".
Заключение
Управление на TTL за токени?
Към момента на написване на тази статия не съществува интегриран начин за определяне на TTL за токените, генерирани чрез този метод на авторизация. Това би била фантастична възможност — да се осигури безопасна автоматизация на авторизацията в Consul.
Има възможност ръчно да се създаде токен с TTL:
Expiration Time (Време на изтичане) — времето, когато този токен ще бъде оттеглен. (Не е задължително; добавено в Consul 1.5.0)- Съществува само за ръчно създаване / актуализиране
Надявам се в близко бъдеще да можем да контролираме как се генерират токените (за всяко правило или метод на авторизация) и да добавим TTL.
Докато е така, се предлага да използвате в логиката си крайната точка за изход.
Също така прочетете и други статии в нашия блог:
Източник: habr.com
