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

Neste tutorial, mostramos como criar um aplicativo da Web no Cloud Run com acesso restrito a usuários conectados e dados armazenados no PostgreSQL. A integração do Identity Platform processa a autenticação do usuário final e fornece tokens de ID do usuário para autorizar o serviço a consultar um banco de dados do Cloud SQL. Esse serviço tem um cliente público que permite aos usuários externos fazer login e acessar uma IU de votação para transmitir os votos.

Para simplificar, este tutorial usa o Google como provedor: os usuários precisam fazer login com uma Conta do Google. 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 Gerenciador de secrets para proteger os dados confidenciais usados para se conectar à instância do Cloud SQL e usando a identidade de serviço com privilégio mínimo.

Durante uma autenticação de usuário final nessa amostra:

  1. o cliente solicita um token de ID assinado para o usuário com base no Identity Platform;
  2. o token de ID assinado é enviado com solicitações para um servidor;
  3. o servidor verifica a identidade do usuário usando esse token de ID assinado e concede acesso ao banco de dados PostgreSQL do Cloud SQL.

Neste tutorial, não mostramos o uso do método de autenticação a seguir:

  • Autenticação do IAM, que usa papéis do IAM para declarar e verificar identidades automaticamente. Isso é recomendado para autenticação serviço a serviço, não para identidades individuais. Para saber mais sobre a autenticação serviço a serviço, consulte o tutorial Como proteger os serviços do Cloud Run. Atualmente, os métodos de token de ID e autenticação baseados em IAM não podem ser combinados.

Objetivos

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

    • autenticar usuários finais para acessar o serviço do Cloud Run usando o Identity Platform;

    • conectar um serviço do Cloud Run a um banco de dados PostgreSQL usando o Gerenciador de secrets para processar dados confidenciais;

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

Custos

Neste tutorial, há componentes faturáveis do Google Cloud, entre eles:

Use a calculadora de preços para gerar uma estimativa de custo com base no uso previsto.

Você já pode concluir este projeto como os créditos do teste gratuito.

Usuários novos do Cloud Platform podem se qualificar para um teste gratuito.

Antes de começar

  1. Faça login na sua conta do Google Cloud. Se você começou a usar o Google Cloud agora, crie uma conta para avaliar o desempenho de nossos produtos em situações reais. Clientes novos também recebem US$ 300 em créditos para executar, testar e implantar cargas de trabalho.
  2. No Console do Google Cloud, na página do seletor de projetos, selecione ou crie um projeto do Google Cloud.

    Acessar o seletor de projetos

  3. Verifique se o faturamento está ativado para seu projeto na nuvem. Saiba como confirmar se o faturamento está ativado para o projeto.

  4. Ative as APIs Cloud Run, Secret Manager, Cloud SQL, Container Registry, and Cloud Build .

    Ative as APIs

  5. Instale e inicie o SDK do Cloud.

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. Se você estiver usando o Cloud Run (totalmente gerenciado), configure o gcloud para a região escolhida e especifique managed como sua plataforma do Cloud Run:

    gcloud config set run/region REGION
    gcloud config set run/platform managed

    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)
  • europe-north1 (Finlândia)
  • europe-west1 (Bélgica)
  • europe-west4 (Países Baixos)
  • us-central1 (Iowa)
  • us-east1 (Carolina do Sul)
  • us-east4 (Norte da Virgínia)
  • us-west1 (Oregon)

Sujeitas aos preços do nível 2

  • asia-east2 (Hong Kong)
  • asia-northeast3 (Seul, Coreia do Sul)
  • asia-southeast1 (Singapura)
  • asia-southeast2 (Jacarta)
  • asia-south1 (Mumbai, Índia)
  • australia-southeast1 (Sydney)
  • europe-central2 (Varsóvia, Polônia)
  • europe-west2 (Londres, Reino Unido)
  • europe-west3 (Frankfurt, Alemanha)
  • europe-west6 (Zurique, Suíça)
  • northamerica-northeast1 (Montreal)
  • southamerica-east1 (São Paulo, Brasil)
  • us-west2 (Los Angeles)
  • us-west3 (Las Vegas)
  • us-west4 (Salt Lake City)

Se você já criou um serviço do Cloud Run, poderá ver a região no painel do Cloud Run no Console do Cloud.

Como recuperar a amostra de código

Para recuperar a amostra 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 o login do usuário por meio de um pop-up do Login do Google fornecido pelo IdP e redirecionado para o Cloud Run com a identidade do usuário.
  1. Um usuário faz a primeira solicitação ao serviço.

  2. O serviço do Cloud Run fornece ao cliente um formulário de login do usuário.

  3. O usuário faz login na janela pop-up do Login do Google que usa o Identity Platform.

  4. O fluxo de autenticação redireciona o usuário de volta para o serviço do Cloud Run com a identidade do usuário.

  5. Quando o usuário transmite um voto, o cliente gera um token de ID e o anexa às solicitações do servidor. O servidor verifica o token de ID e concede acesso de gravação ao Cloud SQL.

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

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 os usuários façam login com as Contas do Google deles abrindo uma janela pop-up e redirecionando-os 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, os métodos do Firebase produzem tokens de ID para identificar e conceder acesso exclusivamente ao usuário. O cliente se comunica com o servidor adicionando o cabeçalho Authorization com o token de ID.

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 se integrar ao Identity Platform e verificar a identidade do usuário do respectivo token de ID 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 necessário para a extração do 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]:
    @wraps(func)
    def decorated_function(*args: Any, **kwargs: Any) -> Any:
        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 se conectar ao Cloud SQL

