1. Panoramica
Modificherai i passaggi predefiniti per il deployment di un servizio in Cloud Run per migliorare la sicurezza, quindi vedrai come accedere all'app di cui è stato eseguito il deployment in modo sicuro. L'app è un "servizio di registrazione dei partner" dell'applicazione Cymbal Eats, utilizzata dalle aziende che collaborano con Cymbal Eats per elaborare gli ordini di cibo.
Cosa imparerai a fare
Apportando alcune piccole modifiche ai passaggi predefiniti minimi per il deployment di un'app in Cloud Run, puoi aumentare significativamente la sua sicurezza. Prenderai un'app esistente e le istruzioni di deployment e modificherai i passaggi di deployment per migliorare la sicurezza dell'app di cui è stato eseguito il deployment.
Vedrai quindi come autorizzare l'accesso all'app ed effettuare richieste autorizzate.
Questo non è un esame esaustivo della sicurezza del deployment delle applicazioni, ma piuttosto un'analisi delle modifiche che puoi apportare a tutti i tuoi futuri deployment di app per migliorarne la sicurezza con il minimo sforzo.
2. Configurazione e requisiti
Configurazione dell'ambiente autonomo
- Accedi alla console Google Cloud e crea un nuovo progetto o riutilizzane uno esistente. Se non hai ancora un account Gmail o Google Workspace, devi crearne uno.



- Il nome del progetto è il nome visualizzato per i partecipanti a questo progetto. È una stringa di caratteri non utilizzata dalle API di Google. Puoi aggiornarlo in qualsiasi momento.
- L'ID progetto è univoco in tutti i progetti Google Cloud ed è immutabile (non può essere modificato dopo l'impostazione). La console Cloud genera automaticamente una stringa univoca, di solito non ti interessa di cosa si tratta. Nella maggior parte dei codelab, devi fare riferimento all'ID progetto (in genere è identificato come
PROJECT_ID). Se non ti piace l'ID generato, puoi generarne un altro casuale. In alternativa, puoi provare a crearne uno e vedere se è disponibile. Non può essere modificato dopo questo passaggio e rimarrà per tutta la durata del progetto. - Per tua informazione, esiste un terzo valore, un numero di progetto, utilizzato da alcune API. Scopri di più su tutti e tre questi valori nella documentazione.
- Successivamente, devi abilitare la fatturazione in Cloud Console per utilizzare le risorse/API Cloud. L'esecuzione di questo codelab non dovrebbe costare molto, se non nulla. Per arrestare le risorse in modo da non incorrere in costi di fatturazione al termine di questo tutorial, puoi eliminare le risorse che hai creato o l'intero progetto. I nuovi utenti di Google Cloud possono beneficiare del programma prova senza costi di 300$.
Attiva Cloud Shell
- Nella console Cloud, fai clic su Attiva Cloud Shell
.

Se non hai mai avviato Cloud Shell, viene visualizzata una schermata intermedia (sotto la piega) che ne descrive le funzionalità. In questo caso, fai clic su Continua e non comparirà più. Ecco come si presenta la schermata intermedia:

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

Questa macchina virtuale è caricata con tutti gli strumenti per sviluppatori di cui hai bisogno. Offre una home directory permanente da 5 GB e viene eseguita in Google Cloud, migliorando notevolmente le prestazioni e l'autenticazione della rete. Gran parte del lavoro per questo codelab, se non tutto, può essere svolto semplicemente con un browser o con Chromebook.
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.
- 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`
- Esegui questo 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].
Configurazione dell'ambiente
Per questo lab, eseguirai i comandi nella riga di comando di Cloud Shell. In genere puoi copiare i comandi e incollarli così come sono, anche se in alcuni casi dovrai modificare i valori dei segnaposto con quelli corretti.
- Imposta una variabile di ambiente sull'ID progetto da utilizzare nei comandi successivi:
export PROJECT_ID=$(gcloud config get-value project)
export REGION=us-central1
export SERVICE_NAME=partner-registration-service
- Abilita l'API del servizio Cloud Run che eseguirà la tua app, l'API Firestore che fornirà l'archiviazione dei dati NoSQL, l'API Cloud Build che verrà utilizzata dal comando di deployment e Artifact Registry che verrà utilizzato per contenere il container dell'applicazione una volta creato:
gcloud services enable \
run.googleapis.com \
firestore.googleapis.com \
cloudbuild.googleapis.com \
artifactregistry.googleapis.com
- Inizializza il database Firestore in modalità Native. Questo comando utilizza l'API App Engine, quindi deve essere abilitata per prima.
Il comando deve specificare una regione per App Engine, che non utilizzeremo, ma che dobbiamo creare per motivi storici, e una regione per il database. Utilizzeremo us-central per App Engine e nam5 per il database. nam5 è la località multiregionale degli Stati Uniti. Le località multiregionali massimizzano la disponibilità e la durabilità del database.
gcloud services enable appengine.googleapis.com
gcloud app create --region=us-central
gcloud firestore databases create --region=nam5
- Clona il repository dell'app di esempio e vai alla directory
git clone https://github.com/GoogleCloudPlatform/cymbal-eats.git
cd cymbal-eats/partner-registration-service
3. Esaminare il file README
Apri l'editor ed esamina i file che compongono l'app. Visualizza README.md, che descrive i passaggi necessari per il deployment di questa app. Alcuni di questi passaggi potrebbero comportare decisioni di sicurezza implicite o esplicite da prendere in considerazione. Modificherai alcune di queste scelte per migliorare la sicurezza dell'app di cui è stato eseguito il deployment, come descritto di seguito:
Passaggio 3: esegui npm install
È importante conoscere la provenienza e l'integrità di qualsiasi software di terze parti utilizzato in un'app. La gestione della sicurezza della catena di fornitura del software è pertinente alla creazione di qualsiasi software, non solo delle app di cui è stato eseguito il deployment in Cloud Run. Questo lab si è concentrato sul deployment, quindi non tratta questo argomento, ma ti consigliamo di approfondirlo separatamente.
Passaggi 4 e 5: modifica ed esecuzione deploy.sh
Questi passaggi eseguono il deployment dell'app su Cloud Run lasciando la maggior parte delle opzioni sui valori predefiniti. Modificherai questo passaggio per rendere il deployment più sicuro in due modi principali:
- Non consentire l'accesso non autenticato. Può essere comodo consentirlo per provare le funzionalità durante l'esplorazione, ma si tratta di un servizio web da utilizzare per i partner commerciali e deve sempre autenticare i propri utenti.
- Specifica che l'applicazione deve utilizzare un service account dedicato personalizzato solo con i privilegi necessari, anziché uno predefinito che probabilmente avrà più accesso alle API e alle risorse del necessario. Questo è noto come principio del privilegio minimo ed è un concetto fondamentale della sicurezza delle applicazioni.
Passaggi da 6 a 11: effettua richieste web di esempio per verificare il comportamento corretto
Poiché il deployment dell'applicazione ora richiede l'autenticazione, queste richieste devono ora includere una prova dell'identità del richiedente. Anziché modificare questi file, effettuerai le richieste direttamente dalla riga di comando.
4. Esegui il deployment del servizio in modo sicuro
Nello script deploy.sh sono state identificate due modifiche necessarie: non consentire l'accesso non autenticato e utilizzare un service account dedicato con privilegi minimi.
Prima creerai un nuovo service account, poi modificherai lo script deploy.sh in modo che faccia riferimento a questo service account e non consenta l'accesso non autenticato, quindi eseguirai il deployment del servizio eseguendo lo script modificato prima di poter eseguire lo script deploy.sh modificato.
Crea un service account e concedigli l'accesso necessario a Firestore/Datastore
gcloud iam service-accounts create partner-sa
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:partner-sa@${PROJECT_ID}.iam.gserviceaccount.com" \
--role=roles/datastore.user
Modifica deploy.sh
Modifica il file deploy.sh per non consentire l'accesso non autenticato(–no-allow-unauthenticated) e per specificare il nuovo service account(–service-account) per l'app di cui è stato eseguito il deployment. Correggi GOOGLE_PROJECT_ID in modo che corrisponda all'ID del tuo progetto.
Eliminerai le prime due righe e modificherai altre tre righe come mostrato di seguito.
gcloud run deploy $SERVICE_NAME \
--source . \
--platform managed \
--region ${REGION} \
--no-allow-unauthenticated \
--project=$PROJECT_ID \
--service-account=partner-sa@${PROJECT_ID}.iam.gserviceaccount.com
Esegui il deployment del servizio
Dalla riga di comando, esegui lo script deploy.sh:
./deploy.sh
Al termine del deployment, l'ultima riga dell'output del comando mostrerà l'URL del servizio della nuova app. Salva l'URL in una variabile di ambiente:
export SERVICE_URL=<URL from last line of command output>
Ora prova a recuperare un ordine dall'app utilizzando lo strumento curl:
curl -i -X GET $SERVICE_URL/partners
Il flag -i per il comando curl indica di includere le intestazioni della risposta nell'output. La prima riga dell'output dovrebbe essere:
HTTP/2 403
L'app è stata implementata con l'opzione per non consentire le richieste non autenticate. Questo comando curl non contiene informazioni di autenticazione, pertanto viene rifiutato da Cloud Run. L'applicazione di cui è stato eseguito il deployment non viene nemmeno eseguita né riceve dati da questa richiesta.
5. Inviare richieste autenticate
L'app di cui è stato eseguito il deployment viene richiamata effettuando richieste web, che ora devono essere autenticate per essere consentite da Cloud Run. Le richieste web vengono autenticate includendo un'intestazione Authorization del modulo:
Authorization: Bearer identity-token
L'identity token è una stringa codificata, firmata in modo criptografico e a breve termine emessa da un provider di autenticazione attendibile. In questo caso, è necessario un token identità valido, non scaduto e rilasciato da Google.
Inviare una richiesta come account utente
Lo strumento Google Cloud CLI può fornire un token per l'utente autenticato predefinito. Esegui questo comando per ottenere un token di identità per il tuo account e salvarlo nella variabile di ambiente ID_TOKEN:
export ID_TOKEN=$(gcloud auth print-identity-token)
Per impostazione predefinita, i token ID emessi da Google sono validi per un'ora. Esegui il seguente comando curl per effettuare la richiesta che è stata rifiutata in precedenza perché non era autorizzata. Questo comando includerà l'intestazione necessaria:
curl -i -X GET $SERVICE_URL/partners \
-H "Authorization: Bearer $ID_TOKEN"
L'output del comando deve iniziare con HTTP/2 200, a indicare che la richiesta è accettabile e verrà soddisfatta. Se aspetti un'ora e riprovi a inviare questa richiesta, non andrà a buon fine perché il token sarà scaduto. Il corpo della risposta si trova alla fine dell'output, dopo una riga vuota:
{"status":"success","data":[]}
Non ci sono ancora partner.
Registra i partner utilizzando i dati JSON di esempio nella directory con due comandi curl:
curl -X POST \
-H "Authorization: Bearer $ID_TOKEN" \
-H "Content-Type: application/json" \
-d "@example-partner.json" \
$SERVICE_URL/partner
e
curl -X POST \
-H "Authorization: Bearer $ID_TOKEN" \
-H "Content-Type: application/json" \
-d "@example-partner2.json" \
$SERVICE_URL/partner
Ripeti la richiesta GET precedente per visualizzare tutti i partner registrati:
curl -i -X GET $SERVICE_URL/partners \
-H "Authorization: Bearer $ID_TOKEN"
Dovresti visualizzare dati JSON con molti più contenuti, che forniscono informazioni sui due partner registrati.
Effettuare una richiesta come account non autorizzato
La richiesta autenticata effettuata nell'ultimo passaggio è andata a buon fine non solo perché è stata autenticata, ma anche perché l'utente autenticato (il tuo account) è stato autorizzato. ovvero l'account aveva l'autorizzazione per richiamare l'app. Non tutti gli account autenticati saranno autorizzati a farlo.
L'account predefinito utilizzato nella richiesta precedente è stato autorizzato perché è l'account che ha creato il progetto contenente l'app e, per impostazione predefinita, gli ha concesso l'autorizzazione per richiamare qualsiasi applicazione Cloud Run nell'account. Questa autorizzazione può essere revocata se necessario, il che è auspicabile in un'applicazione di produzione. Invece di farlo ora, creerai un nuovo service account senza privilegi o ruoli assegnati e lo utilizzerai per tentare di accedere all'app di cui è stato eseguito il deployment.
- Crea un service account chiamato
tester.
gcloud iam service-accounts create tester
- Riceverai un token ID per questo nuovo account in modo molto simile a quello che hai ricevuto in precedenza per il tuo account predefinito. Tuttavia, per farlo è necessario che il tuo account predefinito disponga dell'autorizzazione per simulare l'identità dei service account. Concedi questa autorizzazione al tuo account.
export USER_EMAIL=$(gcloud config list account --format "value(core.account)")
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="user:$USER_EMAIL" \
--role=roles/iam.serviceAccountTokenCreator
- Ora esegui questo comando per salvare un token di identità per questo nuovo account nella variabile di ambiente TEST_IDENTITY. Se il comando mostra un messaggio di errore, attendi un minuto o due e riprova.
export TEST_TOKEN=$( \
gcloud auth print-identity-token \
--impersonate-service-account \
"tester@$PROJECT_ID.iam.gserviceaccount.com" \
)
- Esegui la richiesta web autenticata come prima, ma utilizzando questo token ID:
curl -i -X GET $SERVICE_URL/partners \
-H "Authorization: Bearer $TEST_TOKEN"
L'output del comando inizierà di nuovo con HTTP/2 403 perché la richiesta, sebbene autenticata, non è autorizzata. Il nuovo service account non dispone dell'autorizzazione per richiamare questa app.
Autorizzare un account
Un utente o un service account deve disporre del ruolo Invoker di Cloud Run per un servizio Cloud Run per poter inviare richieste. Assegna questo ruolo al service account del tester con il comando:
export REGION=us-central1
gcloud run services add-iam-policy-binding ${SERVICE_NAME} \
--member="serviceAccount:tester@$PROJECT_ID.iam.gserviceaccount.com" \
--role=roles/run.invoker \
--region=${REGION}
Dopo aver atteso un minuto o due per l'aggiornamento del nuovo ruolo, ripeti la richiesta autenticata. Salva un nuovo TEST_TOKEN se è trascorsa almeno un'ora dal primo salvataggio.
curl -i -X GET $SERVICE_URL/partners \
-H "Authorization: Bearer $TEST_TOKEN"
L'output del comando ora inizia con HTTP/1.1 200 OK e l'ultima riga contiene la risposta JSON. Questa richiesta è stata accettata da Cloud Run ed elaborata dall'app.
6. Autenticazione dei programmi e autenticazione degli utenti
Le richieste autenticate che hai effettuato finora hanno utilizzato lo strumento a riga di comando curl. Avremmo potuto usare anche altri strumenti e linguaggi di programmazione. Tuttavia, le richieste Cloud Run autenticate non possono essere effettuate utilizzando un browser web con pagine web semplici. Se un utente fa clic su un link o su un pulsante per inviare un modulo in una pagina web, il browser non aggiungerà l'intestazione Authorization richiesta da Cloud Run per le richieste autenticate.
Il meccanismo di autenticazione integrato di Cloud Run è destinato all'uso da parte di programmi, non da parte di utenti finali.
Nota:
Cloud Run può ospitare applicazioni web rivolte agli utenti, ma queste applicazioni devono impostare Cloud Run in modo da consentire le richieste non autenticate dai browser web degli utenti. Se le applicazioni richiedono l'autenticazione utente, devono gestirla anziché chiedere a Cloud Run di farlo. L'applicazione può farlo nello stesso modo in cui lo fanno le applicazioni web al di fuori di Cloud Run. Il modo in cui viene eseguita questa operazione non rientra nell'ambito di questo codelab.
Potresti aver notato che le risposte alle richieste di esempio finora sono state oggetti JSON, non pagine web. Questo perché il servizio di registrazione dei partner è destinato all'utilizzo da parte dei programmi e JSON è un formato comodo da utilizzare. Successivamente, scriverai ed eseguirai un programma per utilizzare questi dati.
Richieste autenticate da un programma Python
Un programma può effettuare richieste autenticate di un'applicazione Cloud Run protetta tramite richieste web HTTP standard, ma includendo un'intestazione Authorization. L'unica nuova sfida per questi programmi è ottenere un token di identità valido e non scaduto da inserire nell'intestazione. Questo token verrà convalidato da Cloud Run utilizzando Google Cloud Identity and Access Management (IAM), pertanto deve essere emesso e firmato da un'autorità riconosciuta da IAM. Esistono librerie client disponibili in molti linguaggi che i programmi possono utilizzare per richiedere l'emissione di un token. La libreria client che verrà utilizzata in questo esempio è google.auth di Python. Esistono diverse librerie Python per effettuare richieste web in generale; questo esempio utilizza il popolare modulo requests.
Il primo passaggio consiste nell'installare le due librerie client:
pip install google-auth
pip install requests
Il codice Python per richiedere un token ID per l'utente predefinito è:
credentials, _ = google.auth.default()
credentials.refresh(google.auth.transport.requests.Request())
identity_token = credentials.id_token
Se utilizzi una shell di comando come Cloud Shell o la shell del terminale standard sul tuo computer, l'utente predefinito è quello autenticato all'interno della shell. In Cloud Shell, in genere si tratta dell'utente che ha eseguito l'accesso a Google. In altri casi, è l'utente autenticato con gcloud auth login o un altro comando gcloud. Se l'utente non ha mai eseguito l'accesso, non ci sarà alcun utente predefinito e questo codice non funzionerà.
Per un programma che effettua richieste a un altro programma, in genere non è consigliabile utilizzare l'identità di una persona, ma piuttosto quella del programma richiedente. Gli account di servizio servono a questo. Hai eseguito il deployment del servizio Cloud Run con un service account dedicato che fornisce l'identità utilizzata per effettuare richieste API, ad esempio a Cloud Firestore. Quando un programma viene eseguito su una piattaforma Google Cloud, le librerie client utilizzano automaticamente il service account assegnato come identità predefinita, in modo che lo stesso codice del programma funzioni in entrambe le situazioni.
Il codice Python per effettuare una richiesta con un'intestazione Authorization aggiuntiva è:
auth_header = {"Authorization": "Bearer " + identity_token}
response = requests.get(url, headers=auth_header)
Il seguente programma Python completo effettua una richiesta autenticata al servizio Cloud Run per recuperare tutti i partner registrati e poi stampa i loro nomi e ID assegnati. Copia ed esegui il comando riportato di seguito per salvare questo codice nel file print_partners.py.
cat > ./print_partners.py << EOF
def print_partners():
import google.auth
import google.auth.transport.requests
import requests
credentials, _ = google.auth.default()
credentials.refresh(google.auth.transport.requests.Request())
identity_token = credentials.id_token
auth_header = {"Authorization": "Bearer " + identity_token}
response = requests.get("${SERVICE_URL}/partners", headers=auth_header)
parsed_response = response.json()
partners = parsed_response["data"]
for partner in partners:
print(f"{partner['partnerId']}: {partner['name']}")
print_partners()
EOF
Esegui questo programma con un comando shell. Devi prima autenticarti come utente predefinito, in modo che il programma possa utilizzare queste credenziali. Esegui il comando gcloud auth riportato di seguito:
gcloud auth application-default login
Segui le istruzioni per completare l'accesso. Quindi esegui il programma dalla riga di comando:
python print_partners.py
L'output sarà simile al seguente:
10102: Zippy food delivery
67292: Foodful
La richiesta del programma ha raggiunto il servizio Cloud Run perché è stata autenticata con la tua identità e tu sei il proprietario di questo progetto e quindi autorizzato a eseguirlo per impostazione predefinita. È più comune che questo programma venga eseguito con l'identità di un service account. Quando viene eseguita sulla maggior parte dei prodotti Google Cloud, come Cloud Run o App Engine, l'identità predefinita è un service account e verrà utilizzata al posto di un account personale.
7. Complimenti!
Congratulazioni, hai completato il codelab.
Qual è il passaggio successivo?
Esplora altri codelab di Cymbal Eats:
- Attivazione di Cloud Workflows con Eventarc
- Attivazione dell'elaborazione degli eventi da Cloud Storage
- Connessione a Private CloudSQL da Cloud Run
- Connessione a database completamente gestiti da Cloud Run
- Proteggi l'applicazione serverless con Identity-Aware Proxy (IAP)
- Attivazione di Cloud Run Jobs con Cloud Scheduler
- Protezione del traffico in entrata di Cloud Run
- Connessione ad AlloyDB privato da GKE Autopilot
Esegui la pulizia
Per evitare che al tuo account Google Cloud vengano addebitati costi relativi alle risorse utilizzate in questo tutorial, elimina il progetto che contiene le risorse oppure mantieni il progetto ed elimina le singole risorse.
Elimina il progetto
Il modo più semplice per eliminare la fatturazione è eliminare il progetto creato per il tutorial.