Eseguire la migrazione dal servizio Utenti di App Engine a Cloud Identity Platform (modulo 21)

1. Panoramica

La serie di codelab Serverless Migration Station (tutorial pratici e self-service) e i video correlati mirano ad aiutare gli sviluppatori Google Cloud serverless a modernizzare le applicazioni guidandoli attraverso una o più migrazioni, principalmente abbandonando i servizi legacy. In questo modo le tue app saranno più portabili e avrai più opzioni e flessibilità, consentendoti di integrare e accedere a una gamma più ampia di prodotti Cloud e di eseguire più facilmente l'upgrade a release delle lingue più recenti. Pur concentrandosi inizialmente sui primi utenti di Cloud, principalmente sviluppatori di App Engine (ambiente standard), questa serie è sufficientemente ampia da includere altre piattaforme serverless come Cloud Functions e Cloud Run, o altrove, se applicabile.

Lo scopo di questo codelab è mostrare agli sviluppatori di App Engine Python 2 come eseguire la migrazione da API/servizio App Engine Users a Cloud Identity Platform (GCIP). È prevista anche una migrazione implicita dall'NDB di App Engine a Cloud NDB per l'accesso a Datastore (trattata principalmente nel Modulo 2 sulla migrazione) nonché un upgrade a Python 3.

Il modulo 20 illustra come aggiungere l'utilizzo dell'API Users all'app di esempio del modulo 1. In questo modulo, acquisirai l'app completa del modulo 20 ed eseguirai la migrazione del suo utilizzo a Cloud Identity Platform.

Imparerai a utilizzare

  • Sostituisci l'utilizzo del servizio Utenti di App Engine con Cloud Identity Platform
  • Sostituisci l'utilizzo dell'NDB di App Engine con Cloud NDB (vedi anche il Modulo 2)
  • Configura diversi provider di identità di autenticazione utilizzando Firebase Auth
  • Usa l'API Cloud Resource Manager per ottenere informazioni IAM del progetto
  • Utilizzare l'SDK Admin Firebase per ottenere informazioni sugli utenti
  • Porta l'applicazione di esempio in Python 3

Che cosa ti serve

Sondaggio

Come utilizzerai questo tutorial?

Da leggere solo Leggilo e completa gli esercizi

Come valuteresti la tua esperienza con Python?

Principiante Livello intermedio Eccellente

Come giudichi la tua esperienza di utilizzo dei servizi Google Cloud?

Principiante Livello intermedio Eccellente

2. Sfondo

Il servizio Utenti di App Engine è un sistema di autenticazione utente per l'utilizzo da parte delle app di App Engine. Offre Accedi con Google come provider di identità, fornisce pratici link di accesso e disconnessione da utilizzare nelle app e supporta il concetto di utenti amministratori e di funzionalità riservate agli amministratori. Per migliorare la portabilità delle applicazioni, Google Cloud consiglia di eseguire la migrazione dai servizi legacy in bundle di App Engine ai servizi Cloud autonomi, ad esempio dal servizio Utenti a Cloud Identity Platform.

Identity Platform si basa su Firebase Authentication e aggiunge numerose funzionalità aziendali, tra cui l'autenticazione a più fattori, OIDC e Supporto del servizio SSO basato su SAML, multi-tenancy, SLA del 99, 95% e altro ancora. Queste differenze sono evidenziate anche nella pagina di confronto tra i prodotti Identity Platform e Firebase Authentication. Entrambi i prodotti hanno molte più funzioni rispetto a quelle fornite dal servizio Utenti.

Questo codelab del modulo 21 illustra il passaggio dall'autenticazione utente dell'app dal servizio utenti alle funzionalità di Identity Platform che rispecchiano meglio la funzionalità dimostrata nel modulo 20. Il modulo 21 include anche una migrazione dall'NDB di App Engine a Cloud NDB per l'accesso a Datastore, che ripete la migrazione del Modulo 2.

Mentre il codice del Modulo 20 è "pubblicizzato", Come app di esempio Python 2, l'origine stessa è compatibile con Python 2 e 3 e rimane tale anche dopo la migrazione a Identity Platform (e Cloud NDB) qui nel Modulo 21. È possibile continuare a utilizzare il servizio Utenti durante l'upgrade a Python 3, poiché la migrazione a Identity Platform è facoltativa. Consulta il codelab del Modulo 17 e il video per scoprire come continuare a utilizzare i servizi in bundle durante l'upgrade a runtime di seconda generazione come Python 3.

Questo tutorial illustra i seguenti passaggi:

  1. Configurazione/pre-lavoro
  2. Aggiorna configurazione
  3. Modifica il codice dell'applicazione

3. Configurazione/pre-lavoro

In questa sezione viene spiegato come:

  1. Configura il progetto Cloud
  2. Ottieni app di esempio di riferimento
  3. (Ri)Esegui il deployment e convalida l'app di riferimento
  4. Abilita nuovi servizi/API Google Cloud

Questi passaggi assicurano di iniziare con un codice funzionante pronto per la migrazione a servizi Cloud autonomi.

1. Configura il progetto

Se hai completato il codelab del modulo 20, riutilizza lo stesso progetto (e lo stesso codice). In alternativa, crea un nuovo progetto o riutilizza un altro progetto esistente. Assicurati che il progetto abbia un account di fatturazione attivo e un'app App Engine abilitata. Trova il tuo ID progetto e tienilo a portata di mano durante questo codelab e utilizzalo ogni volta che incontri la variabile PROJ_ID.

2. Ottieni app di esempio di riferimento

Uno dei prerequisiti è un'app App Engine con modulo 20 funzionante, quindi completa il codelab (consigliato; link riportato sopra) oppure copia il codice del modulo 20 dal repository. Che tu utilizzi il tuo o il nostro, questo è il punto in cui inizieremo ("START"). Questo codelab ti guiderà attraverso la migrazione, concludendo con un codice simile a quello presente nella cartella dei repository del modulo 21 ("FINISH").

Copia la cartella di repository del modulo 20. Dovrebbe essere simile all'output seguente e se hai seguito il codelab del Modulo 20, potrebbe avere una cartella lib:

$ ls
README.md               appengine_config.py     templates
app.yaml                main.py                 requirements.txt

3. (Ri)Esegui il deployment e convalida l'app di riferimento

Esegui questi passaggi per eseguire il deployment dell'app del Modulo 20:

  1. Elimina la cartella lib, se presente, ed esegui pip install -t lib -r requirements.txt per ricompilarla. Potresti dover utilizzare pip2 se hai installato sia Python 2 che 3.
  2. Assicurati di aver installato e iniziato lo strumento a riga di comando gcloud e di averne controllato il utilizzo.
  3. Se non vuoi inserire il valore PROJ_ID a ogni comando gcloud eseguito, imposta prima il progetto Cloud con gcloud config set project PROJ_ID.
  4. Esegui il deployment dell'app di esempio con gcloud app deploy
  5. Verifica che l'app venga eseguita come previsto senza errori. Se hai completato il codelab del Modulo 20, l'app mostra le informazioni di accesso dell'utente (email dell'utente, eventuale "badge amministratore" e pulsante di accesso/uscita) in alto insieme alle visite più recenti (illustrate di seguito).

907e64c19ef964f8.png

Se viene eseguito l'accesso come utente normale, vengono visualizzati l'indirizzo email dell'utente e la pagina "Accesso" il pulsante diventa "Esci" Pulsante:

ad7b59916b69a035.png

Quando si esegue l'accesso come utente amministratore, l'indirizzo email dell'utente viene visualizzato insieme a "(amministratore)" accanto:

867bcb3334149e4.png

4. Abilita nuove API/servizi Google Cloud

Introduzione

L'app Module 20 utilizza le API NDB e Users di App Engine, servizi in bundle che non richiedono una configurazione aggiuntiva, al contrario dei servizi Cloud autonomi. Inoltre, l'app aggiornata impiegherà sia Cloud Identity Platform che Cloud Datastore (tramite la libreria client di Cloud NDB). Inoltre, la nostra necessità di determinare gli utenti amministratori di App Engine richiede anche l'utilizzo dell'API Cloud Resource Manager.

Costo

  • App Engine e Cloud Datastore dispongono di " Always Free" e, se rimani al di sotto di questi limiti, non ti viene addebitato alcun costo per il completamento di questo tutorial. Per ulteriori dettagli, vedi anche la pagina dei prezzi di App Engine e la pagina dei prezzi di Cloud Datastore.
  • L'utilizzo di Cloud Identity Platform viene fatturato in base al numero di utenti attivi mensili (MAU) o alle verifiche dell'autenticazione; una versione di "senza costi" è disponibile per ogni modello di utilizzo. Per ulteriori dettagli, consulta la pagina dei prezzi. Inoltre, anche se App Engine e Cloud Datastore richiedono la fatturazione, l'utilizzo di GCIP da solo non richiede l'abilitazione della fatturazione, a condizione che non vengano superate le quote giornaliere senza strumenti, quindi considera questa scelta per i progetti Cloud che non prevedono API/servizi Cloud richiesti per la fatturazione.
  • L'utilizzo dell'API Cloud Resource Manager è per la maggior parte senza costi in base alla relativa pagina dei prezzi.

Gli utenti possono abilitare le API Cloud dalla console Cloud o dalla riga di comando (tramite il comando gcloud, incluso in Cloud SDK), a seconda delle preferenze. Iniziamo con le API Cloud Datastore e Cloud Resource Manager.

Dalla console Cloud

Nella console Cloud, vai alla pagina Libreria del gestore API (relativa al progetto corretto) e cerca un'API utilizzando la barra di ricerca. c7a740304e9d35b.png

Abilita queste API:

Individua e fai clic sul pulsante Abilita per ogni API separatamente: ti potrebbero essere richiesti i dati di fatturazione. Ad esempio, questa è la pagina dell'API Resource Manager:

fc7bd8f4c49d12e5.png

Il pulsante diventa Gestisci una volta attivato (generalmente dopo qualche secondo):

8eca12d6cc7b45b0.png

Abilita Cloud Datastore nello stesso modo:

83811599b110e46b.png

Dalla riga di comando

Sebbene sia visivamente informativo per abilitare le API dalla console, alcuni preferiscono la riga di comando. Avrai il vantaggio aggiuntivo di poter abilitare un numero qualsiasi di API contemporaneamente. Esegui questo comando per abilitare le API Cloud Datastore e Cloud Resource Manager e attendi il completamento dell'operazione, come illustrato qui:

$ gcloud services enable cloudresourcemanager.googleapis.com datastore.googleapis.com
Operation "operations/acat.p2-aaa-bbb-ccc-ddd-eee-ffffff" finished successfully.

Ti potrebbero essere richiesti i dati di fatturazione.

La sezione "URL" per ogni API utilizzata nel comando precedente sono chiamati nomi di servizio API e si trovano nella parte inferiore della pagina della libreria per ciascuna API. Se vuoi abilitare altre API Cloud per le tue app, puoi trovare i nomi dei rispettivi servizi nelle pagine delle API corrispondenti. Questo comando elenca tutti i nomi dei servizi per le API che puoi abilitare:

gcloud services list --available --filter="name:googleapis.com".

Sia nella console Cloud che dalla riga di comando, una volta completati i passaggi precedenti, il nostro campione è ora in grado di accedere a queste API. I passaggi successivi consistono nell'abilitazione di Cloud Identity Platform e apportare le modifiche necessarie al codice.

Abilita e configura Cloud Identity Platform (solo console Cloud)

Cloud Identity Platform è un servizio di Marketplace perché si connette o dipende da una risorsa esterna a Google Cloud, ad esempio Firebase Authentication. Al momento, puoi abilitare i servizi di Marketplace solo dalla console Cloud. Procedi nel seguente modo:

  1. Vai alla pagina Cloud Identity Platform in Cloud Marketplace e fai clic sul pulsante Abilita. Se richiesto, esegui l'upgrade da Firebase Authentication per sbloccare funzionalità aggiuntive, come quelle descritte in precedenza nella sezione Informazioni generali. Ecco la pagina Marketplace in cui è evidenziato il pulsante Attiva: 28475f1c9b29de69.png
  2. Una volta abilitata Identity Platform, potresti essere reindirizzato automaticamente alla pagina Provider di identità. In caso contrario, utilizza questo pratico link per accedervi. fc2d92d42a5d1dd7.png
  3. Attiva il provider di autenticazione Google. Se non è stato configurato alcun provider, fai clic su Add a provider (Aggiungi un provider) e seleziona Google. Quando torni in questa schermata, dovrebbe essere attiva la voce Google. Google è l'unico provider di autenticazione che utilizziamo in questo tutorial per eseguire il mirroring del servizio Utenti di App Engine come un servizio Accedi con Google di base. Nelle tue app puoi attivare provider di autenticazione aggiuntivi.
  4. Dopo aver selezionato e configurato Google e altri provider di autenticazione desiderati, fai clic su Dettagli di configurazione applicazione e, nella finestra di dialogo di verifica, copia apiKey e authDomain nell'oggetto config sulla scheda web e salvali entrambi in un luogo sicuro. Perché non copiarli tutti? Lo snippet in questa finestra di dialogo è codificato e datato, quindi salva le parti più importanti e utilizzale nel nostro codice con un maggiore utilizzo simultaneo di Firebase Auth. Dopo aver copiato i valori e averli salvati in un luogo sicuro, fai clic sul pulsante Chiudi per completare la configurazione necessaria. bbb09dcdd9be538e.png

4. Aggiorna configurazione

Gli aggiornamenti della configurazione includono la modifica di vari file di configurazione e la creazione dell'equivalente di App Engine, ma all'interno dell'ecosistema di Cloud Identity Platform.

appengine_config.py

  • Se esegui l'upgrade a Python 3, elimina appengine_config.py
  • Se prevedi di eseguire la modernizzazione a Identity Platform, ma rimanere su Python 2, non eliminare il file. Lo aggiorneremo in seguito durante il backport di Python 2.

requirements.txt

Il file requirements.txt del modulo 20 riportava solo Flask. Per il modulo 21, aggiungi i seguenti pacchetti:

I contenuti di requirements.txt ora dovrebbero avere il seguente aspetto:

flask
google-auth
google-cloud-ndb
google-cloud-resource-manager
firebase-admin

app.yaml

  • Eseguire l'upgrade a Python 3 significa semplificare il file app.yaml. Rimuovi tutto tranne l'istruzione runtime e impostala su una versione attualmente supportata di Python 3. Attualmente nell'esempio viene utilizzata la versione 3.10.
  • Se continui a utilizzare Python 2, non fare ancora nulla qui.

PRIMA:

runtime: python27
threadsafe: yes
api_version: 1

handlers:
- url: /.*
  script: main.app

L'app di esempio Modulo 20 non ha gestori di file statici. Se le le tue app lo fanno, lasciale invariate. Se vuoi, puoi rimuovere tutti i gestori di script o lasciarli lì come riferimento, purché ne modifichi gli handle in auto, come descritto nella guida alla migrazione di app.yaml. Con queste modifiche, il valore app.yaml aggiornato per Python 3 è stato semplificato e:

DOPO:

runtime: python310

Altri aggiornamenti della configurazione

Sia che resti su Python 2 o che tu esegua la porta su Python 3, se hai una cartella lib, eliminala.

5. Modifica il codice dell'applicazione

Questa sezione presenta gli aggiornamenti al file dell'applicazione principale, main.py, che sostituiscono l'uso del servizio Utenti di App Engine con Cloud Identity Platform. Dopo aver aggiornato l'applicazione principale, aggiorni il modello web templates/index.html.

Aggiorna importazioni e inizializzazione

Segui questi passaggi per aggiornare le importazioni e inizializzare le risorse dell'applicazione:

  1. Per le importazioni, sostituisci NDB di App Engine con Cloud NDB.
  2. Insieme a Cloud NDB, importa anche Cloud Resource Manager.
  3. Identity Platform si basa su Firebase Auth, quindi importa l'SDK Firebase Admin.
  4. Le API Cloud richiedono l'utilizzo di un client API, quindi avvialo per Cloud NDB appena sotto l'inizializzazione di Flask.

Durante l'importazione del pacchetto Cloud Resource Manager, lo utilizzeremo in una fase successiva dell'inizializzazione dell'app. Di seguito sono riportate le importazioni e l'inizializzazione dal modulo 20, seguite dall'aspetto delle sezioni dopo l'implementazione delle modifiche precedenti:

PRIMA:

from flask import Flask, render_template, request
from google.appengine.api import users
from google.appengine.ext import ndb

app = Flask(__name__)

DOPO:

from flask import Flask, render_template, request
from google.auth import default
from google.cloud import ndb, resourcemanager
from firebase_admin import auth, initialize_app

# initialize Flask and Cloud NDB API client
app = Flask(__name__)
ds_client = ndb.Client()

Assistenza per gli utenti amministratori di App Engine

Sono due i componenti da aggiungere all'app che supportano il riconoscimento degli utenti amministratori:

  • _get_gae_admins(): combina un insieme di utenti amministratore; una volta chiamato e salvato
  • is_admin(): controlla se l'utente che ha eseguito l'accesso è un utente amministratore. chiamato a qualsiasi accesso utente

La funzione di utilità, _get_gae_admins(), chiama l'API Resource Manager per recuperare l'elemento allow-policy di Cloud IAM corrente. Il criterio allow-policy definisce e applica i ruoli concessi a determinate entità (utenti umani, account di servizio e così via). La configurazione include:

  • Recupero dell'ID progetto Cloud (PROJ_ID)
  • Creazione di un client API Resource Manager (rm_client)
  • Creazione di un insieme (di sola lettura) di ruoli di amministratore App Engine (_TARGETS)

Resource Manager richiede l'ID progetto Cloud, quindi importa google.auth.default() e chiama questa funzione per ottenere l'ID progetto. Questa chiamata presenta un parametro che appare come un URL, ma che è un ambito di autorizzazione OAuth2. Quando esegui app nel cloud, ad esempio su una VM di Compute Engine o un'app App Engine, viene fornito un account di servizio predefinito che dispone di ampi privilegi. In linea con la best practice del privilegio minimo, ti consigliamo di creare account di servizio gestiti dall'utente personali.

Per le chiamate API, è preferibile ulteriore ridurre l'ambito delle app al livello minimo necessario per funzionare correttamente. La chiamata all'API Resource Manager che effettueremo è get_iam_policy(), che richiede uno dei seguenti ambiti per l'operatività:

  • https://www.googleapis.com/auth/cloud-platform
  • https://www.googleapis.com/auth/cloud-platform.read-only
  • https://www.googleapis.com/auth/cloudplatformprojects
  • https://www.googleapis.com/auth/cloudplatformprojects.readonly

L'app di esempio richiede solo l'accesso di sola lettura al criterio allow. Non modifica il criterio né richiede l'accesso all'intero progetto. Ciò significa che l'app non ha bisogno di nessuna delle prime tre autorizzazioni necessarie. L'ultima opzione è tutto ciò che serve ed è quella che stiamo implementando per l'app di esempio.

Il corpo principale della funzione crea un insieme vuoto di utenti amministratore (admins), recupera allow_policy tramite get_iam_policy() ed esegue il loop di tutte le associazioni cercando specificatamente i ruoli Amministratore di App Engine:

  • roles/viewer
  • roles/editor
  • roles/owner
  • roles/appengine.appAdmin

Per ogni ruolo target trovato, vengono combinati gli utenti che appartengono a quel ruolo, aggiungendoli all'insieme complessivo di utenti amministratori. Termina la restituzione di tutti gli utenti amministratori trovati e memorizzati nella cache come costante (_ADMINS) per l'intera durata di questa istanza App Engine. Vedrai quella chiamata tra poco.

Aggiungi la seguente definizione di funzione _get_gae_admins() a main.py appena sotto, creando un'istanza del client API Cloud NDB (ds_client):

def _get_gae_admins():
    'return set of App Engine admins'
    # setup constants for calling Cloud Resource Manager API
    _, PROJ_ID = default(  # Application Default Credentials and project ID
            ['https://www.googleapis.com/auth/cloudplatformprojects.readonly'])
    rm_client = resourcemanager.ProjectsClient()
    _TARGETS = frozenset((     # App Engine admin roles
            'roles/viewer',
            'roles/editor',
            'roles/owner',
            'roles/appengine.appAdmin',
    ))

    # collate users who are members of at least one GAE admin role (_TARGETS)
    admins = set()                      # set of all App Engine admins
    allow_policy = rm_client.get_iam_policy(resource='projects/%s' % PROJ_ID)
    for b in allow_policy.bindings:     # bindings in IAM allow-policy
        if b.role in _TARGETS:          # only look at GAE admin roles
            admins.update(user.split(':', 1).pop() for user in b.members)
    return admins

Quando gli utenti accedono all'app, si verifica quanto segue:

  1. Dopo che un utente ha eseguito l'accesso a Firebase, viene eseguito un rapido controllo del modello web.
  2. Quando lo stato di autenticazione cambia nel modello, viene effettuata una chiamata fetch() in stile Ajax a /is_admin il cui gestore è la funzione successiva, is_admin().
  3. Il token ID Firebase viene passato nel corpo del POST a is_admin(), che lo estrae dalle intestazioni e chiama l'SDK Admin Firebase per la convalida. Se si tratta di un utente valido, estrai il suo indirizzo email e controlla se si tratta di un utente amministratore.
  4. Il risultato booleano viene quindi restituito al modello come 200 riuscito.

Aggiungi is_admin() a main.py subito dopo _get_gae_admins():

@app.route('/is_admin', methods=['POST'])
def is_admin():
    'check if user (via their Firebase ID token) is GAE admin (POST) handler'
    id_token = request.headers.get('Authorization')
    email = auth.verify_id_token(id_token).get('email')
    return {'admin': email in _ADMINS}, 200

