Обратно към микросервисите заедно с Istio. Част 3

Обратно към микросервисите заедно с Istio. Част 3

Прим. прев.: Първа част от този цикъл беше посветена на запознаването с възможностите на Istio и тяхната демонстрация в действие, втора — фино настройвана маршрутизация и управление на мрежовия трафик. Сега ще говорим за безопасността: за демонстрация на свързаните с нея основни функции авторът използва identity-сервиза Auth0, но по аналогия с него могат да се настройват и други доставчици.

Настроихме Kubernetes-клъстер, в който развихме Istio и примерна микросервисна без приложение Sentiment Analysis, — така бяха демонстрирани възможностите на Istio.

С помощта на Istio успяхме да запазим малкия размер на услугите, тъй като те не се нуждаят от реализиране на такива „слоеве“, като повторни опити за свързване (Retries), таймаути (Timeouts), автоматични прекъсвачи (Circuit Breakers), трасировка (Tracing), мониторинг (Monitoring). Освен това, използвахме техники за напреднало тестване и разгръщане: A/B-тестиране, зеркалирaне и канарейни внедрения.

Обратно към микросервисите заедно с Istio. Част 3

В новият материал ще разгледаме финалните слоеве на пътя към бизнес стойността: автентикация и авторизация — и в Istio това е истинско удоволствие!

Автентикация и авторизация в Istio

Никога не бих повярвал, че ще се вдъхновя от автентикацията и авторизацията. Какво може да предложи Istio от технологична гледна точка, за да направи тези теми интересни и дори да вдъхнови и вас?

Отговорът е прост: Istio прехвърля отговорността за тези възможности от вашите услуги на проксито Envoy. До момента, в който заявките достигнат услугите, те вече са автентифицирани и авторизирани, така че вие просто трябва да пишете полезен за бизнеса код.

Звучи добре? Нека да надникнем вътре!

Автентикация с Auth0

Като сървър за управление на идентичността и достъпа ще използваме Auth0, който има безплатна версия, интуитивен за използване и просто ми харесва. Въпреки това, същите принципи могат да се приложат и спрямо всяка друга реализация на OpenID Connect: KeyCloak, IdentityServer и много други.

За начало, влезте на Auth0 Portal с вашия акаунт, създайте tenant (tenant — „наемател“, логическа единица изолация, подробно в документацията — забележка на преводача) и отидете в Applications > Default App, избирайки Домейн, както е показано на скрийншота по-долу:

Обратно към микросервисите заедно с Istio. Част 3

Посочете този домейн в файла 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 и попълнете формуляра:

Обратно към микросервисите заедно с Istio. Част 3

Важно е тук 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)); }App.js):

}

За да преведете фронтенда за използване на данните на наемателя в Auth0, отворете sa-frontend/src/services/Auth.js и заменете стойностите, които записахме по-горе в него (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) — с достъп до всичките три услуги.

Обратно към микросервисите заедно с Istio. Част 3
Концепция за удостоверяване

За да създадем тези групи, ще използваме разширението Auth0 Authorization и с помощта на Istio ще им предоставим различни нива на достъп.

Инсталиране и конфигуриране на Auth0 Authorization

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

Обратно към микросервисите заедно с Istio. Част 3

Създаване на групи

В Authorization Extension отидете на Groups и създайте група Moderators. Тъй като ще разглеждаме всички удостоверени потребители като обикновени, нуждата от създаване на допълнителна група за тях не е необходима.

Изберете група Moderators, натиснете на Add Members, добавете своя основен акаунт. Оставете някои потребители без никаква група, за да се уверите, че достъпът за тях е забранен. (Новите потребители могат да се създават ръчно през Auth0 Portal > Users > Create User.)

Добавете Group Claim в Access Token

Потребителите са добавени в групи, но тази информация трябва да бъде отразена и в токените за достъп. За да отговаря на OpenID Connect и в същото време да върне групите, които ни трябват, токенът ще трябва да добави своето custom claim. Реализира се чрез правила Auth0.

За да създадете правило, отидете на Auth0 Portal в Rules, натиснете на Създаване на правило и изберете празно правило от шаблоните.

Обратно към микросервисите заедно с Istio. Част 3

Копирайте кода по-долу и го запазете като ново правило Добавяне на Group Claim (namespacedGroup.js):

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.

За обикновените потребители ще разрешим достъп до определени услуги (servicerole.yaml):

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 на всички посетители на страницата (regular-user-service-role-binding.yaml):

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

Конфигурация на достъпа за модератори

За модераторите искаме да включим достъп до всички услуги (mod-service-role.yaml):

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 (mod-service-role-binding.yaml):

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. от преводача

Прочетете също в нашия блог:

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster