Tutorial de autenticação do usuário final para o Cloud Run


Neste tutorial, mostramos como criar um serviço de votação com o seguinte:

  • Um cliente baseado em navegador que:

    1. usa o Identity Platform para buscar um token de ID;
    2. permite que os usuários votem no animal de estimação favorito;
    3. adiciona esse token de ID para uma solicitação ao servidor do Cloud Run que processa o voto.
  • Um servidor do Cloud Run que:

    1. verifica se o usuário final foi autenticado corretamente fornecendo um token de ID válido;
    2. processa o voto do usuário final;
    3. usa as próprias credenciais para enviar o voto ao Cloud SQL para armazenamento.
  • Um banco de dados PostgresSQL que armazena os votos.

Para simplificar, este tutorial usa o Google como provedor: os usuários precisam fazer a autenticação usando uma Conta do Google para receber o token de ID. No entanto, é possível usar outros provedores ou métodos de autenticação para fazer login de usuários.

Esse serviço reduz riscos de segurança usando o Secret Manager para proteger dados confidenciais usados para se conectar à instância do Cloud SQL. Ele também usa uma identidade de serviço com privilégio mínimo para proteger o acesso ao banco de dados.

Objetivos

Grave, crie e implante um serviço no Cloud Run que mostra como:

  • Use o Identity Platform para autenticar um usuário final no back-end do serviço do Cloud Run.

  • Crie uma identidade com privilégio mínimo para que o serviço conceda acesso mínimo aos recursos do Google Cloud.

  • Use o Secret Manager para processar dados confidenciais ao conectar o serviço Cloud Run a um banco de dados PostgreSQL.

Custos

Neste documento, você usará os seguintes componentes faturáveis do Google Cloud:

Para gerar uma estimativa de custo baseada na projeção de uso deste tutorial, use a calculadora de preços. Novos usuários do Google Cloud podem estar qualificados para uma avaliação gratuita.

Antes de começar

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  5. Make sure that billing is enabled for your Google Cloud project.

  6. Enable the Cloud Run, Secret Manager, Cloud SQL, Artifact Registry, and Cloud Build APIs.

    Enable the APIs

Funções exigidas

Para conseguir as permissões necessárias para concluir o tutorial, peça ao administrador para conceder a você os seguintes papéis do IAM no projeto:

Para mais informações sobre a concessão de papéis, consulte Gerenciar o acesso a projetos, pastas e organizações.

Também é possível conseguir as permissões necessárias por meio de papéis personalizados ou de outros papéis predefinidos.

Configuração dos padrões gcloud

Para configurar a gcloud com os padrões do serviço do Cloud Run, realize as etapas a seguir:

  1. Defina seu projeto padrão:

    gcloud config set project PROJECT_ID

    Substitua PROJECT_ID pelo nome do projeto que você criou para este tutorial.

  2. Configure a gcloud para a região escolhida:

    gcloud config set run/region REGION

    Substitua REGION pela região compatível do Cloud Run.

Locais do Cloud Run

O Cloud Run é regional, o que significa que a infraestrutura que executa seus serviços do Cloud Run está localizada em uma região específica e é gerenciada pelo Google para estar disponível de maneira redundante em todas as zonas da região.

Atender aos seus requisitos de latência, disponibilidade ou durabilidade são os principais fatores para selecionar a região em que seus serviços do Cloud Run são executados. Geralmente, é possível selecionar a região mais próxima de seus usuários, mas considere a localização dos outros produtos do Google Cloud usados pelo serviço do Cloud Run. O uso de produtos do Google Cloud em vários locais pode afetar a latência e o custo do serviço.

O Cloud Run está disponível nas regiões a seguir:

Sujeitas aos preços do nível 1

  • asia-east1 (Taiwan)
  • asia-northeast1 (Tóquio)
  • asia-northeast2 (Osaka)
  • asia-south1 (Mumbai, Índia)
  • europe-north1 (Finlândia) Ícone de folha Baixo CO2
  • europe-southwest1 (Madri) Ícone de folha Baixo CO2
  • europe-west1 (Bélgica) Ícone de folha Baixo CO2
  • europe-west4 (Países Baixos) Ícone de folha Baixo CO2
  • europe-west8 (Milão)
  • europe-west9 (Paris) Ícone de folha Baixo CO2
  • me-west1 (Tel Aviv)
  • us-central1 (Iowa) Ícone de folha Baixo CO2
  • us-east1 (Carolina do Sul)
  • us-east4 (Norte da Virgínia)
  • us-east5 (Columbus)
  • us-south1 (Dallas) Ícone de folha Baixo CO2
  • us-west1 (Oregon) Ícone de folha Baixo CO2

Sujeitas aos preços do nível 2

  • africa-south1 (Johannesburgo)
  • asia-east2 (Hong Kong)
  • asia-northeast3 (Seul, Coreia do Sul)
  • asia-southeast1 (Singapura)
  • asia-southeast2 (Jacarta)
  • asia-south2 (Déli, Índia)
  • australia-southeast1 (Sydney)
  • australia-southeast2 (Melbourne)
  • europe-central2 (Varsóvia, Polônia)
  • europe-west10 (Berlim) Ícone de folha Baixo CO2
  • europe-west12 (Turim)
  • europe-west2 (Londres, Reino Unido) Ícone de folha Baixo CO2
  • europe-west3 (Frankfurt, Alemanha) Ícone de folha Baixo CO2
  • europe-west6 (Zurique, Suíça) Ícone de folha Baixo CO2
  • me-central1 (Doha)
  • me-central2 (Damã)
  • northamerica-northeast1 (Montreal) Ícone de folha Baixo CO2
  • northamerica-northeast2 (Toronto) Ícone de folha Baixo CO2
  • southamerica-east1 (São Paulo, Brasil) Ícone de folha Baixo CO2
  • southamerica-west1 (Santiago, Chile) Ícone de folha Baixo CO2
  • us-west2 (Los Angeles)
  • us-west3 (Salt Lake City)
  • us-west4 (Las Vegas)

Se você já criou um serviço do Cloud Run, é possível visualizar a região no painel do Cloud Run no console do Google Cloud.

Como recuperar o exemplo de código

Para recuperar o exemplo de código para uso, siga estas etapas:

  1. Clone o repositório do aplicativo de amostra na máquina local:

    Node.js

    git clone https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git

    Outra alternativa é fazer o download da amostra como um arquivo ZIP e extraí-lo.

    Python

    git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git

    Outra alternativa é fazer o download da amostra como um arquivo ZIP e extraí-lo.

    Java

    git clone https://github.com/GoogleCloudPlatform/java-docs-samples.git

    Outra alternativa é fazer o download da amostra como um arquivo ZIP e extraí-lo.

  2. Mude para o diretório que contém o código de amostra do Cloud Run:

    Node.js

    cd nodejs-docs-samples/run/idp-sql/

    Python

    cd python-docs-samples/run/idp-sql/

    Java

    cd java-docs-samples/run/idp-sql/

Como visualizar a arquitetura

Diagrama de arquitetura
O diagrama mostra um usuário final fazendo login usando uma caixa de diálogo de Login do Google fornecida pelo Identity Platform e sendo redirecionado para o Cloud Run com a identidade do usuário.
  1. Um usuário final faz a primeira solicitação ao servidor do Cloud Run.

  2. O cliente é carregado no navegador.

  3. O usuário fornece credenciais de login na caixa de diálogo de Login do Google do Identity Platform. Um alerta de aceitação do usuário conectado é exibido.

  4. O controle é redirecionado de volta para o servidor. O usuário final vota usando o cliente, que busca um token de ID do Identity Platform e o adiciona ao cabeçalho da solicitação de voto.

  5. Ao receber a solicitação, o servidor verifica o token de ID do Identity Platform, confirmando se o usuário final está devidamente autenticado. Em seguida, o servidor envia o voto para o Cloud SQL, usando suas próprias credenciais.

Noções básicas sobre o código principal

A amostra é implementada como cliente e servidor, conforme descrito a seguir.

Integração com o Identity Platform: código do lado do cliente