Tutto il codice di entrambe le funzioni è necessario per replicare la funzionalità disponibile dal servizio Users, in particolare la sua funzione is_current_user_admin(). Questa chiamata di funzione nel modulo 20 ha fatto tutto il lavoro pesante, a differenza del modulo 21 in cui implementiamo una soluzione sostitutiva. La buona notizia è che l'app non dipende più da un servizio solo App Engine, il che significa che puoi spostare le tue app in Cloud Run o in altri servizi. Inoltre, puoi modificare la definizione di "utente amministratore" per le tue app semplicemente passando ai ruoli desiderati in _TARGETS, mentre il servizio Utenti è impostato come hardcoded per i ruoli di amministratore di App Engine.

Inizializza Firebase Auth e memorizza nella cache gli utenti amministratori di App Engine

Avremmo potuto inizializzare Firebase Auth in alto, vicino allo stesso punto in cui è stata inizializzata l'app Flask e in cui è stato creato il client API Cloud NDB, ma non c'è stato bisogno di farlo fino a quando non è stato definito tutto il codice amministratore, che è dove siamo ora. Allo stesso modo, ora che hai definito _get_gae_admins(), chiamalo per memorizzare nella cache l'elenco degli utenti amministratori.

Aggiungi queste righe subito sotto il corpo della funzione di is_admin():

# initialize Firebase and fetch set of App Engine admins
initialize_app()
_ADMINS = _get_gae_admins()

Consulta gli aggiornamenti del modello dei dati

Il modello dei dati Visit rimane invariato. L'accesso al datastore richiede l'uso esplicito del gestore di contesto del client API Cloud NDB, ds_client.context(). Nel codice, questo significa che devi aggregare le chiamate Datastore in store_visit() e fetch_visits() all'interno dei blocchi with Python. Questo aggiornamento è identico al modulo 2. Apporta le modifiche come segue:

PRIMA:

class Visit(ndb.Model):
    'Visit entity registers visitor IP address & timestamp'
    visitor   = ndb.StringProperty()
    timestamp = ndb.DateTimeProperty(auto_now_add=True)

def store_visit(remote_addr, user_agent):
    'create new Visit entity in Datastore'
    Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()

def fetch_visits(limit):
    'get most recent visits'
    return Visit.query().order(-Visit.timestamp).fetch(limit)

DOPO:

class Visit(ndb.Model):
    'Visit entity registers visitor IP address & timestamp'
    visitor   = ndb.StringProperty()
    timestamp = ndb.DateTimeProperty(auto_now_add=True)

def store_visit(remote_addr, user_agent):
    'create new Visit entity in Datastore'
    with ds_client.context():
        Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()

def fetch_visits(limit):
    'get most recent visits'
    with ds_client.context():
        return Visit.query().order(-Visit.timestamp).fetch(limit)

Sposta la logica di accesso degli utenti nel modello web

Il servizio Utenti di App Engine è lato server, mentre Firebase Auth e Cloud Identity Platform sono prevalentemente lato client. Di conseguenza, gran parte del codice per la gestione degli utenti nell'app del modulo 20 passa al modello web del modulo 21.

In main.py, il contesto web trasmette al modello cinque dati essenziali, i primi quattro elencati sono collegati alla gestione utenti e differiscono a seconda che l'utente abbia eseguito o meno l'accesso:

  • who: indirizzo email dell'utente se ha eseguito l'accesso o in caso contrario
  • admin: badge (amministratore) se l'utente che ha eseguito l'accesso è un amministratore
  • sign: mostra il pulsante Accedi o Esci
  • link: link di accesso o uscita facendo clic sul pulsante
  • visits: visite più recenti

PRIMA:

@app.route('/')
def root():
    'main application (GET) handler'
    store_visit(request.remote_addr, request.user_agent)
    visits = fetch_visits(10)

    # put together users context for web template
    user = users.get_current_user()
    context = {  # logged in
        'who':   user.nickname(),
        'admin': '(admin)' if users.is_current_user_admin() else '',
        'sign':  'Logout',
        'link':  '/_ah/logout?continue=%s://%s/' % (
                      request.environ['wsgi.url_scheme'],
                      request.environ['HTTP_HOST'],
                  ),  # alternative to users.create_logout_url()
    } if user else {  # not logged in
        'who':   'user',
        'admin': '',
        'sign':  'Login',
        'link':  users.create_login_url('/'),
    }

    # add visits to context and render template
    context['visits'] = visits  # display whether logged in or not
    return render_template('index.html', **context)

Tutta la gestione degli utenti passa al modello web, quindi rimangono solo le visite, riportando il gestore principale a quello che avevamo fino al modulo 1 dell'app:

DOPO:

@app.route('/')
def root():
    'main application (GET) handler'
    store_visit(request.remote_addr, request.user_agent)
    visits = fetch_visits(10)
    return render_template('index.html', visits=visits)

Aggiorna modello web

Come appaiono nel modello tutti gli aggiornamenti della sezione precedente? Spostando principalmente la gestione utenti dall'app a Firebase Auth in esecuzione nel modello e una porta parziale di tutto il codice che abbiamo spostato in JavaScript. Abbiamo registrato un lieve calo delle main.py, quindi prevedi una crescita simile nel seguente periodo: templates/index.html.

PRIMA:

<!doctype html>
<html>
<head>
<title>VisitMe Example</title>
</head>
<body>
<p>
Welcome, {{ who }} <code>{{ admin }}</code>
<button id="logbtn">{{ sign }}</button>
</p><hr>

<h1>VisitMe example</h1>
<h3>Last 10 visits</h3>
<ul>
{% for visit in visits %}
    <li>{{ visit.timestamp.ctime() }} from {{ visit.visitor }}</li>
{% endfor %}
</ul>

<script>
document.getElementById("logbtn").onclick = () => {
    window.location.href = '{{ link }}';
};
</script>
</body>
</html>

Sostituisci l'intero modello web con i contenuti seguenti:

DOPO:

<!doctype html>
<html>
<head>
<title>VisitMe Example</title>

<script type="module">
// import Firebase module attributes
import {
        initializeApp
} from "https://www.gstatic.com/firebasejs/9.10.0/firebase-app.js";
import {
        GoogleAuthProvider,
        getAuth,
        onAuthStateChanged,
        signInWithPopup,
        signOut
} from "https://www.gstatic.com/firebasejs/9.10.0/firebase-auth.js";

// Firebase config:
// 1a. Go to: console.cloud.google.com/customer-identity/providers
// 1b. May be prompted to enable GCIP and upgrade from Firebase
// 2. Click: "Application Setup Details" button
// 3. Copy: 'apiKey' and 'authDomain' from 'config' variable
var firebaseConfig = {
        apiKey: "YOUR_API_KEY",
        authDomain: "YOUR_AUTH_DOMAIN",
};

// initialize Firebase app & auth components
initializeApp(firebaseConfig);
var auth = getAuth();
var provider = new GoogleAuthProvider();
//provider.setCustomParameters({prompt: 'select_account'});

// define login and logout button functions
function login() {
    signInWithPopup(auth, provider);
};

function logout() {
    signOut(auth);
};

