Configurazione dell'autenticazione utente di Cloud Service Mesh

L'autenticazione utente di Cloud Service Mesh è una soluzione integrata per l'autenticazione e controllo dell'accesso degli utenti finali basati su browser ai workload di cui è stato eseguito il deployment. Consente l'integrazione con i provider di identità (IDP) esistenti per l'autenticazione degli utenti e utilizza le API e le policy di autorizzazione di Istio per la gestione degli accessi. È un'alternativa facile da usare all'autenticazione JWT (JSON Web Token) di Istio.

Un caso d'uso tipico è quando un'organizzazione utilizza Cloud Service Mesh per ospitare un'applicazione web a cui la sua forza lavoro può accedere tramite un browser web. Inoltre, l'organizzazione deve utilizzare il proprio provider di identità esistente per gestire le identità degli utenti. L'autenticazione utente di Cloud Service Mesh consente agli utenti di autenticarsi facilmente utilizzando un flusso di accesso e consenso OpenID Connect (OIDC) standard basato sul web. Quando l'utente esegue l'autenticazione, Cloud Service Mesh applica le policy di autorizzazione Istio e, in caso di autorizzazione riuscita, trasmette l'identità ai workload in un formato di credenziali di sicurezza sicuro.

Come funziona

L'autenticazione utente di Cloud Service Mesh introduce un nuovo componente, authservice. Questo componente si integra con l'ingress basato su Envoy come servizio di autorizzazione esterno che intercetta tutte le richieste in entrata per l'autenticazione. authservice implementa il lato client del protocollo OIDC e consente l'accesso degli utenti alle applicazioni tramite un browser, dove gli utenti completano un flusso interattivo di autenticazione e consenso per stabilire una sessione di breve durata. authservice implementa protocolli standard di settore per l'integrazione con qualsiasi provider di identità che può fungere da server di autorizzazione OIDC. Quando l'utente viene autenticato, le informazioni sull'entità vengono incapsulate in un RCToken in formato JWT, firmato da authservice, che viene inoltrato al livello di autorizzazione Istio nell'ingress. Questo modello fornisce controllo dell'accesso perimetrale per il traffico verso il mesh. Se l'utente è autorizzato ad accedere a una risorsa, questo RCToken viene inoltrato anche ai microservizi per ottenere informazioni sull'entità e applicare controllo dell'accesso granulare dell'accesso.

Il seguente diagramma mostra la posizione di authservice nel mesh e la sua relazione con le altre parti del mesh, come l'ingress, i workload, il browser dell'utente e qualsiasi IDP esistente.

autenticazione dell'utente finale

Gli amministratori possono installare authservice come componente aggiuntivo di un'installazione di Cloud Service Mesh. Una volta installato, authservice legge la configurazione dell'endpoint OIDC e altre impostazioni associate definite nella risorsa personalizzata UserAuth. L'amministratore può utilizzare le API Cloud Service Mesh ExternalAuthorization per configurare auth_server come filtro sull'ingresso.

Installa il servizio di autenticazione utente

I passaggi seguenti spiegano come configurare authservice.

Prerequisiti

Segui i passaggi descritti in Installa gli strumenti dipendenti e convalida il cluster per:
  • Se utilizzi Cloud Service Mesh gestito su un cluster privato, assicurati che il cluster sia in grado di inviare traffico in uscita all'IDP.

Inoltre, assicurati di soddisfare i prerequisiti seguendo questi passaggi.

Personalizza l'overlay di autenticazione utente dell'installazione

Per installare il servizio di autenticazione utente, devi personalizzare l'installazione di Cloud Service Mesh in modo da aggiungere un fornitore autorizzato esterno a livello di mesh. I passaggi richiesti dipendono dal fatto che tu stia utilizzando Cloud Service Mesh gestito o in-cluster.

Gestito

  1. Aggiorna ConfigMap per includere MeshConfig per l'autenticazione utente. Nel comando seguente, utilizza lo stesso REVISION_LABEL che hai utilizzato durante il provisioning di Cloud Service Mesh gestito (ad esempio asm-managed, asm-managed-rapid o asm-managed-stable):

    kubectl edit configmap istio-REVISION_LABEL -n istio-system
    
  2. Aggiungi il seguente testo nel campo mesh in MeshConfig:

    mesh: |-
    ...
      extensionProviders:
      - name: "asm-userauth-grpc"
        envoyExtAuthzGrpc:
          service: "authservice.asm-user-auth.svc.cluster.local"
          port: "10003"
    
  3. Crea lo spazio dei nomi asm-user-auth.

    kubectl create namespace asm-user-auth
    
  4. Abilita lo spazio dei nomi per l'inserimento. I passaggi dipendono dall'implementazione del control plane.

    Gestito (TD)

    Applica l'etichetta di inserimento predefinita allo spazio dei nomi:

    kubectl label namespace asm-user-auth \
        istio.io/rev- istio-injection=enabled --overwrite
    

    Gestito (Istiod)

    Consigliato: esegui questo comando per applicare l'etichetta di inserimento predefinita allo spazio dei nomi:

    ```sh
    kubectl label namespace asm-user-auth \
        istio.io/rev- istio-injection=enabled --overwrite
    ```
    

    Se sei un utente esistente con il control plane Istiod gestito: ti consigliamo di utilizzare l'inserimento predefinito, ma è supportato anche l'inserimento basato sulla revisione. Segui queste istruzioni:

    1. Esegui questo comando per individuare i canali di rilascio disponibili:
    kubectl -n istio-system get controlplanerevision
    

    L'output è simile al seguente:

    NAME                AGE
    asm-managed-rapid   6d7h
    

    Nell'output, il valore nella colonna NAME è l'etichetta della revisione che corrisponde al canale di rilascio disponibile per la versione di Cloud Service Mesh.

    1. Applica l'etichetta di revisione allo spazio dei nomi:

      kubectl label namespace asm-user-auth \
          istio-injection- istio.io/rev=REVISION_LABEL --overwrite
      
  5. Installa il gateway Istio nello spazio dei nomi asm-user-auth.

    kubectl apply -n asm-user-auth -f DIR_PATH/samples/gateways/istio-ingressgateway
    

Interno al cluster

  1. Scarica l'esempio di overlay di autenticazione utente e aggiornalo se sono presenti personalizzazioni nel mesh. Come best practice, ti consigliamo di conservare questo file di overlay nel controllo del codice sorgente.

    curl https://raw.githubusercontent.com/GoogleCloudPlatform/asm-user-auth/v1.2.5/overlay/user-auth-overlay.yaml > user-auth-overlay.yaml
    
  2. Segui la procedura per installare Cloud Service Mesh con overlay per utilizzare uno script fornito da Google per installare Cloud Service Mesh con l'overlay di autenticazione utente. Ad esempio:

    ./asmcli install \
      --project_id PROJECT_ID \
      --cluster_name CLUSTER_NAME \
      --cluster_location CLUSTER_LOCATION \
      --fleet_id FLEET_PROJECT_ID \
      --output_dir DIR_PATH \
      --enable_all \
      --custom_overlay user-auth-overlay.yaml
    

    I pacchetti di autenticazione utente kpt creano un AuthorizationPolicy per fare riferimento al fornitore autorizzato esterno specificato da pkg/ext-authz.yaml.

  3. Crea lo spazio dei nomi asm-user-auth.

    kubectl create namespace asm-user-auth
    
  4. Abilita lo spazio dei nomi per l'inserimento.

    Consigliato: esegui questo comando per applicare l'etichetta di inserimento predefinita allo spazio dei nomi:

      kubectl label namespace asm-user-auth \
          istio.io/rev- istio-injection=enabled --overwrite
    

    Ti consigliamo di utilizzare l'inserimento predefinito, ma è supportato anche l'inserimento basato sulla revisione: Segui queste istruzioni:

    1. Utilizza il comando seguente per individuare l'etichetta della revisione su istiod:

      kubectl get deploy -n istio-system -l app=istiod -o \
        jsonpath={.items[*].metadata.labels.'istio\.io\/rev'}'{"\n"}'
      
    2. Applica l'etichetta di revisione allo spazio dei nomi. Nel comando seguente, REVISION_LABEL è il valore dell'etichetta di revisione istiod che hai annotato nel passaggio precedente.

      kubectl label namespace asm-user-auth \
          istio-injection- istio.io/rev=REVISION_LABEL --overwrite
      
  5. Installa il gateway Istio nello spazio dei nomi asm-user-auth.

    kubectl apply -n asm-user-auth -f DIR_PATH/samples/gateways/istio-ingressgateway
    

Prepara la configurazione del client OIDC

Imposta la configurazione del client OIDC seguendo questi passaggi. Questa guida utilizza Google come IdP, ma puoi utilizzare qualsiasi IdP che supporti l'autenticazione OIDC.

  1. Nella console Google Cloud , vai ad API e servizi > Credenziali.

    Vai a credenziali

  2. Vai a Crea credenziali, quindi scegli ID client OAuth. Se necessario, imposta le opzioni della schermata per il consenso OAuth, quindi configura le seguenti opzioni:

    • Imposta Tipo di applicazione su Applicazione web.
    • Imposta URI di reindirizzamento autorizzato su https://REDIRECT_HOST/REDIRECT_PATH. Ad esempio, per localhost puoi impostare https://localhost:8443/_gcp_asm_authenticate.

    Quindi, fai clic su Salva.

  3. Inoltre, salva la configurazione del client OIDC per utilizzarla in un secondo momento.

    export OIDC_CLIENT_ID=CLIENT_ID
    export OIDC_CLIENT_SECRET=CLIENT_SECRET
    export OIDC_ISSUER_URI=ISSUER_URI
    export OIDC_REDIRECT_HOST=REDIRECT_HOST
    export OIDC_REDIRECT_PATH=REDIRECT_PATH
    

Scarica i pacchetti kpt

Segui questi passaggi per installare la configurazione authservice consigliata dal repository pubblico. Questi comandi recuperano l'ultimo container authservice e lo avviano come pod nello spazio dei nomi asm-user-auth. Inoltre, configura l'ingress per intercettare tutte le richieste.

Scarica il pacchetto kpt:

kpt pkg get https://github.com/GoogleCloudPlatform/asm-user-auth.git/@v1.2.5 .
cd asm-user-auth/

Imposta l'URL di reindirizzamento e il secret per il gateway in entrata

OAuth2 richiede un URL di reindirizzamento ospitato su un endpoint protetto da HTTPS. Questi comandi sono a scopo di esempio e semplificano la configurazione generando un certificato autofirmato per il gateway in entrata Istio.

  1. Genera un certificato autofirmato:

    openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem \
     -days 365 -nodes -subj '/CN=localhost'
    
  2. Crea un secret per il gateway in entrata per ospitare il traffico HTTPS:

    kubectl create -n asm-user-auth secret tls userauth-tls-cert --key=key.pem \
    --cert=cert.pem
    

Applica le chiavi di crittografia e firma

authservice richiede due set di chiavi per funzionare correttamente. La prima è una chiave simmetrica per la crittografia e la decrittografia. Questa chiave viene utilizzata per criptare lo stato della sessione prima di impostarlo come cookie.

Il secondo set di chiavi è una coppia di chiave pubblica/privata. Questa chiave viene utilizzata per firmare le informazioni dell'utente autenticato in formato JWT come RCToken. La chiave pubblica di questa coppia viene pubblicata in un endpoint predefinito che i sidecar possono utilizzare per convalidare il JWT.

Il pacchetto di autenticazione utente kpt contiene due chiavi di esempio per una configurazione rapida. Tuttavia, puoi utilizzare il tuo sistema di gestione delle chiavi preferito per generare queste chiavi.

  1. Prepara la chiave di crittografia della sessione con il seguente formato o utilizza l'esempio del pkg, che puoi visualizzare tramite cat ./samples/cookie_encryption_key.json.

    {
      "keys":[
         {
            "kty":"oct",
            "kid":"key-0",
            "K":"YOUR_KEY",
            "useAfter": 1612813735
         }
      ]
    }
    

    Puoi generare una chiave AES di test con il seguente comando:

    openssl enc -aes-256-cbc -k mycustomkey -P -md sha1 | grep key
    
  2. Prepara la chiave di firma RCToken con il seguente formato o utilizza l'esempio del pacchetto, che puoi visualizzare tramite cat ./samples/rctoken_signing_key.json.

    {
      "keys":[
         {
            "kty":"RSA",
            "kid":"rsa-signing-key",
            "K":"YOUR_KEY",  # k contains a Base64 encoded PEM format RSA signing key.
            "useAfter": 1612813735  # unix timestamp
         }
      ]
    }
    

    Puoi generare una chiave privata RSA di test a 512 bit con il seguente comando:

    openssl genpkey -algorithm RSA -out rsa_private.pem -pkeyopt rsa_keygen_bits:512
    
  3. Crea il secret di Kubernetes, che authservice monterà nel proprio file system.

    kubectl create secret generic secret-key  \
        --from-file="session_cookie.key"="./samples/cookie_encryption_key.json" \
        --from-file="rctoken.key"="./samples/rctoken_signing_key.json"  \
        --namespace=asm-user-auth
    

Esegui il deployment del servizio di autenticazione utente

I seguenti comandi creano il servizio di autenticazione utente e il deployment nello spazio dei nomi asm-user-auth.

Imposta i valori necessari per la configurazione dell'autenticazione utente. L'ID client e il secret vengono archiviati come secret di Kubernetes, quindi utilizziamo Base64 per codificarli. Visita il repository pubblico per visualizzare tutti i setter disponibili.

kpt fn eval pkg --image gcr.io/kpt-fn/apply-setters:v0.2 --truncate-output=false -- \
  client-id="$(echo -n ${OIDC_CLIENT_ID} | base64 -w0)" \
  client-secret="$(echo -n ${OIDC_CLIENT_SECRET} | base64 -w0)" \
  issuer-uri="${OIDC_ISSUER_URI}" \
  redirect-host="${OIDC_REDIRECT_HOST}" \
  redirect-path="${OIDC_REDIRECT_PATH}"

Applica il pacchetto kpt:

# Remove the potential alpha version CRD if exists.
kubectl delete crd userauthconfigs.security.anthos.io
kubectl apply -f ./pkg/asm_user_auth_config_v1beta1.yaml
kubectl apply -f ./pkg

authservice utilizza la CRD UserAuthConfig per fornire l'autenticazione degli utenti finali. UserAuthConfig è configurabile in fase di runtime e puoi aggiornarlo per modificare il comportamento di authservice e configurarlo con gli endpoint per qualsiasi server di autorizzazione OIDC.

Puoi visualizzare il file tramite cat pkg/user_auth_config.yaml, che contiene i seguenti campi:

apiVersion: security.anthos.io/v1beta1
kind: UserAuthConfig
metadata:
  name: user-auth-config
  namespace: asm-user-auth
spec:
  authentication:
    oidc:
      certificateAuthorityData: ""  # kpt-set: ${ca-cert}
      issuerURI: "<your issuer uri>"  # kpt-set: ${issuer-uri}
      proxy: ""  # kpt-set: ${proxy}
      oauthCredentialsSecret:
        name: "oauth-secret"  # kpt-set: ${secret-name}
        namespace: "asm-user-auth"  # kpt-set: ${secret-namespace}
      redirectURIHost: ""  # kpt-set: ${redirect-host}
      redirectURIPath: "/_gcp_asm_authenticate"  # kpt-set: ${redirect-path}
      scopes: ""  # kpt-set: ${scopes}
      groupsClaim: ""  # kpt-set: ${groups}
  outputJWTAudience: "test_audience"  # kpt-set: ${jwt-audience}

Per descrizioni dettagliate dei campi user_auth_config.yaml, consulta i dettagli di configurazione dell'autenticazione utente.

Configura gli identificatori delle richieste API

Gli identificatori delle richieste API sono un insieme di espressioni Common Expression Language (CEL) utilizzate dall'autenticazione utente di Cloud Service Mesh per identificare le richieste API. Definendo questi identificatori, consenti all'autenticazione utente di Cloud Service Mesh di gestire semanticamente gli errori di autenticazione delle richieste API.

In particolare, quando fornisci espressioni CEL che identificano le tue richieste API, consenti all'autenticazione utente di Cloud Service Mesh di non autenticare le richieste API non autenticate con un codice di stato 401-Unauthorized. Questo è fondamentale per client come CLI e service account, che si aspettano questo codice di stato per le richieste API non autenticate.

Senza identificatori delle richieste API, l'autenticazione utente di Cloud Service Mesh reindirizzerà tutte le richieste non autenticate al provider OpenID Connect (OIDC) configurato, restituendo un codice di stato 302-Found. Questo comportamento di reindirizzamento è generalmente indesiderato per le richieste API, che prevedono un errore 401-Unauthorized in caso di errore.

Per definire gli identificatori delle richieste API, aggiungi una sezione apiRequestIdentifier al tuo UserAuthConfig CR. In questo modo è possibile aggiungere più espressioni CEL. Se vengono fornite più espressioni CEL, una richiesta viene considerata una richiesta API se corrisponde ad almeno una di queste.

L'esempio seguente mostra come designare come richiesta API: qualsiasi richiesta contenente l'intestazione example-api-header, qualsiasi richiesta indirizzata all'host api.example.com o qualsiasi richiesta che ha come target un percorso in /v1/api/.

apiVersion: security.anthos.io/v1beta1
kind: UserAuthConfig
metadata:
  name: user-auth-config
  namespace: asm-user-auth
spec:
  authentication:
    oidc:
      certificateAuthorityData: ""  # kpt-set: ${ca-cert}
      issuerURI: "<your issuer uri>"  # kpt-set: ${issuer-uri}
      proxy: ""  # kpt-set: ${proxy}
      oauthCredentialsSecret:
        name: "oauth-secret"  # kpt-set: ${secret-name}
        namespace: "asm-user-auth"  # kpt-set: ${secret-namespace}
      redirectURIHost: ""  # kpt-set: ${redirect-host}
      redirectURIPath: "/_gcp_asm_authenticate"  # kpt-set: ${redirect-path}
      scopes: ""  # kpt-set: ${scopes}
      groupsClaim: ""  # kpt-set: ${groups}
  outputJWTAudience: "test_audience"  # kpt-set: ${jwt-audience}
  apiRequestIdentifier: 
    name: "api-request-identifiers"
    expressions: 
    - "'example-api-header' in http_request.headers"
    - "http_request.host == 'api.example.com'"
    - "matches(http_request.path, '/v1/api/(.*)')"
    # other expressions go here

Le espressioni CEL di autenticazione utente di Cloud Service Mesh possono essere create dai seguenti campi:

  1. http_request.headers: una mappa delle intestazioni delle richieste HTTP, in cui le chiavi sono stringhe in minuscolo e i valori sono vettori di stringhe.

    Utilizza questo campo nell'espressione CEL per designare le richieste con intestazioni specifiche come richieste API.

  2. http_request.host: l'host dell'URL HTTP richiesto (ad es. api.example.com).

    Utilizza questo campo nell'espressione CEL per designare le richieste a host specifici come richieste API.

  3. http_request.path: il percorso URL HTTP richiesto (ad es. /example-api-path). Inizia sempre con "/" e non contiene il componente di query dell'URL della richiesta.

    Utilizza questo campo nell'espressione CEL per designare le richieste con percorsi specifici come richieste API.

La sezione successiva mostra esempi di espressioni CEL che controllano e abbinano parti di questi campi per informare l'autenticazione utente di Cloud Service Mesh su come determinare quali richieste sono richieste API.

Espressioni di esempio

Trova tutte le richieste che contengono l'intestazione X-API-Key:

"'x-api-key' in http_request.headers"

Trova tutte le richieste con l'intestazione X-API-Key impostata su un valore specifico:

"'x-api-key' in http_request.headers && http_request.headers['x-api-key'].values == ['example-value ']"

Abbina tutte le richieste all'host api.example.com:

"http_request.host == api.example.com"

Abbina tutte le richieste al percorso /api/query:

"http_request.path == /api/query"

Abbina tutte le richieste a qualsiasi percorso in /api/:

"matches(http_request.path, '/api/(.*)')"

Esegui le attività post-installazione

Dopo aver completato i passaggi di installazione precedenti, sono necessarie le seguenti attività.

Abilita l'autenticazione utente per le tue applicazioni

Questa sezione mostra come attivare l'autenticazione utente utilizzando httpbin come esempio.

L'autenticazione utente di Cloud Service Mesh utilizza una policy di autorizzazione di tipo CUSTOM per attivare il flusso OIDC.

Dopo aver installato il gateway Istio, configuralo per gestire il traffico HTTPS utilizzando il certificato TLS userauth-tls-cert che hai creato in precedenza. Di seguito è riportata la configurazione di pkg/gateway.yaml che hai appena installato.

apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: userauth
  namespace: asm-user-auth
spec:
  selector:
    istio: ingressgateway
  servers:
  - hosts:
    - '*'
    port:
      name: https
      number: 443
      protocol: HTTPS
    tls:
      mode: SIMPLE
      credentialName: userauth-tls-cert
---
# This ensures the OIDC endpoint has at least some route defined.
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: userauth-oidc
  namespace: asm-user-auth
spec:
  gateways:
  - userauth
  hosts:
  - '*'
  http:
  - match:
    - uri:
        prefix: /status
    - uri:
        prefix: "your-oidc-redirect-path"
    name: user-auth-route
    route:
    - destination:
        host: authservice
        port:
          number: 10004
  1. Etichetta lo spazio dei nomi default per abilitare l'inserimento automatico di istio-proxy per i deployment.

    kubectl label namespace default istio.io/rev=REVISION --overwrite
    
  2. Esegui il deployment di httpbin nello spazio dei nomi default.

    kubectl apply -f https://raw.githubusercontent.com/istio/istio/master/samples/httpbin/httpbin.yaml -n default
    
  3. Aggiorna httpbin per utilizzare questo gateway per gestire il traffico HTTPS e utilizza il port forwarding per accedere all'applicazione localmente:

    kubectl apply -f./samples/httpbin-route.yaml -n default
    kubectl port-forward service/istio-ingressgateway 8443:443 -n asm-user-auth
    
    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: httpbin
      namespace: default
    spec:
      gateways:
      - asm-user-auth/userauth
      hosts:
      - '*'
      http:
      - match:
        - uri:
            prefix: /ip
        - uri:
            prefix: /headers
        name: httpbin-routes
        route:
        - destination:
            host: httpbin.default.svc.cluster.local
            port:
              number: 8000
    

    Il gateway in entrata sulla porta 8443 verrà inoltrato a localhost per rendere l'applicazione accessibile localmente.

  4. Esegui il deployment di samples/rctoken-authz.yaml per abilitare RequestAuthentication e AuthorizationPolicy per verificare l'RCToken per le richieste.

    kubectl apply -f ./samples/rctoken-authz.yaml -n asm-user-auth
    

    Esempio samples/rctoken-authz.yaml:

    apiVersion: security.istio.io/v1beta1
    kind: RequestAuthentication
    metadata:
      name: require-rc-token
    spec:
      selector:
        matchLabels:
          istio: ingressgateway
      jwtRules:
      - issuer: "authservice.asm-user-auth.svc.cluster.local"
        audiences:
        - "test_audience"
        jwksUri: "http://authservice.asm-user-auth.svc.cluster.local:10004/_gcp_user_auth/jwks"
        fromHeaders:
        - name: X-ASM-RCTOKEN
        forwardOriginalToken: true
    ---
    apiVersion: security.istio.io/v1beta1
    kind: AuthorizationPolicy
    metadata:
      name: require-rc-token
    spec:
      selector:
        matchLabels:
          istio: ingressgateway
      action: ALLOW
      rules:
      - when:
        - key: request.auth.claims[iss]
          values:
          - authservice.asm-user-auth.svc.cluster.local
        - key: request.auth.claims[aud]
          values:
          - test_audience
    

Verifica l'autenticazione utente

httpbin gestisce due percorsi: /ip è accessibile pubblicamente e /headers richiede all'utente finale di accedere tramite l'IDP configurato.

  1. Verifica di poter accedere direttamente a /ip visitando https://localhost:8443/ip.

  2. Verifica che venga visualizzata la pagina di accesso OIDC visitando https://localhost:8443/headers.

  3. Dopo aver eseguito l'accesso, fai clic su Avanti e verifica che il reindirizzamento avvenga alla pagina /headers.

Configura le policy di autorizzazione

Dopo aver completato la configurazione nei passaggi precedenti, ogni utente verrà reindirizzato tramite un flusso di autenticazione basato sul web. Al termine del flusso, authservice genera un RCToken in formato JWT, che utilizza per trasmettere le informazioni dell'utente autenticato.

  1. Aggiungi policy di autorizzazione Istio all'ingresso per assicurarti che venga eseguito un controllo di autorizzazione per ogni utente autenticato:

    kubectl apply -f ./samples/httpbin-authz.yaml -n asm-user-auth
    
  2. Il file httpbin-authz.yaml configura il gateway in entrata per convalidare il token RC emesso da authservice e autorizzare solo quando il JWT contiene i campi desiderati, come i segmenti di pubblico e gli emittenti.

    Vedi la seguente policy di autorizzazione di esempio:

    apiVersion: security.istio.io/v1beta1
    kind: AuthorizationPolicy
    metadata:
      name: require-rc-token
    spec:
      selector:
        matchLabels:
          istio: ingressgateway
      action: ALLOW
      rules:
      - to:
        - operation:
            paths: ["/ip"]
      - to:
        when:
        - key: request.auth.claims[iss]
          values:
          - authservice.asm-user-auth.svc.cluster.local
        - key: request.auth.claims[aud]
          values:
          - test_audience
        - key: request.auth.claims[sub]
          values:
          - allowed_user_sub_1  # Change this with the "sub" claim in the RC token. Wildcard '*' will match everything.
    

Configura le impostazioni specifiche dell'ambiente

I passaggi precedenti utilizzano localhost e un certificato HTTPS autofirmato per una configurazione rapida. Per l'utilizzo in produzione reale, utilizza il tuo dominio, ad esempio example.com.

Inoltre, assicurati che certificateAuthorityData abbia il contenuto del certificato radice previsto. Ad esempio, se l'IDP è considerato attendibile con i certificati radice del sistema, puoi lasciare il campo vuoto. Se è presente un proxy HTTPS che termina la connessione HTTPS, deve essere impostato sul certificato radice del proxy.

Gestisci e ruota le chiavi

authservice utilizza due set di chiavi. Puoi ruotare ogni chiave in modo indipendente. Tuttavia, prima di ruotare le chiavi, è importante capire come funziona la rotazione.

Entrambe le chiavi sono in formato JSON. Il campo useAfter specifica il timestamp a partire dal quale la chiave verrà considerata in uso. Durante una rotazione della chiave, devi includere sia le chiavi precedenti che quelle nuove nel file JSON. Ad esempio, nel seguente esempio, new-key verrà utilizzato solo dopo il timestamp 1712813735.

{
   "keys":[
      {
         "kty":"RSA",
         "kid":"old-key",
         "K":"...", # k contains a Base64 encoded PEM format RSA signing key.
         "useAfter": 1612813735, # unix timestamp
      }
      {
      "kty":"RSA",
         "kid":"new-key",
         "K":"...", # k contains a Base64 encoded PEM format RSA signing key.
         "useAfter": 1712813735, # unix timestamp
      }
   ]
}

Cloud Service Mesh utilizza la chiave simmetrica per criptare i dati della sessione archiviati nei cookie del browser. Per garantire la validità delle sessioni esistenti, authservice tenta la decriptazione con tutte le chiavi del set di chiavi. Al momento della rotazione, authservice utilizzerà la nuova chiave per criptare le nuove sessioni e continuerà a tentare la decriptazione con le chiavi precedenti.

La coppia di chiave pubblica/privata viene utilizzata per firmare RCToken. La chiave pubblica viene trasmessa ai sidecar da istiod per la verifica JWT. È fondamentale che i sidecar ricevano la nuova chiave pubblica prima che authservice inizi a utilizzare la nuova chiave privata per firmare RCToken. A questo scopo, authservice inizia a pubblicare la chiave pubblica immediatamente dopo l'aggiunta, ma attende un periodo di tempo significativo prima di iniziare a utilizzarla per firmare RCToken.

In sintesi, quando esegui le rotazioni delle chiavi, ti consigliamo di:

  1. Esegui rotazioni delle chiavi regolari o on demand in base alle tue esigenze.
  2. Nel formato JSON, includi sia la chiave attuale sia quella nuova. Le nuove chiavi devono essere associate a un timestamp futuro. Ti consigliamo di specificare un timestamp almeno un paio di ore prima dell'ora corrente.
  3. Monitora e verifica che i servizi siano ancora integri dopo l'utilizzo della nuova chiave. Attendi almeno un giorno dopo l'utilizzo della nuova chiave prima di procedere con il passaggio successivo.
  4. Rimuovi le vecchie chiavi dalle voci JSON. Non sono più necessari.

Deployment multi-cluster

L'autenticazione utente di Cloud Service Mesh supporta il deployment multi-cluster. Devi eseguire il deployment dell'autenticazione utente in ogni cluster come descritto sopra. La configurazione dell'autenticazione utente, come la risorsa personalizzata UserAuth, il client secret OIDC e le chiavi di crittografia, deve essere replicata in ogni cluster.

Per impostazione predefinita, il gateway in entrata bilancia il carico delle richieste di autenticazione su una qualsiasi delle istanze authservice. Puoi utilizzare la regola di destinazione per configurare il gateway in entrata in modo che invii richieste a authservice nello stesso cluster e che esegua il failover solo su authservice di altri cluster.

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: authservice-fail-over
  namespace: asm-user-auth
spec:
  host: authservice.asm-user-auth.svc.cluster.local
  trafficPolicy:
    loadBalancer:
      localityLbSetting:
        enabled: true
        failover:
        - from:  us-east
          to: us-west
        - from: us-west
          to: us-east

Come per le altre configurazioni, questa deve essere configurata in ogni cluster.

Mappatura delle attestazioni personalizzate

Per configurare la mappatura delle attestazioni personalizzate, configura spec.authentication.oidc.attributeMapping per definire eventuali mappature dall'IDToken del provider di identità originale. La chiave sarà il nome della rivendicazione nell'RCToken e il valore è un'espressione CEL su come analizzare la rivendicazione dall'IDToken, utilizza assertion per fare riferimento all'IDToken.

Esempio:

spec:
  authentication:
    oidc:
      attributeMapping:
        aud_copy: assertion.aud
        decision: 'assertion.sub.startsWith("123") ? "success" : "fail"'

Nell'RCToken, un'attestazione nidificata attributes contiene le attestazioni configurate:

"attributes": {
    "aud_copy": "foo.googleusercontent.com",
    "decision": "success"
}

Se l'espressione CEL non riesce ad analizzare il valore da IDToken, ignorerà l'attestazione senza interrompere il flusso di autenticazione.

Upgrade dell'autenticazione utente

  1. Installa di nuovo i pacchetti di autenticazione utente, poiché contengono il file binario aggiornato per la nuova versione di autenticazione utente:

    kpt pkg get https://github.com/GoogleCloudPlatform/asm-user-auth.git/@v1.2.5 .
    cd asm-user-auth/
    
  2. Salva la configurazione del client OIDC:

    export OIDC_CLIENT_ID=CLIENT_ID
    export OIDC_CLIENT_SECRET=CLIENT_SECRET
    export OIDC_ISSUER_URI=ISSUER_URI
    export OIDC_REDIRECT_HOST=REDIRECT_HOST
    export OIDC_REDIRECT_PATH=REDIRECT_PATH
    
  3. Esegui il deployment del servizio di autenticazione utente per eseguire l'upgrade a una nuova versione.

Dettagli della configurazione dell'autenticazione utente

La tabella seguente descrive ogni campo della CRD:

Nome campo Descrizione
authentication.oidc Questa sezione contiene la configurazione dell'endpoint OIDC e i parametri utilizzati nel flusso OIDC.
authentication.oidc.certificateAuthorityData Questo è il certificato radice SSL del dominio del server di autorizzazione OIDC o del proxy HTTPS, se presente.
authentication.oidc.oauthCredentialsSecret Riferimenti secret al secret di tipo opaco di Kubernetes che contiene client_id e client_secret OIDC OAuth2 nel payload JSON.
authentication.oidc.issuerURI L'URI da utilizzare come emittente nell'RCToken di output.
authentication.oidc.proxy Server proxy per l'IDP OIDC, se applicabile. Con il formato http://user:password@10.10.10.10:8888.
authentication.oidc.redirectURIHost L'host da utilizzare per l'URI di terminazione OAuth. Se lasci vuoto questo campo, verrà utilizzato l'host dell'URL di destinazione e l'URI di reindirizzamento verrà assemblato in modo dinamico.
Questo valore può essere utilizzato quando è richiesta una sessione SSO di autenticazione utente a un livello di dominio superiore. Ad esempio, per attivare il SSO tra profile.example.com/ e admin.example.com/, questo valore può essere impostato su example.com. In questo modo, verrà stabilita una sessione di autenticazione utente su example.com che verrà condivisa tra tutti i sottodomini. Nota: se più domini vengono gestiti dallo stesso mesh, ad esempio example1.com ed example2.com, la funzionalità non può essere utilizzata e si consiglia di lasciare vuoto il campo.
authentication.oidc.redirectURIPath Il percorso dell'endpoint in cui authservice terminerà il flusso OAuth. Devi registrare questo percorso URI più l'host come URI di reindirizzamento autorizzato nel server di autorizzazione per authentication.oidc.clientID.
Inoltre, questo URI deve essere gestito dallo stesso mesh di servizi e dallo stesso Ingress in cui è abilitato authservice.
authentication.oidc.scopes L'ambito OAuth che deve essere richiesto nella richiesta di autenticazione. Elenco separato da virgole di identificatori utilizzati per specificare i privilegi di accesso richiesti oltre all'ambito "openid", ad esempio "groups,allatclaim".
authentication.oidc.groupsClaim Se il idtoken contiene un'attestazione dei gruppi, utilizza questo campo per indicarne il nome. Se specificato, il servizio trasmetterà i dati di questa attestazione all'attestazione groups nell'RCToken di output. Questa attestazione deve contenere un elenco separato da virgole di stringhe, ad esempio ["group1", "group2"].
authentication.oidc.attributeMapping Contiene una o più mappature delle attestazioni da espressioni CEL seguite da idtoken. Tutte le rivendicazioni devono essere indicate da assertion.X, assertion è indicato all'IDToken originale, ad esempio aud_copy: assertion.aud.
authentication.outputJWTAudience Il pubblico dell'RCToken generato da authservice. I sidecar possono convalidare l'RCToken in entrata rispetto a questo valore del pubblico.

Risoluzione dei problemi

  1. Accessibilità di rete all'IDP.

    Possibile log: error: TLS handshake failed..

    Verifica eseguendo curl dal container temporaneo collegato a istio-proxy per chiamare l'URI dell'emittente IDP. Ad esempio, consulta Raccolta dei log di Cloud Service Mesh.

    Se non riesci a connetterti, controlla le regole del firewall o altre configurazioni di rete per il cluster.

  2. Certificato CA radice.

    Log possibile: error: The server's TLS certificate did not match expectations. o error: TLS handshake failed..

    Assicurati che il certificateAuthorityData contenga il certificato CA radice corretto. Se non esiste un proxy HTTPS che termina il traffico HTTPS, questo deve contenere il certificato CA radice per l'IDP. Se esiste, deve contenere l'indirizzo del proxy.

  3. Configurazione del percorso di reindirizzamento.

    Possibile osservazione: ricezione di una pagina di errore 404 durante il flusso di autenticazione OIDC.

    L'autenticazione utente restituisce l'intestazione "Set-Cookie" senza utilizzare l'attributo path, che per impostazione predefinita il browser utilizza la directory dell'URL della richiesta come percorso del cookie (ambito del cookie correlato al percorso). Pertanto, ti consigliamo di non includere "/" nel percorso di reindirizzamento, a meno che non sia intenzionale.

  4. Il sidecar non è in grado di recuperare jwksUri.

    In alcuni scenari, una limitazione del sidecar potrebbe causare un errore di recupero di jwksUri. Se lo spazio dei nomi non è presente utilizzando un carattere jolly (ad esempio ./* o istio-system/*), l'operazione non funzionerà. Devi aggiungere manualmente il loro spazio dei nomi nel sidecar in uscita.

Domande frequenti

  1. Come faccio a eseguire l'upgrade di Cloud Service Mesh con l'autenticazione utente abilitata?

    Segui la procedura di upgrade di Cloud Service Mesh e specifica il file di overlay aggiungendo --custom_overlay user-auth-overlay.yaml alla riga di comando per asmcli install.

  2. Quante risorse dobbiamo allocare per authservice? E quante richieste al secondo può gestire?

    Per impostazione predefinita, authservice è configurato con 2, 0 vCPU e 256 Mi di memoria. Con questa configurazione, authservice è in grado di gestire 500 richieste al secondo. Per gestire quantità maggiori di richieste, devi eseguire il provisioning di più CPU, che è approssimativamente proporzionale alla capacità di gestione delle richieste. Puoi anche configurare più repliche di authservice per aumentare la scalabilità orizzontale.