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

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

Схема 2: Преглед на метода за авторизация в Kubernetes
Няколко забележки: на Consul сървъра не му е необходимо да се намира извън кластерa на 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 за изграждането на цялата инфраструктура, но можете да създадете същата инфраструктура на всяко друго място.
- Стартирайте виртуалната машина (инстанс / сървър).

- Създайте правило за защитната стена (група за сигурност в AWS):
- Обичам да присвоявам същото име на машината на правилото и мрежовия таг, в този случай това е "skywiz-consul-server-poc".
- Намерете IP адреса на локалния си компютър и го добавете в списъка на изходящите IP адреси, за да можем да имаме достъп до потребителския интерфейс (UI).
- Отворете порт 8500 за UI. Щракнете върху Create (Създаване). Скоро отново ще променим тази защитна стена [].
- Добавете правило за защитната стена към инстанса. Върнете се на таблото за мониторинг на 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- Трябва да видите куп изходни данни и в крайна сметка „... update blocked by ACLs“.
- Намерете външния IP адрес на Consul сървъра и отворете браузър с този IP адрес на порт 8500. Уверете се, че интерфейсът на потребителя се отваря.
- Опитайте да добавите двойка ключ/стойност. Трябва да получите грешка. Това е така, защото сме заредили Consul сървъра с ACL и сме забранили всички правила.
- Върнете се в терминала на Consul сървъра и стартирайте процеса във фонов режим или по друг начин, за да работи, и въведете следното:
consul acl bootstrap- Намерете стойността „SecretID“ и се върнете в интерфейса. На таба „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.
- Също така ще използваме Helm chart на Hashicorp с разширен файл с настройки.
- Инсталирайте и конфигурирайте 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 и след няколко минути ще видите, че нашият клъстер ще се появи на таба с възли.

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