Configura l'accesso basato su certificati per la federazione delle identità per i workload

Questo documento descrive come configurare l'accesso basato su certificati per la federazione delle identità per i carichi di lavoro utilizzando i certificati X.509.

L'accesso basato su certificato utilizza TLS reciproca (mTLS) per autenticare sia il client che il server durante un handshake TLS. In questo processo, un binding mTLS incorpora criteri basati sul contesto di trasporto e utilizza lo stato del certificato del client all'interno della sessione TLS per prendere decisioni di autorizzazione.

Per la federazione delle identità per i carichi di lavoro X.509, un binding mTLS garantisce che l'intero flusso di autenticazione sia collegato in modo sicuro a un workload attendibile. In questo modo si riduce il rischio di furto di credenziali, perché l'autenticazione è associata a un endpoint specifico e attendibile.

Panoramica della configurazione dell'accesso basato su certificati per la federazione delle identità per i workload

Di seguito è riportata una panoramica generale della procedura per configurare l'accesso basato su certificati per la federazione delle identità per i workload:

  1. Stabilisci una federazione delle identità per i carichi di lavoro configurando l'attendibilità con l'ancora di attendibilità dei certificati X.509.

  2. Crea un livello di accesso per l'accesso basato su certificati.

  3. Aggiungi il livello di accesso a un criterio di accesso sensibile al contesto che applica l'associazione mTLS.

Prima di iniziare

Verifica di disporre dei seguenti prerequisiti:

Crea un livello di accesso per i certificati

  1. Crea un livello di accesso mTLS. Il livello di accesso mTLS convalida i certificati quando determina l'accesso alle risorse.

    Console

    In Gestore contesto accesso, crea un livello di accesso personalizzato e inserisci la seguente espressione nel campo dell'espressione CEL: request.auth.matchesMtlsTokens(origin) == true.

    gcloud

    Per creare un livello di accesso personalizzato, esegui questo comando:

       gcloud access-context-manager levels create ACCESS_LEVEL_NAME 
    --title=TITLE
    --custom-level-spec=FILE
    --description=DESCRIPTION
    --policy=POLICY_NAME

    Sostituisci quanto segue:

    • ACCESS_LEVEL_NAME: il nome del livello di accesso.
    • TITLE: il titolo del livello di accesso.
    • FILE: un file YAML con i seguenti contenuti: request.auth.matchesMtlsTokens(origin) == true.
    • DESCRIPTION: una descrizione del livello di accesso.
    • POLICY_NAME: il nome della policy di accesso.
  2. Esporta il livello di accesso che hai creato in una variabile di ambiente. Questa variabile viene utilizzata nei passaggi successivi.

      export ACCESS_LEVEL_ID=ACCESS_LEVEL_ID
      

    Sostituisci ACCESS_LEVEL_ID con il nome del livello di accesso, ad esempio accessPolicies/12345/accessLevels/acl_1.

Crea un binding di accesso sensibile al contesto per un pool di identità del workload

  1. Imposta le seguenti variabili di ambiente.

    export ORG_ID=ORG_ID
    export CALLER_PROJECT_ID=CALLER_PROJECT_ID
    export FEDERATED_PRINCIPAL=FEDERATED_PRINCIPAL
    

    Sostituisci quanto segue:

    • ORG_ID: l'ID della tua organizzazione.
    • CALLER_PROJECT_ID: l'ID del progetto da utilizzare per chiamare le API.
    • FEDERATED_PRINCIPAL: il nome dell'entità di identità nel pool di identità del workload che rispetta la policy di accesso sensibile al contesto. Puoi utilizzare una delle seguenti opzioni:

      una singola identità con il formato - principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/subject/SUBJECT_ATTRIBUTE_VALUE

      OPPURE

      tutte le identità in un pool con il formato - principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/*

    gcloud

    gcloud alpha access-context-manager cloud-bindings create \
    --organization=ORG_ID \
    --federated-principal=FEDERATED_PRINCIPAL \
    --level=ACCESS_LEVEL_ID
    --dry-run-level=DRY_RUN_ACCESS_LEVEL_ID
    

    Sostituisci quanto segue:

    • ACCESS_LEVEL_ID: il nome del livello di accesso.
    • DRY_RUN_ACCESS_LEVEL_ID: il nome del livello di accesso di prova. Ti consigliamo di attivare prima un binding di policy dry run per comprendere il potenziale impatto sul traffico esistente.

    curl

    1. Crea un file JSON con l'associazione di accesso sensibile al contesto.

      Puoi fornire un solo livello di accesso in una richiesta, anche se il campo è ripetuto. Puoi utilizzare i seguenti tipi di entità federate:

      • Singola identità: principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/subject/SUBJECT_ATTRIBUTE_VALUE
      • Tutte le identità in un pool: principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/*
      echo { \
        \"principal\": { \
          \"federatedPrincipal\": \"${FEDERATED_PRINCIPAL:?}\" \
        },\
        \"accessLevels\": [\"${ACCESS_LEVEL_ID:?}\"] \
      } \
      >> request.json
      
    2. Utilizza curl per inviare la seguente richiesta HTTP.

      curl -H "X-Goog-User-Project: ${CALLER_PROJECT_ID:?}" -X POST \
         -H "Authorization: Bearer $(gcloud auth print-access-token)" \
         -H "Content-Type: application/json; charset=utf-8" \
         -d @request.json \
       "https://accesscontextmanager.googleapis.com/v1alpha/organizations/${ORG_ID:?}/gcpUserAccessBindings"
      

Autorizza utilizzando le Google Cloud librerie client

Per autorizzare i carichi di lavoro della federazione delle identità per la forza lavoro utilizzando le librerie clientGoogle Cloud , completa i seguenti passaggi.

  1. Crea un file Credenziali predefinite dell'applicazione (ADC) configurato per l'autenticazione della federazione delle identità per la forza lavoro.

    gcloud iam workload-identity-pools create-cred-config IDENTITY_POOL_ID \
    --credential-cert-path WORKLOAD_CERTIFICATE_PATH \
    --credential-cert-private-key-path WORKLOAD_KEY_PATH \
    --output-file ADC_FILE_OUTPUT_PATH
    

    Sostituisci quanto segue:

    • IDENTITY_POOL_ID: l'ID del tuo pool di identità del workload.
    • WORKLOAD_CERTIFICATE_PATH: il percorso del file del certificato del tuo workload.
    • WORKLOAD_KEY_PATH: il percorso del file della chiave privata del tuo workload.
    • ADC_FILE_OUTPUT_PATH: il percorso di output per il file ADC.

    Questo comando genera anche un file di configurazione del certificato nella directory di configurazione predefinita della gcloud CLI. Il file di configurazione del certificato supporta l'autenticazione iniziale e stabilisce handshake mTLS per le richieste successive alle risorse Google Cloud .

  2. Imposta una variabile di ambiente in modo che punti al file ADC. In questo modo, le tue credenziali sono rilevabili dalle librerie client Google.

    export GOOGLE_APPLICATION_CREDENTIALS=${application_default_credentials.json}
    

    Questo passaggio è facoltativo se ometti l'argomento --output-file quando generi il file ADC. Se ometti l'argomento, il file ADC viene creato e letto dalla directory di configurazione predefinita di gcloud CLI.

  3. Per stabilire e testare l'accesso alle API Google Cloud , completa i seguenti passaggi. Puoi utilizzare Go o Python.

    Vai

    1. Utilizza l'esempio seguente per creare un file Go, ad esempio golang_test.go.

      package golang_test
      
      import (
           "io"
           "log"
           "testing"
      
           "cloud.google.com/go/auth/credentials"
           "cloud.google.com/go/auth/httptransport"
      )
      
      func TestGoExample(t *testing.T) {
      
           scopes := []string{
                   "https://www.googleapis.com/auth/pubsub", // Scope for Pub/Sub access
                   // Add other scopes as needed
           }
      
           dopts := credentials.DetectOptions{
                   Scopes: scopes,
           }
      
           // Create httptransport.Options with the scopes
           opts := &httptransport.Options{
                   DetectOpts: &dopts,
           }
           hc, err := httptransport.NewClient(opts)
           if err != nil {
                   t.Fatalf("NewHTTPClient: %v", err)
           }
      
           resp, err := hc.Get("https://pubsub.mtls.googleapis.com/v1/projects/PROJECT_ID/topics")
           if err != nil {
                   t.Fatalf("Get: %v", err)
           }
           t.Logf("Status: %s", resp.Status)
      
           t.Cleanup(func() {
                  resp.Body.Close()
           })
      
           b, err := io.ReadAll(resp.Body)
           if err != nil {
                  t.Fatal(err)
           }
           log.Println(string(b))
      }
      

      Sostituisci PROJECT_ID con l'ID progetto di gcloud CLI.

    2. Per eseguire un test su una VM di Compute Engine, utilizza il seguente comando.

    go mod init example.com
    go mod tidy
    go test -v golang_test.go --count=1
    

    Python

    1. Utilizza l'esempio seguente per creare un file di test, ad esempio python_test.py.

      import google.auth
      import google.auth.transport.requests
      import requests
      
      def test_go_example():
      # Define the required scopes for your application
      scopes = [
         "https://www.googleapis.com/auth/pubsub",  # Scope for Pub/Sub access
         # Add other scopes as needed
      ]
      
      # Obtain Application Default Credentials (ADC) with the specified scopes
      credentials, _ = google.auth.default(scopes=scopes)
      
      # Create an authorized HTTP session using the ADC credentials
      authed_session = google.auth.transport.requests.AuthorizedSession(credentials)
      
      try:
      # Make a GET request to the Pub/Sub API endpoint
      response = authed_session.get(
          "https://pubsub.mtls.googleapis.com/v1/projects/PROJECT_ID/topics"
      )
      
      # Check if the request was successful
      response.raise_for_status()  # Raise an exception for error statuses
      
      # Log the response status and content
      print(f"Status: {response.status_code}")
      print(response.text)
      
      except requests.exceptions.RequestException as e:
      print(f"Error making the request: {e}")
      
      if __name__ == "__main__":
      test_go_example()
      

      Sostituisci PROJECT_ID con l'ID progetto di gcloud CLI.

    2. Per eseguire un test su una VM Compute Engine, completa i seguenti passaggi.

      1. Configura un ambiente virtuale Python.
      2. Installa le librerie richieste.

        pip install google-auth google-auth-httplib2 requests
        
      3. Esegui il test:

        python3 python_test.py
        

Autorizzare l'utilizzo di richieste HTTP semplici

Per autorizzare i carichi di lavoro della federazione delle identità per la forza lavoro utilizzando richieste HTTP semplici, completa i seguenti passaggi.

  1. Ottieni un token di accesso associato al certificato dal servizio token di sicurezza tramite un handshake mTLS standard. Google Cloud

  2. Chiama i servizi Google Cloud con il token di accesso ottenuto dal servizio token di sicurezza. Questo esempio esegue query su Cloud Storage.

    $ curl --key ${workload_key.pem} --cert ${workload_cert.pem} -X GET 'https://storage.mtls.googleapis.com/{replace_with_your_resources}' -H "Authorization: Bearer $ACCESS_TOKEN"
    
  3. Il binding mTLS impone l'utilizzo di mTLS. Esegui questo comando per verificare che una connessione non mTLS non vada a buon fine e restituisca un errore di autorizzazione.

    $ curl -X GET 'https://storage.googleapis.com/{replace_with_your_resources}' -H "Authorization: Bearer $ACCESS_TOKEN"
    

Elenca l'associazione policy

Per elencare il binding della policy per la federazione delle identità per i carichi di lavoro, esegui questo comando.

gcloud

Il seguente comando elenca i binding specifici all'interno di una determinata organizzazione, filtrando quelli che si applicano alle entità federate.

gcloud alpha access-context-manager cloud-bindings list \
--organization=ORG_ID \
--filter='principal:federatedPrincipal'

curl

curl -H "X-Goog-User-Project: ${CALLER_PROJECT_ID:?}" -X GET \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://accesscontextmanager.googleapis.com/v1alpha/organizations/${ORG_ID:?}/gcpUserAccessBindings?filter=principal%3Afederated_principal"

Aggiorna un binding dei criteri

Per aggiornare un binding di policy, aggiungi il nuovo livello di accesso a un file JSON ed esegui il comando seguente.

gcloud

gcloud alpha access-context-manager cloud-bindings update \
--binding=BINDING_ID \
--level=NEW_ACCESS_LEVEL_ID

curl

curl -H "X-Goog-User-Project: ${CALLER_PROJECT_ID:?}" -X PATCH \
 -H "Authorization: Bearer $(gcloud auth print-access-token)" \
 -H "Content-Type: application/json; charset=utf-8" \
 -d @request.json \
"https://accesscontextmanager.googleapis.com/v1alpha/organizations/${ORG_ID:?}/gcpUserAccessBindings/${BINDING_ID:?}?updateMask=access_levels"

Eliminare un binding delle policy

Per eliminare un binding delle policy, esegui questo comando.

gcloud

gcloud alpha access-context-manager cloud-bindings delete \
--binding=BINDING_ID

curl

curl -H "X-Goog-User-Project: ${CALLER_PROJECT_ID:?}" -X DELETE \
   -H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://accesscontextmanager.googleapis.com/v1alpha/organizations/${ORG_ID:?}/gcpUserAccessBindings/${BINDING_ID:?}"

Risoluzione dei problemi

Di seguito sono riportati alcuni problemi comuni e le azioni suggerite per risolverli:

  • Errore: 403 Forbidden, user does not have permission.

    Azione:controlla il criterio IAM per verificare che il pool di identità del workload abbia accesso alla tua risorsa Google Cloud .

  • Errore: Unauthorized_client: Could not obtain a value for google.subject from the given credential.

    Azione:il backend non è riuscito a estrarre un valore per google.subject dal certificato client in base alla mappatura degli attributi. Controlla il certificato client per verificare che il campo utilizzato per eseguire la mappatura abbia un valore.

  • Se riscontri negazioni di accesso impreviste dopo aver attivato l'accesso sensibile al contesto, puoi sbloccare rapidamente il traffico rimuovendo il binding dell'accesso sensibile al contesto utilizzando il seguente comando:

    gcloud alpha access-context-manager cloud-bindings delete
    

    Dopo il ripristino dell'accesso, esamina il log di controllo per determinare il motivo per cui le richieste sono state rifiutate.