Torna ai microservizi con Istio. Parte 3

Torna ai microservizi con Istio. Parte 3

Nota di traduzione.: Prima parte di questo ciclo è stata dedicata alla scoperta delle potenzialità di Istio e alla loro dimostrazione in azione, seconda — routing fine-tuned e gestione del traffico di rete. Adesso parleremo della sicurezza: per dimostrare le relative funzionalità di base, l'autore utilizza il servizio di identità Auth0, ma anche altri provider possono essere configurati in modo analogo.

Abbiamo configurato un cluster Kubernetes in cui abbiamo distribuito Istio e un esempio di applicazione di microservizi Sentiment Analysis, dimostrando così le potenzialità di Istio.

Grazie a Istio siamo riusciti a mantenere ridotte le dimensioni dei servizi, poiché non necessitano dell'implementazione di "strati" come i tentativi di riconnessione (Retries), i timeout (Timeouts), i circuit breaker (Circuit Breakers), la tracciatura (Tracing), e il monitoraggio (Monitoring). Inoltre, abbiamo utilizzato tecniche di test avanzate e distribuzione: A/B testing, mirroring e deployment canarino.

Torna ai microservizi con Istio. Parte 3

Nel nuovo materiale ci concentreremo sugli strati finali verso il valore aziendale: autenticazione e autorizzazione — e in Istio è un vero piacere!

Autenticazione e autorizzazione in Istio

Non avrei mai creduto di poter essere ispirato dall'autenticazione e dall'autorizzazione. Cosa può offrire Istio dal punto di vista tecnologico per rendere questi temi coinvolgenti e persino ispiratori per voi?

La risposta è semplice: Istio sposta la responsabilità di queste funzionalità dai vostri servizi al proxy Envoy. Quando le richieste raggiungono i servizi, sono già autenticate e autorizzate, quindi non vi resta che scrivere codice utile per il business.

Suona bene? Andiamo a dare un'occhiata dentro!

Autenticazione con Auth0

Come server per la gestione dell'identità e dell'accesso utilizzeremo Auth0, che ha una versione di prova, è intuitivo da usare e mi piace semplicemente. Tuttavia, gli stessi principi possono essere applicati anche ad altre implementazioni di OpenID Connect: KeyCloak, IdentityServer e molte altre.

Per iniziare, visitate Auth0 Portal con il vostro account, create un tenant (tenant — "affittuario", unità logica di isolamento, vedi documentazione — nota del traduttore.) e navigate a Applications > Default App, selezionando Dominio, come mostrato nello screenshot qui sotto:

Torna ai microservizi con Istio. Parte 3

Specifica questo dominio nel file resource-manifests/istio/security/auth-policy.yaml (sorgente):

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

Avendo a disposizione questa risorsa, Pilot (uno dei tre componenti base del Control Plane in Istio — nota del traduttore) configura gli Envoy per l'autenticazione delle richieste prima di reindirizzarle ai servizi: sa-web-app e sa-feedback. Allo stesso tempo, la configurazione non si applica agli Envoy del servizio sa-frontend, permettendoci di lasciare il frontend non autenticato. Per applicare la politica (Policy), esegui il comando:

$ kubectl apply -f resource-manifests/istio/security/auth-policy.yaml
policy.authentication.istio.io "auth-policy" creata

Torna alla pagina e fai una richiesta — vedrai che terminerà con stato 401 Unauthorized. Ora reindirizziamo gli utenti del frontend all'autenticazione con Auth0.

Autenticazione delle richieste con Auth0

Per autenticare le richieste dell'utente finale, è necessario creare un'API in Auth0 che rappresenti i servizi autenticati (reviews, details e ratings). Per creare l'API, vai a Auth0 Portal > APIs > Create API e compila il modulo:

Torna ai microservizi con Istio. Parte 3

Un'informazione importante qui è Identifier, che utilizzeremo successivamente nello script. Scriviamolo così:

  • Audience: {YOUR_AUDIENCE}

I dettagli rimanenti di cui abbiamo bisogno si trovano nell'Auth0 Portal nella sezione Applications — seleziona Test Application (creata automaticamente insieme all'API).

Qui annoteremo:

  • Dominio: {YOUR_DOMAIN}
  • Client Id: {YOUR_CLIENT_ID}

Scorri fino al campo di testo Test Application Allowed Callback URLs (URL consentiti per il callback), in cui indicheremo l'URL a cui deve essere invocato il call dopo che l'autenticazione è completata. Nel nostro caso: http://{EXTERNAL_IP}/callback

E per

