Migra del servicio de usuarios de App Engine a Cloud Identity Platform (módulo 21)

1. Descripción general

La serie de codelabs Serverless Migration Station (instructivos prácticos y autoaprendizaje) y los videos relacionados tienen como objetivo ayudar a los desarrolladores de Google Cloud sin servidores a modernizar sus apps guiándolos a través de una o más migraciones, en especial al alejarse de los servicios heredados. De esta manera, tus apps serán más portátiles, y tendrás más opciones y flexibilidad, lo que te permitirá integrarlas con una variedad más amplia de productos de Cloud y acceder a ella, y actualizar con mayor facilidad a versiones de idiomas más recientes. Aunque inicialmente se enfoca en los primeros usuarios de Cloud, principalmente los desarrolladores de App Engine (entorno estándar), esta serie es lo suficientemente amplia como para incluir otras plataformas sin servidores como Cloud Functions y Cloud Run, o cualquier otra, si corresponde.

El propósito de este codelab es mostrarles a los desarrolladores de App Engine de Python 2 cómo migrar de la API o el servicio de usuarios de App Engine a Cloud Identity Platform (GCIP). También hay una migración implícita de App Engine NDB a Cloud NDB para el acceso a Datastore (que se aborda principalmente en el Módulo de migración 2), así como una actualización a Python 3.

El módulo 20 explica cómo agregar el uso de la API de usuarios a la app de ejemplo del módulo 1. En este módulo, tomarás la app finalizada del Módulo 20 y migrarás su uso a Cloud Identity Platform.

En un próximo lab,

  • Reemplaza el uso del servicio de usuarios de App Engine por Cloud Identity Platform.
  • Reemplaza el uso de App Engine NDB por Cloud NDB (consulta también el Módulo 2).
  • Configura diferentes proveedores de identidad de autenticación con Firebase Auth
  • Usa la API de Cloud Resource Manager para obtener información de IAM del proyecto
  • Usa el SDK de Firebase Admin para obtener información de los usuarios
  • Cómo migrar la aplicación de ejemplo a Python 3

Requisitos

Encuesta

¿Cómo usarás este instructivo?

Solo leerlo Léelo y completa los ejercicios. .

¿Cómo calificarías tu experiencia en Python?

Principiante Intermedio Avanzado

¿Cómo calificarías tu experiencia en el uso de los servicios de Google Cloud?

Principiante Intermedio Avanzado .
.

2. Información general

El servicio de usuarios de App Engine es un sistema de autenticación de usuarios para que lo usen las apps de App Engine. Proporciona Acceso con Google como su proveedor de identidad, proporciona vínculos de acceso y salida convenientes para usar en apps y admite el concepto de usuarios administradores y funcionalidad exclusiva de administrador. Para mejorar la portabilidad de la aplicación, Google Cloud recomienda migrar de servicios empaquetados de App Engine heredados a servicios independientes de Cloud, por ejemplo, del servicio de usuarios a Cloud Identity Platform, entre otros.

Identity Platform se basa en Firebase Authentication y agrega una serie de funciones empresariales, como la autenticación de varios factores, OIDC y Compatibilidad con SSO de SAML, multiusuario, ANS del 99.95% y mucho más. Estas diferencias también se destacan en la página de comparación de productos de Identity Platform y Firebase Authentication. Ambos productos tienen muchas más funciones que la funcionalidad proporcionada por el servicio de usuarios.

Este codelab del módulo 21 muestra cómo cambiar la autenticación de usuarios de la app del servicio de usuarios a las funciones de Identity Platform que reflejan con mayor precisión la funcionalidad que se demostró en el módulo 20. En el módulo 21, también se presenta una migración de App Engine NBS a Cloud Datastore para el acceso a Datastore, en la que se repite la migración del Módulo 2.

Mientras que el código del módulo 20 está “anunciado” Como app de ejemplo de Python 2, la fuente en sí es compatible con Python 2 y 3, y se mantiene así incluso después de migrar a Identity Platform (y Cloud NDB) en el módulo 21. Es posible seguir usando el servicio de usuarios mientras actualizas a Python 3, ya que migrar a Identity Platform es opcional. Consulta el codelab del módulo 17 y el video para aprender a seguir usando los servicios en paquetes mientras actualizas a entornos de ejecución de 2a generación, como Python 3.

En este instructivo, se muestran los siguientes pasos:

  1. Configurar/trabajo previo
  2. Actualizar configuración
  3. Modifica el código de la aplicación

3. Configurar/trabajo previo

Esta sección explica cómo:

  1. Configura el proyecto de Cloud
  2. Obtén app de ejemplo del modelo de referencia
  3. (Re)Implementa y valida la app de referencia
  4. Habilitar nuevas APIs o servicios de Google Cloud

Estos pasos garantizan que comiences con un código funcional que está listo para migrar a servicios de Cloud independientes.

1. Configura el proyecto

Si completaste el codelab del módulo 20, vuelve a usar ese mismo proyecto (y código). Como alternativa, crea un proyecto completamente nuevo o reutiliza otro proyecto existente. Asegúrate de que el proyecto tenga una cuenta de facturación activa y una app de App Engine habilitada. Busca tu ID del proyecto, tenlo a mano durante este codelab y úsalo cuando encuentres la variable PROJ_ID.

2. Obtén app de ejemplo del modelo de referencia

Uno de los requisitos previos es contar con una app de App Engine del Módulo 20 que funcione, así que completa el codelab (se recomienda incluir el vínculo anterior) o copia el código del módulo 20 del repositorio. Ya sea que use el suyo o el nuestro, aquí es por donde comenzaremos ("COMENZAR"). En este codelab, se explica la migración y se concluye con un código similar al que hay en la carpeta del repositorio del Módulo 21 (“FINISH”).

Copia la carpeta del repositorio del módulo 20. Debería verse como el siguiente resultado, y es posible que tenga una carpeta lib si realizaste el codelab del módulo 20:

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

3. (Re)Implementa y valida la app de referencia

Ejecuta los siguientes pasos para implementar la app del módulo 20:

  1. Borra la carpeta lib si hay una y ejecuta pip install -t lib -r requirements.txt para volver a propagarla. Es posible que debas usar pip2 si tienes instalados Python 2 y 3.
  2. Asegúrate de haber instalado e inicializado la herramienta de línea de comandos de gcloud y de haber revisado su uso.
  3. Si no quieres ingresar tu PROJ_ID con cada comando gcloud emitido, configura el proyecto de Cloud con gcloud config set project PROJ_ID primero.
  4. Implementa la app de ejemplo con gcloud app deploy
  5. Confirma que la app se ejecute como se espera y sin errores. Si completaste el codelab del módulo 20, la app mostrará la información de acceso del usuario (correo electrónico del usuario, posible “insignia de administrador” y botón para acceder y salir) en la parte superior junto con las visitas más recientes (que se ilustran a continuación).

907e64c19ef964f8.png

Al acceder como usuario normal, se muestra la dirección de correo electrónico del usuario y la opción "Acceder" del botón cambia a “Salir” :

ad7b59916b69a035.png

Al acceder como usuario administrador, la dirección de correo electrónico del usuario aparece junto con "(administrador)" junto a él:

867bcb3334149e4.png

4. Habilitar nuevos servicios o APIs de Google Cloud

Introducción

La app del Módulo 20 usa las API de App Engine NDB y Users, servicios agrupados que no requieren una configuración adicional, pero los servicios independientes de Cloud sí lo hacen. La app actualizada empleará Cloud Identity Platform y Cloud Datastore (a través de la biblioteca cliente de Cloud NDB). Además, la necesidad de determinar los usuarios administradores de App Engine también requiere el uso de la API de Cloud Resource Manager.

Costo

  • App Engine y Cloud Datastore tienen la opción "Siempre gratuito" nivel y, siempre que te mantengas por debajo de esos límites, no se generarán cargos si completas este instructivo. Consulta también la página de precios de App Engine y la página de precios de Cloud Datastore para obtener más detalles.
  • El uso de Cloud Identity Platform se factura según la cantidad de usuarios activos por mes (MAU) o verificaciones de autenticación. alguna versión de "gratis" está disponible para cada modelo de uso. Consulta su página de precios para obtener más detalles. Además, si bien App Engine y Cloud Datastore requieren facturación, el uso de GCIP por sí solo no requiere que se habilite la facturación, siempre y cuando no se excedan las cuotas diarias sin instrumentación, por lo que debes tener esto en cuenta para los proyectos de Cloud que no incluyen APIs o servicios de Cloud que requieren facturación.
  • El uso de la API de Cloud Resource Manager es gratuito en su mayor parte según su página de precios.

Los usuarios habilitan las APIs de Cloud desde la consola de Cloud o desde la línea de comandos (a través del comando gcloud, que forma parte del SDK de Cloud), según tus preferencias. Comencemos con las APIs de Cloud Datastore y Cloud Resource Manager.

Desde la consola de Cloud

Ve a la página Biblioteca del Administrador de APIs (para el proyecto correcto) en la consola de Cloud y busca una API con la barra de búsqueda. c7a740304e9d35b.png

Habilita estas APIs:

Busca el botón Habilitar para cada API por separado y haz clic en él. Es posible que se te soliciten datos de facturación. Por ejemplo, esta es la página de la API de Resource Manager:

fc7bd8f4c49d12e5.png

El botón cambia a Administrar cuando se habilita (por lo general, después de unos segundos):

8eca12d6cc7b45b0.png

Habilita Cloud Datastore de la misma manera:

83811599b110e46b.png

Desde la línea de comandos

Aunque resulta visualmente informativo habilitar las APIs desde la consola, algunos prefieren la línea de comandos. Tienes la ventaja adicional de poder habilitar cualquier cantidad de APIs a la vez. Ejecuta este comando para habilitar las APIs de Cloud Datastore y Cloud Resource Manager, y espera a que se complete la operación, como se muestra aquí:

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

Es posible que se le soliciten datos de facturación.

Las "URL" de cada API usada en el comando anterior se denominan nombres de servicios de API y se encuentran al final de la página de la biblioteca para cada API. Si quieres habilitar otras APIs de Cloud para tus propias apps, puedes encontrar sus nombres de servicio correspondientes en las páginas de las APIs correspondientes. Con este comando, se enumeran todos los nombres de servicios para las APIs que puedes habilitar:

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

Ya sea en la consola de Cloud o en la línea de comandos, una vez que hayas completado los pasos anteriores, nuestra muestra podrá acceder a esas APIs. Los próximos pasos son habilitar Cloud Identity Platform y realizar los cambios de código necesarios.

Habilita y configura Cloud Identity Platform (solo la consola de Cloud)

