
Прим. прев.: от този цикъл беше посветена на запознаването с възможностите на Istio и тяхната демонстрация в действие, — фино настройвана маршрутизация и управление на мрежовия трафик. Сега ще говорим за безопасността: за демонстрация на свързаните с нея основни функции авторът използва identity-сервиза Auth0, но по аналогия с него могат да се настройват и други доставчици.
Настроихме Kubernetes-клъстер, в който развихме Istio и примерна микросервисна без приложение Sentiment Analysis, — така бяха демонстрирани възможностите на Istio.
С помощта на Istio успяхме да запазим малкия размер на услугите, тъй като те не се нуждаят от реализиране на такива „слоеве“, като повторни опити за свързване (Retries), таймаути (Timeouts), автоматични прекъсвачи (Circuit Breakers), трасировка (Tracing), мониторинг (Monitoring). Освен това, използвахме техники за напреднало тестване и разгръщане: A/B-тестиране, зеркалирaне и канарейни внедрения.

В новият материал ще разгледаме финалните слоеве на пътя към бизнес стойността: автентикация и авторизация — и в Istio това е истинско удоволствие!
Автентикация и авторизация в Istio
Никога не бих повярвал, че ще се вдъхновя от автентикацията и авторизацията. Какво може да предложи Istio от технологична гледна точка, за да направи тези теми интересни и дори да вдъхнови и вас?
Отговорът е прост: Istio прехвърля отговорността за тези възможности от вашите услуги на проксито Envoy. До момента, в който заявките достигнат услугите, те вече са автентифицирани и авторизирани, така че вие просто трябва да пишете полезен за бизнеса код.
Звучи добре? Нека да надникнем вътре!
Автентикация с Auth0
Като сървър за управление на идентичността и достъпа ще използваме Auth0, който има безплатна версия, интуитивен за използване и просто ми харесва. Въпреки това, същите принципи могат да се приложат и спрямо всяка друга : KeyCloak, IdentityServer и много други.
За начало, влезте на с вашия акаунт, създайте tenant (tenant — „наемател“, логическа единица изолация, подробно в — забележка на преводача) и отидете в Applications > Default App, избирайки Домейн, както е показано на скрийншота по-долу:

Посочете този домейн в файла resource-manifests/istio/security/auth-policy.yaml ():
apiVersion: authentication.istio.io/v1alpha1
kind: Policy
metadata:
name: auth-policy
spec:
targets:
- name: sa-web-app
- name: sa-feedback
origins:
- jwt:
issuer: "https://{YOUR_DOMAIN}/"
jwksUri: "https://{YOUR_DOMAIN}/.well-known/jwks.json"
principalBinding: USE_ORIGIN С този ресурс, Pilot (един от трите основни компонента Control Plane в Istio — бел. ред.) настройва Envoy за аутентификация на заявките преди да ги пренасочи към услугите: sa-web-app и sa-feedback. В същото време конфигурацията не се прилага към Envoy на услугата sa-frontend, позволявайки ни да оставим фронтенда неаутентифициран. За да приложите политиката (Policy), изпълнете командата:
$ kubectl apply -f resource-manifests/istio/security/auth-policy.yaml
policy.authentication.istio.io “auth-policy” createdВърнете се на страницата и направете заявка — ще видите, че тя ще завърши със статус 401 Unauthorized. Сега ще пренасочим потребителите на фронтенда към аутентификация с Auth0.
Аутентификация на заявките с Auth0
За да аутентифицирате заявките на крайния потребител, е необходимо да създадете API в Auth0, който ще представлява аутентифицирани услуги (ревюта, детайли и оценки). За да създадете API, отидете в Auth0 Portal > APIs > Create API и попълнете формуляра:

Важно е тук Identifier, който след това ще използваме в скрипта. Запишете го така:
- Audience: {YOUR_AUDIENCE}
Останалите нужни детайли се намират в Auth0 Portal в раздела Applications — изберете Test Application (създава се автоматично заедно с API).
Тук ще запишем:
- Домейн: {YOUR_DOMAIN}
- Client Id: {YOUR_CLIENT_ID}
Превъртете надолу до текстовото поле Test Application Allowed Callback URLs (разрешени URL адреси за callback), в което ще укажем URL адреса, на който трябва да се изпрати извикването след приключване на аутентификацията. В нашия случай това е: http://{EXTERNAL_IP}/callback
А заAllowed Logout URLs (разрешени URL адреси за разлогиниране) добавете: http://{EXTERNAL_IP}/logout
Преминете към фронтенда.Актуализиране на фронтенда
Превключете на клон
auth0 репозитория [istio-mastery] . В този клон кодът на фронтенда е променен, за да пренасочва потребителите към Auth0 за аутентификация и да използва JWT токен в заявките към останалите услуги. Последното е реализирано по следния начин (analyzeSentence() { fetch('/sentiment', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${auth.getAccessToken()}` // Access Token }, body: JSON.stringify({ sentence: this.textField.getValue() }) }) .then(response => response.json()) .then(data => this.setState(data)); }):
} За да преведете фронтенда за използване на данните на наемателя в Auth0, отворете sa-frontend/src/services/Auth.js и заменете стойностите, които записахме по-горе в него ():
const Config = {
clientID: '{YOUR_CLIENT_ID}',
domain:'{YOUR_DOMAIN}',
audience: '{YOUR_AUDIENCE}',
ingressIP: '{EXTERNAL_IP}' // Използва се за пренасочване след удостоверяване
}Приложението е готово. Посочете своя Docker ID в командите по-долу при изграждане и деплой на направените промени:
$ docker build -f sa-frontend/Dockerfile
-t $DOCKER_USER_ID/sentiment-analysis-frontend:istio-auth0
sa-frontend
$ docker push $DOCKER_USER_ID/sentiment-analysis-frontend:istio-auth0
$ kubectl set image deployment/sa-frontend
sa-frontend=$DOCKER_USER_ID/sentiment-analysis-frontend:istio-auth0Опитайте приложението! Ще бъдете пренасочени към Auth0, където трябва да влезете (или да се регистрирате), след което ще бъдете върнати обратно на страницата, от която ще се извършват удостоверените заявки. Ако опитате командите с curl, споменати в първите части на статията, ще получите код 401 Status Code, сигнализиращ, че заявката не е удостоверена.
Ще направим следващата стъпка — ще удостоверим заявките.
Удостоверяване с Auth0
Аутентификацията позволява да разберем кой е потребителят, но за да разберем до какво има достъп, е необходимо удостоверяване. Istio предлага инструменти и за това.
Като пример, да създадем две групи потребители (вижте схемата по-долу):
- Потребители (users) — с достъп само до услугите SA-WebApp и SA-Frontend;
- Модератори (moderators) — с достъп до всичките три услуги.

Концепция за удостоверяване
За да създадем тези групи, ще използваме разширението Auth0 Authorization и с помощта на Istio ще им предоставим различни нива на достъп.
Инсталиране и конфигуриране на Auth0 Authorization
В портала Auth0 отидете на разширенията (Extensions) и инсталирайте Auth0 Authorization. След инсталацията отидете на Authorization Extension, а там — на конфигурацията на наемателя, като кликнете вдясно горе и изберете съответната опция от менюто (Configuration). Активирайте групите (Groups) и натиснете бутона за публикуване на правилото (Publish rule).

Създаване на групи
В Authorization Extension отидете на Groups и създайте група Moderators. Тъй като ще разглеждаме всички удостоверени потребители като обикновени, нуждата от създаване на допълнителна група за тях не е необходима.
Изберете група Moderators, натиснете на Add Members, добавете своя основен акаунт. Оставете някои потребители без никаква група, за да се уверите, че достъпът за тях е забранен. (Новите потребители могат да се създават ръчно през Auth0 Portal > Users > Create User.)
Добавете Group Claim в Access Token
Потребителите са добавени в групи, но тази информация трябва да бъде отразена и в токените за достъп. За да отговаря на OpenID Connect и в същото време да върне групите, които ни трябват, токенът ще трябва да добави своето . Реализира се чрез правила Auth0.
За да създадете правило, отидете на Auth0 Portal в Rules, натиснете на Създаване на правило и изберете празно правило от шаблоните.

Копирайте кода по-долу и го запазете като ново правило Добавяне на Group Claim ():
function (user, context, callback) {
context.accessToken['https://sa.io/group'] = user.groups[0];
return callback(null, user, context);
}Забележка: този код взима първата група на потребителя, определена в Authorization Extension, и я добавя в access-токена като custom claim (под собственото си пространство на имената, както изисква Auth0).
Върнете се на страницата Rules и проверете, че имате две правила, записани в следния ред:
- auth0-authorization-extension
- Добавяне на Group Claim
Порядъкът е важен, защото полето за група асинхронно получава правилото auth0-authorization-extension и след това се добавя като claim с второто правило. В резултат получавате такъв access-токен:
{
"https://sa.io/group": "Moderators",
"iss": "https://sentiment-analysis.eu.auth0.com/",
"sub": "google-oauth2|196405271625531691872"
// [съкратено за наглядност]
} Сега е необходимо да конфигурирате Envoy-прокси за проверка на потребителския достъп, за което групата ще се вземе от claim (https://sa.io/group) в връщания access-токен. Това е тема за следващия раздел на статията.
Конфигурация на авторизацията в Istio
За да заработи авторизацията, е необходимо да активирате RBAC за Istio. За това ще използваме следната конфигурация:
apiVersion: "rbac.istio.io/v1alpha1"
kind: RbacConfig
metadata:
name: default
spec:
mode: 'ON_WITH_INCLUSION' # 1
inclusion:
services: # 2
- "sa-frontend.default.svc.cluster.local"
- "sa-web-app.default.svc.cluster.local"
- "sa-feedback.default.svc.cluster.local" Обяснения:
- 1 — активираме RBAC само за услугите и пространствата на имената, изброени в полето
Inclusion; - 2 — изброяваме списък с нашите услуги.
Приложете конфигурацията с тази команда:
$ kubectl apply -f resource-manifests/istio/security/enable-rbac.yaml
rbacconfig.rbac.istio.io/default created Сега всички услуги изискват управление на достъпа на основата на роли (Role-Based Access Control). С други думи, достъпът до всички услуги е забранен и ще доведе до отговор RBAC: достъп забраненСега ще разрешим достъпа на упълномощени потребители.
Конфигурация на достъпа за обикновени потребители
Всички потребители трябва да имат достъп до услугите SA-Frontend и SA-WebApp. Това се реализира чрез следните ресурси на Istio:
- ServiceRole — определя правата, които има потребителят;
- ServiceRoleBinding — определя на кого се отнася тази ServiceRole.
За обикновените потребители ще разрешим достъп до определени услуги ():
apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRole
metadata:
name: regular-user
namespace: default
spec:
rules:
- services:
- "sa-frontend.default.svc.cluster.local"
- "sa-web-app.default.svc.cluster.local"
paths: ["*"]
methods: ["*"] А чрез regular-user-binding прилагаме ServiceRole на всички посетители на страницата ():
apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRoleBinding
metadata:
name: regular-user-binding
namespace: default
spec:
subjects:
- user: "*"
roleRef:
kind: ServiceRole
name: "regular-user"Означава ли «всички потребители», че и неидентифицираните потребители ще получат достъп до SA WebApp? Не, политиката ще провери валидността на JWT токена.
Прилагаме конфигурации:
$ kubectl apply -f resource-manifests/istio/security/user-role.yaml
servicerole.rbac.istio.io/regular-user created
servicerolebinding.rbac.istio.io/regular-user-binding createdКонфигурация на достъпа за модератори
За модераторите искаме да включим достъп до всички услуги ():
apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRole
metadata:
name: mod-user
namespace: default
spec:
rules:
- services: ["*"]
paths: ["*"]
methods: ["*"] Но искаме тези права само за потребители, при които в access-токена присъства claim https://sa.io/group со значением Moderators ():
apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRoleBinding
metadata:
name: mod-user-binding
namespace: default
spec:
subjects:
- properties:
request.auth.claims[https://sa.io/group]: "Moderators"
roleRef:
kind: ServiceRole
name: "mod-user" Прилагаме конфигурации:
$ kubectl apply -f resource-manifests/istio/security/mod-role.yaml
servicerole.rbac.istio.io/mod-user created
servicerolebinding.rbac.istio.io/mod-user-binding createdПоради кеширане в envoy-ите, за да влязат в сила правилата за авторизация, могат да са необходими няколко минути. След това ще можете да се уверите, че потребителите и модераторите имат различни нива на достъп.
Заключение по тази част
Честно казано: виждали ли сте някога по-прост, безусилиен, мащабируем и безопасен подход към аутентификацията и авторизацията?
Само три ресурса на Istio (RbacConfig, ServiceRole и ServiceRoleBinding) бяха необходими, за да постигнем прецизен контрол над аутентификацията и авторизацията на достъпа на крайни потребители до услугите.
Освен това, ние преместихме решението на тези проблеми извън нашите услуги в envoy, достигайки:
- намаляване на количеството типичен код, в който могат да се съдържат проблеми със сигурността и бъгове;
- снижаване на броя на глупавите ситуации, в които един endpoint се оказа достъпен отвън и забрави да съобщи за това;
- елиминирането на нуждата от актуализиране на всички услуги при всяко добавяне на нова роля или разрешение;
- за това, че новите услуги остават прости, безопасни и бързи.
Извод
Istio позволява на екипите да се фокусират върху важните за бизнеса задачи, без да добавя накладни разходи на услугите, връщайки ги в статус на «микро».
Статията (в три части) предостави основни знания и готова практическа инструкция за започване на работа с Istio в реални проекти.
P.S. от преводача
Прочетете също в нашия блог:
- «Назад към микросервисите с Istio»: , ;
- «»;
- «».
Източник: habr.com
