Autenticarsi utilizzando un'identità dell'agente in GKE

Gli agenti Google Kubernetes Engine (GKE) con un'identità dell'agente possono utilizzare questa identità per l'autenticazione alle API Google Cloud e a strumenti e servizi esterni. Gli agenti possono utilizzare la propria identità o agire per conto degli utenti finali. Questo documento mostra agli sviluppatori di applicazioni agent come configurare le loro applicazioni per l'autenticazione a varie risorse. Dovresti già sapere come richiedere un'identità agente per un agente GKE.

A seconda della risorsa a cui l'agente deve accedere, l'amministratore della piattaforma potrebbe dover configurare il vault delle credenziali di Auth Manager per eseguire workflow aggiuntivi. Ad esempio, affinché un agente possa autenticarsi su GitHub per conto di un utente finale, un provider di autenticazione OAuth a tre passaggi in Auth Manager deve gestire l'accesso, l'autorizzazione e il reindirizzamento dell'utente. In qualità di sviluppatore, modifichi il tuo agente per chiamare il provider di autenticazione corretto e gestire la ripresa della conversazione per l'utente finale.

Limitazioni

  • Consulta le limitazioni dell'identità dell'agente.
  • Puoi utilizzare la libreria di autenticazione Google per ottenere token di accesso e ID solo per Python. La libreria di autenticazione potrebbe non ottenere token vincolati per altre lingue. Se utilizzi un'altra lingua, passa ai token non associati impostando la variabile di ambiente GOOGLE_API_ENABLE_RUNTIME_BOUND_TOKEN su false.

Prima di iniziare

Prima di iniziare, assicurati di aver eseguito le seguenti operazioni:

  • Abilita l'API Google Kubernetes Engine.
  • Abilita l'API Google Kubernetes Engine
  • Per utilizzare Google Cloud CLI per questa attività, installala e poi inizializza gcloud CLI. Se hai già installato gcloud CLI, scarica l'ultima versione eseguendo il comando gcloud components update. Le versioni precedenti di gcloud CLI potrebbero non supportare l'esecuzione dei comandi in questo documento.

Ruoli obbligatori

Per ottenere le autorizzazioni necessarie per configurare gli agenti di cui è stato eseguito il deployment nei cluster GKE, chiedi all'amministratore di concederti il ruolo IAM Kubernetes Engine Developer (roles/container.developer) nel progetto. Per saperne di più sulla concessione dei ruoli, consulta Gestisci l'accesso a progetti, cartelle e organizzazioni.

Potresti anche riuscire a ottenere le autorizzazioni richieste tramite i ruoli personalizzati o altri ruoli predefiniti.

Autenticarsi alle API Google Cloud

Per autenticarsi alle Google Cloud API come identità dell'agente, l'agente può utilizzare un token di accesso all'identità dell'agente dal server dei metadati sui nodi. Le modifiche che potresti dover apportare al codice dipendono dal modo in cui chiami Google Cloud le API, come segue.

Utilizza le librerie client di Cloud

Se utilizzi una versione delle librerie client di Cloud che include la versione 2.61.0 o successive della libreria google-auth, le Credenziali predefinite dell'applicazione (ADC) ottengono automaticamente un token di accesso all'identità dell'agente. Non devi apportare ulteriori modifiche al codice. Se abiliti l'inserimento di certificati per i pod impostando l'annotazione iam.gke.io/inject-podcertificates: "true", il token di accesso viene associato al certificato X.509 per impostazione predefinita, a meno che tu non disattivi i token associati.

Per ottenere token di accesso non associati quando utilizzi le librerie client di Cloud, esegui una delle seguenti operazioni:

  • Attiva l'inserimento del certificato nel pod e imposta la variabile di ambiente GOOGLE_API_ENABLE_RUNTIME_BOUND_TOKEN su false.
  • Non attivare l'inserimento di certificati nel pod.

Utilizzare chiamate dirette agli endpoint API Google Cloud

Se non utilizzi le librerie client Cloud per interagire con un servizio, puoi utilizzare l'identità dell'agente per autenticarti a un'API Google Cloud procedendo nel seguente modo:

  1. Ottieni un token di accesso dal server di metadati sul nodo. Puoi ottenere un token utilizzando uno dei seguenti metodi:

    • Token di accesso vincolati: utilizza la libreria Python google-auth, che rileva il certificato X.509 del pod e ottiene automaticamente token di accesso vincolati per impostazione predefinita. Per altri linguaggi di programmazione, utilizza token non associati.

    • Token di accesso non associati: se il pod non dispone del bundle di credenziali dell'identità dell'agente, utilizza la libreria di autenticazione Google per il tuo linguaggio di programmazione. La libreria di autenticazione recupera automaticamente i token di accesso non associati e aggiorna i token in scadenza. Per le applicazioni Python nei pod che hanno il bundle di credenziali, imposta la variabile di ambiente GOOGLE_API_ENABLE_RUNTIME_BOUND_TOKEN nella specifica del pod su false, come nel seguente esempio:

      # Multiple lines are omitted here.
      spec:
        containers:
        - name: example-agent
          image: example-image
          env:
          - name: GOOGLE_API_ENABLE_RUNTIME_BOUND_TOKEN
            value: "false"
      # Multiple lines are omitted here.
      

      Questa variabile di ambiente impedisce alla libreria di ottenere token di accesso e token ID vincolati.

  2. Per i token di accesso vincolati, invia la richiesta all'endpoint mTLS dell'API e includi la catena di certificati X.509 dell'identità dell'agente nel trasporto HTTP. Se utilizzi la libreria di autenticazione Google per Python, la libreria gestisce la configurazione del trasporto HTTP per te.

L'esempio seguente mostra come utilizzare la libreria di autenticazione Google per Python per ottenere un token di accesso vincolato ed effettuare una richiesta all'endpoint mTLS di Cloud Storage:

import google.auth
from google.auth.transport.requests import AuthorizedSession


def call_storage_api_mtls(bucket_name: str) -> None:
    # Discover the Pod's X.509 certificate chain by using the auth library
    credentials, project = google.auth.default(
        scopes=["https://www.googleapis.com/auth/cloud-platform"]
    )
    # Configure the mTLS session by using the Pod's certificate chain
    session = AuthorizedSession(credentials)
    session.configure_mtls_channel()
    # Call the Google Cloud mTLS endpoint
    mtls_url = f"https://storage.mtls.googleapis.com/storage/v1/b/{bucket_name}/o"
    response = session.get(mtls_url)
    response.raise_for_status()
    print(response.json())

Autenticarsi su strumenti e servizi esterni

Per autenticarti con strumenti e servizi esterni, puoi configurare l'agente in modo che recuperi le credenziali richieste dal gestore di autenticazione di Agent Identity. Un amministratore della piattaforma configura vari provider di autenticazione nel gestore dell'autenticazione, ognuno dei quali gestisce flussi di lavoro e credenziali di autenticazione specifici. Modifichi il codice dell'applicazione per chiamare un provider di autenticazione specifico e, a seconda del workflow di autenticazione, per gestire il consenso dell'utente e la ripresa della conversazione. Le modifiche specifiche che apporti all'agente dipendono da ciò a cui devi accedere, come segue:

Auth Manager gestisce i workflow di autenticazione corrispondenti e concede all'agente l'accesso alle credenziali criptate, che possono poi essere incluse nelle richieste al servizio esterno. Per saperne di più su cosa deve fare l'amministratore della piattaforma per configurare questi provider di autenticazione e concedere l'accesso all'identità dell'agente, consulta Flussi di lavoro di autenticazione per gli agenti.

Autenticarsi in altri agenti

Nelle architetture multi-agente, gli agenti collaborano spesso richiamando direttamente agenti peer o servizi downstream. Puoi stabilire una comunicazione diretta tra i workload degli agenti utilizzando i token di identità. Puoi ottenere un token ID associato o non associato dal server dei metadati di GKE e utilizzarlo per autenticarti direttamente ad altri agenti.

Per ottenere un token ID e utilizzarlo in una richiesta HTTP, utilizza la libreria di autenticazione Google per Python. La libreria gestisce automaticamente l'individuazione dei certificati e l'acquisizione dei token ID. Se utilizzi un linguaggio di programmazione diverso, la libreria di autenticazione Google potrebbe non ottenere token ID vincolati. Passa ai token ID non associati.