Cloud Identity Platform es un servicio de Marketplace porque se conecta a un recurso fuera de Google Cloud o depende de él, por ejemplo, Firebase Authentication. En este momento, solo puedes habilitar los servicios de Marketplace en la consola de Cloud. Siga los pasos que se indican a continuación:

  1. Ve a la página de Cloud Identity Platform en Cloud Marketplace y haz clic en el botón Habilitar. Actualiza desde Firebase Authentication si se te solicita. Con esta acción, desbloqueas funciones adicionales, como las que se describieron antes en la sección Segundo plano. Esta es la página de Marketplace en la que se destaca el botón Habilitar: 28475f1c9b29de69.png
  2. Una vez que se habilite Identity Platform, es posible que se te dirija automáticamente a la página Proveedores de identidad. De lo contrario, usa este vínculo conveniente para acceder. fc2d92d42a5d1dd7.png
  3. Habilita el proveedor de Google Auth. Si no se configuraron proveedores, haz clic en Agregar un proveedor y selecciona Google. Cuando regreses a esta pantalla, la entrada Google debería estar habilitada. Google es el único proveedor de autenticación que usamos en este instructivo para duplicar el servicio de usuarios de App Engine como un servicio ligero de Acceso con Google. En tus propias apps, puedes habilitar proveedores de autenticación adicionales.
  4. Una vez que hayas seleccionado y configurado Google y otros proveedores de autenticación deseados, haz clic en Detalles de configuración de la aplicación y, en la ventana de diálogo de garantía, copia apiKey y authDomain en el objeto config de la pestaña Web, y guarda ambos en un lugar seguro. ¿Por qué no copiarlo todo? El fragmento de este diálogo está codificado y tiene una fecha, por lo que solo debes guardar los bits más importantes y usarlos en nuestro código con un uso más simultáneo de Firebase Auth. Después de copiar los valores y guardarlos en un lugar seguro, haz clic en el botón Cerrar para completar toda la configuración necesaria. bbb09dcdd9be538e.png

4. Actualizar configuración

Las actualizaciones de la configuración incluyen el cambio de varios archivos de configuración y la creación del equivalente de App Engine, pero dentro del ecosistema de Cloud Identity Platform.

appengine_config.py

  • Si actualizas a Python 3, borra appengine_config.py.
  • Si planeas modernizar a Identity Platform, pero te quedaste en Python 2, no borres el archivo. En su lugar, lo actualizaremos más adelante durante la portabilidad a versiones anteriores de Python 2.

requirements.txt

El archivo requirements.txt del módulo 20 solo mostraba Flask. Para el módulo 21, agrega los siguientes paquetes:

El contenido de requirements.txt debería verse de la siguiente manera:

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

app.yaml

  • La actualización a Python 3 implica simplificar el archivo app.yaml. Quita todo excepto la directiva del entorno de ejecución y configúralo en una versión compatible actual de Python 3. Actualmente, el ejemplo usa la versión 3.10.
  • Si te quedas con Python 2, aún no debes realizar ninguna acción aquí.

ANTES:

runtime: python27
threadsafe: yes
api_version: 1

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

La app de muestra del módulo 20 no tiene controladores de archivos estáticos. Si tus apps lo hacen, déjalas intactas. Si lo deseas, puedes quitar todos los controladores de secuencia de comandos o dejarlos allí como referencia, siempre y cuando los cambies a auto, como se describe en la guía de migración de app.yaml. Con estos cambios, el app.yaml actualizado para Python 3 se simplifica a:

DESPUÉS:

runtime: python310

Otras actualizaciones de configuración

Ya sea que permanezcas en Python 2 o tengan portabilidad a Python 3, si tienes una carpeta lib, bórrala.

5. Modifica el código de la aplicación

En esta sección, se incluyen actualizaciones para el archivo principal de la aplicación, main.py, que reemplazan el uso del servicio de usuarios de App Engine por Cloud Identity Platform. Después de actualizar la aplicación principal, actualizarás la plantilla web templates/index.html.

Actualizar las importaciones y la inicialización

Sigue los pasos que se indican a continuación para actualizar las importaciones y, además, inicializar los recursos de la aplicación:

  1. Para las importaciones, reemplaza App Engine NDB por Cloud NDB.
  2. Junto con Cloud NDB, también importa Cloud Resource Manager.
  3. Identity Platform se basa en Firebase Auth, así que importa el SDK de Firebase Admin.
  4. Las APIs de Cloud requieren el uso de un cliente de API, así que inícialo para Cloud NDB justo debajo de inicializar Flask.

Si bien el paquete de Cloud Resource Manager se importa aquí, lo usaremos en una etapa posterior de la inicialización de la app. A continuación, se muestran las importaciones y la inicialización del módulo 20, seguidas de cómo deberían verse las secciones después de implementar los cambios anteriores:

ANTES:

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

app = Flask(__name__)

DESPUÉS:

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()

Asistencia para usuarios administradores de App Engine

Hay dos componentes para agregar a la app que admiten el reconocimiento de usuarios administradores:

  • _get_gae_admins(): Recopila un conjunto de usuarios administradores. llamado una vez y guardó
  • is_admin(): Verifica si un usuario que accedió es un usuario administrador. con cualquier sesión de usuario

La función de utilidad, _get_gae_admins(), llama a la API de Resource Manager para recuperar la política de permiso de Cloud IAM actual. La política de permisos define y aplica qué roles se otorgan a qué principales (usuarios humanos, cuentas de servicio, etcétera). La configuración incluye lo siguiente:

  • Recuperando el ID del proyecto de Cloud (PROJ_ID)
  • Crea un cliente de la API de Resource Manager (rm_client)
  • Crear un conjunto (de solo lectura) de funciones de administrador de App Engine (_TARGETS)