Este exemplo usa SDKs do Firebase para integração com o Identity Platform a fim de fazer login e gerenciar usuários. Para se conectar ao Identity Platform, o JavaScript do lado do cliente mantém a referência às credenciais do projeto como um objeto de configuração e importa os SDKs do Firebase para JavaScript necessários:

const config = {
  apiKey: 'API_KEY',
  authDomain: 'PROJECT_ID.firebaseapp.com',
};
<!-- Firebase App (the core Firebase SDK) is always required and must be listed first-->
<script src="https://www.gstatic.com/firebasejs/7.18/firebase-app.js"></script>
<!-- Add Firebase Auth service-->
<script src="https://www.gstatic.com/firebasejs/7.18/firebase-auth.js"></script>

O SDK do Firebase para JavaScript processa o fluxo de login solicitando que o usuário final faça login na Conta do Google em uma janela pop-up. Em seguida, ele o redireciona de volta para o serviço.

function signIn() {
  const provider = new firebase.auth.GoogleAuthProvider();
  provider.addScope('https://www.googleapis.com/auth/userinfo.email');
  firebase
    .auth()
    .signInWithPopup(provider)
    .then(result => {
      // Returns the signed in user along with the provider's credential
      console.log(`${result.user.displayName} logged in.`);
      window.alert(`Welcome ${result.user.displayName}!`);
    })
    .catch(err => {
      console.log(`Error during sign in: ${err.message}`);
      window.alert('Sign in failed. Retry or check your browser logs.');
    });
}

Quando um usuário faz login corretamente, o cliente usa os métodos do Firebase para produzir um token de ID. O cliente adiciona o token de ID ao cabeçalho Authorization da solicitação para o servidor.

async function vote(team) {
  if (firebase.auth().currentUser) {
    // Retrieve JWT to identify the user to the Identity Platform service.
    // Returns the current token if it has not expired. Otherwise, this will
    // refresh the token and return a new one.
    try {
      const token = await firebase.auth().currentUser.getIdToken();
      const response = await fetch('/', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded',
          Authorization: `Bearer ${token}`,
        },
        body: 'team=' + team, // send application data (vote)
      });
      if (response.ok) {
        const text = await response.text();
        window.alert(text);
        window.location.reload();
      }
    } catch (err) {
      console.log(`Error when submitting vote: ${err}`);
      window.alert('Something went wrong... Please try again!');
    }
  } else {
    window.alert('User not signed in.');
  }
}

Integração com o Identity Platform: código do lado do servidor

O servidor usa o SDK Admin do Firebase para verificar o token do ID do usuário enviado pelo cliente. Se o token de ID fornecido tiver o formato correto, não tiver expirado e estiver devidamente assinado, o método retornará o token de ID decodificado. O servidor extrai o uid do Identity Platform para esse usuário.

Node.js

const firebase = require('firebase-admin');
// Initialize Firebase Admin SDK
firebase.initializeApp();

// Extract and verify Id Token from header
const authenticateJWT = (req, res, next) => {
  const authHeader = req.headers.authorization;
  if (authHeader) {
    const token = authHeader.split(' ')[1];
    // If the provided ID token has the correct format, is not expired, and is
    // properly signed, the method returns the decoded ID token
    firebase
      .auth()
      .verifyIdToken(token)
      .then(decodedToken => {
        const uid = decodedToken.uid;
        req.uid = uid;
        next();
      })
      .catch(err => {
        req.logger.error(`Error with authentication: ${err}`);
        return res.sendStatus(403);
      });
  } else {
    return res.sendStatus(401);
  }
};

Python

def jwt_authenticated(func: Callable[..., int]) -> Callable[..., int]:
    """Use the Firebase Admin SDK to parse Authorization header to verify the
    user ID token.

    The server extracts the Identity Platform uid for that user.
    """

    @wraps(func)
    def decorated_function(*args: a, **kwargs: a) -> a:
        header = request.headers.get("Authorization", None)
        if header:
            token = header.split(" ")[1]
            try:
                decoded_token = firebase_admin.auth.verify_id_token(token)
            except Exception as e:
                logger.exception(e)
                return Response(status=403, response=f"Error with authentication: {e}")
        else:
            return Response(status=401)

        request.uid = decoded_token["uid"]
        return func(*args, **kwargs)

    return decorated_function

Java

/** Extract and verify Id Token from header */
private String authenticateJwt(Map<String, String> headers) {
  String authHeader =
      (headers.get("authorization") != null)
          ? headers.get("authorization")
          : headers.get("Authorization");
  if (authHeader != null) {
    String idToken = authHeader.split(" ")[1];
    // If the provided ID token has the correct format, is not expired, and is
    // properly signed, the method returns the decoded ID token
    try {
      FirebaseToken decodedToken = FirebaseAuth.getInstance().verifyIdToken(idToken);
      String uid = decodedToken.getUid();
      return uid;
    } catch (FirebaseAuthException e) {
      logger.error("Error with authentication: " + e.toString());
      throw new ResponseStatusException(HttpStatus.FORBIDDEN, "", e);
    }
  } else {
    logger.error("Error no authorization header");
    throw new ResponseStatusException(HttpStatus.UNAUTHORIZED);
  }
}

Como conectar o servidor ao Cloud SQL

O servidor conecta-se ao soquete do domínio Unix da instância do Cloud SQL usando o formato: /cloudsql/CLOUD_SQL_CONNECTION_NAME.

Node.js

/**
 * Connect to the Cloud SQL instance through UNIX Sockets
 *
 * @param {object} credConfig The Cloud SQL connection configuration from Secret Manager
 * @returns {object} Knex's PostgreSQL client
 */
const connectWithUnixSockets = async credConfig => {
  const dbSocketPath = process.env.DB_SOCKET_PATH || '/cloudsql';
  // Establish a connection to the database
  return Knex({
    client: 'pg',
    connection: {
      user: credConfig.DB_USER, // e.g. 'my-user'
      password: credConfig.DB_PASSWORD, // e.g. 'my-user-password'
      database: credConfig.DB_NAME, // e.g. 'my-database'
      host: `${dbSocketPath}/${credConfig.CLOUD_SQL_CONNECTION_NAME}`,
    },
    ...config,
  });
};

Python

def init_unix_connection_engine(
    db_config: dict[str, int]
) -> sqlalchemy.engine.base.Engine:
    """Initializes a Unix socket connection pool for a Cloud SQL instance of PostgreSQL.

    Args:
        db_config: a dictionary with connection pool config

    Returns:
        A SQLAlchemy Engine instance.
    """
    creds = credentials.get_cred_config()
    db_user = creds["DB_USER"]
    db_pass = creds["DB_PASSWORD"]
    db_name = creds["DB_NAME"]
    db_socket_dir = creds.get("DB_SOCKET_DIR", "/cloudsql")
    cloud_sql_connection_name = creds["CLOUD_SQL_CONNECTION_NAME"]

    pool = sqlalchemy.create_engine(
        # Equivalent URL:
        # postgres+pg8000://<db_user>:<db_pass>@/<db_name>
        #                         ?unix_sock=<socket_path>/<cloud_sql_instance_name>/.s.PGSQL.5432
        sqlalchemy.engine.url.URL.create(
            drivername="postgresql+pg8000",
            username=db_user,  # e.g. "my-database-user"
            password=db_pass,  # e.g. "my-database-password"
            database=db_name,  # e.g. "my-database-name"
            query={
                "unix_sock": f"{db_socket_dir}/{cloud_sql_connection_name}/.s.PGSQL.5432"
                # e.g. "/cloudsql", "<PROJECT-NAME>:<INSTANCE-REGION>:<INSTANCE-NAME>"
            },
        ),
        **db_config,
    )
    pool.dialect.description_encoding = None
    logger.info("Database engine initialized from unix connection")

    return pool

Java

Use a integração de ativação do Spring Cloud Google Cloud PostgreSQL para interagir com os bancos de dados do PostgreSQL no Cloud SQL usando bibliotecas JDBC do Spring. Defina o Cloud SQL para MySQL para configurar automaticamente um bean DataSource, que, junto do Spring JDBC, fornece um objeto JdbcTemplate que permite operações como consulta e modificação de um banco de dados.

# Uncomment and add env vars for local development
# spring.datasource.username=${DB_USER}
# spring.datasource.password=${DB_PASSWORD}
# spring.cloud.gcp.sql.database-name=${DB_NAME}
# spring.cloud.gcp.sql.instance-connection-name=${CLOUD_SQL_CONNECTION_NAME}  
private final JdbcTemplate jdbcTemplate;

public VoteController(JdbcTemplate jdbcTemplate) {
  this.jdbcTemplate = jdbcTemplate;
}

Como lidar com configurações confidenciais com o Gerenciador de secrets

O Secret Manager permite o armazenamento centralizado e seguro de dados sensíveis, como a configuração do Cloud SQL. O servidor usa uma variável de ambiente para injetar no ambiente de execução as credenciais do Cloud SQL contidas no Secret Manager. Saiba mais sobre como usar secrets com o Cloud Run.

Node.js

// CLOUD_SQL_CREDENTIALS_SECRET is the resource ID of the secret, passed in by environment variable.
// Format: projects/PROJECT_ID/secrets/SECRET_ID/versions/VERSION
const {CLOUD_SQL_CREDENTIALS_SECRET} = process.env;
if (CLOUD_SQL_CREDENTIALS_SECRET) {
  try {
    // Parse the secret that has been added as a JSON string
    // to retrieve database credentials
    return JSON.parse(CLOUD_SQL_CREDENTIALS_SECRET.toString('utf8'));
  } catch (err) {
    throw Error(
      `Unable to parse secret from Secret Manager. Make sure that the secret is JSON formatted: ${err}`
    );
  }
}

Python

def get_cred_config() -> dict[str, str]:
    """Retrieve Cloud SQL credentials stored in Secret Manager
    or default to environment variables.

    Returns:
        A dictionary with Cloud SQL credential values
    """
    secret = os.environ.get("CLOUD_SQL_CREDENTIALS_SECRET")
    if secret:
        return json.loads(secret)

Java

/** Retrieve config from Secret Manager */
public static HashMap<String, Object> getConfig() {
  String secret = System.getenv("CLOUD_SQL_CREDENTIALS_SECRET");
  if (secret == null) {
    throw new IllegalStateException("\"CLOUD_SQL_CREDENTIALS_SECRET\" is required.");
  }
  try {
    HashMap<String, Object> config = new Gson().fromJson(secret, HashMap.class);
    return config;
  } catch (JsonSyntaxException e) {
    logger.error(
        "Unable to parse secret from Secret Manager. Make sure that it is JSON formatted: "
            + e);
    throw new RuntimeException(
        "Unable to parse secret from Secret Manager. Make sure that it is JSON formatted.");
  }
}

Configurar o Identity Platform

O Identity Platform requer a configuração manual no console do Google Cloud.

  1. No console do Google Cloud, acesse a página do Marketplace do Identity Platform.

    Acesse a página do Identity Platform no Marketplace

  2. Clique em Ativar Identity Platform.

  3. Crie sua tela de permissão OAuth:

    1. Em uma nova janela, acesse a página APIs e serviços > Credenciais.

      Acesse a página APIs e serviços > Credenciais

    2. Selecione a página Tela de permissão OAuth.

    3. Para fins de teste, selecione Externo.

    4. Clique em Criar.

    5. Na caixa de diálogo Informações do aplicativo,

      1. informe o nome do aplicativo;
      2. selecione um dos e-mails exibidos de suporte ao usuário;
      3. insira o e-mail que você quer usar como contato do desenvolvedor.
    6. Clique em Salvar e continuar.

    7. Na caixa de diálogo Escopos, clique em Salvar e continuar.

    8. Na caixa de diálogo Testar usuários, clique em Salvar e continuar.

    9. Na caixa de diálogo Resumo, clique em Voltar ao painel.

    10. Em Status da publicação, clique em Publicar aplicativo.

    11. Clique em Confirmar.

  4. Crie e consiga seu ID do cliente OAuth e Secret:

    1. Acesse a página APIs e serviços > Credenciais

    2. Na parte superior da página, clique em Criar credenciais e selecione OAuth client ID.

    3. Em Tipo de aplicativo, selecione Web app e informe o nome.

    4. Clique em Criar.

    5. Anote client_id e client_secret para uso posterior neste procedimento.

  5. Configure o Google como provedor:

    1. Acesse a página "Provedores de identidade" no console do Cloud.

      Acesse a página "Provedores do Identity Platform"

    2. Clique em Adicionar um provedor.

    3. Selecione Google na lista.

    4. Nas definições da configuração do SDK da Web, insira os valores client_id e client_secret das etapas anteriores.

    5. Em Configurar seu aplicativo, clique em Detalhes de configuração.

    6. Copie os valores apiKey e authDomain no static/config.js da amostra para inicializar o SDK do cliente do Identity Platform.

    7. Clique em Salvar.

Como implantar o serviço

Siga as etapas abaixo para concluir o provisionamento e a implantação da infraestrutura ou automatizar o processo no Cloud Shell clicando em "Executar no Google Cloud":

Executar no Google Cloud

  1. Crie uma instância do Cloud SQL com um banco de dados PostgreSQL usando o console ou a CLI:

    gcloud sql instances create CLOUD_SQL_INSTANCE_NAME \
        --database-version=POSTGRES_12 \
        --region=CLOUD_SQL_REGION \
        --cpu=2 \
        --memory=7680MB \
        --root-password=DB_PASSWORD
  2. Adicione seus valores da credencial do Cloud SQL a postgres-secrets.json:

    Node.js

    {
      "CLOUD_SQL_CONNECTION_NAME": "PROJECT_ID:REGION:INSTANCE",
      "DB_NAME": "postgres",
      "DB_USER": "postgres",
      "DB_PASSWORD": "PASSWORD_SECRET"
    }
    

    Python

    {
      "CLOUD_SQL_CONNECTION_NAME": "PROJECT_ID:REGION:INSTANCE",
      "DB_NAME": "postgres",
      "DB_USER": "postgres",
      "DB_PASSWORD": "PASSWORD_SECRET"
    }
    

    Java

    {
      "spring.cloud.gcp.sql.instance-connection-name": "PROJECT_ID:REGION:INSTANCE",
      "spring.cloud.gcp.sql.database-name": "postgres",
      "spring.datasource.username": "postgres",
      "spring.datasource.password": "PASSWORD_SECRET"
    }

  3. Crie um secret com controle de versões usando o console ou a CLI:

    gcloud secrets create idp-sql-secrets \
        --replication-policy="automatic" \
        --data-file=postgres-secrets.json
  4. Crie uma conta de serviço para o servidor usando o console ou a CLI:

    gcloud iam service-accounts create idp-sql-identity
  5. Conceda papéis para acesso ao Secret Manager e ao Cloud SQL usando o console ou a CLI:

    1. Permita que a conta de serviço associada ao servidor acesse o secret criado:

      gcloud secrets add-iam-policy-binding idp-sql-secrets \
        --member serviceAccount:idp-sql-identity@PROJECT_ID.iam.gserviceaccount.com \
        --role roles/secretmanager.secretAccessor
    2. Permita que a conta de serviço associada ao servidor acesse o Cloud SQL:

      gcloud projects add-iam-policy-binding PROJECT_ID \
        --member serviceAccount:idp-sql-identity@PROJECT_ID.iam.gserviceaccount.com \
        --role roles/cloudsql.client
  6. Crie um Artifact Registry:

    gcloud artifacts repositories create REPOSITORY \
        --repository-format docker \
        --location REGION
    • REPOSITORY é o nome do repositório. Para cada local de repositório em um projeto, os nomes dos repositórios precisam ser exclusivos.
  7. Crie a imagem do contêiner usando o Cloud Build:

    Node.js

    gcloud builds submit --tag REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/idp-sql

    Python

    gcloud builds submit --tag REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/idp-sql

    Java

    Esta amostra usa o Jib (em inglês) para criar imagens do Docker usando ferramentas comuns do Java. O Jib otimiza builds de contêiner sem a necessidade de um Dockerfile ou de ter o Docker (em inglês) instalado. Saiba mais sobre como criar contêineres Java com o Jib.

    1. Use o auxiliar de credencial do gcloud para autorizar o Docker a enviar por push ao Artifact Registry.

      gcloud auth configure-docker

    2. Use o plug-in do Maven do Jib para criar e enviar por push o contêiner ao Artifact Registry.

      mvn compile jib:build -Dimage=REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/idp-sql

  8. Implante a imagem de contêiner no Cloud Run usando o console ou a CLI. O servidor é implantado para permitir o acesso não autenticado. Dessa maneira, o usuário pode carregar o cliente e iniciar o processo. O servidor verifica manualmente o token de ID adicionado à solicitação de votação, autenticando o usuário final.

    gcloud run deploy idp-sql \
        --image REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/idp-sql \
        --allow-unauthenticated \
        --service-account idp-sql-identity@PROJECT_ID.iam.gserviceaccount.com \
        --add-cloudsql-instances PROJECT_ID:REGION:CLOUD_SQL_INSTANCE_NAME \
        --update-secrets CLOUD_SQL_CREDENTIALS_SECRET=idp-sql-secrets:latest

    Observe também as flags --service-account, --add-cloudsql-instances e --update-secrets, que especificam a identidade do serviço, a conexão da instância do Cloud SQL e o nome do secret com a versão como variável de ambiente, respectivamente.

