Migrar do serviço de usuários do App Engine para o Cloud Identity Platform (módulo 21)

1. Visão geral

A série de codelabs da Serverless Migration Station (tutoriais práticos e autoguiados) e os vídeos relacionados têm como objetivo ajudar os desenvolvedores sem servidor do Google Cloud a modernizar os aplicativos orientando-os em uma ou mais migrações, principalmente a migração de serviços legados. Isso torna seus apps mais portáteis e oferece mais opções e flexibilidade, permitindo que você se integre e acesse uma variedade maior de produtos do Cloud e faça upgrade mais fácil para versões de linguagem mais recentes. Embora o foco inicial seja nos primeiros usuários do Cloud, principalmente desenvolvedores do App Engine (ambiente padrão), esta série é ampla o suficiente para incluir outras plataformas sem servidor, como o Cloud Functions e o Cloud Run, ou em outro lugar, se aplicável.

O objetivo deste codelab é mostrar aos desenvolvedores do App Engine em Python 2 como migrar da API/serviço de usuários do App Engine para a Cloud Identity Platform (GCIP). Há também uma migração implícita do App Engine NDB para o Cloud NDB para acesso ao Datastore (abordado principalmente no Módulo 2 de migração), além de um upgrade para o Python 3.

O módulo 20 mostra como adicionar o uso da API Users ao app de exemplo do módulo 1. Neste módulo, você vai pegar o app concluído do módulo 20 e migrar o uso dele para o Cloud Identity Platform.

Você vai aprender a

  • Substitua o uso do serviço Usuários do App Engine pelo Cloud Identity Platform
  • Substitua o uso do NDB do App Engine pelo NDB do Cloud (consulte também o Módulo 2).
  • Configurar diferentes provedores de identidade de autenticação usando o Firebase Auth
  • Usar a API Resource Manager para receber informações do IAM do projeto
  • Usar o SDK Admin do Firebase para receber informações do usuário
  • Portar o aplicativo de amostra para o Python 3

O que é necessário

Pesquisa

Como você usará este tutorial?

Apenas leitura Leitura e exercícios

Como você classificaria sua experiência com Python?

Iniciante Intermediário Proficiente

Como você classificaria sua experiência de uso dos serviços do Google Cloud?

Iniciante Intermediário Proficiente

2. Contexto

O serviço Usuários do App Engine é um sistema de autenticação de usuários para uso por apps do App Engine. Ele oferece o Login do Google como provedor de identidade, links convenientes de login e logout para uso em apps e suporte ao conceito de usuários administradores e funcionalidades exclusivas para administradores. Para melhorar a portabilidade do aplicativo, o Google Cloud recomenda migrar dos serviços agrupados legados do App Engine para os serviços autônomos do Cloud, por exemplo, do serviço Usuários para a Cloud Identity Platform, entre outros.

O Identity Platform é baseado no Firebase Authentication e adiciona vários recursos empresariais, incluindo autenticação multifator, suporte a OIDC e SSO SAML, multilocação, SLA de 99, 95% e muito mais. Essas diferenças também são destacadas na página de comparação de produtos do Identity Platform e do Firebase Authentication. Ambos os produtos têm muito mais recursos do que a funcionalidade fornecida pelo serviço Usuários.

Este codelab do módulo 21 demonstra como mudar a autenticação de usuário do app do serviço Usuários para os recursos da Identity Platform que mais se assemelham à funcionalidade demonstrada no módulo 20. O Módulo 21 também apresenta uma migração do NDB do App Engine para o Cloud NDB para acesso ao Datastore, repetindo a migração do Módulo 2.

Embora o código do Módulo 20 seja "anunciado" como um app de exemplo do Python 2, a origem em si é compatível com Python 2 e 3, e permanece assim mesmo após a migração para o Identity Platform (e o Cloud NDB) aqui no Módulo 21. É possível continuar usando o serviço Usuários ao fazer upgrade para o Python 3, já que a migração para o Identity Platform é opcional. Consulte o codelab do módulo 17 e o vídeo para saber como continuar usando os serviços agrupados ao fazer upgrade para ambientes de execução de segunda geração, como o Python 3.

Este tutorial inclui as seguintes etapas:

  1. Configuração/Pré-trabalho
  2. Atualizar a configuração
  3. Modificar o código do aplicativo

3. Configuração/Pré-trabalho

Esta seção explica como:

  1. Configurar seu projeto do Cloud
  2. Receber app de amostra do valor de referência
  3. (Re)Implantar e validar o app de referência
  4. Ativar novos serviços/APIs do Google Cloud

Essas etapas garantem que você está começando com um código funcional pronto para migração para serviços autônomos do Cloud.

1. Configurar projeto

Se você concluiu o codelab do Módulo 20, reutilize o mesmo projeto (e código). Se preferir, crie um novo projeto ou reutilize outro. Verifique se o projeto tem uma conta de faturamento ativa e um app do App Engine ativado. Encontre o ID do projeto e tenha ele em mãos durante este codelab. Use-o sempre que encontrar a variável PROJ_ID.

2. Receber app de amostra do valor de referência

Um dos pré-requisitos é um app do App Engine do módulo 20 em funcionamento. Por isso, conclua o codelab (recomendado; link acima) ou copie o código do módulo 20 do repositório. Independentemente de você usar o seu ou o nosso, é aqui que vamos começar ("START"). Este codelab orienta você na migração, concluindo com um código semelhante ao que está na pasta do repositório do Módulo 21 ("FINISH").

Copie a pasta do repositório do módulo 20. Ele vai ficar parecido com a saída abaixo e pode ter uma pasta lib se você fez o codelab do módulo 20:

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

3. (Re)Implantar e validar o app de referência

Siga estas etapas para implantar o app do módulo 20:

  1. Exclua a pasta lib se houver uma e execute pip install -t lib -r requirements.txt para preenchê-la novamente. Talvez seja necessário usar pip2 se você tiver o Python 2 e o 3 instalados.
  2. Verifique se você instalou e inicializou a ferramenta de linha de comando gcloud e se revisou o uso dela.
  3. Se você não quiser inserir seu PROJ_ID com cada comando gcloud emitido, defina primeiro o projeto na nuvem com gcloud config set project PROJ_ID.
  4. Implante o app de exemplo com gcloud app deploy
  5. Confirme se o app está funcionando como esperado e sem erros. Se você concluiu o codelab do módulo 20, o app mostra as informações de login do usuário (e-mail, possível "selo de administrador" e botão de login/logout) na parte de cima, junto com as visitas mais recentes (ilustradas abaixo).

907e64c19ef964f8.png

Ao fazer login como um usuário comum, o endereço de e-mail dele é exibido, e o botão "Login" muda para "Logout":

ad7b59916b69a035.png

Ao fazer login como um usuário administrador, o endereço de e-mail dele é exibido com "(admin)" ao lado:

867bcb3334149e4.png

4. Ativar novas APIs/serviços do Cloud

Introdução

O app do módulo 20 usa as APIs NDB e Users do App Engine, serviços em pacote que não exigem configuração adicional. No entanto, os serviços independentes do Cloud exigem. O app atualizado vai usar a Cloud Identity Platform e o Cloud Datastore (pela biblioteca de cliente do Cloud NDB). Além disso, nossa necessidade de determinar os usuários administradores do App Engine também exige o uso da API Resource Manager do Cloud.

Custo

  • O App Engine e o Cloud Datastore têm cotas do nível "Sempre sem custo financeiro". Se você não ultrapassar esses limites, não vai gerar cobranças ao concluir este tutorial. Consulte também as páginas de preços do App Engine e do Cloud Datastore para mais detalhes.
  • O uso da plataforma Cloud Identity é cobrado dependendo do número de usuários ativos por mês (MAUs) ou verificações de autenticação. Alguma versão "sem custo financeiro" está disponível para cada modelo de uso. Consulte a página de preços para mais detalhes. Além disso, embora o App Engine e o Cloud Datastore exijam faturamento, o uso do GCIP por si só não exige a ativação do faturamento, desde que você não exceda as cotas diárias sem instrumentação. Considere isso para projetos do Cloud que não envolvem APIs/serviços do Cloud que exigem faturamento.
  • O uso da API Resource Manager é sem custo financeiro na maior parte, conforme a página de preços.

Os usuários ativam as APIs do Cloud no Console do Cloud ou na linha de comando (com o comando gcloud, parte do SDK Cloud), dependendo da preferência. Vamos começar com as APIs Cloud Datastore e Cloud Resource Manager.

No Console do Cloud

Acesse a página da biblioteca do API Manager (para o projeto correto) no console do Cloud e pesquise uma API usando a barra de pesquisa. c7a740304e9d35b.png

Ative estas APIs:

Encontre e clique no botão Ativar para cada API separadamente. Talvez seja necessário informar dados de faturamento. Por exemplo, esta é a página da API Resource Manager:

fc7bd8f4c49d12e5.png

O botão muda para "Gerenciar" quando é ativado (geralmente após alguns segundos):

8eca12d6cc7b45b0.png

Ative o Cloud Datastore da mesma forma:

83811599b110e46b.png

Na linha de comando

Embora seja visualmente informativo ativar APIs no console, algumas pessoas preferem a linha de comando. Além disso, você pode ativar quantas APIs quiser de uma só vez. Execute este comando para ativar as APIs Cloud Datastore e Cloud Resource Manager e aguarde a conclusão da operação, conforme ilustrado aqui:

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

Talvez seja necessário inserir informações de faturamento.

Os "URLs" de cada API usada no comando acima são chamados de nomes de serviço da API e podem ser encontrados na parte de baixo da página da biblioteca de cada API. Se quiser ativar outras APIs do Cloud para seus próprios apps, encontre os nomes de serviço nas páginas de API correspondentes. Esse comando lista todos os nomes de serviços das APIs que podem ser ativadas:

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

No console do Cloud ou na linha de comando, depois de concluir as etapas acima, nossa amostra poderá acessar essas APIs. As próximas etapas são ativar o Cloud Identity Platform e fazer as mudanças necessárias no código.

Ativar e configurar o Cloud Identity Platform (somente no console do Cloud)

A Cloud Identity Platform é um serviço do Marketplace porque se conecta ou depende de um recurso fora do Google Cloud, como o Firebase Authentication. No momento, só é possível ativar os serviços do Marketplace no console do Cloud. Siga as etapas abaixo:

  1. Acesse a página do Cloud Identity Platform no Cloud Marketplace e clique no botão Ativar. Faça upgrade do Firebase Authentication se solicitado. Isso desbloqueia outros recursos, como os descritos anteriormente na seção Segundo plano. Esta é a página do Marketplace com o botão Ativar em destaque: 28475f1c9b29de69.png
  2. Depois que o Identity Platform for ativado, você poderá acessar automaticamente a página Provedores de identidade. Caso contrário, use este link para acessar. fc2d92d42a5d1dd7.png
  3. Ative o provedor do Google Auth. Se nenhum provedor tiver sido configurado, clique em Adicionar um provedor e selecione Google. Quando você voltar a essa tela, a entrada Google estará ativada. O Google é o único provedor de autenticação que usamos neste tutorial para espelhar o serviço Usuários do App Engine como um serviço leve de Login do Google. Nos seus próprios apps, é possível ativar outros provedores de autenticação.
  4. Depois de selecionar e configurar o Google e outros provedores de autenticação desejados, clique em Detalhes da configuração do aplicativo e, na janela de diálogo que aparecer, copie apiKey e authDomain no objeto config na guia "Web", salvando os dois em um lugar seguro. Por que não copiar tudo? O snippet nesta caixa de diálogo é codificado e desatualizado. Portanto, salve apenas as partes mais importantes e use-as no nosso código com mais uso simultâneo do Firebase Auth. Depois de copiar os valores e salvá-los em um lugar seguro, clique no botão Fechar para concluir toda a configuração necessária. bbb09dcdd9be538e.png

4. Atualizar a configuração

As atualizações na configuração incluem a mudança de vários arquivos de configuração e a criação do equivalente ao App Engine, mas no ecossistema da Cloud Identity Platform.

appengine_config.py

  • Se estiver fazendo upgrade para o Python 3, exclua appengine_config.py
  • Se você planeja modernizar para o Identity Platform, mas permanecer no Python 2, não exclua o arquivo. Em vez disso, vamos atualizar mais tarde durante o backport do Python 2.

requirements.txt

O arquivo requirements.txt do Módulo 20 listava apenas o Flask. Para o módulo 21, adicione os seguintes pacotes:

O conteúdo de requirements.txt agora vai ficar assim:

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

app.yaml

  • Fazer upgrade para o Python 3 significa simplificar o arquivo app.yaml. Remova tudo, exceto a diretiva de ambiente de execução, e defina uma versão compatível do Python 3. O exemplo usa a versão 3.10.
  • Se você vai continuar usando o Python 2, não faça nada por enquanto.

ANTES:

runtime: python27
threadsafe: yes
api_version: 1

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

O app de exemplo do módulo 20 não tem gerenciadores de arquivos estáticos. Se seus apps fizerem isso, deixe-os intactos. Se quiser, remova todos os manipuladores de script ou deixe-os como referência, desde que você mude os identificadores para auto, conforme descrito no guia de migração do app.yaml. Com essas mudanças, o app.yaml atualizado para Python 3 é simplificado para:

AFTER:

runtime: python310

Outras atualizações de configuração

Se você vai continuar usando o Python 2 ou migrar para o Python 3, exclua a pasta lib.

5. Modificar o código do aplicativo

Esta seção apresenta atualizações no arquivo principal do aplicativo, main.py, substituindo o uso do serviço Usuários do App Engine pela Cloud Identity Platform. Depois de atualizar o aplicativo principal, atualize o modelo da Web, templates/index.html.

Atualizar importações e inicialização

Siga as etapas abaixo para atualizar as importações e inicializar os recursos do aplicativo:

  1. Para as importações, substitua o NDB do App Engine pelo NDB do Cloud.
  2. Além do Cloud NDB, importe também o Cloud Resource Manager.
  3. O Identity Platform é baseado no Firebase Auth. Portanto, importe o SDK Admin do Firebase.
  4. As APIs do Cloud exigem o uso de um cliente de API. Portanto, inicie-o para o Cloud NDB logo abaixo da inicialização do Flask.

Embora o pacote do Cloud Resource Manager seja importado aqui, vamos usá-lo em uma etapa posterior na inicialização do app. Confira abaixo as importações e a inicialização do módulo 20, seguidas de como as seções devem ficar após a implementação das mudanças acima:

ANTES:

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

app = Flask(__name__)

AFTER:

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

Suporte para usuários administradores do App Engine

Há dois componentes para adicionar ao app que oferecem suporte ao reconhecimento de usuários administradores:

  • _get_gae_admins(): reúne um conjunto de usuários administradores. É chamado uma vez e salvo.
  • is_admin(): verifica se o usuário conectado é um administrador. É chamado em qualquer login de usuário.

A função utilitária, _get_gae_admins(), chama a API Resource Manager para buscar a política de permissão do Cloud IAM atual. A política de permissão define e aplica quais papéis são concedidos a quais principais (usuários humanos, contas de serviço etc.). A configuração inclui:

  • Como buscar o ID do projeto na nuvem (PROJ_ID)
  • Como criar um cliente da API Resource Manager (rm_client)
  • Criar um conjunto (somente leitura) de papéis de administrador do App Engine (_TARGETS)

O Resource Manager exige o ID do projeto na nuvem. Portanto, importe google.auth.default() e chame essa função para receber o ID do projeto. Essa chamada tem um parâmetro que parece um URL, mas é um escopo de permissão OAuth2. Ao executar apps na nuvem, por exemplo, em uma VM do Compute Engine ou um app do App Engine, uma conta de serviço padrão é fornecida com privilégios amplos. De acordo com a prática recomendada de privilégio mínimo, recomendamos que você crie suas próprias contas de serviço gerenciadas pelo usuário.

Para chamadas de API, é melhor reduzir ainda mais o escopo dos apps ao nível mínimo necessário para funcionar corretamente. A chamada de API Resource Manager que vamos fazer é get_iam_policy(), que precisa de um dos seguintes escopos para operar:

  • 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

O app de exemplo só precisa de acesso somente leitura à política de permissão. Ele não modifica a política nem precisa de acesso a todo o projeto. Isso significa que o app não precisa de nenhuma das três primeiras permissões. A última é tudo o que é necessário, e é o que estamos implementando para o app de exemplo.

O corpo principal da função cria um conjunto vazio de usuários administradores (admins), busca o allow_policy usando get_iam_policy() e passa por todas as vinculações dele procurando especificamente funções de administrador do App Engine:

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

Para cada função de destino encontrada, ele reúne quais usuários pertencem a essa função, adicionando-os ao conjunto geral de usuários administradores. Ele termina retornando todos os usuários administradores encontrados e armazenados em cache como uma constante (_ADMINS) durante o ciclo de vida dessa instância do App Engine. Vamos ver essa chamada em breve.

Adicione a seguinte definição de função _get_gae_admins() a main.py logo abaixo da instanciação do cliente da 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 os usuários fazem login no app, acontece o seguinte:

  1. Uma verificação rápida é feita no modelo da Web depois que um usuário faz login no Firebase.
  2. Quando o estado de autenticação muda no modelo, uma chamada fetch() no estilo Ajax é feita para /is_admin, cujo manipulador é a próxima função, is_admin().
  3. O token de ID do Firebase é transmitido no corpo POST para is_admin(), que o extrai dos cabeçalhos e chama o SDK Admin do Firebase para validá-lo. Se for um usuário válido, extraia o endereço de e-mail dele e verifique se é um administrador.
  4. O resultado booleano é retornado ao modelo como um 200 bem-sucedido.

Adicione is_admin() a main.py logo após _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 o código das duas funções é necessário para replicar a funcionalidade disponível no serviço Usuários, especificamente a função is_current_user_admin(). Essa chamada de função no Módulo 20 fez todo o trabalho pesado, ao contrário do Módulo 21, em que implementamos uma solução de substituição. A boa notícia é que o app não depende mais de um serviço exclusivo do App Engine, o que significa que você pode mover seus apps para o Cloud Run ou outros serviços. Além disso, você também pode mudar a definição de "usuário administrador" para seus próprios apps apenas mudando para os papéis desejados em _TARGETS. Já o serviço Usuários é fixado no código para os papéis de administrador do App Engine.

Inicializar o Firebase Auth e armazenar em cache os usuários administradores do App Engine

Poderíamos ter inicializado o Firebase Auth na parte de cima, perto do mesmo local em que o app Flask é inicializado e o cliente da API Cloud NDB é criado, mas não havia necessidade até que todo o código de administrador fosse definido, que é onde estamos agora. Da mesma forma, agora que _get_gae_admins() está definido, chame-o para armazenar em cache a lista de usuários administradores.

Adicione estas linhas logo abaixo do corpo da função is_admin():

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

Acessar atualizações do modelo de dados

O modelo de dados Visit não muda. O acesso ao Datastore exige o uso explícito do gerenciador de contexto do cliente da API Cloud NDB, ds_client.context(). No código, isso significa encapsular as chamadas do Datastore em store_visit() e fetch_visits() dentro de blocos with do Python. Essa atualização é idêntica ao Módulo 2. Faça as mudanças da seguinte maneira:

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)

AFTER:

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)

Mover a lógica de login do usuário para o modelo da Web

O serviço Usuários do App Engine é do lado do servidor, enquanto o Firebase Auth e o Cloud Identity Platform são predominantemente do lado do cliente. Como resultado, grande parte do código de gerenciamento de usuários no app do módulo 20 é movida para o modelo da Web do módulo 21.

Em main.py, o contexto da Web transmite cinco dados essenciais ao modelo. Os quatro primeiros listados estão vinculados ao gerenciamento de usuários e variam dependendo se o usuário fez login ou não:

  • who: e-mail do usuário se ele estiver conectado ou user caso contrário.
  • admin: selo (administrador) se o usuário conectado for um administrador
  • sign: mostra o botão Fazer login ou Sair.
  • link: links de login ou logout ao clicar em um botão
  • visits: visitas mais recentes

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)

Todo o gerenciamento de usuários está sendo movido para o modelo da Web. Assim, ficamos apenas com as visitas, trazendo o manipulador principal de volta ao que tínhamos no app do Módulo 1:

AFTER:

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

Atualizar modelo da Web

Como ficam todas as atualizações da seção anterior no modelo? Principalmente, mover o gerenciamento de usuários do app para o Firebase Auth em execução no modelo e uma porta parcial de todo o código que movemos para JavaScript. Vimos main.py diminuir bastante, então espere um crescimento semelhante em 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>

Substitua todo o modelo da Web pelo conteúdo abaixo:

AFTER:

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

Há muitos componentes neste corpo HTML, então vamos analisá-los um de cada vez.

Importações do Firebase

Ainda no cabeçalho do documento HTML, depois do título da página, importe os componentes necessários do Firebase. Os componentes do Firebase agora são divididos em vários módulos para aumentar a eficiência. O código para inicializar o Firebase é importado do módulo principal do App do Firebase, enquanto as funções que gerenciam a autenticação do Firebase, o Google como um provedor de autenticação, o login e logout e o "callback" de mudança de estado de autenticação são importados do módulo de autenticação do Firebase:

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

Configuração do Firebase

Antes, durante a parte de configuração do Identity Platform deste tutorial, você salvou o apiKey e o authDomain da caixa de diálogo Detalhes da configuração do aplicativo. Adicione esses valores à variável firebaseConfig na próxima seção. Um link com instruções mais detalhadas está disponível nos comentários:

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

Inicialização do Firebase

A próxima seção inicializa o Firebase com essas informações de configuração.

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

Isso define a capacidade de usar o Google como um provedor de autenticação e oferece uma opção comentada para mostrar o seletor de contas mesmo que haja apenas uma Conta do Google registrada na sessão do navegador. Em outras palavras, quando você tem várias contas, o "seletor de contas" aparece como esperado: a38369389b7c4c7e.png. No entanto, se houver apenas um usuário na sessão, o processo de login será concluído automaticamente sem interação do usuário. (O pop-up aparece e desaparece.) Para forçar a exibição da caixa de diálogo do seletor de contas para um usuário (em vez de fazer login imediatamente no app), remova o comentário da linha do parâmetro personalizado. Se ativado, até mesmo os logins de usuário único vão abrir o seletor de contas: b75624cb68d94557.png

Funções de login e logout

As próximas linhas de código compõem as funções para os cliques nos botões de login ou logout:

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

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

Ações de login e logout

A última seção principal neste bloco <script> é a função chamada para cada mudança de autenticação (login ou logout).

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

O código no módulo 20 que determina se um contexto de modelo "usuário conectado" ou "usuário desconectado" deve ser enviado é transferido aqui. A condição na parte de cima resulta em true se o usuário fizer login com sucesso, acionando as seguintes ações:

  1. O endereço de e-mail do usuário é definido para exibição.
  2. O botão Fazer login muda para Sair.
  3. Uma chamada no estilo Ajax para /is_admin é feita para determinar se o selo de usuário administrador (admin) precisa ser mostrado.

Quando o usuário faz logout, a cláusula else é executada para redefinir todas as informações do usuário:

  1. Nome de usuário definido como user
  2. Qualquer selo de administrador removido
  3. O botão Sair voltou a ser Fazer login

Variáveis de modelo

Depois que a seção de cabeçalho termina, o corpo principal começa com as variáveis de modelo que são substituídas por elementos HTML que mudam conforme necessário:

  1. Nome de usuário exibido
  2. Crachá de administrador do (admin) (se aplicável)
  3. Botão Fazer login ou Sair
<body>
<p>
Welcome, <span id="who"></span> <span id="admin"><code>(admin)</code></span>
<button id="logbtn"></button>
</p><hr>

Visitas mais recentes e variáveis de elementos HTML

O código das visitas mais recentes não muda, e o bloco <script> final define as variáveis dos elementos HTML que mudam para fazer login e sair, listados acima:

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

Isso conclui as mudanças necessárias no aplicativo e no modelo da Web para mudar das APIs NDB e Users do App Engine para o Cloud NDB e a Identity Platform, além de fazer upgrade para o Python 3. Parabéns por chegar ao novo app de exemplo do módulo 21. Nossa versão está disponível para revisão na pasta do repositório do módulo 21b.

A próxima parte do codelab é opcional (*) e apenas para usuários cujos apps precisam permanecer no Python 2, mostrando as etapas necessárias para chegar a um app do Módulo 21 do Python 2 em funcionamento.

6. *Backport do Python 2

Esta seção opcional é para desenvolvedores que estão fazendo uma migração do Identity Platform, mas precisam continuar executando no ambiente de execução do Python 2. Se isso não for um problema para você, pule esta seção.

Para criar uma versão funcional em Python 2 do app do módulo 21, você precisa do seguinte:

  1. Requisitos de ambiente de execução: arquivos de configuração que oferecem suporte ao Python 2 e mudanças necessárias no aplicativo principal para evitar incompatibilidades com o Python 3
  2. Mudança secundária na biblioteca:o Python 2 foi descontinuado antes que alguns recursos necessários fossem adicionados à biblioteca de cliente do Resource Manager. Por isso, você precisa de uma maneira alternativa de acessar essa funcionalidade ausente.

Vamos seguir essas etapas agora, começando pela configuração.

Restaurar appengine_config.py

Neste tutorial, você aprendeu a excluir appengine_config.py porque ele não é usado pelo ambiente de execução do App Engine em Python 3. Para o Python 2, não só é preciso preservar o módulo 20 appengine_config.py, mas também atualizá-lo para oferecer suporte ao uso de bibliotecas de terceiros integradas, ou seja, grpcio e setuptools. Esses pacotes são necessários sempre que o app do App Engine usa bibliotecas de cliente do Cloud, como as do Cloud NDB e do Cloud Resource Manager.

Você vai adicionar esses pacotes a app.yaml em breve, mas para que o app acesse eles, a função pkg_resources.working_set.add_entry() de setuptools precisa ser chamada. Isso permite que bibliotecas de terceiros copiadas (autônomos ou fornecidos) instaladas na pasta lib se comuniquem com bibliotecas integradas.

Implemente as seguintes atualizações no arquivo appengine_config.py para efetuar essas mudanças:

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)

Esse código por si só não é suficiente para oferecer suporte ao uso de setuptools e grpcio. São necessárias mais algumas linhas. Atualize appengine_config.py para que fique assim:

AFTER:

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)

Mais detalhes sobre as mudanças necessárias para oferecer suporte às bibliotecas de cliente do Cloud podem ser encontrados na documentação de migração de serviços agrupados.

app.yaml

Assim como appengine_config.py, o arquivo app.yaml precisa ser revertido para um que seja compatível com o Python 2. Vamos começar com o módulo 20 original app.yaml:

ANTES:

runtime: python27
threadsafe: yes
api_version: 1

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

Além de setuptools e grpcio, conforme mencionado anteriormente, há uma dependência (não explicitamente relacionada à migração do Identity Platform) que exige o uso da biblioteca de cliente do Cloud Storage, e ela precisa de outro pacote integrado de terceiros, o ssl. Adicione os três em uma nova seção libraries, selecionando as versões "mais recentes" disponíveis desses pacotes, para app.yaml:

AFTER:

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

No módulo 21, adicionamos Google Auth, Cloud NDB, Cloud Resource Manager e SDK Admin do Firebase ao requirements.txt do Python 3. A situação do Python 2 é mais complexa:

  • A API Resource Manager oferece a funcionalidade de política de permissão necessária para o app de exemplo. Infelizmente, esse suporte ainda não estava disponível na versão final do Python 2 da biblioteca de cliente do Cloud Resource Manager. Ele está disponível apenas na versão do Python 3.
  • Por isso, é necessário ter uma maneira alternativa de acessar esse recurso pela API. A solução é usar a biblioteca de cliente de nível inferior das APIs do Google para se comunicar com a API. Para mudar para essa biblioteca de cliente, substitua google-cloud-resource-manager pelo pacote google-api-python-client de nível mais baixo.
  • Como o Python 2 foi desativado, o gráfico de dependências que oferece suporte ao módulo 21 exige o bloqueio de determinados pacotes em versões específicas. Alguns pacotes precisam ser mencionados mesmo que não estejam especificados no app.yaml do Python 3.

ANTES:

flask

Começando com o requirements.txt do módulo 20, atualize-o para o seguinte para ter um app do módulo 21 funcional:

AFTER:

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

Os números de pacote e versão serão atualizados no repositório à medida que as dependências mudarem, mas este app.yaml é suficiente para um app funcional no momento da redação deste artigo.

Outras atualizações de configuração

Se você não tiver excluído a pasta lib no início deste codelab, faça isso agora. Com o requirements.txt recém-atualizado, execute este comando conhecido para instalar esses requisitos no lib:

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

Se você tiver o Python 2 e o 3 instalados no sistema de desenvolvimento, talvez seja necessário usar pip2 em vez de pip.

Modificar o código do aplicativo

Felizmente, a maioria das mudanças necessárias está nos arquivos de configuração. A única mudança necessária no código do aplicativo é uma pequena atualização para usar a biblioteca de cliente da API do Google de nível inferior em vez da biblioteca de cliente do Resource Manager para acessar a API. Não é necessário atualizar o modelo da Web templates/index.html.

Atualizar importações e inicialização

Substitua a biblioteca de cliente do Resource Manager (google.cloud.resourcemanager) pela biblioteca de cliente das APIs do Google (googleapiclient.discovery), conforme ilustrado abaixo:

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

AFTER:

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

Suporte para usuários administradores do App Engine

Algumas mudanças são necessárias em _get_gae_admins() para oferecer suporte ao uso da biblioteca de cliente de nível mais baixo. Vamos discutir o que está mudando primeiro e depois fornecer todo o código para atualização.

O código do Python 2 exige o uso das credenciais e do ID do projeto retornados de google.auth.default(). As credenciais não são usadas no Python 3, então foram atribuídas a uma variável genérica de sublinhado ( _ ). Como ele é necessário para a versão do Python 2, mude o sublinhado para CREDS. Além disso, em vez de criar um cliente da API Resource Manager, você vai criar um endpoint de serviço da API, semelhante em conceito a um cliente de API. Por isso, vamos manter o mesmo nome de variável (rm_client). Uma diferença é que a instanciação de um endpoint de serviço exige credenciais (CREDS).

Essas mudanças estão refletidas no código abaixo:

ANTES:

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

AFTER:

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)

Outra diferença é que a biblioteca de cliente do Resource Manager retorna objetos de política de permissão que usam a notação de atributo com pontos, enquanto a biblioteca de cliente de nível inferior retorna dicionários Python em que colchetes ( [ ] ) são usados. Por exemplo, use binding.role para a biblioteca de cliente do Resource Manager e binding['role'] para a biblioteca de nível inferior. O primeiro também usa nomes "separados_por_sublinhado" em vez da biblioteca de nível mais baixo, que prefere nomes "CamelCased" e uma maneira um pouco diferente de transmitir parâmetros da API.

Essas diferenças de uso são mostradas abaixo:

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)

AFTER:

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

Juntando todas essas mudanças, substitua o _get_gae_admins() do Python 3 por esta versão equivalente do 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

A função is_admin() não requer atualizações porque depende de _get_gae_admins(), que já foi atualizado.

Assim terminam as mudanças necessárias para fazer o backport do app do módulo 21 do Python 3 para o Python 2. Parabéns por chegar ao app de exemplo atualizado do Módulo 21! Todo o código está na pasta do repositório do módulo 21a.

7. Resumo/limpeza

As últimas etapas do codelab são garantir que os principais (usuários ou contas de serviço) que executam esse app tenham as permissões adequadas para isso. Depois, implante o app para confirmar que ele funciona como esperado e que as mudanças são refletidas na saída.

Capacidade de ler a política de permissão do IAM

Antes, apresentamos os quatro papéis necessários para ser reconhecido como um usuário administrador do App Engine, mas agora há um quinto papel para conhecer:

  • roles/viewer
  • roles/editor
  • roles/owner
  • roles/appengine.appAdmin
  • roles/resourcemanager.projectIamAdmin (para principais que acessam a política de permissão do IAM)

Com o papel roles/resourcemanager.projectIamAdmin, os principais podem determinar se um usuário final é membro de alguma das funções de administrador do App Engine. Sem a associação a roles/resourcemanager.projectIamAdmin, as chamadas à API Resource Manager para receber a política de permissão vão falhar.

Você não precisa fazer nenhuma ação explícita aqui, já que seu app será executado na conta de serviço padrão do App Engine, que recebe automaticamente a associação a esse papel. Mesmo que você use a conta de serviço padrão durante a fase de desenvolvimento, recomendamos criar e usar uma conta de serviço gerenciada pelo usuário com as permissões mínimas necessárias para que o app funcione corretamente. Para conceder a associação a uma conta de serviço, execute o seguinte 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 é o ID do projeto na nuvem, e USR_MGD_SVC_ACCT@PROJ_ID.iam.gserviceaccount.com é a conta de serviço gerenciada pelo usuário que você cria para seu app. Esse comando gera a política do IAM atualizada para seu projeto, em que é possível confirmar se a conta de serviço é membro de roles/resourcemanager.projectIamAdmin. Para mais informações, consulte a documentação de referência. Repetindo, não é necessário emitir esse comando neste codelab, mas salve-o como referência para modernizar seus próprios apps.

Implantar e verificar o aplicativo

Faça upload do app para a nuvem com o comando padrão gcloud app deploy. Depois da implantação, você vai notar uma funcionalidade quase idêntica ao app do módulo 20, exceto que você substituiu o serviço Usuários do App Engine pela Cloud Identity Platform (e pelo Firebase Auth) para Gerenciamento de usuários:

3a83ae745121d70.png

Uma diferença que você vai notar em comparação com o módulo 20 é que clicar em "Login" resulta em um pop-up em vez de um redirecionamento, como mostrado em algumas das capturas de tela abaixo. Assim como no módulo 20, o comportamento varia um pouco dependendo de quantas Contas do Google foram registradas no navegador.

Se não houver usuários registrados no navegador ou se houver um único usuário que ainda não fez login, um pop-up genérico do Google Sign-in vai aparecer:

8437f5f3d489a942.png

Se um único usuário estiver registrado no navegador, mas fizer login em outro lugar, nenhuma caixa de diálogo vai aparecer (ou ela vai surgir e fechar imediatamente), e o app vai entrar em um estado conectado (exibindo o e-mail do usuário e o botão Sair).

Alguns desenvolvedores podem querer fornecer um seletor de contas, mesmo para um único usuário:

b75624cb68d94557.png

Para implementar isso, remova a marca de comentário da linha provider.setCustomParameters({prompt: 'select_account'}); no modelo da Web, conforme descrito anteriormente.

Se houver vários usuários, a caixa de diálogo do seletor de contas vai aparecer (veja abaixo). Se o usuário ainda não tiver feito login, ele vai receber uma solicitação. Se você já estiver conectado, o pop-up vai desaparecer, e o app vai entrar em um estado conectado.

c454455b6020d5e4.png

O estado conectado do módulo 21 é idêntico à interface do usuário do módulo 20:

49ebe4dcc1eff11f.png

O mesmo acontece quando um usuário administrador faz login:

44302f35b39856eb.png

Ao contrário do módulo 21, o módulo 20 sempre acessa a lógica do conteúdo do modelo da Web no app (código do lado do servidor). Uma falha do Módulo 20 é que uma visita é registrada quando o usuário final acessa o app pela primeira vez, e outra é registrada quando um usuário faz login.

No módulo 21, a lógica de login acontece apenas no modelo da Web (código do lado do cliente). Não há uma viagem obrigatória do lado do servidor para determinar qual conteúdo mostrar. A única chamada feita ao servidor é a verificação de usuários administradores depois que um usuário final faz login. Isso significa que os logins e logoffs não registram visitas adicionais, então a lista de visitas mais recentes permanece constante para ações de gerenciamento de usuários. Observe que as capturas de tela acima exibem o mesmo conjunto de quatro visitas em vários logins de usuários.

As capturas de tela do módulo 20 demonstram o "bug de visita dupla" no início deste codelab. Registros de visitas separados são mostrados para cada ação de login ou logout. Verifique os carimbos de data/hora da visita mais recente de cada captura de tela mostrando a ordem cronológica.