Resource Manager requiere el ID del proyecto de Cloud, así que importa google.auth.default() y llama a esa función para obtener el ID del proyecto. Esa llamada incluye un parámetro que parece una URL, pero es un alcance de permiso OAuth2. Cuando se ejecutan apps en la nube, por ejemplo, en una VM de Compute Engine o en una app de App Engine, se proporciona una cuenta de servicio predeterminada con amplios privilegios. De acuerdo con la práctica recomendada de privilegio mínimo, te sugerimos que crees tus propias cuentas de servicio administradas por el usuario.

Para las llamadas a la API, es mejor reducir aún el alcance de tus apps al nivel mínimo necesario para funcionar correctamente. La llamada a la API de Resource Manager que realizaremos es get_iam_policy(), que necesita uno de los siguientes permisos para funcionar:

  • 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

La app de ejemplo solo necesita acceso de solo lectura a la política allow-policy. No modifica la política ni necesita acceso a todo el proyecto. Eso significa que la app no necesita ninguno de los tres primeros permisos necesarios. El último es todo lo que se requiere, y eso es lo que implementaremos para la app de ejemplo.

El cuerpo principal de la función crea un conjunto vacío de usuarios administradores (admins), recupera el allow_policy a través de get_iam_policy() y recorre todas sus vinculaciones en busca de roles de administrador de App Engine específicamente:

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

Por cada rol objetivo encontrado, se recopilan los usuarios que pertenecen a ese rol y se los agrega al conjunto general de usuarios administradores. Termina mostrando todos los usuarios administradores encontrados y almacenados en caché como una constante (_ADMINS) durante la vida útil de esta instancia de App Engine. En breve, veremos esa llamada.

Agrega la siguiente definición de función _get_gae_admins() a main.py justo debajo para crear una instancia del cliente de la API de 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

Cuando los usuarios acceden a la app, ocurre lo siguiente:

  1. Se realiza una verificación rápida a partir de la plantilla web después de que un usuario accede a Firebase.
  2. Cuando cambia el estado de autenticación en la plantilla, se realiza una llamada fetch() de estilo Ajax a /is_admin cuyo controlador es la siguiente función, is_admin().
  3. El token de ID de Firebase se pasa en el cuerpo de POST a is_admin(), que lo quita de los encabezados y llama al SDK de Firebase Admin para validarlo. Si es un usuario válido, extrae su dirección de correo electrónico y verifica si es un usuario administrador.
  4. El resultado booleano se devuelve a la plantilla como un número 200 correcto.

Agrega is_admin() a main.py justo después de _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

Todo el código de ambas funciones es necesario para replicar la funcionalidad disponible en el servicio de usuarios, específicamente su función is_current_user_admin(). Esta llamada a función del módulo 20 se encargó de todo el trabajo pesado, a diferencia del módulo 21, en el que implementamos una solución de reemplazo. La buena noticia es que la app ya no depende de un servicio exclusivo de App Engine, lo que significa que puedes mover tus apps a Cloud Run o a otros servicios. Además, puedes cambiar la definición de “usuario administrador” para tus propias apps con solo cambiar a los roles deseados en _TARGETS, mientras que el servicio de usuarios está codificado para los roles de administrador de App Engine.

Inicializa Firebase Auth y almacena en caché los usuarios administradores de App Engine.

Podríamos haber inicializado Firebase Auth en la parte superior, cerca del mismo punto en el que se inicializa la app de Flask y se crea el cliente de la API de Cloud NDB, pero no fue necesario hacerlo hasta que se definió todo el código de administrador, que es donde estamos ahora. De manera similar, ahora que se definió _get_gae_admins(), llámalo para almacenar en caché la lista de usuarios administradores.

Agrega estas líneas justo debajo del cuerpo de la función de is_admin():

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

Visitar las actualizaciones de modelos de datos

El modelo de datos de Visit no cambia. El acceso a Datastore requiere el uso explícito de ds_client.context(), el administrador de contexto del cliente de la API de Cloud NDB. En el código, esto significa que unes las llamadas de Datastore en store_visit() y fetch_visits() dentro de los bloques with de Python. Esta actualización es idéntica al Módulo 2. Realiza los cambios de la siguiente manera:

ANTES:

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)

DESPUÉS:

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)

Mueve la lógica de acceso del usuario a la plantilla web

El servicio de usuarios de App Engine funciona del servidor, mientras que Firebase Auth y Cloud Identity Platform son principalmente del cliente. Como resultado, gran parte del código de administración de usuarios de la app del Módulo 20 se traslada a la plantilla web del Módulo 21.

En main.py, el contexto web pasa cinco datos esenciales a la plantilla. Los primeros cuatro están vinculados a la administración de usuarios y difieren en función de si el usuario accedió o no:

  • who: Es el correo electrónico del usuario si accedió a su cuenta o es el usuario de otra manera.
  • admin: Es la insignia (administrador) si el usuario que accedió es un administrador.
  • sign: Mostrar el botón Acceder o Salir
  • link: Vínculos de acceso o salida cuando se hace clic en un botón
  • visits: visitas más recientes

ANTES:

@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)

Toda la administración de usuarios se trasladará a la plantilla web, por lo que solo quedan las visitas para que el controlador principal vuelva a lo que teníamos en la app del Módulo 1:

DESPUÉS:

@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)

Actualizar plantilla web

¿Cómo se ven todas las actualizaciones de la sección anterior en la plantilla? Principalmente, se traslada la administración de usuarios de la app a Firebase Auth que se ejecuta en la plantilla y una portabilidad parcial de todo el código que trasladamos a JavaScript. main.py se redujo bastante, por lo que se espera un crecimiento similar en templates/index.html.

ANTES:

<!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>

Reemplaza toda la plantilla web con el siguiente contenido:

DESPUÉS:

<!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>

Hay muchos componentes en este cuerpo HTML, así que vamos a analizarlos una parte a la vez.

Importaciones de Firebase

Mientras se encuentra en el encabezado del documento HTML, una vez que pase el título de la página, importa los componentes de Firebase necesarios. Los componentes de Firebase ahora están divididos en varios módulos para mayor eficiencia. El código para inicializar Firebase se importa desde el módulo principal de la app de Firebase, mientras que las funciones que administran la autenticación de Firebase, Google como proveedor de autenticación, el acceso y la salida, y el estado de autenticación cambian la “devolución de llamada”. se importan desde el módulo de 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";

Configuración de Firebase

Antes, durante la parte de configuración de Identity Platform de este instructivo, guardaste apiKey y authDomain del diálogo Detalles de configuración de la aplicación. Agrega esos valores a la variable firebaseConfig en la siguiente sección. Puedes encontrar un vínculo con instrucciones más detalladas en los comentarios:

// 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",
};

Inicialización de Firebase

En la siguiente sección, se inicializa Firebase con esta información de configuración.

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

Esto establece la capacidad de usar Google como proveedor de autenticación y proporciona una opción marcada para mostrar el selector de cuentas, incluso si solo hay una Cuenta de Google registrada en la sesión del navegador. En otras palabras, si tienes varias cuentas, verás este "selector de cuentas". como se esperaba: a38369389b7c4c7e.png Sin embargo, si solo hay un usuario en la sesión, el proceso de acceso se completa automáticamente sin ninguna interacción del usuario. (Aparecerá la ventana emergente y luego desaparecerá). Puedes hacer que el diálogo del selector de cuentas se muestre para un usuario (en lugar de acceder de inmediato a la aplicación). Para ello, quita el comentario de la línea del parámetro personalizado. Si está habilitada, incluso los accesos de un solo usuario muestran el selector de cuentas: b75624cb68d94557.png

Funciones de acceso y salida

Las siguientes líneas de código conforman las funciones para los clics en los botones de acceso o cierre de sesión:

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

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

Acciones de acceso y salida

La última sección importante de este bloque <script> es la función a la que se llama para cada cambio de Auth (acceder o salir).

// 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>

El código del módulo 20 que determina si se debe enviar a un usuario que accedió el contexto de la plantilla en comparación con “el usuario salió” del contexto se traslada aquí. El condicional de la parte superior genera true si el usuario accedió correctamente, lo que activa las siguientes acciones:

  1. Se configuró la dirección de correo electrónico del usuario para su visualización.
  2. El botón Acceder cambia a Salir.
  3. Se realiza una llamada de estilo Ajax a /is_admin para determinar si se muestra la insignia de usuario administrador de (admin).

Cuando el usuario sale de su cuenta, se ejecuta la cláusula else para restablecer toda la información del usuario:

  1. Nombre de usuario configurado como user
  2. Se quitó cualquier insignia de administrador
  3. El botón Salir cambió de nuevo a Acceder

Variables de plantilla

Una vez finalizada la sección del encabezado, el cuerpo principal comienza con las variables de la plantilla que se reemplazan por elementos HTML que cambian según sea necesario:

  1. Nombre de usuario visible
  2. Insignia de administrador de (admin) (si corresponde)
  3. Botón Acceder o Salir
<body>
<p>
Welcome, <span id="who"></span> <span id="admin"><code>(admin)</code></span>
<button id="logbtn"></button>
</p><hr>

Visitas más recientes y variables de elementos HTML

El código de visitas más recientes no cambia, y el bloque <script> final establece las variables de los elementos HTML que cambian para acceder y salir de la lista anterior:

<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>

Con esto concluye los cambios necesarios en la aplicación y la plantilla web para cambiar de App Engine NDB y las APIs de usuarios a Cloud NDB e Identity Platform, así como para actualizar a Python 3. Felicitaciones por llegar a tu nueva app de ejemplo del Módulo 21. Nuestra versión está disponible para su revisión en la carpeta del repositorio del módulo 21b.

La siguiente parte del codelab es opcional (*) y solo para usuarios cuyas apps deben permanecer en Python 2, y te guiará a través de los pasos necesarios para llegar a una app de Python 2 Módulo 21 que funcione.

6. *Portabilidad a versiones anteriores de Python 2

Esta sección opcional está destinada a desarrolladores que realizan una migración de Identity Platform, pero que deben continuar ejecutándose en el entorno de ejecución de Python 2. Si esto no es un problema para ti, omite esta sección.

Para crear una versión de Python 2 funcional de la app del Módulo 21, necesitas lo siguiente:

  1. Requisitos del entorno de ejecución: Archivos de configuración compatibles con Python 2 y cambios necesarios en la aplicación principal para evitar incompatibilidades con Python 3
  2. Cambio menor en la biblioteca: Python 2 dejó de estar disponible antes de que se agregaran algunas funciones necesarias a la biblioteca cliente de Resource Manager. Como resultado, necesitas una forma alternativa de acceder a esa funcionalidad faltante.

Comencemos con la configuración.

Restablecer appengine_config.py

Anteriormente en este instructivo, se te indicó que borraras appengine_config.py, ya que no lo usa el entorno de ejecución de App Engine de Python 3. En el caso de Python 2, no solo se debe preservar, sino que también se debe actualizar el appengine_config.py del módulo 20 para que admita el uso de bibliotecas de terceros integradas, es decir, grpcio y setuptools. Esos paquetes son necesarios cada vez que tu aplicación de App Engine usa bibliotecas cliente de Cloud, como las de Cloud NDB y Cloud Resource Manager.

Agregarás esos paquetes a app.yaml por un momento, pero para que tu app acceda a ellos, se debe llamar a la función pkg_resources.working_set.add_entry() de setuptools. Esto permite que las bibliotecas de terceros copiadas (agrupadas automáticamente o de proveedores) instaladas en la carpeta lib puedan comunicarse con las bibliotecas integradas.

Implementa las siguientes actualizaciones en tu archivo appengine_config.py para aplicar estos cambios:

ANTES:

from google.appengine.ext import vendor

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

Este código por sí solo no es suficiente para admitir el uso de setuptools y grpcio. Necesitan algunas líneas más, así que actualiza appengine_config.py para que se vea de la siguiente manera:

DESPUÉS:

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)

Puedes encontrar más detalles sobre los cambios necesarios para admitir las bibliotecas cliente de Cloud en la documentación sobre migración de servicios en paquetes.

app.yaml

Al igual que appengine_config.py, el archivo app.yaml debe revertirse a uno compatible con Python 2. Comencemos con el módulo 20 app.yaml original:

ANTES:

runtime: python27
threadsafe: yes
api_version: 1

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

Además de setuptools y grpcio, como se mencionó anteriormente, hay una dependencia (no relacionada de forma explícita con la migración de Identity Platform) que requiere el uso de la biblioteca cliente de Cloud Storage y que necesita otro paquete integrado de terceros, ssl. Agrégalos en una nueva sección libraries y selecciona la opción “más reciente”. versiones disponibles de esos paquetes a app.yaml:

DESPUÉS:

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

En el módulo 21, agregamos Google Auth, Cloud NDB, Cloud Resource Manager y el SDK de Firebase Admin al requirements.txt de Python 3. La situación de Python 2 es más compleja:

  • La API de Resource Manager proporciona la funcionalidad de política de permisos necesaria para la app de ejemplo. Lamentablemente, esta compatibilidad aún no estaba disponible en la versión final de Python 2 de la biblioteca cliente de Cloud Resource Manager. (solo está disponible en la versión de Python 3).
  • Como resultado, se requiere una forma alternativa de acceder a esta función desde la API. La solución es utilizar la biblioteca cliente de las APIs de Google de nivel inferior para comunicarse con la API. Para cambiar a esta biblioteca cliente, reemplaza google-cloud-resource-manager con el paquete google-api-python-client de nivel inferior.
  • Debido a que Python 2 dejó de estar disponible, el gráfico de dependencias que admite el Módulo 21 requiere que ciertos paquetes se bloqueen en versiones específicas. Algunos paquetes deben llamarse incluso si no se especifican en el app.yaml de Python 3.

ANTES:

flask

A partir del requirements.txt del Módulo 20, actualízalo a lo siguiente para una app del Módulo 21 que funcione:

DESPUÉS:

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

Los números de paquete y versión se actualizarán en el repositorio a medida que cambien las dependencias, pero este app.yaml es suficiente para una app en funcionamiento en el momento en que se redactó este documento.

Otras actualizaciones de configuración

Si no borraste la carpeta lib de antes en este codelab, hazlo ahora. Con el requirements.txt recientemente actualizado, ejecuta este comando conocido para instalar los siguientes requisitos en lib:

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

Si tienes Python 2 y 3 instalados en tu sistema de desarrollo, es posible que debas usar pip2 en lugar de pip.

Modifica el código de la aplicación

Afortunadamente, la mayoría de los cambios necesarios están en los archivos de configuración. El único cambio necesario en el código de la aplicación es una actualización menor para usar la biblioteca cliente de la API de Google de nivel inferior en lugar de la biblioteca cliente de Resource Manager para acceder a la API. No hay actualizaciones necesarias para la plantilla web templates/index.html.

Actualiza las importaciones y la inicialización

Reemplaza la biblioteca cliente de Resource Manager (google.cloud.resourcemanager) por la biblioteca cliente de las APIs de Google (googleapiclient.discovery), como se ilustra a continuación:

ANTES:

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

DESPUÉS:

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

Asistencia para usuarios administradores de App Engine

Se necesitan algunos cambios en _get_gae_admins() para admitir el uso de la biblioteca cliente de nivel inferior. Primero, analicemos qué cambiará y, luego, te daremos todo el código para actualizar.

El código de Python 2 requiere el uso de las credenciales y del ID del proyecto que muestra google.auth.default(). Las credenciales no se usan en Python 3, por lo que se asignó a una variable ficticia genérica ( _). Como es necesario para la versión de Python 2, cambia el guion bajo a CREDS. Además, en lugar de crear un cliente de la API de Resource Manager, crearás un extremo de servicio de API, un concepto similar al de un cliente de API, por lo que mantendremos el mismo nombre de variable (rm_client). Una diferencia es que para crear una instancia de extremo de servicio se requieren credenciales (CREDS).