Allowed Logout URLs (URL consentiti per il logout) aggiungiamo: http://{EXTERNAL_IP}/logout

Passiamo al frontend.

Aggiornamento del frontend

Cambia il ramo

auth0 del repository [istio-mastery] . In questo ramo il codice del frontend è stato modificato per reindirizzare gli utenti a Auth0 per l'autenticazione e utilizzare il token JWT nelle richieste ad altri servizi. Ultimo, implementato nel seguente modo (. In questo branch, il codice frontend è stato modificato in modo da reindirizzare gli utenti a Auth0 per l'autenticazione e utilizzare un token JWT nelle richieste agli altri servizi. Questo è stato realizzato nel seguente modo (App.js):

analyzeSentence() {
    fetch('/sentiment', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${auth.getAccessToken()}` // Token di Accesso
        },
        body: JSON.stringify({ sentence: this.textField.getValue() })
    })
        .then(response => response.json())
        .then(data => this.setState(data));
}

Per tradurre il frontend per l'utilizzo dei dati del tenant in Auth0, apri sa-frontend/src/services/Auth.js e sostituisci i valori che abbiamo annotato sopra (Auth.js):

const Config = {
    clientID: '{YOUR_CLIENT_ID}',
    domain: '{YOUR_DOMAIN}',
    audience: '{YOUR_AUDIENCE}',
    ingressIP: '{EXTERNAL_IP}' // Utilizzato per il redirect dopo l'autenticazione
}

L'app è pronta. Indica il tuo Docker ID nei comandi qui sotto durante la costruzione e il deploy delle modifiche effettuate:

$ 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

Prova l'applicazione! Sarai reindirizzato a Auth0, dove dovrai effettuare il login (o registrarti), dopodiché sarai riportato alla pagina da cui verranno effettuate le richieste già autenticate. Se provi a eseguire i comandi menzionati nelle prime parti dell'articolo con curl, riceverai il codice 401 Status Code, che segnala che la richiesta non è autorizzata.

Facciamo il passo successivo: autorizziamo le richieste.

Autorizzazione con Auth0

L'autenticazione ci permette di capire chi è l'utente, ma per sapere a cosa ha accesso è necessaria l'autorizzazione. Istio offre strumenti anche per questo.

Come esempio, creeremo due gruppi di utenti (vedi lo schema qui sotto):

  • Utenti (users) — con accesso solo ai servizi SA-WebApp e SA-Frontend;
  • Moderatori (moderators) — con accesso a tutti e tre i servizi.

Torna ai microservizi con Istio. Parte 3
Concetto di autorizzazione

Per creare questi gruppi utilizzeremo l'estensione Auth0 Authorization e grazie a Istio daremo loro diversi livelli di accesso.

Installazione e configurazione di Auth0 Authorization

Nel portale Auth0 vai a estensioni (Extensions) e installa Auth0 Authorization. Dopo l'installazione, vai su Authorization Extension, quindi alla configurazione del tenant cliccando a destra in alto e selezionando l'opzione di menu appropriata (Configuration). Attiva i gruppi (Groups) e fai clic sul pulsante per pubblicare la regola (Publish rule).

Torna ai microservizi con Istio. Parte 3

Creazione di gruppi

Nell'Authorization Extension vai a Groups e crea un gruppo Moderatori. Poiché considereremo tutti gli utenti autenticati come normali, non c'è bisogno di creare un ulteriore gruppo per loro.

Seleziona gruppo Moderatori, fai clic su Aggiungi membri, aggiungi il tuo account principale. Lascia alcuni utenti senza alcun gruppo, per assicurarti che l'accesso a loro sia negato. (Nuovi utenti possono essere creati manualmente tramite Auth0 Portal > Utenti > Crea utente.)

Aggiungi il Group Claim nel Token di Accesso

Gli utenti sono stati aggiunti ai gruppi, tuttavia queste informazioni devono essere riflesse anche nei token di accesso. Per conformarsi a OpenID Connect e restituire i gruppi necessari, il token dovrà aggiungere il proprio custom claim. Questo viene realizzato tramite regole Auth0.

Per creare una regola, vai su Auth0 Portal a Regole, fai clic su Crea regola e seleziona una regola vuota dai modelli.

Torna ai microservizi con Istio. Parte 3

Copia il codice qui sotto e salvalo come nuova regola Aggiungi Group Claim (namespacedGroup.js):

function (user, context, callback) {
    context.accessToken['https://sa.io/group'] = user.groups[0];
    return callback(null, user, context);
}

Nota: questo codice prende il primo gruppo dell'utente, definito nell'Authorization Extension, e lo aggiunge nel token di accesso come custom claim (sotto il proprio namespace, come richiesto da Auth0).

Torna alla pagina Regole e verifica che tu abbia due regole registrate nel seguente ordine:

  • auth0-authorization-extension
  • Aggiungi Group Claim

L’ordine è importante, poiché il campo gruppo riceve la regola in modo asincrono auth0-authorization-extension e viene quindi aggiunto come claim dalla seconda regola. Di conseguenza, si ottiene un token di accesso come il seguente:

{
 "https://sa.io/group": "Moderators",
 "iss": "https://sentiment-analysis.eu.auth0.com/",
 "sub": "google-oauth2|196405271625531691872"
 // [ridotto per chiarezza]
}

Ora è necessario configurare il proxy Envoy per verificare l'accesso degli utenti, per cui il gruppo sarà estratto dal claim (https://sa.io/group) nel token di accesso restituito. Questo è un argomento per la prossima sezione dell'articolo.

Configurazione dell'autorizzazione in Istio

Per far funzionare l'autorizzazione, è necessario attivare RBAC per Istio. Per fare ciò, utilizziamo la seguente configurazione:

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" 

Spiegazioni:

  • 1 — attiviamo RBAC solo per i servizi e gli spazi dei nomi elencati nel campo Inclusione;
  • 2 — elenchiamo la nostra lista di servizi.

Applicheremo la configurazione con questo comando:

$ kubectl apply -f resource-manifests/istio/security/enable-rbac.yaml
rbacconfig.rbac.istio.io/default created

Ora tutti i servizi richiedono la gestione degli accessi basata sui ruoli (Role-Based Access Control). In altre parole, l'accesso a tutti i servizi è vietato e porterà a una risposta RBAC: accesso negato. Ora consentiamo l'accesso agli utenti autorizzati.

Configurazione dell'accesso per gli utenti normali

Tutti gli utenti devono avere accesso ai servizi SA-Frontend e SA-WebApp. Questo è realizzato con le seguenti risorse di Istio:

  • ServiceRole — definisce i diritti dell'utente;
  • ServiceRoleBinding — definisce a chi si riferisce questa ServiceRole.

Per gli utenti normali, consentiamo l'accesso a determinati servizi (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: ["*"]

E tramite regular-user-binding applicheremo la ServiceRole a tutti i visitatori della pagina (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"

Significa che "tutti gli utenti" implica che anche gli utenti non autenticati avranno accesso a SA WebApp? No, la politica verificherà la validità del token JWT.

Applicheremo le configurazioni:

$ 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

Configurazione dell'accesso per i moderatori

Per i moderatori vogliamo abilitare l'accesso a tutti i servizi (mod-service-role.yaml):

apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRole
metadata:
  name: mod-user
  namespace: default
spec:
  rules:
  - services: ["*"]
    paths: ["*"]
    methods: ["*"]

Ma vogliamo tali diritti solo per quegli utenti il cui token di accesso contiene un claim https://sa.io/group con valore Moderatori (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" 

Applicheremo le configurazioni:

$ 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

A causa della memorizzazione nella cache negli envoy, potrebbero essere necessari alcuni minuti affinché le regole di autorizzazione abbiano effetto. Dopo di che, potrai verificare che gli utenti e i moderatori abbiano livelli di accesso diversi.

Conclusione su questa parte

Bene, davvero: avete mai visto un approccio più semplice, senza sforzi, scalabile e sicuro per l'autenticazione e l'autorizzazione?

Bastano tre risorse di Istio (RbacConfig, ServiceRole e ServiceRoleBinding) per ottenere un controllo preciso sull'autenticazione e l'autorizzazione dell'accesso degli utenti finali ai servizi.

Inoltre, abbiamo spostato la gestione di questi problemi dai nostri servizi a envoy, ottenendo:

  • una riduzione della quantità di codice standardizzato in cui potrebbero sorgere problemi di sicurezza e bug;
  • una diminuzione delle situazioni imbarazzanti in cui un endpoint è risultato accessibile dall'esterno senza avvisarlo;
  • l'eliminazione della necessità di aggiornare tutti i servizi ogni volta che viene aggiunta una nuova funzione o ruolo;
  • che i nuovi servizi rimangono semplici, sicuri e veloci.

Conclusione

Istio consente ai team di concentrare le proprie risorse su compiti importanti per il business, riportando i servizi allo stato di 'micro'.

L'articolo (in tre parti) ha fornito basi teoriche e una guida pratica per iniziare a lavorare con Istio in progetti reali.

P.S. dal traduttore

Leggi anche nel nostro blog:

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster