Panoramica dei criteri di autorizzazione

A differenza di un'applicazione monolitica che potrebbe essere in esecuzione in un unico luogo, le app di microservizi distribuite a livello globale effettuano chiamate oltre i confini di rete. Ciò significa più punti di accesso alle tue applicazioni e più opportunità per attacchi dannosi. Inoltre, poiché i pod Kubernetes hanno IP temporanei, le regole firewall tradizionali basate su IP non sono adeguate per proteggere l'accesso tra i carichi di lavoro. In un'architettura di microservizi è necessario un nuovo approccio alla sicurezza. Basandosi su funzionalità di sicurezza come gli account di servizio Kubernetes e i criteri di sicurezza Istio, Cloud Service Mesh offre ancora più funzionalità per aiutarti a proteggere le tue applicazioni.

Questa pagina fornisce agli operatori delle applicazioni una panoramica della AuthorizationPolicy risorsa personalizzata (RP). I criteri di autorizzazione ti consentono di abilitare il controllo dell'accesso ai carichi di lavoro a livello di applicazione (L7) e di trasporto (L3/4). Configura i criteri di autorizzazione per specificare le autorizzazioni: cosa è consentito fare a questo servizio o utente?

Criteri di autorizzazione

Le richieste tra i servizi nel tuo mesh (e tra utenti finali e servizi) sono consentite per impostazione predefinita. Utilizza il AuthorizationPolicy CR per definire criteri granulari per i tuoi carichi di lavoro. Dopo aver applicato i criteri di autorizzazione, Cloud Service Mesh li distribuisce ai proxy sidecar. Quando le richieste arrivano in un workload, il proxy sidecar controlla i criteri di autorizzazione per determinare se la richiesta deve essere consentita o negata.

Consulta la sezione Funzionalità supportate per informazioni dettagliate sui campi della RP AuthorizationPolicy supportati dalla piattaforma.

Ambito dei criteri

Puoi applicare un criterio all'intero mesh di servizi, a uno spazio dei nomi o a un singolo carico di lavoro.

  • Per applicare un criterio a livello di mesh, specifica il nome dello spazio dei nomi principale, istio-system, nel campo metadata:namespace:

    apiVersion: "security.istio.io/v1beta1"
    kind: "AuthorizationPolicy"
    metadata:
      name: "mesh-wide"
      namespace: istio-system
    spec:
    ...
    
  • Per applicare un criterio a uno spazio dei nomi, specifica lo spazio dei nomi nel metadata:namespace campo:

    apiVersion: "security.istio.io/v1beta1"
    kind: "AuthorizationPolicy"
    metadata:
      name: "currencyservice"
      namespace: currencyservice
    spec:
    ...
    
  • Per limitare un criterio a un carico di lavoro specifico, includi un campo selector.

    apiVersion: "security.istio.io/v1beta1"
    kind: "AuthorizationPolicy"
    metadata:
      name: "frontend"
      namespace: demo
    spec:
      selector:
        matchLabels:
          app: frontend
       ...
    

Struttura di base

Un criterio di autorizzazione include l'ambito del criterio, un action e un elenco di rules:

  • Come descritto nella sezione precedente, l'ambito del criterio può essere l'intero mesh, uno spazio dei nomi o un carico di lavoro specifico. Se lo includi, il campo selector specifica il target del criterio.

  • Il campo action specifica se ALLOW o DENY la richiesta. Se non specifichi un'azione, per impostazione predefinita viene impostata su ALLOW. Per chiarezza, ti consigliamo di specificare sempre l'azione. I criteri di autorizzazione supportano anche le azioni AUDIT e CUSTOM. L'azione AUDIT è supportata solo su alcune piattaforme. Per maggiori dettagli, consulta la sezione Funzionalità supportate.

  • rules specifica quando attivare l'azione.

    • Il campo from in rules specifica le origini della richiesta.

    • Il campo to in rules specifica le operazioni della richiesta.

    • Il campo when specifica le condizioni aggiuntive necessarie per applicare la regola.

Nel seguente esempio:

  • Il criterio viene applicato alle richieste al servizio frontend nello spazio dei nomi demo.

  • Le richieste sono consentite quando "hello:world" è nell'intestazione della richiesta; in caso contrario, le richieste vengono rifiutate.

apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
  name: "hello-world"
  namespace: demo
spec:
  selector:
    matchLabels:
      app: frontend
  action: ALLOW
  rules:
  - when:
    - key: request.headers[hello]
      values: ["world"]

Controllo dell'accesso per l'operazione di richiesta