Estos cambios se reflejan en el siguiente código:

ANTES:

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

DESPUÉS:

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)

La otra diferencia es que la biblioteca cliente de Resource Manager muestra objetos allow-policy que usan notación de atributos con puntos, mientras que la biblioteca cliente de nivel inferior muestra diccionarios de Python en los que se usan corchetes ( [ ]). Por ejemplo, usa binding.role para la biblioteca cliente de Resource Manager frente a binding['role'] para la biblioteca de nivel inferior. El primero también usa “separado por guion bajo” en comparación con la biblioteca de nivel inferior que prefiere "CamelCased" más una forma ligeramente diferente de pasar parámetros de API.

Estas diferencias de uso se muestran a continuación:

ANTES:

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)

DESPUÉS:

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'])

Después de unir todos estos cambios, reemplaza el _get_gae_admins() de Python 3 por esta versión equivalente de Python 2:

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 función is_admin() no requiere ninguna actualización porque se basa en _get_gae_admins(), que ya se actualizó.

Con esto concluye los cambios necesarios para aplicar portabilidad a versiones anteriores de la app del módulo 21 de Python 3 a Python 2. Felicitaciones por llegar a la app de ejemplo actualizada del Módulo 21. Encontrarás todo el código en la carpeta del repositorio del módulo 21a.

7. Resumen/limpieza

Los últimos pasos del codelab son garantizar que las principales (usuarios o cuentas de servicio) que ejecuten esta app tengan los permisos adecuados para hacerlo. Luego, implementa la app para confirmar que funcione según lo previsto y que los cambios se reflejen en el resultado.

Capacidad de leer políticas de permisos de IAM

Anteriormente, te presentamos las cuatro funciones necesarias para que te reconozcan como usuario administrador de App Engine, pero ahora hay una quinta con la que debes familiarizarte:

  • roles/viewer
  • roles/editor
  • roles/owner
  • roles/appengine.appAdmin
  • roles/resourcemanager.projectIamAdmin (para las principales que acceden a la política de permisos de IAM)

El rol roles/resourcemanager.projectIamAdmin permite a las principales determinar si un usuario final es miembro de alguno de los roles de administrador de App Engine. Sin la membresía en roles/resourcemanager.projectIamAdmin, fallarán las llamadas a la API de Cloud Resource Manager para obtener la política de permiso.

No es necesario que realices ninguna acción explícita aquí, ya que la app se ejecutará con la cuenta de servicio predeterminada de App Engine, a la que se le otorga automáticamente la membresía en este rol. Incluso si usas la cuenta de servicio predeterminada durante la fase de desarrollo, te recomendamos que crees y uses una cuenta de servicio administrada por el usuario con los permisos mínimos necesarios para que la app funcione correctamente. Para otorgar membresía a una cuenta de servicio de este tipo, ejecuta el siguiente 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 es el ID del proyecto de Cloud y USR_MGD_SVC_ACCT@PROJ_ID.iam.gserviceaccount.com es la cuenta de servicio administrada por el usuario que creas para tu app. Este comando genera la política de IAM actualizada para tu proyecto, en la que puedes confirmar que la cuenta de servicio tiene membresía de roles/resourcemanager.projectIamAdmin. Para obtener más información, consulta la documentación de referencia. Para repetir, no es necesario que emitas ese comando en este codelab, pero guárdalo como referencia para modernizar tus propias apps.

Implementa y verifica la aplicación

Sube la app a la nube con el comando gcloud app deploy estándar. Una vez implementado, deberías ver una funcionalidad casi idéntica a la de la app del Módulo 20, con la excepción de que reemplazaste correctamente el servicio Usuarios de App Engine con Cloud Identity Platform (y Firebase Auth) para la administración de usuarios:

3a83ae745121d70.png

Una diferencia que notarás en comparación con el Módulo 20 es que, si haces clic en el panel de acceso, se mostrará una ventana emergente en lugar de un redireccionamiento, como se muestra en algunas de las siguientes capturas de pantalla. Sin embargo, al igual que el módulo 20, el comportamiento difiere un poco según la cantidad de Cuentas de Google que se hayan registrado en el navegador.

Si no hay usuarios registrados en el navegador o solo un usuario que no haya accedido aún, aparecerá una ventana emergente genérica de Acceso con Google:

8437f5f3d489a942.png

Si un solo usuario está registrado en tu navegador, pero accede desde otro lugar, no aparecerá ningún diálogo (o aparecerá y se cerrará de inmediato), y la aplicación entra en un estado de acceso (muestra el correo electrónico del usuario y el botón Salir).

Es posible que algunos desarrolladores deseen proporcionar un selector de cuentas, incluso para un solo usuario:

b75624cb68d94557.png

Para implementar esto, quita el comentario de la línea provider.setCustomParameters({prompt: 'select_account'}); en la plantilla web como se describió anteriormente.

Si hay varios usuarios, aparecerá el diálogo del selector de cuentas (consulta a continuación). Si aún no accedió, se le preguntará al usuario. Si ya accediste, la ventana emergente desaparece y la app entra en un estado de acceso.

c454455b6020d5e4.png

El estado de acceso del Módulo 21 es idéntico al de la interfaz de usuario del Módulo 20:

49ebe4dcc1eff11f.png

Lo mismo sucede cuando accede un usuario administrador:

44302f35b39856eb.png

A diferencia del módulo 21, el módulo 20 siempre accede a la lógica para el contenido de la plantilla web desde la app (código del servidor). Una falla del Módulo 20 es que se registra una visita cuando el usuario final accede a la app por primera vez y otra se registra cuando el usuario accede.