// check if admin & switch to logout button on login; reset everything on logout
onAuthStateChanged(auth, async (user) => {
    if (user && user != null) {
        var email = user.email;
        who.innerHTML = email;
        logbtn.onclick = logout;
        logbtn.innerHTML = "Logout";
        var idToken = await user.getIdToken();
        var rsp = await fetch("/is_admin", {
                method: "POST",
                headers: {Authorization: idToken}
        });
        var data = await rsp.json();
        if (data.admin) {
            admin.style.display = "inline";
        }
    } else {
        who.innerHTML = "user";
        admin.style.display = "none";
        logbtn.onclick = login;
        logbtn.innerHTML = "Login";
    }
});
</script>
</head>

<body>
<p>
Welcome, <span id="who"></span> <span id="admin"><code>(admin)</code></span>
<button id="logbtn"></button>
</p><hr>

<h1>VisitMe example</h1>
<h3>Last 10 visits</h3>
<ul>
{% for visit in visits %}
    <li>{{ visit.timestamp.ctime() }} from {{ visit.visitor }}</li>
{% endfor %}
</ul>

<script>
var who    = document.getElementById("who");
var admin  = document.getElementById("admin");
var logbtn = document.getElementById("logbtn");
</script>
</body>
</html>

Il corpo del codice HTML contiene molti componenti, pertanto esaminiamo un elenco alla volta.

Importazioni Firebase

Rimani nell'intestazione del documento HTML e una volta passato il titolo della pagina, importa i componenti Firebase necessari. I componenti di Firebase ora sono suddivisi in più moduli per garantire l'efficienza. Il codice per inizializzare Firebase viene importato dal modulo principale dell'app Firebase, mentre le funzioni che gestiscono Firebase auth, Google come provider di autenticazione, accesso e uscita e stato di autenticazione cambiano "callback" sono tutte importate dal modulo Firebase Auth:

<!doctype html>
<html>
<head>
<title>VisitMe Example</title>

<script type="module">
// import Firebase module attributes
import {
        initializeApp
} from "https://www.gstatic.com/firebasejs/9.10.0/firebase-app.js";
import {
        GoogleAuthProvider,
        getAuth,
        onAuthStateChanged,
        signInWithPopup,
        signOut
} from "https://www.gstatic.com/firebasejs/9.10.0/firebase-auth.js";

Configurazione di Firebase

In precedenza, durante la parte di questo tutorial dedicata alla configurazione di Identity Platform, hai salvato apiKey e authDomain dalla finestra di dialogo Dettagli di configurazione applicazione. Aggiungi questi valori alla variabile firebaseConfig nella sezione successiva. Nei commenti è disponibile un link a ulteriori istruzioni:

// Firebase config:
// 1a. Go to: console.cloud.google.com/customer-identity/providers
// 1b. May be prompted to enable GCIP and upgrade from Firebase
// 2. Click: "Application Setup Details" button
// 3. Copy: 'apiKey' and 'authDomain' from 'config' variable
var firebaseConfig = {
        apiKey: "YOUR_API_KEY",
        authDomain: "YOUR_AUTH_DOMAIN",
};

Inizializzazione di Firebase

La sezione successiva inizializza Firebase con queste informazioni di configurazione.

// initialize Firebase app & auth components
initializeApp(firebaseConfig);
var auth = getAuth();
var provider = new GoogleAuthProvider();
//provider.setCustomParameters({prompt: 'select_account'});

