Autenticazione per la chiamata (2ª generazione)

Per richiamare una Cloud Function autenticata, principal deve soddisfare i seguenti requisiti:

  • Disporre dell'autorizzazione per richiamare la funzione.
  • Fornisci un token ID quando richiama la funzione.

Che cos'è un'entità? Come descritto in Proteggere le funzioni Cloud Functions, Cloud Functions supporta due diversi tipi di identità, che sono anche denominate principal:

  • Account di servizio: si tratta di account speciali che fungono da identità di un una persona fisica, ad esempio una funzione, un'applicazione o una VM. Ti offrono un modo per autenticare queste non persone.
  • Account utente: questi account rappresentano persone, sia come account individuali Titolari di Account Google o come parte di una persona giuridica controllata da Google, ad esempio un soggetto Gruppo.

Consulta la panoramica di IAM per scoprire di più su IAM di base concetti.

Per richiamare una Cloud Function autenticata, l'entità deve avere Autorizzazione IAM:

  • run.routes.invoke. Di solito avviene tramite Ruolo Invoker di Cloud Run. Questo deve essere assegnata alla risorsa del servizio Cloud Run.

Per concedere queste autorizzazioni, utilizza add-invoker-policy-binding come mostrato Autenticazione della funzione per le chiamate di funzione.

Per l'autorizzazione per creare, aggiornare o eseguire altre azioni amministrative su un , l'entità deve avere un ruolo appropriato. I ruoli includono le autorizzazioni che definiscono le azioni consentite all'entità. Consulta Utilizzo di IAM per autorizzare l'accesso per ulteriori informazioni.

Richiamare una funzione può avere ulteriori complessità. Le funzioni basate su eventi possono: essere richiamato solo dall'origine evento a cui sono iscritti, Funzioni HTTP possono essere richiamate da diversi tipi di identità, provenienti da luoghi diversi. L'invocatore può essere uno sviluppatore che sta testando la funzione o un'altra funzione o servizio che vuole utilizzare la funzione. Per impostazione predefinita, Le identità devono fornire un token ID con la richiesta di autenticazione. Inoltre, all'account utilizzato deve essere stata concessa le autorizzazioni appropriate.

Scopri di più su come generare e utilizzare i token ID.

Esempi di autenticazione

Questa sezione mostra alcuni esempi diversi di autenticazione invocazione.

Esempio 1: autenticare i test degli sviluppatori

In qualità di sviluppatore, devi avere accesso per creare, aggiornare ed eliminare funzioni. questa viene concessa utilizzando normale (IAM).

Tuttavia, in qualità di sviluppatore, potresti dover richiamare le tue funzioni per ai fini di test. Per richiamare una funzione utilizzando curl o strumenti simili, tieni presente seguenti:

  • Assegna un ruolo al tuo account utente Cloud Functions contenente l'autorizzazione di chiamata.

  • Se stai lavorando dalla tua macchina locale, configura l'accesso da riga di comando inizializzare Google Cloud CLI.

  • Fornisci la tua richiesta con le credenziali di autenticazione generate da Google Token ID archiviato in un'intestazione Authorization. Ad esempio, richiedi un token ID utilizzando gcloud eseguendo questo comando:

    curl  -H "Authorization: Bearer $(gcloud auth print-identity-token)" \
      https://FUNCTION_URL
    

    dove FUNCTION_URL è l'URL della funzione. Recupera questo URL dalla pagina Cloud Functions del console Google Cloud o eseguendo il comando gcloud functions describe come mostrato nel primo passaggio dell'esempio del comando di deployment di Google Cloud CLI.

Puoi utilizzare i token creati da gcloud per richiamare funzioni HTTP in qualsiasi progetto purché il tuo account abbia cloudfunctions.functions.invoke l'autorizzazione per la funzione che viene richiamata. A scopo di sviluppo, usa Token ID generati da gcloud. Tuttavia, tieni presente che questi token non hanno un pubblico , il che li rende suscettibili di attacchi di inoltro. In produzione ambienti, utilizza i token ID emessi per un account di servizio con il specificato per il segmento di pubblico. Questo approccio migliora la sicurezza limitando l'utilizzo dei token solo al servizio previsto.

Come sempre, ti consigliamo di assegnare l'insieme minimo di autorizzazioni necessari per sviluppare e utilizzare le tue funzioni. Assicurati che i ruoli IAM i criteri delle tue funzioni sono limitati al numero minimo di utenti e account di servizio.

Esempio 2: autenticare una funzione per effettuare chiamate di funzione

Quando si creano servizi che collegano più funzioni, è una buona idea garantire che ogni funzione possa inviare richieste solo a un sottoinsieme specifico di altre funzioni. Ad esempio, se hai una funzione login, dovrebbe essere in grado per accedere alla funzione user profiles, ma probabilmente non dovrebbe essere in grado per accedere alla funzione search.

a configurare la funzione ricevente in modo che accetti le richieste da una specifica chiamata devi concedere il ruolo richiamar appropriato alla chiamata l'account di servizio della funzione sulla funzione ricevente. Il ruolo invoker è Invoker di Cloud Run (roles/run.invoker) e deve essere concesso sul servizio sottostante:

Console

Utilizza Invoker di Cloud Run:

  1. Vai alla console Google Cloud:

    Vai alla console Google Cloud

  2. Nell'elenco dei servizi Cloud Run, fai clic sulla casella di controllo accanto funzione ricevente. Non fare clic sulla funzione in sé.

    Si apre il riquadro Autorizzazioni.

  3. Fai clic su Aggiungi entità.

  4. Inserisci l'identità del servizio chiamante. Di solito è un'email per impostazione predefinita PROJECT_NUMBER-compute@developer.gserviceaccount.com.

    Tieni presente che il numero del progetto è diverso dall'ID e dal progetto . Puoi trovare il numero del tuo progetto nella console Google Cloud Pagina Dashboard.

  5. Seleziona il ruolo Cloud Run Invoker da Seleziona un ruolo menu a discesa.

  6. Fai clic su Salva.

gcloud

Usa il comando gcloud functions add-invoker-policy-binding:

gcloud functions add-invoker-policy-binding RECEIVING_FUNCTION \
  --member='serviceAccount:CALLING_FUNCTION_IDENTITY'

La add-invoker-policy-binding aggiunge un criterio IAM per il ruolo di callback associazione che consente al membro specificato (entità) di richiamare l'oggetto personalizzata. Google Cloud CLI rileva automaticamente la generazione della funzione e aggiunge il ruolo Invoker corretto (run.invoker per 2ª generazione).

Sostituisci quanto segue:

  • RECEIVING_FUNCTION: il nome del funzione ricevente.
  • CALLING_FUNCTION_IDENTITY: la funzione di chiamata Identity, l'indirizzo email di un account di servizio.

Dal momento che richiamerà la funzione ricevente, la funzione di chiamata deve fornire anche un token ID firmato da Google per l'autenticazione. Si tratta di una procedura in due passaggi di elaborazione:

  1. Crea un token ID firmato da Google con il campo per il pubblico (aud) impostato su URL della funzione ricevente.

  2. Includi il token ID in una Authorization: Bearer ID_TOKEN nell'intestazione richiesta alla funzione.

Il modo di gran lunga più semplice e affidabile per gestire questo processo è utilizzare le librerie di autenticazione, come mostrato di seguito, per generare e utilizzare questo token.

Genera token ID

Questa sezione descrive i diversi modi in cui puoi generare il token ID di cui un'entità ha bisogno per richiamare una funzione.

L'accesso non autenticato senza un token ID è possibile, ma deve essere abilitato. Consulta Utilizzo di IAM per autorizzare l'accesso per ulteriori informazioni.

Genera i token in modo programmatico

Dopo che il codice riportato di seguito ha generato un token ID, quest'ultimo chiama il tuo Cloud Function con quel token per tuo conto. Questo codice funziona in cui le librerie possono ottenere le credenziali di autenticazione, inclusi gli ambienti che supportano Credenziali predefinite dell'applicazione.

Node.js

/**
 * TODO(developer): Uncomment these variables before running the sample.
 */

// Cloud Functions uses your function's url as the `targetAudience` value
// const targetAudience = 'https://project-region-projectid.cloudfunctions.net/myFunction';
// For Cloud Functions, endpoint (`url`) and `targetAudience` should be equal
// const url = targetAudience;


const {GoogleAuth} = require('google-auth-library');
const auth = new GoogleAuth();

async function request() {
  console.info(`request ${url} with target audience ${targetAudience}`);
  const client = await auth.getIdTokenClient(targetAudience);

  // Alternatively, one can use `client.idTokenProvider.fetchIdToken`
  // to return the ID Token.
  const res = await client.request({url});
  console.info(res.data);
}

request().catch(err => {
  console.error(err.message);
  process.exitCode = 1;
});

Python

import urllib

import google.auth.transport.requests
import google.oauth2.id_token


def make_authorized_get_request(endpoint, audience):
    """
    make_authorized_get_request makes a GET request to the specified HTTP endpoint
    by authenticating with the ID token obtained from the google-auth client library
    using the specified audience value.
    """

    # Cloud Functions uses your function's URL as the `audience` value
    # audience = https://project-region-projectid.cloudfunctions.net/myFunction
    # For Cloud Functions, `endpoint` and `audience` should be equal

    req = urllib.request.Request(endpoint)

    auth_req = google.auth.transport.requests.Request()
    id_token = google.oauth2.id_token.fetch_id_token(auth_req, audience)

    req.add_header("Authorization", f"Bearer {id_token}")
    response = urllib.request.urlopen(req)

    return response.read()

Vai


import (
	"context"
	"fmt"
	"io"

	"google.golang.org/api/idtoken"
)

// `makeGetRequest` makes a request to the provided `targetURL`
// with an authenticated client using audience `audience`.
func makeGetRequest(w io.Writer, targetURL string, audience string) error {
	// For Cloud Functions, endpoint (`serviceUrl`) and `audience` are the same.
	// Example `audience` value (Cloud Functions): https://<PROJECT>-<REGION>-<PROJECT_ID>.cloudfunctions.net/myFunction
	// (`targetURL` and `audience` will differ for GET parameters)
	ctx := context.Background()

	// client is a http.Client that automatically adds an "Authorization" header
	// to any requests made.
	client, err := idtoken.NewClient(ctx, audience)
	if err != nil {
		return fmt.Errorf("idtoken.NewClient: %w", err)
	}

	resp, err := client.Get(targetURL)
	if err != nil {
		return fmt.Errorf("client.Get: %w", err)
	}
	defer resp.Body.Close()
	if _, err := io.Copy(w, resp.Body); err != nil {
		return fmt.Errorf("io.Copy: %w", err)
	}

	return nil
}

Java

import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpResponse;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.auth.oauth2.IdTokenCredentials;
import com.google.auth.oauth2.IdTokenProvider;
import java.io.IOException;

public class Authentication {

  // makeGetRequest makes a GET request to the specified Cloud Run or
  // Cloud Functions endpoint `serviceUrl` (must be a complete URL), by
  // authenticating with an ID token retrieved from Application Default
  // Credentials using the specified `audience`.
  //
  // For Cloud Functions, endpoint (`serviceUrl`) and `audience` are the same.
  // Example `audience` value (Cloud Functions): https://project-region-projectid.cloudfunctions.net/myFunction
  public static HttpResponse makeGetRequest(String serviceUrl, String audience) throws IOException {
    GoogleCredentials credentials = GoogleCredentials.getApplicationDefault();
    if (!(credentials instanceof IdTokenProvider)) {
      throw new IllegalArgumentException("Credentials are not an instance of IdTokenProvider.");
    }
    IdTokenCredentials tokenCredential =
        IdTokenCredentials.newBuilder()
            .setIdTokenProvider((IdTokenProvider) credentials)
            .setTargetAudience(audience)
            .build();

    GenericUrl genericUrl = new GenericUrl(serviceUrl);
    HttpCredentialsAdapter adapter = new HttpCredentialsAdapter(tokenCredential);
    HttpTransport transport = new NetHttpTransport();
    HttpRequest request = transport.createRequestFactory(adapter).buildGetRequest(genericUrl);
    return request.execute();
  }
}

Genera i token manualmente

Se stai richiamando una funzione e per qualche motivo non puoi utilizzare il librerie di autenticazione, esistono due modi per ottenere il token ID manualmente, utilizzando il server di metadati Compute oppure creando un JWT autofirmato e scambiandolo con un token ID firmato da Google.

Utilizzare il server dei metadati

Puoi utilizzare il server di metadati di Compute per recuperare i token ID con uno specifico pubblico come segue:

curl "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=AUDIENCE" \
     -H "Metadata-Flavor: Google"

Sostituisci AUDIENCE con l'URL della funzione che stai richiamando. Puoi recuperare questo URL come descritto nella sezione Test per l'autenticazione degli sviluppatori riportata sopra.

Scambia un JWT autofirmato con un token ID firmato da Google

  1. Concedi il ruolo Invoker di Cloud Functions (roles/cloudfunctions.invoker) a l'account di servizio della funzione chiamante sulla funzione ricevente.

  2. Crea un un account di servizio e una chiave e scaricare il file con la chiave privata (in formato JSON) sull'host da cui la funzione o il servizio chiamante effettua le proprie richieste.

  3. Crea un JWT con l'intestazione impostata su {"alg":"RS256","typ":"JWT"}. Il payload dovrebbe includi un'attestazione target_audience impostata sull'URL della funzione ricevente e rivendicazioni iss e sub impostate sull'indirizzo email dell'account di servizio in precedenza. Deve includere anche le rivendicazioni exp e iat. aud la rivendicazione deve essere impostata su https://www.googleapis.com/oauth2/v4/token.

  4. Usa la chiave privata scaricata sopra per firmare il JWT.

  5. Utilizzando questo JWT, invia una richiesta POST a https://www.googleapis.com/oauth2/v4/token. I dati di autenticazione devono essere incluso nell'intestazione e nel corpo della richiesta.

    Nell'intestazione:

    Authorization: Bearer $JWT - where $JWT is the JWT you just created
    Content-Type: application/x-www-form-urlencoded
    

    Nel corpo:

    grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=$JWT
    

    Sostituisci $JWT con il JWT appena creato

    Questo restituisce un altro JWT che include un id_token firmato da Google.

Invia la richiesta GET/POST alla funzione ricevente. Includi il token firmato da Google Token ID in un'intestazione Authorization: Bearer ID_TOKEN_JWT nella richiesta.

Passaggi successivi