Puoi controllare l'accesso a specifiche operazioni di richiesta, come i metodi HTTP o le porte TCP, aggiungendo una sezione to in rules. Nell'esempio seguente, solo i metodi HTTP GET e POST sono consentiti per currencyservice nello spazio dei nomi demo.

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
 name: currencyservice
 namespace: demo
spec:
 selector:
   matchLabels:
     app: currencyservice
 action: ALLOW
 rules:
 - to:
   - operation:
       methods: ["GET", "POST"]

Controllo dell'accesso sull'identità autenticata

Negli esempi precedenti, i criteri consentono richieste da carichi di lavoro non autenticati. Se hai attivato l'autenticazione TLS reciproca STRICT (mTLS), puoi limitare l'accesso in base all'identità del carico di lavoro o dello spazio dei nomi da cui proviene la richiesta nella sezione source.

  • Utilizza il campo principals o notPrincipal per controllare l'accesso a livello di workload.

  • Utilizza il campo namespaces o notNamespaces per controllare l'accesso a livello di spazio dei nomi.

Tutti i campi precedenti richiedono l'abilitazione di STRICTmTLS. Se non riesci a impostare mTLS per STRICT, consulta Rifiutare le richieste in testo non cifrato per una soluzione alternativa.

Carico di lavoro identificato

Nell'esempio seguente, le richieste a currencyservice sono consentite solo dal servizio frontend. Le richieste a currencyservice da altri carichi di lavoro vengono rifiutate.

apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
  name: "currencyservice"
  namespace: demo
spec:
  selector:
    matchLabels:
      app: currencyservice
  action: ALLOW
  rules:
  - from:
    - source:
        principals: ["example-project-1234.svc.id.goog/ns/demo/sa/frontend-sa"]

Per specificare un account di servizio, principals deve avere il seguente formato:

principals: ["PROJECT_ID.svc.id.goog/ns/NAMESPACE/sa/SERVICE_ACCOUNT_NAME"]

Se utilizzi Cloud Service Mesh all'interno del cluster con la CA Citadel, cluster.local è il dominio attendibile. In tutti gli altri casi,PROJECT_ID.svc.id.googè il dominio attendibile per la mesh.

Spazio dei nomi identificato

L'esempio seguente mostra un criterio che nega le richieste se l'origine non è lo spazio dei nomi foo:

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
 name: httpbin-deny
 namespace: foo
spec:
 selector:
   matchLabels:
     app: httpbin
     version: v1
 action: DENY
 rules:
 - from:
   - source:
       notNamespaces: ["foo"]

Corrispondenza del valore

La maggior parte dei campi nei criteri di autorizzazione supporta tutti i seguenti schemi di corrispondenza:

  • Corrispondenza esatta: corrispondenza esatta della stringa.
  • Corrispondenza con caratteri jolly utilizzando il carattere jolly "*":
    • Corrispondenza del prefisso: una stringa che termina con "*". Ad esempio, "test.example.*" corrisponde a "test.example.com" o "test.example.com.cn".
    • Corrispondenza del suffisso: una stringa con un carattere iniziale "*". Ad esempio, "*.example.com" corrisponde a "eng.example.com" o "test.eng.example.com".
  • Corrispondenza di presenza: per specificare che un campo deve essere presente e non vuoto, utilizza il formato fieldname: ["*"]. Questo è diverso dal lasciare un campo senza specificarlo, il che significa che corrisponde a qualsiasi valore, incluso quello vuoto.

Esistono alcune eccezioni. Ad esempio, i seguenti campi supportano solo la corrispondenza esatta:

  • Il campo key nella sezione when
  • ipBlocks nella sezione source
  • Il campo ports nella sezione to

Il seguente criterio di esempio consente l'accesso ai percorsi con il prefisso /test/* o il suffisso */info:

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: tester
  namespace: default
spec:
  selector:
    matchLabels:
      app: products
  action: ALLOW
  rules:
  - to:
    - operation:
        paths: ["/test/*", "*/info"]

Corrispondenza di esclusione

Per trovare corrispondenze a condizioni negative come notValues nel campo when, notIpBlocks nel campo source, notPorts nel campo to, Cloud Service Mesh supporta la corrispondenza per esclusione. L'esempio seguente richiede una richiesta validaprincipals, che deriva dall'autenticazione JWT, se il percorso della richiesta non è/healthz. Pertanto, il criterio esclude le richieste al percorso /healthz dall'autenticazione JWT:

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: disable-jwt-for-healthz
  namespace: default
spec:
  selector:
    matchLabels:
      app: products
  action: ALLOW
  rules:
  - to:
    - operation:
        notPaths: ["/healthz"]
    from:
    - source:
        requestPrincipals: ["*"]

Rifiutare le richieste in testo non cifrato

In Cloud Service Mesh, mTLS automatico è abilitato per impostazione predefinita. Con mTLS automatico, un proxy sidecar client rileva automaticamente se il server ha un sidecar. Il sidecar client invia mTLS ai carichi di lavoro con sidecar e testo normale ai carichi di lavoro senza sidecar. Per la massima sicurezza, ti consigliamo di abilitare mTLS RIGOROSO.

Se non riesci ad attivare mTLS con la modalità STRICT per un workload o un spazio dei nomi, puoi:

  • crea un criterio di autorizzazione per consentire esplicitamente il traffico con namespaces o principals non vuoti oppure
  • Rifiutare il traffico con namespaces o principals vuoti.

Poiché namespaces e principals possono essere estratti solo con una richiesta mTLS, questi criteri rifiutano efficacemente qualsiasi traffico in testo non cifrato.

La seguente norma nega la richiesta se l'entità nella richiesta è vuota (come nel caso delle richieste in testo normale). Il criterio consente le richieste se l'entità non è vuota. ["*"] indica una corrispondenza non vuota e l'utilizzo con notPrincipals indica la corrispondenza con il principale vuoto.

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: require-mtls
  namespace: NAMESPACE
spec:
  action: DENY
  rules:
  - from:
    - source:
        notPrincipals: ["*"]

Precedenza dei criteri di autorizzazione

Puoi configurare criteri di autorizzazione ALLOW e DENY separati, ma devi comprendere la precedenza dei criteri e il comportamento predefinito per assicurarti che i criteri facciano ciò che vuoi. Il seguente diagramma descrive la precedenza delle norme.

precedenza dei criteri di autorizzazione

I criteri di esempio nelle sezioni seguenti illustrano alcuni dei comportamenti predefiniti e le situazioni in cui potresti trovarli utili.

Non consentire nulla

L'esempio seguente mostra un criterio ALLOW che non corrisponde a nulla. Per impostazione predefinita, se non sono presenti altri criteri ALLOW, le richieste vengono sempre rifiutate.

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: allow-nothing
spec:
  action: ALLOW

È buona norma di sicurezza iniziare con il criterio che non consente nulla e aggiungere gradualmente altri criteri ALLOW per aprire ulteriori accessi a un carico di lavoro.

Rifiuta tutto l'accesso

L'esempio seguente mostra un criterio DENY che corrisponde a tutto. Poiché i criteri DENY vengono valutati prima dei criteri ALLOW, tutte le richieste vengono rifiutate anche se esiste un criterio ALLOW che corrisponde alla richiesta.

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: deny-all
spec:
  action: DENY
  rules:
  - {}

Un criterio di rifiuto di tutti è utile se vuoi disattivare temporaneamente tutto l'accesso a un workload.

Consenti tutto

L'esempio seguente mostra un criterio ALLOW che corrisponde a tutto e consente l'accesso completo a un carico di lavoro. Il criterio consenti tutto rende inutili gli altri criteri ALLOW perché consente sempre la richiesta.

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: allow-all
spec:
  action: ALLOW
  rules:
  - {}

Un criterio consenti tutto è utile se vuoi esporre temporaneamente l'accesso completo a un workload. Se sono presenti norme DENY, le richieste potrebbero comunque essere rifiutate poiché le norme DENY vengono valutate prima di quelle ALLOW.

Best practice

  1. Crea un account di servizio Kubernetes per ogni servizio e specificalo nel deployment. Ad esempio:

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: frontend-sa
      namespace: demo
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: frontend
      namespace:demo
    spec:
      selector:
        matchLabels:
          app: frontend
      template:
        metadata:
          labels:
            app: frontend
        spec:
          serviceAccountName: frontend-sa
        ...
    
  2. Inizia con un criterio che non consente nulla e incrementa gradualmente il numero di criteri ALLOW per concedere più accesso ai carichi di lavoro.

  3. Se utilizzi JWT per il tuo servizio:

    1. Crea un criterio DENY per bloccare le richieste non autenticate, ad esempio:

      apiVersion: security.istio.io/v1beta1
      kind: AuthorizationPolicy
      metadata:
        name: requireJWT
        namespace: admin
      spec:
        action: DENY
        rules:
        -  from:
          - source:
              notRequestPrincipals: ["*"]
      
    2. Applica un criterio che non ammette nulla.

    3. Definisci i criteri ALLOW per ogni carico di lavoro. Per esempi, consulta Token JWT.

Passaggi successivi

Scopri di più sulle funzionalità di sicurezza di Cloud Service Mesh:

Scopri di più sui criteri di autorizzazione nella documentazione di Istio: