Scopri come richiamare le funzioni Cloud Run autenticate

1. Introduzione

Panoramica

Le funzioni Cloud Run sono una soluzione di calcolo leggera che consente agli sviluppatori di creare funzioni autonome a uso specifico che possono essere attivate tramite HTTPS o rispondere a CloudEvents senza dover gestire un ambiente server o di runtime. Scopri di più sulle funzioni Cloud Run nel nostro post del blog.

Esistono due approcci principali per controllare le chiamate alle funzioni di Cloud Run: proteggere l'accesso in base all'identità e proteggere l'accesso mediante i controlli dell'accesso basati sulla rete. Questo codelab si concentra sul primo approccio e illustra tre scenari per garantire l'accesso in base all'identità per invocare una funzione:

  1. Utilizzare il token di identità gcloud per invocare una funzione a scopo di sviluppo e test locali
  2. Sostituisci un account di servizio durante lo sviluppo e i test locali per utilizzare le stesse credenziali di produzione
  3. Utilizza le librerie client di Google per gestire l'autenticazione alle API Google Cloud, ad esempio quando un servizio deve invocare una funzione

Cosa imparerai a fare

  • Come configurare l'autenticazione su una funzione Cloud Run e verificare che l'autenticazione sia stata configurata correttamente
  • Richiama una funzione autenticata da un ambiente di sviluppo locale fornendo il token per la tua identità gcloud
  • Come creare un account di servizio e concedergli il ruolo appropriato per richiamare una funzione
  • Come eseguire l'impersonificazione di un servizio da un ambiente di sviluppo locale con i ruoli appropriati per l'invocazione di una funzione

2. Configurazione e requisiti

Prerequisiti

Attiva Cloud Shell

  1. Nella console Cloud, fai clic su Attiva Cloud Shell d1264ca30785e435.png.

84688aa223b1c3a2.png

Se è la prima volta che avvii Cloud Shell, viene visualizzata una schermata intermedia che descrive di cosa si tratta. Se viene visualizzata una schermata intermedia, fai clic su Continua.

d95252b003979716.png

Dovrebbero bastare pochi istanti per eseguire il provisioning e connettersi a Cloud Shell.

7833d5e1c5d18f54.png

Questa macchina virtuale è caricata con tutti gli strumenti di sviluppo necessari. Offre una home directory permanente da 5 GB e viene eseguita in Google Cloud, migliorando notevolmente le prestazioni di rete e l'autenticazione. Gran parte, se non tutto, del lavoro in questo codelab può essere svolto con un browser.

Una volta eseguita la connessione a Cloud Shell, dovresti vedere che il tuo account è già autenticato e il progetto è già impostato sul tuo ID progetto.

  1. Esegui questo comando in Cloud Shell per verificare che l'account sia autenticato:
gcloud auth list

Output comando

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Esegui il seguente comando in Cloud Shell per verificare che il comando gcloud conosca il tuo progetto:
gcloud config list project

Output comando

[core]
project = <PROJECT_ID>

In caso contrario, puoi impostarlo con questo comando:

gcloud config set project <PROJECT_ID>

Output comando

Updated property [core/project].

3. Creare e testare una funzione Cloud Run autenticata

Se richiedi l'autenticazione, l'entità che richiama la funzione deve avere il ruolo Invoker di Cloud Run. In caso contrario, la funzione restituirà un errore 403 Forbidden. Questo codelab mostrerà come concedere i ruoli Invoker appropriati a un principio.

Configura le variabili di ambiente locali per i comandi gcloud semplificati

Innanzitutto, creerai alcune variabili di ambiente per migliorare la leggibilità dei comandi gcloud utilizzati in questo codelab.

REGION=us-central1
PROJECT_ID=$(gcloud config get-value project)

Crea il codice sorgente per la funzione

Sebbene questo codelab utilizzi Node.js, puoi utilizzare qualsiasi runtime supportato dalle librerie client di Google Auth.

Innanzitutto, crea una directory e accedi tramite cd.

mkdir auth-function-codelab && cd $_

Poi, crea il file package.json.

touch package.json

echo '{
  "dependencies": {
    "@google-cloud/functions-framework": "^3.0.0"
  }
}
' > package.json

Quindi, crea il file di origine index.js.

touch index.js

echo 'const functions = require("@google-cloud/functions-framework");

functions.http("helloWorld", (req, res) => {
 res.send(`Hello ${req.query.name || req.body.name || "World"}!`);
});' > index.js

Crea la funzione autenticata

Di seguito sono riportati i passaggi per creare una funzione autenticata per il runtime nodejs20. Tuttavia, puoi utilizzare qualsiasi runtime supportato dalle librerie client di autenticazione Google.

FUNCTION_NAME=authenticated-function-codelab
ENTRY_POINT=helloWorld

Per eseguire il deployment di una funzione Cloud Run direttamente su Cloud Run, esegui il seguente comando:

gcloud beta run deploy $FUNCTION_NAME \
      --source . \
      --function helloWorld \
      --region $REGION \
      --no-allow-unauthenticated

e poi salvare l'URL della funzione come variabile di ambiente da utilizzare in seguito.

FUNCTION_URL="$(gcloud run services describe $FUNCTION_NAME --region $REGION --format 'value(status.url)')"

Se preferisci eseguire il deployment come Cloud Functions 2ª gen., utilizza il seguente comando:

gcloud functions deploy nodejs-http-function \
  --gen2 \
  --runtime=nodejs20 \
  --region=$REGION \
  --source=. \
  --entry-point=helloWorld \
  --trigger-http \
  --no-allow-unauthenticated

e poi salvare l'URL della funzione come variabile di ambiente da utilizzare in seguito.

FUNCTION_URL="$(gcloud functions describe $FUNCTION_NAME --gen2 --region us-central1 --format='get(serviceConfig.uri)')"

Verifica che la funzione richieda l'autenticazione tentando di richiamarla come chiamante anonimo

Evocherai la funzione senza autenticazione per verificare di ricevere l'errore 403 previsto.

Da una riga di comando, esegui il seguente comando curl:

curl -i $FUNCTION_URL

Verrà visualizzato il seguente risultato:

<html><head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>403 Forbidden</title>
</head>
<body text=#000000 bgcolor=#ffffff>
<h1>Error: Forbidden</h1>
<h2>Your client does not have permission to get URL <code>/</code> from this server.</h2>
<h2></h2>
</body></html>

Ora è tutto pronto per esaminare tre scenari in cui puoi richiamare la funzione fornendo l'autenticazione.

4. Scenario 1: utilizzo del token di identità gcloud

In qualità di sviluppatore, ti servirà un modo per testare la funzione durante lo sviluppo locale. In questa sezione, eseguirai un rapido test per verificare che la funzione sia autenticata correttamente utilizzando la tua identità.

Verifica di aver eseguito l'autenticazione utilizzando gcloud eseguendo il seguente comando:

gcloud auth list

Dovresti vedere un asterisco accanto all'identità attiva, ad esempio:

Credentialed Accounts
ACTIVE  ACCOUNT

*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`

Puoi trovare ulteriori informazioni sulla configurazione di gcloud init e gcloud auth login nella documentazione.

Quindi, richiama la funzione e passale il token di identità.

curl $FUNCTION_URL -H "Authorization: bearer $(gcloud auth print-identity-token)"

Ora vedrai il risultato:

Hello World!

Risoluzione dei problemi

Se ricevi un errore 403 Forbidden, assicurati che la tua identità abbia il ruolo Invoker di Cloud Run. Puoi utilizzare la console IAM per verificare i ruoli assegnati a un'entità.

Sebbene l'utilizzo del tuo token di identità sia un modo rapido per testare la funzione durante lo sviluppo, l'autore della chiamata della funzione autenticata avrà bisogno dei ruoli appropriati; in caso contrario, l'autore della chiamata riceverà un errore 403 Forbidden.

Ti consigliamo di seguire il principio del privilegio minimo limitando il numero di identità e account di servizio che dispongono di ruoli per richiamare la funzione. Nel prossimo scenario, imparerai a creare un nuovo account di servizio e a concedergli i ruoli appropriati per richiamare la funzione.

5. Scenario 2: simulazione dell'identità di un account di servizio

In questo scenario, assumerai l'identità (ovvero acquisirai le autorizzazioni) di un account di servizio per richiamare una funzione durante lo sviluppo e il test in locale. Se usi l'identità di un account di servizio, puoi testare la tua funzione con le stesse credenziali dell'account di produzione.

In questo modo, non solo verificherai i ruoli, ma rispetterai anche il principio del privilegio minimo non dovendo concedere il ruolo Invoker di Cloud Function ad altre identità solo a scopo di test locale.

Ai fini di questo codelab, creerai un nuovo account di servizio con solo i ruoli per invocare la funzione creata in questo codelab.

Crea un nuovo service account

Innanzitutto, dovrai creare un paio di variabili d'ambiente aggiuntive per rappresentare gli account di servizio utilizzati nei comandi gcloud.

SERVICE_ACCOUNT_NAME="invoke-functions-codelab"
SERVICE_ACCOUNT_ADDRESS=$SERVICE_ACCOUNT_NAME@$PROJECT_ID.iam.gserviceaccount.com

Il passaggio successivo consiste nel creare l'account di servizio.

gcloud iam service-accounts create $SERVICE_ACCOUNT_NAME \
  --display-name="Cloud Run function Authentication codelab"

Concedi all'account di servizio il ruolo Invoker di Cloud Run:

gcloud run services add-iam-policy-binding $FUNCTION_NAME \
  --region=us-central1  \
  --member serviceAccount:$SERVICE_ACCOUNT_ADDRESS \
  --role='roles/run.invoker'

Esegui la chiamata alla funzione fingendo di essere l'account di servizio

A questo scopo, dovrai rubare l'identità dell'account di servizio appena creato ottenendo il token ID.

Aggiungi i ruoli richiesti per la rappresentazione

Per rubare l'identità di un account di servizio, il tuo account utente deve disporre del ruolo Creatore token account di servizio (roles/iam.serviceAccountTokenCreator) per generare un token ID per l'account di servizio.

Per concedere questo ruolo al tuo account utente attivo, puoi eseguire i seguenti comandi:

ACCOUNT_EMAIL=$(gcloud auth list --filter=status:ACTIVE --format="value(account)")

gcloud iam service-accounts add-iam-policy-binding $SERVICE_ACCOUNT_ADDRESS  \
  --member user:$ACCOUNT_EMAIL \
  --role='roles/iam.serviceAccountTokenCreator'

Utilizza il token ID dell'account di servizio

Attendi un paio di minuti per la propagazione delle autorizzazioni. Ora puoi invocare la funzione passando il token ID dell'account di servizio.

curl $FUNCTION_URL -H "Authorization: bearer $(gcloud auth print-identity-token --impersonate-service-account $SERVICE_ACCOUNT_ADDRESS)" 

Verrà visualizzato quanto segue:

WARNING: This command is using service account impersonation. All API calls will be executed as [invoke-functions-codelab@<project-id>.iam.gserviceaccount.com].

Hello World!

6. Scenario 3: utilizza le librerie client di Google

Per questa ultima parte del codelab, eseguirai un piccolo servizio localmente per generare un token ID per un account di servizio e poi chiamerai la funzione in modo programmatico utilizzando le librerie client di Google Auth e le credenziali predefinite dell'applicazione (ADC). Per saperne di più sulle librerie client di Google, consulta la sezione Descrizione delle librerie client della documentazione.

L'utilizzo di ADC è particolarmente importante quando vuoi scrivere e testare la funzione localmente (ad esempio sul tuo laptop, in Cloud Shell e così via) mentre interagisci con altre risorse Google Cloud (ad esempio Cloud Storage, API Vision e così via). In questo esempio, scoprirai come fare in modo che un servizio richiami un'altra funzione che richiede l'autenticazione. Per ulteriori informazioni su ADC e sviluppo locale, consulta il post del blog Come sviluppare e testare le funzioni Cloud in locale | Blog di Google Cloud

Esegui il comando gcloud per impersonare un account di servizio

ADC trova automaticamente le credenziali in base all'ambiente dell'applicazione e le utilizza per autenticarsi alle API Google Cloud. Il flag –impersonate-service-account consente di impersonare un account di servizio utilizzando la sua identità per l'autenticazione contro le API Google Cloud.

Per rubare l'identità di un account di servizio, puoi eseguire il seguente comando:

gcloud auth application-default login --impersonate-service-account=$SERVICE_ACCOUNT_ADDRESS

Ora esegui i comandi gcloud come account di servizio anziché come identità.

Crea ed esegui un servizio per richiamare una funzione autenticata

Ogni runtime ha la propria libreria client di autenticazione Google che puoi installare. Questo codelab illustra la procedura per creare ed eseguire un'app Node.js localmente.

Ecco i passaggi per Node.js:

  1. Crea una nuova directory
mkdir local-dev && cd $_
  1. Crea una nuova app Node.js
npm init -y
  1. Installa la libreria client di Google Auth
npm install google-auth-library
  1. Crea un file index.js
  2. Recupera l'URL della funzione Cloud Run, che aggiungerai al codice nel passaggio successivo.
echo $FUNCTION_URL
  1. Aggiungi il seguente codice a index.js. Assicurati di modificare la variabile targetAudience nell'URL della funzione Cloud Run.

index.js

// Cloud Functions uses your function's url as the `targetAudience` value

const targetAudience = '<YOUR-CLOUD-RUN-FUNCTION-URL>';

// 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}`);

    // this call retrieves the ID token for the impersonated service account
    const client = await auth.getIdTokenClient(targetAudience);

    const res = await client.request({ url });
    console.info(res.data);
}

request().catch(err => {
    console.error(err.message);
    process.exitCode = 1;
});
  1. Esegui l'app
node index.js

Dovresti vedere il messaggio "Hello World!".

Risoluzione dei problemi

Se viene visualizzato l'errore "Autorizzazione "iam.serviceAccounts.getOpenIdToken" negata per la risorsa (o potrebbe non esistere), attendi alcuni minuti per la propagazione del ruolo Creatore token account di servizio.

Se hai ricevuto l'errore Impossibile recuperare il token ID in questo ambiente, utilizza GCE o imposta la variabile di ambiente GOOGLE_APPLICATION_CREDENTIALS su un file JSON delle credenziali dell'account di servizio, potresti aver dimenticato di eseguire il comando

gcloud auth application-default login --impersonate-service-account=$SERVICE_ACCOUNT_ADDRESS

7. Complimenti!

Complimenti per aver completato il codelab.

Consigliamo di consultare la documentazione su come proteggere le funzioni di Cloud Run.

Ti consigliamo anche questo post del blog sullo sviluppo locale con le funzioni Cloud Run per scoprire come sviluppare e testare la tua funzione Cloud Run nel tuo ambiente di sviluppo locale.

Argomenti trattati

  • Come configurare l'autenticazione su una funzione Cloud Run e verificare che l'autenticazione sia stata configurata correttamente
  • Richiama una funzione autenticata da un ambiente di sviluppo locale fornendo il token per la tua identità gcloud
  • Come creare un account di servizio e concedergli il ruolo appropriato per richiamare una funzione
  • Come eseguire l'impersonificazione di un servizio da un ambiente di sviluppo locale con i ruoli appropriati per l'invocazione di una funzione

8. Esegui la pulizia

Per evitare addebiti involontari, ad esempio questa funzione Cloud Functions viene richiamata inavvertitamente più volte rispetto all'allocazione mensile dei richiami della funzione Cloud Run nel livello senza costi, puoi eliminare la funzione Cloud Functions o eliminare il progetto che hai creato nel passaggio 2.

Per interrompere l'identità dell'account di servizio, puoi eseguire nuovamente l'accesso utilizzando la tua identità:

gcloud auth application-default login

Per eliminare la funzione Cloud Run, vai alla console Cloud Run all'indirizzo https://console.cloud.google.com/functions/. Assicurati che il progetto creato nel passaggio 2 sia quello attualmente selezionato.

Seleziona my-authenticated-function di cui hai eseguito il deployment in precedenza. Poi tocca Elimina.

Se scegli di eliminare l'intero progetto, puoi andare alla pagina https://console.cloud.google.com/cloud-resource-manager, selezionare il progetto creato nel passaggio 2 e scegliere Elimina. Se elimini il progetto, dovrai modificare i progetti nel tuo Cloud SDK. Puoi visualizzare l'elenco di tutti i progetti disponibili eseguendo gcloud projects list.