In questo modo viene impostata la possibilità di utilizzare Google come provider di autenticazione e viene fornita un'opzione di commento per mostrare il selettore di account anche se nella sessione del browser è registrato un solo Account Google. In altre parole, quando disponi di più account, ti viene presentato questo "selettore account" come previsto: a38369389b7c4c7e.png Tuttavia, se nella sessione è presente un solo utente, la procedura di accesso viene completata automaticamente senza interazione da parte dell'utente. Il popup appare, poi scompare. Puoi forzare la visualizzazione della finestra di dialogo del selettore account per un singolo utente (anziché accedere immediatamente all'app) rimuovendo il commento dalla riga del parametro personalizzato. Se attivati, anche gli accessi di un singolo utente mostrano il selettore dell'account: b75624cb68d94557.png

Funzioni di accesso e disconnessione

Le righe di codice successive costituiscono le funzioni per i clic sul pulsante di accesso o di disconnessione:

// define login and logout button functions
function login() {
    signInWithPopup(auth, provider);
};

function logout() {
    signOut(auth);
};

Azioni di accesso e uscita

L'ultima sezione importante di questo blocco <script> è la funzione che viene richiamata per ogni modifica dell'autorizzazione (accesso o uscita).

// check if admin & switch to logout button on login; reset everything on logout
onAuthStateChanged(auth, async (user) => {
    if (user && user != null) {
        var email = user.email;
        who.innerHTML = email;
        logbtn.onclick = logout;
        logbtn.innerHTML = "Logout";
        var idToken = await user.getIdToken();
        var rsp = await fetch("/is_admin", {
                method: "POST",
                headers: {Authorization: idToken}
        });
        var data = await rsp.json();
        if (data.admin) {
            admin.style.display = "inline";
        }
    } else {
        who.innerHTML = "user";
        admin.style.display = "none";
        logbtn.onclick = login;
        logbtn.innerHTML = "Login";
    }
});
</script>
</head>

Il codice nel modulo 20 che determina se inviare o meno un "utente che ha eseguito l'accesso" contesto del modello e "utente disconnesso" contesto è stato trasferito qui. Il condizionale in alto genera true se l'utente ha eseguito l'accesso, attivando le seguenti azioni:

  1. L'indirizzo email dell'utente è impostato per la visualizzazione.
  2. Il pulsante Accedi diventa Esci.
  3. Viene effettuata una chiamata in stile Ajax a /is_admin per determinare se mostrare il badge dell'utente amministratore di (admin).

Quando l'utente si disconnette, viene eseguita la clausola else per reimpostare tutte le informazioni dell'utente:

  1. Nome utente impostato su utente
  2. Qualsiasi badge amministrativo rimosso
  3. Il pulsante Esci è stato reimpostato su Accedi

Variabili del modello

Al termine della sezione dell'intestazione, il corpo principale inizia con le variabili del modello che vengono sostituite da elementi HTML che cambiano in base alle esigenze:

  1. Nome utente visualizzato
  2. Badge di amministrazione di (admin) (se applicabile)
  3. Pulsante Accedi o Esci
<body>
<p>
Welcome, <span id="who"></span> <span id="admin"><code>(admin)</code></span>
<button id="logbtn"></button>
</p><hr>

Visite più recenti e variabili degli elementi HTML

Il codice delle visite più recenti non cambia e il blocco <script> finale imposta le variabili per gli elementi HTML che cambiano per l'accesso e la disconnessione elencati sopra:

<h1>VisitMe example</h1>
<h3>Last 10 visits</h3>
<ul>
{% for visit in visits %}
    <li>{{ visit.timestamp.ctime() }} from {{ visit.visitor }}</li>
{% endfor %}
</ul>

<script>
var who    = document.getElementById("who");
var admin  = document.getElementById("admin");
var logbtn = document.getElementById("logbtn");
</script>
</body>
</html>

Questo conclude le modifiche necessarie nell'applicazione e nel modello web per passare dalle API NDB e utente di App Engine a Cloud NDB e Identity Platform, nonché l'upgrade a Python 3. Congratulazioni per aver lanciato la nuova app di esempio del Modulo 21. La nostra versione è disponibile per la revisione nella cartella di repository del Modulo 21b.

La parte successiva del codelab è facoltativa (*) e solo per gli utenti le cui app devono rimanere su Python 2, che ti guiderà attraverso i passaggi necessari per arrivare a un'app Python 2 Modulo 21 funzionante.

6. *Backport Python 2

Questa sezione facoltativa è riservata agli sviluppatori che eseguono una migrazione di Identity Platform, ma che devono continuare a eseguire il runtime Python 2. Se questo non è un problema per te, salta questa sezione.

Per creare una versione Python 2 funzionante dell'app Modulo 21, è necessario quanto segue:

  1. Requisiti di runtime: file di configurazione che supportano Python 2 e modifiche richieste nell'applicazione principale per evitare incompatibilità con Python 3.
  2. Modifica di minore entità alla libreria: Python 2 è stato deprecato prima che alcune funzionalità richieste venissero aggiunte alla libreria client di Resource Manager. Di conseguenza, hai bisogno di un modo alternativo per accedere alla funzionalità mancante.

Eseguiamo ora questi passaggi, iniziando dalla configurazione.

Ripristina appengine_config.py

In precedenza in questo tutorial ti abbiamo consigliato di eliminare appengine_config.py poiché non è utilizzato dal runtime di App Engine di Python 3. Per Python 2, non solo deve essere conservato, ma il Modulo 20 appengine_config.py deve essere aggiornato per supportare l'uso di librerie di terze parti integrate, ovvero grpcio e setuptools. Questi pacchetti sono richiesti ogni volta che la tua app App Engine utilizza librerie client di Cloud come quelle per Cloud NDB e Cloud Resource Manager.

Tra poco aggiungerai questi pacchetti a app.yaml, ma per consentire l'accesso alla tua app è necessario chiamare la funzione pkg_resources.working_set.add_entry() di setuptools. Ciò consente alle librerie di terze parti copiate (in bundle o fornite dal fornitore) installate nella cartella lib di comunicare con le librerie integrate.

Implementa i seguenti aggiornamenti al tuo file appengine_config.py per applicare queste modifiche:

PRIMA:

from google.appengine.ext import vendor

# Set PATH to your libraries folder.
PATH = 'lib'
# Add libraries installed in the PATH folder.
vendor.add(PATH)

Questo codice da solo non è sufficiente a supportare l'utilizzo di setuptools e grpcio. Sono necessarie alcune altre righe, quindi aggiorna appengine_config.py in modo che abbia il seguente aspetto:

DOPO:

import pkg_resources
from google.appengine.ext import vendor

# Set PATH to your libraries folder.
PATH = 'lib'
# Add libraries installed in the PATH folder.
vendor.add(PATH)
# Add libraries to pkg_resources working set to find the distribution.
pkg_resources.working_set.add_entry(PATH)

Ulteriori dettagli sulle modifiche necessarie per supportare le librerie client di Cloud sono disponibili nella documentazione relativa alla migrazione dei servizi in bundle.

app.yaml

Come per appengine_config.py, il file app.yaml deve essere ripristinato a uno che supporti Python 2. Iniziamo con il modulo originale 20 app.yaml:

PRIMA:

runtime: python27
threadsafe: yes
api_version: 1

handlers:
- url: /.*
  script: main.app

Oltre a setuptools e grpcio, come accennato in precedenza, esiste una dipendenza (non esplicitamente correlata alla migrazione di Identity Platform) che richiede l'utilizzo della libreria client di Cloud Storage e che richiede un altro pacchetto integrato di terze parti, ssl. Aggiungi tutti e tre in una nuova sezione di libraries, selezionando il "più recente" versioni disponibili di questi pacchetti, in app.yaml:

DOPO:

runtime: python27
threadsafe: yes
api_version: 1

handlers:
- url: /.*
  script: main.app

libraries:
- name: grpcio
  version: latest
- name: setuptools
  version: latest
- name: ssl
  version: latest

requirements.txt

Per il modulo 21, abbiamo aggiunto Google Auth, Cloud NDB, Cloud Resource Manager e l'SDK Admin Firebase alla versione requirements.txt di Python 3. La situazione per Python 2 è più complessa:

  • L'API Resource Manager fornisce la funzionalità allow-policy necessaria per l'app di esempio. Purtroppo questo supporto non è ancora disponibile nella versione finale Python 2 della libreria client di Cloud Resource Manager. (È disponibile solo nella versione Python 3).
  • Di conseguenza, è necessario un modo alternativo per accedere a questa funzionalità dall'API. La soluzione consiste nell'utilizzare la libreria client delle API di Google di livello inferiore per comunicare con l'API. Per passare a questa libreria client, sostituisci google-cloud-resource-manager con il pacchetto google-api-python-client di livello inferiore.
  • Poiché Python 2 è stato ritirato, il grafico delle dipendenze che supporta il Modulo 21 richiede il blocco di determinati pacchetti a versioni specifiche. Alcuni pacchetti devono essere richiamati anche se non sono specificati nel app.yaml di Python 3.

PRIMA:

flask

A partire dal modulo 20 requirements.txt, aggiornalo come segue per un'app del modulo 21 funzionante:

DOPO:

grpcio==1.0.0
protobuf<3.18.0
six>=1.13.0
flask
google-gax<0.13.0
google-api-core==1.31.1
google-api-python-client<=1.11.0
google-auth<2.0dev
google-cloud-datastore==1.15.3
google-cloud-firestore==1.9.0
google-cloud-ndb
google-cloud-pubsub==1.7.0
firebase-admin

Il pacchetto e i numeri di versione verranno aggiornati nel repository man mano che le dipendenze cambiano, ma questo app.yaml è sufficiente per un'app funzionante al momento della stesura del presente documento.

Altri aggiornamenti della configurazione

Se non hai eliminato la cartella lib in precedenza in questo codelab, fallo ora. Con l'aggiornamento requirements.txt appena aggiornato, esegui questo comando familiare per installare questi requisiti in lib:

pip install -t lib -r requirements.txt  # or pip2

Se sul tuo sistema di sviluppo sono installati sia Python 2 che 3, potrebbe essere necessario utilizzare pip2 anziché pip.

Modifica il codice dell'applicazione

Fortunatamente, la maggior parte delle modifiche necessarie si trova nei file di configurazione. L'unica modifica necessaria al codice dell'applicazione è un aggiornamento minore che prevede l'utilizzo della libreria client dell'API di Google di livello inferiore anziché la libreria client di Resource Manager per accedere all'API. Non sono richiesti aggiornamenti al modello web templates/index.html.

Aggiornare le importazioni e l'inizializzazione

Sostituisci la libreria client di Resource Manager (google.cloud.resourcemanager) con la libreria client delle API di Google (googleapiclient.discovery), come illustrato di seguito:

PRIMA:

from flask import Flask, render_template, request
from google.auth import default
from google.cloud import ndb, resourcemanager
from firebase_admin import auth, initialize_app

DOPO:

from flask import Flask, render_template, request
from google.auth import default
from google.cloud import ndb
from googleapiclient import discovery
from firebase_admin import auth, initialize_app

Assistenza per gli utenti amministratori di App Engine

Sono necessarie alcune modifiche in _get_gae_admins() per supportare l'utilizzo della libreria client di livello inferiore. Prima di tutto, parliamo di cosa cambierà e poi ti forniremo tutto il codice da aggiornare.

Il codice Python 2 richiede l'utilizzo sia delle credenziali sia dell'ID progetto restituito da google.auth.default(). Le credenziali non vengono utilizzate in Python 3, quindi sono state assegnate a una variabile dummy con un trattino basso generico ( _). Poiché è necessario per la versione Python 2, modifica il trattino basso in CREDS. Inoltre, anziché creare un client API Resource Manager, creerai un endpoint di servizio API con un concetto simile a un client API, quindi conserveremo lo stesso nome di variabile (rm_client). Una differenza è che per creare un'istanza di un endpoint di servizio sono necessarie le credenziali (CREDS).

Queste modifiche sono riflesse nel codice riportato di seguito:

PRIMA:

_, PROJ_ID = default(  # Application Default Credentials and project ID
        ['https://www.googleapis.com/auth/cloudplatformprojects.readonly'])
rm_client = resourcemanager.ProjectsClient()

DOPO:

CREDS, PROJ_ID = default(  # Application Default Credentials and project ID
        ['https://www.googleapis.com/auth/cloud-platform'])
rm_client = discovery.build('cloudresourcemanager', 'v1', credentials=CREDS)

L'altra differenza è che la libreria client di Resource Manager restituisce oggetti allow-policy che utilizzano la notazione puntata-attributo, mentre la libreria client di livello inferiore restituisce i dizionari Python in cui vengono utilizzate le parentesi quadre ( [ ]). Ad esempio, usa binding.role per la libreria client di Resource Manager anziché binding['role'] per la libreria di livello inferiore. Il primo utilizza anche "underscore_separated" nomi rispetto alla libreria di livello inferiore che preferisce "CamelCased" più un modo leggermente diverso per passare i parametri API.

Queste differenze di utilizzo sono mostrate di seguito:

PRIMA:

allow_policy = rm_client.get_iam_policy(resource='projects/%s' % PROJ_ID)
for b in allow_policy.bindings:     # bindings in IAM allow-policy
    if b.role in _TARGETS:          # only look at GAE admin roles
        admins.update(user.split(':', 1).pop() for user in b.members)

DOPO:

allow_policy = rm_client.projects().getIamPolicy(resource=PROJ_ID).execute()
for b in allow_policy['bindings']:  # bindings in IAM allow-policy
    if b['role'] in _TARGETS:       # only look at GAE admin roles
        admins.update(user.split(':', 1).pop() for user in b['members'])

Combinando tutte queste modifiche, sostituisci Python 3 _get_gae_admins() con questa versione Python 2 equivalente:

def _get_gae_admins():
    'return set of App Engine admins'
    # setup constants for calling Cloud Resource Manager API
    CREDS, PROJ_ID = default(  # Application Default Credentials and project ID
            ['https://www.googleapis.com/auth/cloud-platform'])
    rm_client = discovery.build('cloudresourcemanager', 'v1', credentials=CREDS)
    _TARGETS = frozenset((     # App Engine admin roles
            'roles/viewer',
            'roles/editor',
            'roles/owner',
            'roles/appengine.appAdmin',
    ))

    # collate users who are members of at least one GAE admin role (_TARGETS)
    admins = set()                      # set of all App Engine admins
    allow_policy = rm_client.projects().getIamPolicy(resource=PROJ_ID).execute()
    for b in allow_policy['bindings']:  # bindings in IAM allow-policy
        if b['role'] in _TARGETS:       # only look at GAE admin roles
            admins.update(user.split(':', 1).pop() for user in b['members'])
    return admins

La funzione is_admin() non richiede aggiornamenti perché si basa su _get_gae_admins() che è già stato aggiornato.

Con questo si concludono le modifiche necessarie per il backporting dell'app Python 3 Modulo 21 in Python 2. Congratulazioni per aver scaricato l'app di esempio aggiornata del Modulo 21. Troverai tutto il codice nella cartella di repository del Modulo 21a.

7. Riepilogo/Pulizia

Gli ultimi passaggi nel codelab sono garantire che le entità (utenti o account di servizio) che eseguono questa app abbiano le autorizzazioni appropriate, poi eseguire il deployment dell'app per confermare che funzioni come previsto e le modifiche si riflettono nell'output.

Può leggere i criteri di autorizzazione IAM

In precedenza ti abbiamo illustrato i quattro ruoli necessari per essere riconosciuti come utente amministratore di App Engine, ma ora c'è un quinto ruolo con cui acquisire familiarità:

  • roles/viewer
  • roles/editor
  • roles/owner
  • roles/appengine.appAdmin
  • roles/resourcemanager.projectIamAdmin (per le entità che accedono al criterio di autorizzazione IAM)

Il ruolo roles/resourcemanager.projectIamAdmin consente alle entità di determinare se un utente finale è membro di uno dei ruoli amministrativi di App Engine. Senza l'appartenenza a roles/resourcemanager.projectIamAdmin, le chiamate all'API Cloud Resource Manager per ottenere il criterio di autorizzazione non andranno a buon fine.

Non devi intraprendere alcuna azione esplicita qui, perché la tua app verrà eseguita nell'account di servizio predefinito di App Engine, a cui viene automaticamente concessa l'appartenenza a questo ruolo. Anche se utilizzi l'account di servizio predefinito durante la fase di sviluppo, ti consigliamo vivamente di creare e utilizzare un account di servizio gestito dall'utente con le autorizzazioni minime necessarie per il corretto funzionamento dell'app. Per concedere l'iscrizione a un account di servizio di questo tipo, esegui questo comando:

$ gcloud projects add-iam-policy-binding PROJ_ID --member="serviceAccount:USR_MGD_SVC_ACCT@PROJ_ID.iam.gserviceaccount.com" --role=roles/resourcemanager.projectIamAdmin

PROJ_ID è l'ID progetto Cloud e USR_MGD_SVC_ACCT@PROJ_ID.iam.gserviceaccount.com è l'account di servizio gestito dall'utente che crei per la tua app. Questo comando restituisce il criterio IAM aggiornato per il progetto, dove puoi confermare che l'account di servizio è membro di roles/resourcemanager.projectIamAdmin. Per ulteriori informazioni, consulta la documentazione di riferimento. Per ripetere l'operazione, non è necessario emettere questo comando in questo codelab, ma salvalo come riferimento per la modernizzazione delle tue app.

Esegui il deployment e verifica l'applicazione

Carica la tua app nel cloud con il comando gcloud app deploy standard. Una volta eseguito il deployment, dovresti vedere una funzionalità quasi identica all'app del modulo 20, tranne per il fatto che hai sostituito il servizio Utenti di App Engine con Cloud Identity Platform (e Firebase Auth) per la gestione degli utenti:

3a83ae745121d70.png

Una differenza che noterai rispetto al Modulo 20 è che, se fai clic sull'accesso, viene visualizzato un popup invece di un reindirizzamento, come mostrato in alcuni degli screenshot seguenti. Come nel caso del Modulo 20, tuttavia, il comportamento varia leggermente in base al numero di Account Google registrati con il browser.

Se non ci sono utenti registrati con il browser o un singolo utente che non ha ancora eseguito l'accesso, viene visualizzato un popup Accedi con Google generico:

8437f5f3d489a942.png

Se un singolo utente è registrato con il tuo browser, ma esegue l'accesso altrove, non viene visualizzata alcuna finestra di dialogo (oppure si apre e si chiude immediatamente) e l'app passa allo stato di accesso (vengono visualizzati l'email dell'utente e il pulsante Esci).

Alcuni sviluppatori potrebbero voler fornire un selettore account, anche per un singolo utente:

b75624cb68d94557.png

Per implementarlo, rimuovi il commento dalla riga provider.setCustomParameters({prompt: 'select_account'}); nel modello web come descritto in precedenza.

Se ci sono più utenti, viene visualizzata la finestra di dialogo del selettore dell'account (vedi di seguito). Se non ha ancora eseguito l'accesso, all'utente verrà chiesto di farlo. Se hai già eseguito l'accesso, il popup scompare e l'app passa allo stato di accesso.

c454455b6020d5e4.png

Lo stato di accesso del modulo 21 è identico a quello dell'interfaccia utente del modulo 20:

49ebe4dcc1eff11f.png

Lo stesso vale quando un utente amministratore ha eseguito l'accesso:

44302f35b39856eb.png

A differenza del modulo 21, il modulo 20 accede sempre alla logica per i contenuti del modello web dall'app (codice lato server). Un difetto del Modulo 20 è che una visita viene registrata quando l'utente finale accede all'app per la prima volta, mentre un'altra viene registrata quando un utente esegue l'accesso.

Per il modulo 21, la logica di accesso avviene solo nel modello web (codice lato client). Non è richiesto un trip lato server per determinare quali contenuti visualizzare. L'unica chiamata effettuata al server è la verifica degli utenti amministratore dopo l'accesso di un utente finale. Ciò significa che accessi e disconnessioni non registrano ulteriori visite, pertanto l'elenco delle visite più recenti rimane costante per le azioni di gestione degli utenti. Nota che gli screenshot riportati sopra mostrano lo stesso insieme di quattro visite per più accessi utente.

Gli screenshot del modulo 20 dimostrano il "bug della visita doppia" all'inizio di questo codelab. Log delle visite separati per ogni azione di accesso o uscita. Controlla i timestamp della visita più recente per ogni screenshot che mostra l'ordine cronologico.

Esegui la pulizia

Generale

Se per il momento hai finito, ti consigliamo di disabilitare l'app App Engine per evitare di incorrere in fatturazione. Tuttavia, se desideri eseguire altri test o sperimentarli, la piattaforma App Engine ha una quota senza costi, pertanto, se non superi il livello di utilizzo, non ti verrà addebitato alcun costo. Questo riguarda il computing, ma potrebbero essere addebitati costi anche per i servizi App Engine pertinenti, quindi consulta la pagina dei prezzi per ulteriori informazioni. Se la migrazione coinvolge altri servizi Cloud, questi vengono fatturati separatamente. In entrambi i casi, se applicabile, consulta la sezione "Specifici di questo codelab" di seguito.

Per garantire la piena divulgazione, il deployment su una piattaforma di serverless computing di Google Cloud come App Engine comporta costi minori di build e archiviazione. Cloud Build e Cloud Storage hanno una quota senza costi specifica. Lo spazio di archiviazione dell'immagine esaurisce una parte della quota. Tuttavia, potresti risiedere in una regione che non ha un livello senza costi, quindi tieni presente l'utilizzo dello spazio di archiviazione per ridurre al minimo i costi potenziali. "cartelle" specifiche di Cloud Storage da esaminare includono:

  • console.cloud.google.com/storage/browser/LOC.artifacts.PROJECT_ID.appspot.com/containers/images
  • console.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com
  • I link allo spazio di archiviazione riportati sopra dipendono dalla tua PROJECT_ID e dalla tua LOCazione, ad esempio "us" se la tua app è ospitata negli Stati Uniti.

Se invece non intendi continuare con questa applicazione o con altri codelab di migrazione correlati e vuoi eliminare tutto completamente, chiudi il progetto.

Specifico di questo codelab

I servizi elencati di seguito sono esclusivi per questo codelab. Per ulteriori informazioni, fai riferimento alla documentazione di ciascun prodotto:

Passaggi successivi

Oltre a questo tutorial, altri moduli di migrazione che si concentrano sull'abbandono dei servizi in bundle legacy da prendere in considerazione includono:

  • Modulo 2: migrazione da App Engine ndb a Cloud NDB
  • Moduli 7-9: migrazione dalla coda di attività di App Engine (attività push) a Cloud Tasks
  • Moduli 12-13: migrazione da App Engine Memcache a Cloud Memorystore
  • Moduli 15-16: migrazione dal Blobstore di App Engine a Cloud Storage
  • Moduli 18-19: migrazione dalla coda di attività di App Engine (attività pull) a Cloud Pub/Sub

App Engine non è più l'unica piattaforma serverless in Google Cloud. Se hai un'app App Engine di piccole dimensioni o con funzionalità limitate e vuoi convertirla in un microservizio autonomo oppure vuoi suddividere un'app monolitica in più componenti riutilizzabili, questi sono ottimi motivi per passare a Cloud Functions. Se la containerizzazione è diventata parte del flusso di lavoro per lo sviluppo delle applicazioni, in particolare se è costituita da una pipeline CI/CD (integrazione continua/distribuzione continua o deployment), valuta la possibilità di eseguire la migrazione a Cloud Run. Questi scenari sono trattati nei seguenti moduli:

  • Eseguire la migrazione da App Engine a Cloud Functions: consulta il Modulo 11
  • Esegui la migrazione da App Engine a Cloud Run: consulta il Modulo 4 per containerizzare la tua app con Docker oppure il Modulo 5 per eseguire questa operazione senza container, conoscenze di Docker o Dockerfile

Il passaggio a un'altra piattaforma serverless è facoltativo e prima di apportare modifiche ti consigliamo di valutare le opzioni migliori per le tue app e i tuoi casi d'uso.

Indipendentemente dal modulo di migrazione successivo, sarà possibile accedere a tutti i contenuti di Serverless Migration Station (codelab, video, codice sorgente [se disponibile]) nel relativo repository open source. L'elemento README del repository fornisce anche indicazioni sulle migrazioni da prendere in considerazione e su eventuali "ordine" pertinenti dei Moduli di migrazione.

8. Risorse aggiuntive

Di seguito sono elencate le risorse aggiuntive per gli sviluppatori che esplorano ulteriormente questo modulo di migrazione o quelli correlati. Di seguito puoi fornire un feedback su questi contenuti, trovare link al codice e vari documenti che potrebbero esserti utili.

Problemi/feedback dei codelab

Se riscontri problemi con questo codelab, cercali prima di procedere con l'invio. Link per eseguire ricerche e creare nuovi problemi:

Risorse di migrazione

I link alle cartelle repository per il modulo 20 (START) e il modulo 21 (FINISH) sono disponibili nella tabella seguente.

Codelab

Python 2

Python 3

Modulo 20

codice

(n/d)

Modulo 21 (questo codelab)

codice

codice

Riferimenti online

Di seguito sono riportate le risorse pertinenti per questo tutorial:

Cloud Identity Platform e Cloud Marketplace

Cloud Resource Manager, Cloud IAM, SDK Firebase Admin

Utenti di App Engine, NDB di App Engine, Cloud NDB, Cloud Datastore

Altri riferimenti al Modulo di migrazione

Migrazione ad App Engine

Piattaforma App Engine

Cloud SDK

Altre informazioni sul cloud

Video

Licenza

Questo lavoro è concesso in licenza ai sensi di una licenza Creative Commons Attribution 2.0 Generic.