Limpar

Geral

Se você terminou por enquanto, recomendamos que desative o app do App Engine para evitar cobranças. No entanto, se você quiser testar ou experimentar mais, a plataforma do App Engine tem uma cota sem custo financeiro. Portanto, enquanto você não exceder esse nível de uso, não vai receber cobranças. Isso é para computação, mas também pode haver cobranças por serviços relevantes do App Engine. Consulte a página de preços para mais informações. Se essa migração envolver outros serviços do Cloud, eles serão cobrados separadamente. Em qualquer caso, se aplicável, consulte a seção "Específico para este codelab" abaixo.

Para total transparência, a implantação em uma plataforma de computação sem servidor do Google Cloud, como o App Engine, gera custos mínimos de build e armazenamento. O Cloud Build e o Cloud Storage têm cotas sem custo financeiro próprias. O armazenamento dessa imagem usa parte dessa cota. No entanto, talvez você more em uma região que não tem um nível sem custo financeiro. Por isso, fique de olho no uso do armazenamento para minimizar possíveis custos. As "pastas" específicas do Cloud Storage que você precisa analisar incluem:

  • 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
  • Os links de armazenamento acima dependem do seu PROJECT_ID e da LOCação. Por exemplo, "us" se o app estiver hospedado nos EUA.

Por outro lado, se você não quiser continuar com este aplicativo ou outros codelabs de migração relacionados e quiser excluir tudo completamente, desligue seu projeto.

Específico para este codelab

Os serviços listados abaixo são exclusivos deste codelab. Consulte a documentação de cada produto para mais informações:

  • O serviço App Engine Datastore é fornecido pelo Cloud Datastore (Cloud Firestore no modo Datastore), que também tem um nível sem custo financeiro. Consulte a página de preços para mais informações.
  • O uso da plataforma Identity Platform tem um nível de "gratuidade", dependendo de quais serviços você usa. Consulte a página de preços para mais detalhes.
  • O uso da API Resource Manager é sem custo financeiro na maior parte, conforme a página de preços.

Próximas etapas

Além deste tutorial, outros módulos de migração que se concentram em migrar dos serviços agrupados legados incluem:

  • Módulo 2: migrar do App Engine ndb para o Cloud NDB
  • Módulos 7 a 9: migrar da fila de tarefas do App Engine (tarefas push) para o Cloud Tasks
  • Módulos 12 e 13: migrar do Memcache do App Engine para o Cloud Memorystore
  • Módulos 15 e 16: migrar do Blobstore do App Engine para o Cloud Storage
  • Módulos 18 e 19: migrar da fila de tarefas do App Engine (tarefas pull) para o Cloud Pub/Sub

O App Engine não é mais a única plataforma sem servidor no Google Cloud. Se você tem um app pequeno do App Engine ou um com funcionalidade limitada e quer transformá-lo em um microsserviço independente, ou se quer dividir um app monolítico em vários componentes reutilizáveis, esses são bons motivos para considerar a migração para o Cloud Functions. Se a contêinerização se tornou parte do seu fluxo de trabalho de desenvolvimento de aplicativos, principalmente se ele consistir em um pipeline de CI/CD (integração contínua/entrega ou implantação contínua), considere migrar para o Cloud Run. Esses cenários são abordados nos seguintes módulos:

  • Migrar do App Engine para o Cloud Functions: consulte o Módulo 11
  • Migrar do App Engine para o Cloud Run: consulte o Módulo 4 para contentorizar seu app com o Docker ou o Módulo 5 para fazer isso sem contêineres, conhecimento do Docker ou Dockerfiles

A mudança para outra plataforma sem servidor é opcional. Recomendamos considerar as melhores opções para seus apps e casos de uso antes de fazer qualquer mudança.

Independente do módulo de migração que você considerar em seguida, todo o conteúdo da Estação de migração sem servidor (codelabs, vídeos, código-fonte [quando disponível]) pode ser acessado no repositório de código aberto. O README do repositório também oferece orientações sobre quais migrações considerar e a "ordem" relevante dos módulos de migração.

8. Outros recursos

Confira abaixo outros recursos para desenvolvedores que querem saber mais sobre este ou outros módulos de migração relacionados. Abaixo, você pode enviar feedback sobre este conteúdo, encontrar links para o código e vários documentos que podem ser úteis.

Problemas/feedback dos codelabs

Se você encontrar problemas com este codelab, pesquise seu problema antes de preenchê-lo. Links para pesquisar e criar novos problemas:

Recursos de migração

Os links para as pastas do repositório do módulo 20 (START) e do Módulo 21 (FINISH) podem ser encontrados na tabela abaixo.

Codelab

Python 2

Python 3

Módulo 20

código

(n/a)

Módulo 21 (este codelab)

código

código

Referências on-line

Confira abaixo os recursos relevantes para este tutorial:

Cloud Identity Platform e Cloud Marketplace

Cloud Resource Manager, Cloud IAM, SDK Admin do Firebase

Usuários do App Engine, NDB do App Engine, NDB do Cloud, Cloud Datastore

Outras referências do módulo de migração

Migração do App Engine

Plataforma do App Engine

SDK do Cloud

Outras informações da nuvem

Vídeos

Licença

Este conteúdo está sob a licença Atribuição 2.0 Genérica da Creative Commons.