Ottenere un token ID

Per richiedere un token ID nel codice dell'agente, utilizza la libreria di autenticazione Google per il tuo linguaggio di programmazione. Puoi utilizzare la libreria per richiedere token ID associati o non associati, come segue:

  • Token ID vincolati: utilizza l'annotazione iam.gke.io/inject-podcertificates: "true" per attivare l'inserimento del certificato per il tuo pod. La libreria di autenticazione per Python richiede automaticamente un token ID associato al certificato dal server di metadati GKE. Utilizza i token ID vincolati quando esegui l'autenticazione tra gli agenti in esecuzione su Google Cloud utilizzando mTLS.
  • Token ID non associati:

    • Attiva l'inserimento del certificato per il pod ed esegui una delle seguenti operazioni:
      • Nel codice dell'applicazione, nella funzione id_token.fetch_id_token, imposta l'argomento bind_id_token sul valore False. Questo argomento fa sì che la libreria di autenticazione richieda token ID senza vincoli. Le richieste di token di accesso non sono interessate.
      • Nella specifica del pod, imposta la variabile di ambiente GOOGLE_API_ENABLE_RUNTIME_BOUND_TOKEN sul valore false. Questa variabile di ambiente impedisce alla libreria di richiedere token di accesso vincolati e token ID.
    • Non attivare l'inserimento di certificati per il tuo pod. La libreria di autenticazione riceve un token ID non associato perché non è presente alcun bundle di credenziali nel pod.

    Utilizza i token ID non associati quando esegui l'autenticazione per Google Cloud API, servizi esterni o altri agenti utilizzando una connessione non mTLS.

I seguenti esempi mostrano come richiedere un token ID associato o non associato per un agente per cui è abilitata l'inserimento delle credenziali:

  • Richiedi un token ID associato:

    import google.auth.transport.requests
    from google.oauth2 import id_token
    
    # Application Default Credentials automatically requests a certificate-bound
    # ID token.
    def get_bound_id_token(target_audience: str) -> str:
        auth_req = google.auth.transport.requests.Request()
        return id_token.fetch_id_token(auth_req, audience=target_audience)
    

    Il token di identità vincolato include l'impronta del certificato SHA-256 della catena di certificati X.509 del pod nel parametro cnf.x5t#S256.

  • Richiedi un token ID non associato:

    import google.auth.transport.requests
    from google.oauth2 import id_token
    
    def get_unbound_id_token(target_audience: str) -> str:
        auth_req = google.auth.transport.requests.Request()
        return id_token.fetch_id_token(
            auth_req,
            audience=target_audience,
            # Always get an unbound ID token, even if the Pod has a credential
            # bundle.
            bind_id_token=False,
        )
    

Utilizzare il token ID in una richiesta a un altro agente

Dopo aver ottenuto un token ID per l'agente, puoi utilizzarlo per autenticarti direttamente a un altro agente. La modalità di autenticazione della connessione dipende dall'utilizzo o meno di un token ID vincolato, come segue:

  • Per i token ID vincolati, stabilisci una connessione mTLS con l'agente ricevente e autentica la connessione utilizzando entrambe le seguenti credenziali dalla directory /var/run/secrets/workload-spiffe-credentials/ nel pod:
    • Il bundle di credenziali dell'identità dell'agente nel file x509.credential-bundle.private-key.pem, che contiene la catena di certificati foglia per il pod.
    • Il bundle di attendibilità del cluster che si trova nel file TRUST_DOMAIN.spiffe-trust-bundle.pem. Questo file contiene il certificato CA radice per l'agente di ricezione e viene utilizzato per convalidare la catena di certificati dell'agente di ricezione durante l'handshake mTLS. Gli agenti chiamanti e riceventi devono trovarsi nello stesso pool di identità degli agenti.
  • Per i token ID non associati, stabilisci una connessione non mTLS con l'agente ricevente.

Gli esempi seguenti mostrano come inviare una richiesta a un altro agente utilizzando un token ID vincolato o non vincolato:

  • Token ID vincolato: includi il token ID vincolato nell'intestazione Authorization: Bearer della richiesta che invii all'endpoint mTLS dell'agente ricevente. Autentica la connessione TLS utilizzando il certificato X.509 e la chiave privata del pod:

    import ssl
    import urllib3
    
    BUNDLE_PATH = "/var/run/secrets/workload-spiffe-credentials/x509.credential-bundle.private-key.pem"
    TRUST_BUNDLE_PATH = "/var/run/secrets/workload-spiffe-credentials/TRUST_DOMAIN.spiffe-trust-bundle.pem"
    
    def call_peer_agent_bound_mtls(target_mtls_url: str, target_audience: str) -> None:
    
        # Configure the mTLS context by using the certificate chain and trust
        # bundle from the Pod.
        ctx = ssl.create_default_context(cafile=TRUST_BUNDLE_PATH)
        ctx.load_cert_chain(BUNDLE_PATH)
        http = urllib3.PoolManager(ssl_context=ctx, assert_hostname=False)
    
        # Call a peer agent's mTLS endpoint by using the bound ID token and Pod
        # certificate chain.
        bound_id_token = get_bound_id_token(target_audience)
        response = http.request(
            "POST",
            target_mtls_url,
            headers={"Authorization": f"Bearer {bound_id_token}"},
            json={"task": "analyze_data"},
            timeout=10,
        )
        print(response.json())
    

    Sostituisci TRUST_DOMAIN con il dominio di attendibilità per il pool di identità dell'agente.

  • Token ID non associato: includi il token nell'intestazione Authorization: Bearer della richiesta all'agente peer:

    import requests
    
    def call_peer_agent_unbound(target_url: str, target_audience: str) -> None:
        unbound_id_token = get_unbound_id_token(target_audience)
        # Send the request by using a standard TLS connection or plain HTTP.
        response = requests.post(
            target_url,
            headers={"Authorization": f"Bearer {unbound_id_token}"},
            json={"task": "analyze_data"},
            timeout=10,
        )
        response.raise_for_status()
        print(response.json())
    

Convalida la richiesta nell'agente ricevente

Nell'agente ricevente, convalida il token ID nella richiesta in entrata nel seguente modo. Puoi utilizzare librerie crittografiche come Tink per eseguire questi passaggi di verifica anziché scrivere codice personalizzato.

  1. Estrai il token ID dall'intestazione della richiesta Authorization: Bearer.
  2. Verifica che l'attestazione iss (emittente) nel token ID sia il pool di identità dell'agente per l'agente chiamante. L'emittente è una delle seguenti, a seconda che l'agente chiamante si trovi in un progetto che fa parte di un'organizzazione:
    • Progetto che si trova in un'organizzazione: https://sts.googleapis.com/v1/organizations/ORGANIZATION_ID/locations/global/workloadIdentityPools/agents.global.org-ORGANIZATION_ID.system.id.goog, dove ORGANIZATION_ID è l'ID organizzazione dell'organizzazione che contiene il progetto dell'agente chiamante.
    • Progetto che non fa parte di un'organizzazione: https://sts.googleapis.com/v1/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/agents.global.proj-PROJECT_NUMBER.system.id.goog, dove PROJECT_NUMBER è il numero di progetto del cluster GKE dell'agente chiamante.
  3. Scopri l'URI del set di chiavi web JSON (JWKS) per l'emittente e memorizza nella cache le chiavi web JSON (JWK) pubbliche. L'endpoint per JWKS ha il formato ISSUER_URL/openid/jwks, dove ISSUER_URL è l'URL dell'emittente.
  4. Convalida la firma del token utilizzando le seguenti informazioni dell'intestazione JOSE del token ID:
    • La JWK pubblica che corrisponde al parametro di intestazione kid.
    • L'algoritmo crittografico che corrisponde al parametro di intestazione alg, ad esempio RS256.
  5. Verifica che l'impronta del certificato SHA-256 nel parametro cnf.x5t#S256 corrisponda all'impronta del certificato X.509 utilizzato dall'agente chiamante per autenticare la connessione mTLS.
  6. Verifica le seguenti rivendicazioni nel token ID:
    • L'ora di scadenza nella rivendicazione exp è nel futuro.
    • Il pubblico nell'attestazione aud è l'agente ricevente.
  7. Autorizza la richiesta in base all'ID SPIFFE presente nella rivendicazione sub (soggetto) del token.

Passaggi successivi