1. Visão geral
Você vai modificar as etapas padrão para implantar um serviço no Cloud Run e melhorar a segurança. Depois, vai aprender a acessar o app implantado de maneira segura. O app é um "serviço de registro de parceiros" do aplicativo Cymbal Eats, usado por empresas que trabalham com a Cymbal Eats para processar pedidos de comida.
O que você vai aprender
Ao fazer algumas pequenas mudanças nas etapas padrão mínimas para implantar um app no Cloud Run, é possível aumentar significativamente a segurança dele. Você vai pegar um app e instruções de implantação atuais e mudar as etapas de implantação para melhorar a segurança do app implantado.
Em seguida, você vai aprender a autorizar o acesso ao app e fazer solicitações autorizadas.
Este não é um estudo exaustivo sobre a segurança da implantação de aplicativos, mas sim uma análise das mudanças que você pode fazer em todas as suas futuras implantações de apps para melhorar a segurança com muito pouco esforço.
2. Configuração e requisitos
Configuração de ambiente personalizada
- Faça login no Console do Google Cloud e crie um novo projeto ou reutilize um existente. Crie uma conta do Gmail ou do Google Workspace, se ainda não tiver uma.



- O Nome do projeto é o nome de exibição para os participantes do projeto. É uma string de caracteres não usada pelas APIs do Google É possível atualizar o local a qualquer momento.
- O ID do projeto precisa ser exclusivo em todos os projetos do Google Cloud e não pode ser mudado após a definição. O console do Cloud gera automaticamente uma string exclusiva. Em geral, não importa o que seja. Na maioria dos codelabs, é necessário fazer referência ao ID do projeto, normalmente identificado como
PROJECT_ID. Se você não gostar do ID gerado, crie outro aleatório. Se preferir, teste o seu e confira se ele está disponível. Ele não pode ser mudado após essa etapa e permanece durante o projeto. - Para sua informação, há um terceiro valor, um Número do projeto, que algumas APIs usam. Saiba mais sobre esses três valores na documentação.
- Em seguida, ative o faturamento no console do Cloud para usar os recursos/APIs do Cloud. A execução deste codelab não será muito cara, se tiver algum custo. Para encerrar os recursos e evitar cobranças além deste tutorial, exclua os recursos criados ou o projeto inteiro. Novos usuários do Google Cloud estão qualificados para o programa de US$ 300 de avaliação sem custos.
Ativar o Cloud Shell
- No Console do Cloud, clique em Ativar o Cloud Shell
.

Se você nunca iniciou o Cloud Shell, vai ver uma tela intermediária abaixo da dobra com a descrição dele. Se esse for o caso, clique em Continuar e você não a verá novamente. Esta é a aparência dessa tela única:

Leva apenas alguns instantes para provisionar e se conectar ao Cloud Shell.

Essa máquina virtual contém todas as ferramentas de desenvolvimento necessárias. Ela oferece um diretório principal persistente de 5 GB, além de ser executada no Google Cloud. Isso aprimora o desempenho e a autenticação da rede. Praticamente todo o seu trabalho neste codelab pode ser feito em um navegador ou no seu Chromebook.
Depois de se conectar ao Cloud Shell, você já estará autenticado e o projeto já estará configurado com seu ID do projeto.
- Execute o seguinte comando no Cloud Shell para confirmar que você está autenticado:
gcloud auth list
Resposta ao comando
Credentialed Accounts
ACTIVE ACCOUNT
* <my_account>@<my_domain.com>
To set the active account, run:
$ gcloud config set account `ACCOUNT`
- Execute o comando a seguir no Cloud Shell para confirmar se o comando gcloud sabe sobre seu projeto:
gcloud config list project
Resposta ao comando
[core] project = <PROJECT_ID>
Se o projeto não estiver configurado, configure-o usando este comando:
gcloud config set project <PROJECT_ID>
Resposta ao comando
Updated property [core/project].
Configuração do ambiente
Você vai executar comandos na linha de comando do Cloud Shell neste laboratório. Normalmente, é possível copiar e colar os comandos como estão, mas, em alguns casos, é necessário mudar os valores de marcador de posição para os corretos.
- Defina uma variável de ambiente para o ID do projeto para uso em comandos posteriores:
export PROJECT_ID=$(gcloud config get-value project)
export REGION=us-central1
export SERVICE_NAME=partner-registration-service
- Ative a API do serviço Cloud Run que vai executar seu app, a API Firestore que vai fornecer armazenamento de dados NoSQL, a API Cloud Build que será usada pelo comando de implantação e o Artifact Registry, que será usado para armazenar o contêiner do aplicativo quando ele for criado:
gcloud services enable \
run.googleapis.com \
firestore.googleapis.com \
cloudbuild.googleapis.com \
artifactregistry.googleapis.com
- Inicialize o banco de dados do Firestore no modo nativo. Esse comando usa a API App Engine, então ela precisa ser ativada primeiro.
O comando precisa especificar uma região para o App Engine, que não vamos usar, mas precisamos criar por motivos históricos, e uma região para o banco de dados. Vamos usar us-central para o App Engine e nam5 para o banco de dados. nam5 é a localização multirregional dos Estados Unidos. Os locais multirregionais maximizam a disponibilidade e a durabilidade do banco de dados.
gcloud services enable appengine.googleapis.com
gcloud app create --region=us-central
gcloud firestore databases create --region=nam5
- Clone o repositório do app de exemplo e navegue até o diretório.
git clone https://github.com/GoogleCloudPlatform/cymbal-eats.git
cd cymbal-eats/partner-registration-service
3. Revisar o README
Abra o editor e confira os arquivos que compõem o app. Veja README.md, que descreve as etapas necessárias para implantar esse app. Algumas dessas etapas podem envolver decisões de segurança implícitas ou explícitas a serem consideradas. Você vai mudar algumas dessas opções para melhorar a segurança do app implantado, conforme descrito aqui:
Etapa 3: executar npm install
É importante conhecer a procedência e a integridade de qualquer software de terceiros usado em um app. Gerenciar a segurança da cadeia de fornecimento de software é relevante para a criação de qualquer software, não apenas apps implantados no Cloud Run. Este laboratório se concentrou na implantação, então não aborda essa área, mas você pode pesquisar o assunto separadamente.
Etapas 4 e 5: editar e executar deploy.sh
Essas etapas implantam o app no Cloud Run, deixando a maioria das opções nos valores padrão. Você vai modificar essa etapa para tornar a implantação mais segura de duas maneiras principais:
- Não permita acesso não autenticado. Pode ser conveniente permitir isso para testar coisas durante a exploração, mas este é um serviço da Web para uso por parceiros comerciais e sempre deve autenticar seus usuários.
- Especifique que o aplicativo precisa usar uma conta de serviço dedicada com apenas os privilégios necessários, em vez de uma padrão que provavelmente terá mais acesso à API e aos recursos do que o necessário. Isso é conhecido como princípio de privilégio mínimo e é um conceito fundamental da segurança de aplicativos.
Etapas de 6 a 11: fazer solicitações da Web de amostra para verificar o comportamento correto
Como a implantação do aplicativo agora exige autenticação, essas solicitações precisam incluir um comprovante da identidade do solicitante. Em vez de alterar esses arquivos, você fará solicitações diretamente da linha de comando.
4. Implante o serviço com segurança
Foram identificadas duas mudanças necessárias no script deploy.sh: não permitir acesso não autenticado e usar uma conta de serviço dedicada com privilégios mínimos.
Primeiro, crie uma conta de serviço. Em seguida, edite o script deploy.sh para referenciar essa conta e não permitir acesso não autenticado. Depois, implante o serviço executando o script modificado antes de executar o script deploy.sh modificado.
Crie uma conta de serviço e conceda a ela o acesso necessário ao Firestore/Datastore
gcloud iam service-accounts create partner-sa
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:partner-sa@${PROJECT_ID}.iam.gserviceaccount.com" \
--role=roles/datastore.user
Editar deploy.sh
Modifique o arquivo deploy.sh para não permitir o acesso não autenticado(–no-allow-unauthenticated) e especifique a nova conta de serviço(–service-account) para o app implantado. Corrija o GOOGLE_PROJECT_ID para o ID do seu projeto.
Você vai excluir as duas primeiras linhas e mudar outras três, conforme mostrado abaixo.
gcloud run deploy $SERVICE_NAME \
--source . \
--platform managed \
--region ${REGION} \
--no-allow-unauthenticated \
--project=$PROJECT_ID \
--service-account=partner-sa@${PROJECT_ID}.iam.gserviceaccount.com
Implante o serviço
Na linha de comando, execute o script deploy.sh:
./deploy.sh
Quando a implantação for concluída, a última linha da resposta ao comando vai mostrar o URL do serviço do novo app. Salve o URL em uma variável de ambiente:
export SERVICE_URL=<URL from last line of command output>
Agora tente buscar um pedido do app usando a ferramenta curl:
curl -i -X GET $SERVICE_URL/partners
A flag -i do comando curl instrui a incluir cabeçalhos de resposta na saída. A primeira linha da saída precisa ser:
HTTP/2 403
O app foi implantado com a opção de não permitir solicitações não autenticadas. Esse comando curl não contém informações de autenticação e, portanto, é recusado pelo Cloud Run. O aplicativo implantado não é executado nem recebe dados dessa solicitação.
5. Fazer solicitações autenticadas
O app implantado é invocado fazendo solicitações da Web, que agora precisam ser autenticadas para que o Cloud Run as permita. As solicitações da Web são autenticadas incluindo um cabeçalho Authorization no formato:
Authorization: Bearer identity-token
O token de identidade é uma string codificada, assinada criptograficamente e de curto prazo emitida por um provedor de autenticação confiável. Nesse caso, é necessário um token de identidade válido, não expirado e emitido pelo Google.
Fazer uma solicitação como sua conta de usuário
A ferramenta da CLI do Google Cloud pode fornecer um token para o usuário autenticado padrão. Execute este comando para receber um token de identidade da sua conta e salve-o na variável de ambiente ID_TOKEN:
export ID_TOKEN=$(gcloud auth print-identity-token)
Por padrão, os tokens de identidade emitidos pelo Google são válidos por uma hora. Execute o comando curl a seguir para fazer a solicitação que foi rejeitada antes por não estar autorizada. Esse comando vai incluir o cabeçalho necessário:
curl -i -X GET $SERVICE_URL/partners \
-H "Authorization: Bearer $ID_TOKEN"
A resposta ao comando precisa começar com HTTP/2 200, indicando que a solicitação é aceitável e está sendo atendida. Se você esperar uma hora e tentar fazer essa solicitação de novo, ela vai falhar porque o token terá expirado. O corpo da resposta está no final da saída, depois de uma linha em branco:
{"status":"success","data":[]}
Ainda não há parceiros.
Registre parceiros usando os dados JSON de amostra no diretório com dois comandos curl:
curl -X POST \
-H "Authorization: Bearer $ID_TOKEN" \
-H "Content-Type: application/json" \
-d "@example-partner.json" \
$SERVICE_URL/partner
e
curl -X POST \
-H "Authorization: Bearer $ID_TOKEN" \
-H "Content-Type: application/json" \
-d "@example-partner2.json" \
$SERVICE_URL/partner
Repita a solicitação GET anterior para ver todos os parceiros registrados agora:
curl -i -X GET $SERVICE_URL/partners \
-H "Authorization: Bearer $ID_TOKEN"
Você deverá ver dados JSON com muito mais conteúdo, fornecendo informações sobre os dois parceiros registrados.
Fazer uma solicitação como uma conta não autorizada
A solicitação autenticada feita na última etapa foi bem-sucedida não apenas porque foi autenticada, mas também porque o usuário autenticado (sua conta) foi autorizado. Ou seja, a conta tinha permissão para invocar o app. Nem todas as contas autenticadas têm essa autorização.
A conta padrão usada na solicitação anterior foi autorizada porque é a conta que criou o projeto que contém o app. Por padrão, isso deu a ela permissão para invocar qualquer aplicativo do Cloud Run na conta. Essa permissão pode ser revogada, o que é desejável em um aplicativo de produção. Em vez disso, você vai criar uma conta de serviço sem privilégios ou papéis atribuídos e usá-la para tentar acessar o app implantado.
- Crie uma conta de serviço chamada
tester.
gcloud iam service-accounts create tester
- Você vai receber um token de identidade para essa nova conta da mesma forma que recebeu um para sua conta padrão anteriormente. No entanto, isso exige que sua conta padrão tenha permissão para representar contas de serviço. Conceda essa permissão à sua conta.
export USER_EMAIL=$(gcloud config list account --format "value(core.account)")
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="user:$USER_EMAIL" \
--role=roles/iam.serviceAccountTokenCreator
- Agora execute o comando a seguir para salvar um token de identidade para essa nova conta na variável de ambiente TEST_IDENTITY. Se o comando mostrar uma mensagem de erro, aguarde um ou dois minutos e tente de novo.
export TEST_TOKEN=$( \
gcloud auth print-identity-token \
--impersonate-service-account \
"tester@$PROJECT_ID.iam.gserviceaccount.com" \
)
- Faça a solicitação da Web autenticada como antes, mas usando este token de identidade:
curl -i -X GET $SERVICE_URL/partners \
-H "Authorization: Bearer $TEST_TOKEN"
A resposta ao comando vai começar novamente com HTTP/2 403 porque a solicitação, embora autenticada, não está autorizada. A nova conta de serviço não tem permissão para invocar esse app.
Autorizar uma conta
Um usuário ou uma conta de serviço precisa ter o papel de invocador do Cloud Run em um serviço do Cloud Run para fazer solicitações a ele. Atribua esse papel à conta de serviço do testador com o comando:
export REGION=us-central1
gcloud run services add-iam-policy-binding ${SERVICE_NAME} \
--member="serviceAccount:tester@$PROJECT_ID.iam.gserviceaccount.com" \
--role=roles/run.invoker \
--region=${REGION}
Depois de aguardar um ou dois minutos para que a nova função seja atualizada, repita a solicitação autenticada. Salve um novo TEST_TOKEN se tiver passado uma hora ou mais desde que ele foi salvo pela primeira vez.
curl -i -X GET $SERVICE_URL/partners \
-H "Authorization: Bearer $TEST_TOKEN"
A resposta ao comando agora começa com HTTP/1.1 200 OK, e a última linha contém a resposta JSON. Essa solicitação foi aceita pelo Cloud Run e processada pelo app.
6. Autenticação de programas x autenticação de usuários
As solicitações autenticadas que você fez até agora usaram a ferramenta de linha de comando curl. Há outras ferramentas e linguagens de programação que poderiam ter sido usadas. No entanto, as solicitações autenticadas do Cloud Run não podem ser feitas usando um navegador da Web com páginas da Web simples. Se um usuário clicar em um link ou em um botão para enviar um formulário em uma página da Web, o navegador não vai adicionar o cabeçalho Authorization exigido pelo Cloud Run para solicitações autenticadas.
O mecanismo de autenticação integrado do Cloud Run é destinado ao uso por programas, não por usuários finais.
Observação:
O Cloud Run pode hospedar aplicativos da Web voltados ao usuário, mas esses tipos de aplicativos precisam configurar o Cloud Run para permitir solicitações não autenticadas dos navegadores da Web dos usuários. Se os aplicativos exigirem autenticação do usuário, o aplicativo precisará processá-la em vez de pedir que o Cloud Run faça isso. O aplicativo pode fazer isso da mesma forma que os aplicativos da Web fora do Cloud Run. Como isso é feito está fora do escopo deste codelab.
Você deve ter notado que as respostas aos exemplos de solicitações até agora foram objetos JSON, não páginas da Web. Isso porque esse serviço de registro de parceiros é destinado ao uso por programas, e o JSON é uma forma conveniente para eles consumirem. Em seguida, você vai escrever e executar um programa para consumir e usar esses dados.
Solicitações autenticadas de um programa em Python
Um programa pode fazer solicitações autenticadas de um aplicativo seguro do Cloud Run usando solicitações da Web HTTP padrão, mas incluindo um cabeçalho Authorization. O único novo desafio para esses programas é conseguir um token de identidade válido e não expirado para colocar nesse cabeçalho. Esse token será validado pelo Cloud Run usando o Google Cloud Identity and Access Management (IAM). Portanto, ele precisa ser emitido e assinado por uma autoridade reconhecida pelo IAM. Há bibliotecas de cliente disponíveis em várias linguagens que os programas podem usar para solicitar a emissão de um token. A biblioteca de cliente usada neste exemplo é a google.auth do Python. Há várias bibliotecas Python para fazer solicitações da Web em geral. Este exemplo usa o módulo requests, que é muito usado.
A primeira etapa é instalar as duas bibliotecas de cliente:
pip install google-auth
pip install requests
O código Python para solicitar um token de identidade para o usuário padrão é:
credentials, _ = google.auth.default()
credentials.refresh(google.auth.transport.requests.Request())
identity_token = credentials.id_token
Se você estiver usando um shell de comando, como o Cloud Shell ou o shell de terminal padrão no seu computador, o usuário padrão será aquele que foi autenticado nesse shell. No Cloud Shell, geralmente é o usuário conectado ao Google. Em outros casos, é o usuário autenticado com gcloud auth login ou outro comando gcloud. Se o usuário nunca tiver feito login, não haverá um usuário padrão, e esse código vai falhar.
Para um programa que faz solicitações de outro programa, geralmente não é recomendável usar a identidade de uma pessoa, mas sim a do programa solicitante. É para isso que as contas de serviço servem. Você implantou o serviço do Cloud Run com uma conta de serviço dedicada que fornece a identidade usada ao fazer solicitações de API, como para o Cloud Firestore. Quando um programa é executado em uma plataforma do Google Cloud, as bibliotecas de cliente usam automaticamente a conta de serviço atribuída a ele como identidade padrão. Assim, o mesmo código de programa funciona nas duas situações.
O código Python para fazer uma solicitação com um cabeçalho de autorização adicionado é:
auth_header = {"Authorization": "Bearer " + identity_token}
response = requests.get(url, headers=auth_header)
O programa Python completo a seguir faz uma solicitação autenticada ao serviço do Cloud Run para recuperar todos os parceiros registrados e imprimir os nomes e IDs atribuídos. Copie e execute o comando abaixo para salvar esse código no arquivo print_partners.py.
cat > ./print_partners.py << EOF
def print_partners():
import google.auth
import google.auth.transport.requests
import requests
credentials, _ = google.auth.default()
credentials.refresh(google.auth.transport.requests.Request())
identity_token = credentials.id_token
auth_header = {"Authorization": "Bearer " + identity_token}
response = requests.get("${SERVICE_URL}/partners", headers=auth_header)
parsed_response = response.json()
partners = parsed_response["data"]
for partner in partners:
print(f"{partner['partnerId']}: {partner['name']}")
print_partners()
EOF
Você vai executar esse programa com um comando do shell. Primeiro, você precisa se autenticar como o usuário padrão para que o programa possa usar essas credenciais. Execute o comando gcloud auth abaixo:
gcloud auth application-default login
Siga as instruções para concluir o login. Em seguida, execute o programa na linha de comando:
python print_partners.py
A saída será semelhante a esta:
10102: Zippy food delivery
67292: Foodful
A solicitação do programa chegou ao serviço do Cloud Run porque foi autenticada com sua identidade, e você é o proprietário deste projeto e, portanto, autorizado a executá-lo por padrão. É mais comum que esse programa seja executado com a identidade de uma conta de serviço. Quando executada na maioria dos produtos do Google Cloud, como o Cloud Run ou o App Engine, a identidade padrão é uma conta de serviço e é usada em vez de uma conta pessoal.
7. Parabéns!
Parabéns, você concluiu o codelab.
Qual é a próxima etapa?
Confira outros codelabs do Cymbal Eats:
- Como acionar o Cloud Workflows com o Eventarc
- Acionamento do processamento de eventos do Cloud Storage
- Como se conectar ao CloudSQL particular pelo Cloud Run
- Como se conectar a bancos de dados totalmente gerenciados pelo Cloud Run
- Proteger um aplicativo sem servidor com o Identity-Aware Proxy (IAP)
- Como acionar jobs do Cloud Run com o Cloud Scheduler
- Como proteger o tráfego de entrada do Cloud Run
- Como se conectar ao AlloyDB particular pelo Autopilot do GKE
Limpar
Para evitar cobranças na sua conta do Google Cloud pelos recursos usados no tutorial, exclua o projeto ou mantenha o projeto e exclua cada um dos recursos.
Excluir o projeto
O jeito mais fácil de evitar cobranças é excluindo o projeto que você criou para este tutorial.