Toques finais

O Identity Platform exige que você autorize o URL de serviço do Cloud Run como um redirecionamento permitido depois de fazer login do usuário:

  1. Para editar o provedor do Google, clique no ícone de caneta na página Provedores de identidade.

  2. Clique em Adicionar domínio em "Domínios autorizados" no painel à direita e insira o URL do serviço do Cloud Run.

    Localize o URL do serviço nos registros após a criação ou implantação ou encontre-o a qualquer momento usando:

    gcloud run services describe idp-sql --format 'value(status.url)'
  3. Acesse a página APIs e serviços > Credenciais

    1. Clique no ícone do lápis ao lado do seu ID do cliente OAuth para editá-lo e no botão Adicionar URI Authorized redirect URIs click the.

    2. No campo, copie e cole o URL a seguir e clique no botão Salvar na parte inferior da página.

    https://PROJECT_ID.firebaseapp.com/__/auth/handler

Testar

Para testar o serviço completo:

  1. Navegue até o URL fornecido pela etapa de implantação acima.

  2. Clique no botão Fazer login com o Google e siga o fluxo de autenticação.

  3. Dê seu voto!

    Você verá o seguinte:

    A captura de tela da interface do usuário mostra o número de votos de cada equipe e uma lista de votos.

Se você optar por continuar desenvolvendo esses serviços, lembre-se de que eles têm acesso restrito do gerenciamento de identidade e acesso (IAM, na sigla em inglês) ao restante do Google Cloud e precisarão receber mais papéis do IAM para acessar muitos outros serviços.

Limpar

Se você criou um novo projeto para este tutorial, exclua o projeto. Se você usou um projeto atual e quer mantê-lo sem as alterações incluídas neste tutorial, exclua os recursos criados para o tutorial.

Como excluir o projeto

O jeito mais fácil de evitar cobranças é excluindo o projeto que você criou para o tutorial.

Para excluir o projeto:

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

Como excluir recursos do tutorial

  1. Exclua o serviço do Cloud Run que você implantou neste tutorial:

    gcloud run services delete SERVICE-NAME

    SERVICE-NAME é o nome escolhido do serviço.

    Também é possível excluir os serviços do Cloud Run no Console do Google Cloud.

  2. Remova a configuração da região padrão da gcloud que você adicionou durante a configuração do tutorial:

     gcloud config unset run/region
    
  3. Remova a configuração do projeto:

     gcloud config unset project
    
  4. Exclua outros recursos do Google Cloud criados neste tutorial:

A seguir