Para el módulo 21, la lógica de acceso se lleva a cabo solo en la plantilla web (código del cliente). No es necesario realizar un viaje del servidor para determinar qué contenido mostrar. La única llamada que se hace al servidor es la verificación de los usuarios administradores después de que accede un usuario final. Esto significa que los accesos y las salidas no registran visitas adicionales, de modo que la lista de visitas más recientes se mantiene igual para las acciones de administración de usuarios. Observa que las capturas de pantalla anteriores muestran el mismo conjunto de cuatro visitas a través de múltiples accesos de usuario.

Las capturas de pantalla del módulo 20 demuestran el “error de visita doble” al comienzo de este codelab. Se muestran registros de visitas separados para cada acción de acceso o salida. Revisa las marcas de tiempo de la visita más reciente en cada captura de pantalla que muestren el orden cronológico.

Limpia

General

Si ya terminaste, te recomendamos que inhabilites la aplicación de App Engine para evitar que se te facture. Sin embargo, si deseas probar o experimentar un poco más, la plataforma de App Engine tiene una cuota gratuita y, siempre y cuando no superes ese nivel de uso, no se te debería cobrar. Eso es para procesamiento, pero es posible que también se apliquen cargos por servicios relevantes de App Engine, así que consulta la página de precios para obtener más información. Si esta migración implica otros servicios de Cloud, estos se facturan por separado. En ambos casos, si corresponde, consulta la sección "Específico de este codelab" a continuación.

Para una divulgación completa, la implementación en una plataforma de procesamiento sin servidores de Google Cloud, como App Engine, genera costos menores de compilación y almacenamiento. Cloud Build tiene su propia cuota gratuita, al igual que Cloud Storage. El almacenamiento de esa imagen ocupa parte de esa cuota. Sin embargo, es posible que vivas en una región que no cuenta con ese nivel gratuito, así que ten en cuenta el uso que haces del almacenamiento para minimizar posibles costos. “Carpetas” específicas de Cloud Storage que debes revisar incluyen

  • 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
  • Los vínculos de almacenamiento anteriores dependen de tu PROJECT_ID y tu LOC; por ejemplo, "us" si tu app está alojada en EE.UU.

Por otro lado, si no vas a continuar con esta aplicación o algún otro codelab de migración relacionado y quieres borrar todo por completo, cierra tu proyecto.

Información específica de este codelab

Los servicios que se indican a continuación son exclusivos de este codelab. Consulta la documentación de cada producto para obtener más información:

Próximos pasos

Más allá de este instructivo, otros módulos de migración que se enfocan en alejarse de los servicios en paquetes heredados que se deben considerar incluyen los siguientes:

App Engine ya no es la única plataforma sin servidores en Google Cloud. Si tienes una aplicación pequeña de App Engine o una con funcionalidad limitada y deseas convertirla en un microservicio independiente, o si deseas dividir una aplicación monolítica en varios componentes reutilizables, estas son buenas razones para considerar cambiar a Cloud Functions. Si la creación de contenedores se volvió parte del flujo de trabajo de desarrollo de tu aplicación, en especial si consta de una canalización de CI/CD (integración continua/entrega o implementación continuas), considera migrar a Cloud Run. Estas situaciones se abordan en los siguientes módulos:

  • Migra de App Engine a Cloud Functions: consulta el Módulo 11.
  • Migra de App Engine a Cloud Run. Consulta el Módulo 4 para alojar tu app en contenedores con Docker, o el Módulo 5 para hacerlo sin contenedores, conocimiento sobre Docker ni Dockerfile.

Cambiar a otra plataforma sin servidores es opcional, y te recomendamos que consideres las mejores opciones para tus apps y casos de uso antes de realizar cualquier cambio.

Independientemente del módulo de migración que consideres a continuación, puedes acceder a todo el contenido de Serverless Migration Station (codelabs, videos, código fuente [si está disponible]) a través de su repositorio de código abierto. El README del repositorio también proporciona orientación sobre qué migraciones considerar y cualquier "orden" relevante. de los módulos de migración.

8. Recursos adicionales

A continuación, se incluyen recursos adicionales para los desarrolladores que exploran este módulo o los módulos de migración relacionados en mayor detalle. A continuación, puedes proporcionar comentarios sobre este contenido, encontrar vínculos al código y varios documentos que te pueden resultar útiles.

Problemas o comentarios sobre Codelabs

Si encuentras algún problema con este Codelab, primero busca el problema antes de enviarlo. Vínculos para buscar y crear problemas nuevos:

Recursos de migración

En la siguiente tabla, encontrarás los vínculos a las carpetas de repo del Módulo 20 (COMENZAR) y Módulo 21 (FINALIZAR).

Codelab

Python 2

Python 3

Módulo 20

código

(n/a)

Módulo 21 (este codelab)

código

código

Referencias en línea

A continuación, hay recursos relevantes para este instructivo:

Cloud Identity Platform y Cloud Marketplace

Cloud Resource Manager, Cloud IAM y SDK de Firebase Admin

Usuarios de App Engine, App Engine NDB, Cloud NDB y Cloud Datastore

Otras referencias del módulo de migración

Migración de App Engine

Plataforma de App Engine

SDK de Cloud

Otra información de Cloud

Videos

Licencia

Este trabajo cuenta con una licencia Atribución 2.0 Genérica de Creative Commons.