Oltre ad autenticare gli utenti, potrebbe essere necessario consentire ad altri servizi di interagire con l'API. Sebbene le applicazioni client possano fornire agli utenti una richiesta di accesso web per inviare le loro credenziali, è necessario un altro approccio per la comunicazione sicura tra i servizi. Questa pagina mostra l'approccio che consigliamo per implementare l'autenticazione tra i servizi e fornisce codice campione.
Panoramica
Per identificare un servizio che invia richieste alla tua API, utilizza un account di servizio. Il servizio chiamante utilizza la chiave privata dell'account di servizio per firmare un token web JSON (JWT) sicuro e invia il JWT firmato nella richiesta alla tua API.
Per implementare l'autenticazione service-to-service nell'API e nel servizio di chiamata:
- Crea un account di servizio e una chiave per il servizio di chiamata da utilizzare.
- Aggiungi il supporto per l'autenticazione nel documento OpenAPI relativo al servizio Cloud Endpoints.
Aggiungi al servizio di chiamata un codice che:
- Crea un JWT e lo firma con la chiave privata dell'account di servizio.
- Invia il JWT firmato in una richiesta all'API.
ESP convalida che le affermazioni nel JWT corrispondano alla configurazione nel documento OpenAPI prima di inoltrare la richiesta alla tua API. ESP non controlla le autorizzazioni di Cloud Identity che hai concesso per l'account di servizio.
Prerequisiti
Questa pagina presuppone che tu abbia già:
Creazione di un account di servizio con una chiave
Devi avere un account di servizio con un file di chiave privata che il servizio di chiamata utilizza per firmare il JWT. Se hai più di un servizio che invia richieste alla tua API, puoi creare un account di servizio per rappresentare tutti i servizi di chiamata. Se devi distinguere tra i servizi, ad esempio perché potrebbero avere autorizzazioni diverse, puoi creare un account di servizio e una chiave per ogni servizio di chiamata.
Questa sezione mostra come utilizzare la console Google Cloud e lo strumento a riga di comando gcloud
per creare l'account di servizio e il file della chiave privata e per assegnare all'account di servizio il ruolo Creatore token account di servizio. Per informazioni sull'utilizzo di un'API per eseguire questa attività, consulta Creazione e gestione degli account di servizio.
Per creare un account di servizio e una chiave:
Console Google Cloud
Crea un account di servizio:
Nella console Google Cloud, vai alla pagina Crea account di servizio.
Seleziona il progetto che vuoi utilizzare.
Inserisci un nome nel campo Nome account di servizio.
(Facoltativo) Nel campo Descrizione account di servizio, inserisci una descrizione.
Fai clic su Crea.
Fai clic sul campo Seleziona un ruolo. In Tutti i ruoli, seleziona Account di servizio > Creatore token account di servizio.
Fai clic su Fine.
Non chiudere la finestra del browser. Lo utilizzerai nel passaggio successivo.
Crea una chiave dell'account di servizio:
- Nella console Google Cloud, fai clic sull'indirizzo email dell'account di servizio che hai creato.
- Fai clic su Chiavi.
- Fai clic su Aggiungi chiave, quindi su Crea nuova chiave.
- Fai clic su Crea. Un file JSON contenente i download della chiave privata dell'account di servizio sul computer.
- Fai clic su Chiudi.
gcloud
Puoi eseguire i comandi seguenti utilizzando Google Cloud CLI sulla tua macchina locale o all'interno di Cloud Shell.
Imposta l'account predefinito per
gcloud
. Se disponi di più account, assicurati di scegliere quello che si trova nel progetto Google Cloud che vuoi utilizzare.gcloud auth login
Visualizza gli ID dei tuoi progetti Google Cloud.
gcloud projects list
Imposta il progetto predefinito. Sostituisci
PROJECT_ID
con l'ID del progetto Google Cloud che vuoi utilizzare.gcloud config set project PROJECT_ID
Crea un account di servizio. Sostituisci
SA_NAME
eSA_DISPLAY_NAME
con il nome e il nome visualizzato che vuoi utilizzare.gcloud iam service-accounts create SA_NAME \ --display-name "SA_DISPLAY_NAME"
Visualizza l'indirizzo email dell'account di servizio appena creato.
gcloud iam service-accounts list
Aggiungi il ruolo Creatore token account di servizio. Sostituisci
SA_EMAIL_ADDRESS
con l'indirizzo email dell'account di servizio.gcloud projects add-iam-policy-binding PROJECT_ID \ --member serviceAccount:SA_EMAIL_ADDRESS \ --role roles/iam.serviceAccountTokenCreator
Crea un file della chiave dell'account di servizio nella directory di lavoro corrente. Sostituisci
FILE_NAME
con il nome che vuoi usare per il file della chiave. Per impostazione predefinita, il comandogcloud
crea un file JSON.gcloud iam service-accounts keys create FILE_NAME.json \ --iam-account SA_EMAIL_ADDRESS
Consulta il riferimento di gcloud
per ulteriori informazioni sui comandi precedenti.
Per informazioni sulla salvaguardia della chiave privata, consulta le best practice per la gestione delle credenziali.
Configurazione dell'API per supportare l'autenticazione
Devi avere un oggetto requisito di sicurezza e un oggetto definizioni di sicurezza nel documento OpenAPI affinché ESP possa convalidare le attestazioni nel JWT firmato.
Aggiungi l'account di servizio come emittente nel tuo documento OpenAPI.
securityDefinitions: DEFINITION_NAME: authorizationUrl: "" flow: "implicit" type: "oauth2" x-google-issuer: "SA_EMAIL_ADDRESS" x-google-jwks_uri: "https://www.googleapis.com/robot/v1/metadata/x509/SA_EMAIL_ADDRESS"
- Sostituisci
DEFINITION_NAME
con una stringa che identifica questa definizione di sicurezza. Puoi sostituirlo con il nome dell'account di servizio o con un nome che identifichi il servizio di chiamata. - Sostituisci
SA_EMAIL_ADDRESS
con l'indirizzo email dell'account di servizio. - Puoi definire più definizioni di sicurezza nel documento OpenAPI, ma ogni definizione deve avere un valore
x-google-issuer
diverso. Se hai creato account di servizio separati per ogni servizio di chiamata, puoi creare una definizione di sicurezza per ogni account di servizio, ad esempio:
securityDefinitions: service-1: authorizationUrl: "" flow: "implicit" type: "oauth2" x-google-issuer: "service-1@example-project-12345.iam.gserviceaccount.com" x-google-jwks_uri: "https://www.googleapis.com/robot/v1/metadata/x509/service-1@example-project-12345.iam.gserviceaccount.com" service-2: authorizationUrl: "" flow: "implicit" type: "oauth2" x-google-issuer: "service-2@example-project-12345.iam.gserviceaccount.com" x-google-jwks_uri: "https://www.googleapis.com/robot/v1/metadata/x509/service-2@example-project-12345.iam.gserviceaccount.com"
- Sostituisci
Se vuoi, aggiungi
x-google-audiences
alla sezionesecurityDefinitions
. Se non aggiungix-google-audiences
, ESP richiede che l'attestazione"aud"
(pubblico) nel JWT sia nel formatohttps://SERVICE_NAME
, dove SERVICE_NAME è il nome del servizio Endpoints, che hai configurato nel campohost
del documento OpenAPI, a meno che non venga utilizzato il flag--disable_jwt_audience_service_name_check
. Se viene utilizzato il flag ex-google-audiences
non è specificato, il campo JWTaud
non viene selezionato.Se vuoi, aggiungi
x-google-jwt-locations
alla sezionesecurityDefinitions
. Puoi utilizzare questo valore per definire una località JWT personalizzata. Le posizioni JWT predefinite sono l'intestazioneAuthorization
(preceduta da "Bearer"), l'intestazioneX-Goog-Iap-Jwt-Assertion
o il parametro di queryaccess_token
. Nota:- Se specifichi
x-google-jwt-locations
, Endpoints ignora tutte le località predefinite. x-google-jwt-locations
è supportato solo da ESPv2.
- Se specifichi
Aggiungi una sezione
security
al livello superiore del file (non in posizione rientrata o nidificata) da applicare all'intera API oppure a livello di metodo per applicare a un metodo specifico. Se utilizzi le sezionisecurity
sia a livello di API che a livello di metodo, le impostazioni a livello di metodo prevalgono su quelle a livello di API.security: - DEFINITION_NAME: []
- Sostituisci
DEFINITION_NAME
con il nome che hai utilizzato nella sezionesecurityDefinitions
. Se hai più di una definizione nella sezione
securityDefinitions
, aggiungile nella sezionesecurity
, ad esempio:security: - service-1: [] - service-2: []
- Sostituisci
Esegui il deployment del documento OpenAPI aggiornato. Sostituisci
OPENAPI_DOC
con il nome del tuo documento OpenAPI.gcloud endpoints services deploy OPENAPI_DOC
Prima che ESP inoltri una richiesta alla tua API, ESP verifica:
- La firma del JWT mediante la chiave pubblica, che si trova nell'URI specificato nel campo
x-google-jwks_uri
del documento OpenAPI. - Che la dichiarazione
"iss"
(emittente) nel JWT corrisponda al valore specificato nel campox-google-issuer
. - Che l'attestazione
"aud"
(pubblico) nel JWT contenga il nome del servizio di endpoint o corrisponda a uno dei valori specificati nel campox-google-audiences
. - Che il token non sia scaduto utilizzando la dichiarazione
"exp"
(scadenza).
Per ulteriori informazioni su x-google-issuer
, x-google-jwks_uri
, x-google-audiences
e x-google-jwt-locations
, consulta la pagina relativa alle estensioni OpenAPI.
Esecuzione di una richiesta autenticata a un'API Endpoints
Per effettuare una richiesta autenticata, il servizio di chiamata invia un JWT firmato dall'account di servizio specificato nel documento OpenAPI. Il servizio di chiamata deve:
- Crea un JWT e firmalo con la chiave privata dell'account di servizio.
- Invia il JWT firmato in una richiesta all'API.
Il seguente codice campione illustra questa procedura per alcuni linguaggi. Per effettuare una richiesta autenticata in altri linguaggi, fai riferimento a jwt.io per un elenco delle librerie supportate.
-
Nel servizio chiamante, aggiungi la funzione seguente e passa i seguenti
parametri:
Java -
saKeyfile
: il percorso completo del file delle chiavi private dell'account di servizio. -
saEmail
: l'indirizzo email dell'account di servizio. -
audience
: se hai aggiunto il campox-google-audiences
al documento OpenAPI, impostaaudience
su uno dei valori specificati perx-google-audiences
. Altrimenti, impostaaudience
suhttps://SERVICE_NAME
, doveSERVICE_NAME
è il nome del servizio Endpoints. -
expiryLength
: la scadenza del JWT, in secondi.
Python -
sa_keyfile
: il percorso completo del file delle chiavi private dell'account di servizio. -
sa_email
: l'indirizzo email dell'account di servizio. -
audience
: se hai aggiunto il campox-google-audiences
al documento OpenAPI, impostaaudience
su uno dei valori specificati perx-google-audiences
. Altrimenti, impostaaudience
suhttps://SERVICE_NAME
, doveSERVICE_NAME
è il nome del servizio Endpoints. -
expiry_length
: la scadenza del JWT, in secondi.
Vai -
saKeyfile
: il percorso completo del file delle chiavi private dell'account di servizio. -
saEmail
: l'indirizzo email dell'account di servizio. -
audience
: se hai aggiunto il campox-google-audiences
al documento OpenAPI, impostaaudience
su uno dei valori specificati perx-google-audiences
. Altrimenti, impostaaudience
suhttps://SERVICE_NAME
, doveSERVICE_NAME
è il nome del servizio Endpoints. -
expiryLength
: la scadenza del JWT, in secondi.
La funzione crea un JWT, lo firma utilizzando il file di chiave privata e restituisce il JWT firmato.
Java Python Vai -
-
Nel servizio chiamante, aggiungi la funzione seguente per inviare il JWT firmato
nell'intestazione
Authorization: Bearer
della richiesta all'API:Java Python Vai
Quando invii una richiesta utilizzando un JWT, per motivi di sicurezza, ti consigliamo di inserire il token di autenticazione nell'intestazione Authorization: Bearer
. Ad esempio:
curl --request POST \ --header "Authorization: Bearer ${TOKEN}" \ "${ENDPOINTS_HOST}/echo"
dove ENDPOINTS_HOST
e TOKEN
sono variabili di ambiente contenenti rispettivamente
il nome host dell'API e il token di autenticazione.
Ricezione di risultati autenticati nell'API
L'ESP in genere inoltra tutte le intestazioni che riceve. Tuttavia, sostituisce l'intestazione Authorization
originale quando l'indirizzo di backend viene specificato da x-google-backend
nella specifica OpenAPI o BackendRule
nella configurazione del servizio gRPC.
ESP invierà il risultato dell'autenticazione in X-Endpoint-API-UserInfo
all'API di backend. Ti consigliamo di utilizzare questa intestazione anziché l'intestazione Authorization
originale. Questa intestazione è una stringa che base64url
codifica
un oggetto JSON. Il formato dell'oggetto JSON è diverso tra ESPv2 ed ESP.
Per ESPv2, l'oggetto JSON è esattamente il payload JWT originale. Per ESP, l'oggetto JSON utilizza nomi di campo diversi e inserisci il payload JWT originale nel campo claims
.
Per ulteriori informazioni sul formato, consulta Gestire i JWT nel servizio di backend.