O serviço 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, str]
) -> sqlalchemy.engine.base.Engine:
    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(
            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": "{}/{}/.s.PGSQL.5432".format(
                    db_socket_dir, cloud_sql_connection_name  # e.g. "/cloudsql"
                )  # i.e "<PROJECT-NAME>:<INSTANCE-REGION>:<INSTANCE-NAME>"
            },
        ),
        **db_config,
    )
    pool.dialect.description_encoding = None
    logger.info("Database engine initialised from unix conection")

    return pool

Java

Use a integração de inicialização do Spring Cloud Google Cloud PostgreSQL para interagir com os bancos de dados do PostgreSQL no Google Cloud SQL usando bibliotecas JDBC do Spring JDBC. 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 Gerenciador de secrets permite o armazenamento centralizado e seguro de dados confidenciais, como a configuração do Cloud SQL. O serviço carrega as credenciais do Cloud SQL do Gerenciador de secrets por meio da biblioteca de cliente.

Node.js

const {SecretManagerServiceClient} = require('@google-cloud/secret-manager');
let client;

async function getSecrets(secretName) {
  if (!client) client = new SecretManagerServiceClient();
  try {
    const [version] = await client.accessSecretVersion({name: secretName});
    return version.payload.data;
  } catch (err) {
    throw Error(`Error accessing Secret Manager: ${err}`);
  }
}

Python

def get_cred_config() -> Dict[str, str]:
    if "CLOUD_SQL_CREDENTIALS_SECRET" in os.environ:
        name = os.environ["CLOUD_SQL_CREDENTIALS_SECRET"]
        client = secretmanager.SecretManagerServiceClient()
        response = client.access_secret_version(request={"name": name})
        logger.info("Credentials pulled from CLOUD_SQL_CREDENTIALS_SECRET")
        return json.loads(response.payload.data.decode("UTF-8"))

Java

/** Retrieve config from Secret Manager */
public static HashMap<String, Object> getConfig(
    String secretVersionName) throws IOException {
  // Initialize client that will be used to send requests. This client only needs to be created
  // once, and can be reused for multiple requests. After completing all of your requests, call
  // the "close" method on the client to safely clean up any remaining background resources.
  try (SecretManagerServiceClient client = SecretManagerServiceClient.create()) {
    // Retrieve secret version
    AccessSecretVersionResponse response = client.accessSecretVersion(secretVersionName);
    String json = response.getPayload().getData().toStringUtf8();

    // Convert JSON secret to a Map
    HashMap<String, Object> config = new Gson().fromJson(json, HashMap.class);
    return config;
  } catch (IOException e) {
    logger.error("Unable to create Secret Manager client: " + e.toString());
    throw new RuntimeException("Unable to retrieve config secrets.");
  } catch (ApiException e) {
    logger.error("Unable to retrieve config secrets: " + e.toString());
    throw new RuntimeException("Unable to retrieve config secrets.");
  }
}

Como enviar o serviço

Configuração do Identity Platform

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

  1. No Console do Cloud, acesse a página do Identity Platform no Marketplace.

    Acessar a página do Identity Platform no Marketplace

  2. Clique em Ativar Identity Platform. Isso gera um ID do cliente OAuth2 com o nome: Web client (auto created by Google Service).

  3. Faça o download do ID OAuth2 gerado:

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

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

    2. No registro de "Cliente da Web (criado automaticamente pelos Serviços do Google)", clique no ícone de download.

    3. Na saída JSON salva, anote o client_id e o client_secret.

  4. Configure o Google como provedor:

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

      Acessar a página "Provedores do Identity Platform"

    2. Clique em Adicionar um provedor.

    3. Selecione Google na lista.

    4. Na configuração do SDK da Web, insira os valores do JSON que você fez o download anteriormente:

      1. ID do cliente da Web: client_id

      2. Chave secreta do cliente da Web: client_secret

    5. Clique em Configurar tela.

      1. Selecione Externo em "Tipo de usuário".

      2. Preencha os campos obrigatórios (e-mail de suporte, e-mail do desenvolvedor).

      3. Continue até chegar na página Resumo.

    6. Em "Configure sua aplicação", clique em Detalhes de configuração. Copie o snippet no static/config.js da amostra para inicializar o SDK do cliente do Identity Platform.

    7. Clique em Save.

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 usando o console ou a CLI:

    gcloud iam service-accounts create idp-sql-identity
  5. Adicione vinculações de acesso do Gerenciador de secrets e do Cloud SQL usando o console ou a CLI:

    1. Permita que a conta de serviço 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 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 a imagem do contêiner usando o Cloud Build:

    Node.js

    gcloud builds submit --tag gcr.io/PROJECT_ID/idp-sql

    Python

    gcloud builds submit --tag gcr.io/PROJECT_ID/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 Container Registry.

      gcloud auth configure-docker

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

      mvn compile jib:build -Dimage=gcr.io/PROJECT_ID/idp-sql

  7. Implante a imagem do contêiner no Cloud Run usando o console ou a CLI:

    gcloud run deploy idp-sql \
        --image gcr.io/PROJECT_ID/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-env-vars CLOUD_SQL_CREDENTIALS_SECRET=projects/PROJECT_ID/secrets/idp-sql-secrets/versions/latest

    Com o uso específico de sinalizações, --service-account, --add-cloudsql-instances e --update-env-vars, para especificar a identidade do serviço, a conexão da instância do Cloud SQL e o nome completo do caminho do secret como uma variável de ambiente, respectivamente.

Toques finais

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 da caneta na página Provedores de identidade.

  2. Em "Domínios autorizados", clique em Adicionar domínio 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)'

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

Limpeza

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. No Console do Cloud, acesse a página Gerenciar recursos:

    Acessar "Gerenciar recursos"

  2. Na lista de projetos, selecione o projeto que você quer excluir e clique em Excluir .
  3. Na caixa de diálogo, digite o ID do projeto e clique em Encerrar para excluí-lo.

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