Neste tutorial, mostramos como publicar mensagens de aplicativos para dispositivos móveis ou do cliente no Pub/Sub usando um proxy que processa a lógica de autenticação e autorização em vez das credenciais do lado do cliente.
Mesmo que você autentique mensagens do cliente no Pub/Sub usando o Identity and Access Management (IAM), essas credenciais de longa duração nunca expiram. Em aplicativos do lado do cliente, essas credenciais podem ser descobertas por meio de técnicas como descompilação de aplicativos e engenharia reversa.
Em vez disso, é possível descarregar a autenticação e a lógica de autorização para um proxy que executa as seguintes tarefas:
- Autentica solicitações recebidas para validar o usuário.
- Encaminha solicitações para o Pub/Sub junto com as permissões apropriadas do IAM.
Neste tutorial, mostramos como implementar um proxy do Pub/Sub no Google Kubernetes Engine (GKE). Este tutorial é destinado a desenvolvedores de aplicativos e arquitetos de sistemas que definem e implementam o design para aplicativos móveis ou do lado do cliente. Para isso, presumimos que você entenda os conceitos fundamentais do Kubernetes (em inglês) e esteja familiarizado com o Cloud Endpoints.
Fluxo de solicitação para este tutorial
Para entender como o Pub/Sub se encaixa em um pipeline de streaming, considere uma análise de fluxo de cliques. Nesse caso de uso, convém entender como os usuários interagem com seu aplicativo para dispositivos móveis. Para receber esses insights, você captura a atividade do usuário em tempo real. O diagrama a seguir mostra o fluxo de dados.
Os dados capturados pelo aplicativo são enviados ao Pub/Sub por meio de um proxy. O Pub/Sub pode ter assinantes downstream, como o Dataflow ou o Dataproc, que agregam os dados para você realizar análises significativas.
O diagrama a seguir mostra uma visualização detalhada do fluxo de solicitação que este tutorial segue.
As próximas seções explicam como os vários componentes deste diagrama interagem.
Autenticação do usuário
Os aplicativos para dispositivos móveis podem usar vários métodos para autenticar usuários. O fluxo de autenticação é específico para seu aplicativo. Neste tutorial, mostramos uma dessas soluções para autenticar usuários. Uma implementação desta solução acompanha este tutorial.
Solicitações do app cliente para o proxy do Pub/Sub
O back-end do aplicativo gera um token de autenticação de curta duração que o cliente armazena localmente (por exemplo, usando o sistema Android Keystore ou os serviços do conjunto de chaves do iOS, link em inglês). Neste tutorial, usamos tokens de código do OpenID Connect (OIDC), link em inglês, para autenticar o app cliente. O Google emite e assina o token de código OIDC.
O aplicativo do lado do cliente envia uma solicitação ao proxy do Pub/Sub usando o token de código OIDC. O proxy do Pub/Sub valida o token e encaminha a solicitação para o Pub/Sub com as credenciais apropriadas do IAM.
Como publicar mensagens
Depois que o aplicativo cliente for autenticado, o proxy do Pub/Sub enviará uma solicitação de publicação para o Pub/Sub. Com o IAM, o Pub/Sub ajuda a garantir que o autor da chamada (o proxy do Pub/Sub) tenha as permissões certas para enviar solicitações de publicação. Neste tutorial, o proxy do Pub/Sub usa a conta de serviço padrão do Compute Engine para autenticar com o Pub/Sub. A conta de serviço padrão do Compute Engine tem o editor Papel de IAM (roles/editor
), que fornece
acesso de editor ao proxy do Pub/Sub.
Objetivos
- Crie um cluster do GKE para executar um proxy do Pub/Sub.
- Crie um tópico do Pub/Sub.
- Implante o proxy do Pub/Sub.
- Configure o Endpoints para autenticar solicitações para o proxy do Pub/Sub.
- Verifique se as mensagens foram publicadas no Pub/Sub.
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.
Ao concluir as tarefas descritas neste documento, é possível evitar o faturamento contínuo excluindo os recursos criados. Saiba mais em Limpeza.
Antes de começar
-
No console do Google Cloud, acesse a página do seletor de projetos.
-
Selecione ou crie um projeto do Google Cloud.
-
Verifique se a cobrança está ativada para o seu projeto do Google Cloud.
-
No Console do Google Cloud, ative o Cloud Shell.
Na parte inferior do Console do Google Cloud, uma sessão do Cloud Shell é iniciada e exibe um prompt de linha de comando. O Cloud Shell é um ambiente shell com a CLI do Google Cloud já instalada e com valores já definidos para o projeto atual. A inicialização da sessão pode levar alguns segundos.
- Defina as variáveis de ambiente necessárias para este tutorial:
export PROJECT=$(gcloud config get-value project) export REGION=us-central1 export ZONE=${REGION}-b export CLUSTER=pubsub-proxy export TOPIC=proxy-test export SERVICE_ACCOUNT=publish-test export ENDPOINTS_SERVICE="pubtest.endpoints.${PROJECT}.cloud.goog" export GENERATE_TOKEN="https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts"
- Ative as APIs para Cloud Build, Compute Engine, Google Kubernetes Engine, Artifact Analysis, Container Registry, Endpoints, Service Management, Service Control e Pub/Sub:
gcloud services enable \ cloudbuild.googleapis.com \ compute.googleapis.com \ container.googleapis.com \ containeranalysis.googleapis.com \ containerregistry.googleapis.com \ endpoints.googleapis.com \ servicemanagement.googleapis.com \ servicecontrol.googleapis.com \ pubsub.googleapis.com
Como criar um tópico do Pub/Sub
No Cloud Shell, crie um tópico do Pub/Sub para o qual você publica mensagens:
gcloud pubsub topics create $TOPIC
Como criar um cluster do GKE
No Cloud Shell, crie um cluster do GKE:
gcloud container clusters create $CLUSTER \ --zone $ZONE \ --scopes "https://www.googleapis.com/auth/cloud-platform"
Receba credenciais para o cluster em execução:
gcloud container clusters get-credentials $CLUSTER \ --zone $ZONE \ --project $PROJECT
Como criar uma imagem de contêiner
No Cloud Shell, clone o repositório de código:
git clone https://github.com/GoogleCloudPlatform/solutions-pubsub-proxy-rest
Use o Cloud Build para criar uma imagem de contêiner a partir da origem e salve-a no Container Registry:
cd solutions-pubsub-proxy-rest && \ gcloud builds submit --tag gcr.io/$PROJECT/pubsub-proxy:v1
Como criar um endereço IP externo estático
No Cloud Shell, crie um endereço IP externo estático que seja atribuído posteriormente ao balanceador de carga do proxy do Pub/Sub:
gcloud compute addresses create service-ip --region $REGION
Armazene o endereço IP estático em uma variável de ambiente,
PROXY_IP
:PROXY_IP=$(gcloud compute addresses describe service-ip \ --region $REGION --format='value(address)')
Como implantar endpoints
O proxy do Pub/Sub usa o Endpoints para autenticar solicitações de usuários. O Endpoints usa o Extensible Service Proxy (ESP) para fornecer recursos de gerenciamento de API, como autenticação, monitoramento, rastreamento, e gerenciamento do ciclo de vida da API. Neste tutorial, usamos o Endpoints apenas para autenticar solicitações recebidas para o proxy do Pub/Sub.
Neste tutorial, você implantará o ESP como um arquivo secundário (em inglês) com o proxy do Pub/Sub. O ESP intercepta e autentica solicitações recebidas antes de encaminhá-las ao proxy do Pub/Sub.
No Cloud Shell, substitua o marcador
[PROJECT_ID]
pelo código do projeto do Google Cloud no arquivoopenapi.yaml
:sed -i -e "s/\[PROJECT_ID\]/$PROJECT/g" openapi.yaml
No arquivo de manifesto da OpenAPI, substitua o marcador
[IP_ADDRESS]
pelo valor dePROXY_IP
:sed -i -e "s/\[IP_ADDRESS\]/$PROXY_IP/g" openapi.yaml
Implante a definição de serviço da OpenAPI no Endpoints:
gcloud endpoints services deploy openapi.yaml
O comando anterior cria o seguinte:
- Um
serviço gerenciado
com o nome que você especificou no campo de host do arquivo
openapi.yaml
(pubtest.endpoints.project-id.cloud.goog
), em queproject-id
é o ID do projeto do Google Cloud. - Um registro A DNS que usa o nome do serviço e o mapeamento do endereço IP do balanceador de carga do proxy do Pub/Sub definido na extensão
x-google-endpoints
no arquivoopenapi.yaml
.
Durante a implantação, você vê um aviso que pode ser ignorado porque este tutorial usa tokens de código OIDC para autenticação em vez de chaves de API.
WARNING: openapi.yaml: Operation 'post' in path '/publish': Operation does not require an API key; callers may invoke the method without specifying an associated API-consuming project. To enable API key all the SecurityRequirement Objects (https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#security-requirement-object) inside security definition must reference at least one SecurityDefinition of type : 'apiKey'.
- Um
serviço gerenciado
com o nome que você especificou no campo de host do arquivo
Verifique se o serviço está implantado corretamente:
gcloud endpoints services describe ${ENDPOINTS_SERVICE}
A saída será assim:
[...] producerProjectId: project-id serviceConfig: documentation: summary: Pub/Sub proxy exposed as an Endpoint API [...] name: pubtest.endpoints.project-id.cloud.goog title: PubSub Proxy usage: {} serviceName: pubtest.endpoints.project-id.cloud.goog
Na saída:
project-id
: o ID do seu projeto do Google Cloud.
Como implantar um proxy
No Cloud Shell, gere um certificado SSL autoassinado para permitir conexões HTTPS com o proxy.
openssl req -x509 -nodes -days 365 \ -newkey rsa:2048 -keyout ./nginx.key \ -out ./nginx.crt \ -subj "/CN=${ENDPOINTS_SERVICE}"
Crie uma chave secreta do Kubernetes usando o certificado SSL e a chave privada:
kubectl create secret generic nginx-ssl \ --from-file=./nginx.crt \ --from-file=./nginx.key
Substitua o marcador
[PROJECT_ID]
no arquivo de manifesto de implantação pelo ID do projeto do Google Cloud:sed -i -e "s/\[PROJECT_ID\]/$PROJECT/g" kube/deployment.yaml
Substitua o marcador
[IP_ADDRESS]
no arquivo de manifesto de serviço pelo valor dePROXY_IP
:sed -i -e "s/\[IP_ADDRESS\]/$PROXY_IP/g" kube/service.yaml
Implante o proxy:
kubectl apply -f kube/
Verifique se a implantação foi bem-sucedida:
kubectl rollout status deployment/pubsub-proxy
A saída será assim:
[...] deployment "pubsub-proxy" successfully rolled out
Verifique se dois contêineres (ESP e proxy do Pub/Sub) estão em execução no pod:
kubectl get pods $(kubectl get pod \ -l app=pubsub-proxy \ -o jsonpath="{.items[0].metadata.name}") \ -o jsonpath={.spec.containers[*].name}
A resposta será semelhante a:
esp pubsub-proxy
Fique atento ao valor de
EXTERNAL-IP
para mudar de<pending>
para o endereço IP externo estático que você criou anteriormente:kubectl get svc pubsub-proxy -w
A saída será assim:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE pubsub-proxy LoadBalancer 10.7.247.212 <pending> 443:31104/TCP 6m32s pubsub-proxy LoadBalancer 10.7.247.212 <PROXY_IP> 443:31104/TCP 6m5s
Para parar de assistir, pressione
CTRL+C
.Depois que o proxy do Pub/Sub for implantado, ele será exposto em
https://${ENDPOINTS_SERVICE}/publish
. Pode levar alguns minutos para a nova configuração do DNS se propagar.Verifique a configuração do DNS:
watch nslookup ${ENDPOINTS_SERVICE}
A saída será assim:
Server: 169.254.169.254 Address: 169.254.169.254#53 Non-authoritative answer: Name: pubtest.endpoints.project-id.cloud.goog Address: gke-load-balancer-ip
Na saída:
gke-load-balancer-ip
: o endereço IP do balanceador de carga do GKE (IP do proxy).
Para parar de assistir, pressione
CTRL+C
.
Se alguma das etapas anteriores resultar em um erro, consulte as etapas de solução de problemas.
Como gerar um token de autenticação
O procedimento a seguir para gerar um token de autenticação é um exemplo. Para o ambiente de produção, é necessário que os usuários gerem os próprios tokens de autenticação. Por exemplo, é possível encontrar um código de amostra para receber um token de código OIDC de maneira programática na documentação do Identity-Aware Proxy.
Para gerar um token de autenticação, faça o seguinte:
Crie uma conta de serviço do Google Cloud para a qual você gera um token de código OIDC:
gcloud iam service-accounts create \ $SERVICE_ACCOUNT \ --display-name $SERVICE_ACCOUNT
Consiga a identidade do e-mail da conta de serviço:
SA_EMAIL=${SERVICE_ACCOUNT}@${PROJECT}.iam.gserviceaccount.com
Conceda o papel Criador de token da conta de serviço (
roles/iam.serviceAccountTokenCreator
) do IAM para a conta de serviço:gcloud iam service-accounts add-iam-policy-binding $SA_EMAIL \ --member user:$(gcloud config get-value account) \ --role roles/iam.serviceAccountTokenCreator
Usando a API de credenciais do IAM, gere um token de código OIDC.
TOKEN=$(curl -s ${GENERATE_TOKEN}/${SA_EMAIL}:generateIdToken \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \ -d '{"audience": "'${ENDPOINTS_SERVICE}'", "includeEmail": "true"}' | jq -r ".token")
O nome do serviço do Endpoints é especificado no campo
audience
. A declaraçãoaudience
identifica o destinatário para o qual o token é destinado.Verifique se o token foi criado:
echo $TOKEN
O JSON Web Token (JWT) é semelhante ao seguinte:
eyJhbGciOiJSUzI1NiIsImtpZCI6IjY4NjQyODlm[...].eyJhdWQiOiJwdWJ0ZXN0LmVuZHBvaW50cy52aXR hbC1vY3RhZ29uLTEwOTYxMi5jbG91ZC5nb[...].SjBI4TZjZAlYo6lFKkrvfAcVUp_AJzFKoSsjNbmD_n[...]
Como chamar o Pub/Sub usando um proxy
No Cloud Shell, publique uma mensagem de teste:
curl -i -k -X POST https://${ENDPOINTS_SERVICE}/publish \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"topic": "'$TOPIC'", "messages": [ {"attributes": {"key1": "value1", "key2" : "value2"}, "data": "test data"}]}'
A saída será assim:
HTTP/2 200 server: nginx date: Sun, 02 Jun 2019 03:53:46 GMT ...
Verifique se a mensagem foi publicada no tópico do Pub/Sub:
kubectl logs -f --tail=5 deployment/pubsub-proxy -c pubsub-proxy
Os registros de implantação do proxy do Pub/Sub exibem a mensagem
Successfully published
:2019-06-02 03:49:39.723:INFO:oejs.Server:main: Started @2554ms Jun 02, 2019 3:53:44 AM com.google.pubsub.proxy.publish.PublishMessage getPublisher INFO: Creating new publisher for: proxy-test Jun 02, 2019 3:53:47 AM com.google.pubsub.proxy.publish.PublishMessage$1 onSuccess INFO: Successfully published: 569006136173844
Como solucionar problemas
No Cloud Shell, verifique o estado dos dois contêineres no pod proxy do Pub/Sub:
kubectl describe pods $(kubectl get pod -l app=pubsub-proxy \ -o jsonpath="{.items[0].metadata.name}")
Na saída do registro, o status dos contêineres é
Running
:[...] Containers: esp: [...] State: Running Started: Fri, 21 Jun 2019 16:41:30 +0530 Ready: True Restart Count: 0 [...] pubsub-proxy: State: Running Started: Fri, 21 Jun 2019 16:41:42 +0530 Ready: True Restart Count: 0 [...]
(Opcional) Verifique os registros do contêiner para ver se há outros erros. Por exemplo, para verificar os registros de proxy do Pub/Sub, execute o seguinte comando:
kubectl logs -f --tail=10 deployment/pubsub-proxy -c pubsub-proxy
Para receber ajuda com a solução de problemas, consulte os seguintes documentos:
Limpeza
Para evitar cobranças na sua conta do Google Cloud pelos recursos usados neste tutorial, exclua o projeto do Google Cloud criado para este tutorial ou exclua os recursos associados a ele.
Excluir o projeto do Google Cloud
A maneira mais fácil de eliminar o faturamento é excluir o projeto que você criou para o tutorial.
- No Console do Google Cloud, acesse a página Gerenciar recursos.
- Na lista de projetos, selecione o projeto que você quer excluir e clique em Excluir .
- Na caixa de diálogo, digite o ID do projeto e clique em Encerrar para excluí-lo.
Excluir os recursos
Se você quiser manter o projeto do Google Cloud usado neste tutorial, exclua os recursos individuais:
No Cloud Shell, exclua o cluster do GKE:
gcloud container clusters delete $CLUSTER --zone $ZONE --async
Exclua o código baixado, os artefatos e outras dependências:
cd .. && rm -rf solutions-pubsub-proxy-rest
Exclua a imagem no Container Registry:
gcloud container images list-tags \ gcr.io/$PROJECT/pubsub-proxy \ --format 'value(digest)' | \ xargs -I {} gcloud container images delete \ --force-delete-tags --quiet \ gcr.io/${PROJECT}/pubsub-proxy@sha256:{}
Exclua o tópico Pub/Sub:
gcloud pubsub topics delete $TOPIC
Exclua a conta de serviço:
gcloud iam service-accounts delete $SA_EMAIL
Exclua o Endpoints:
gcloud endpoints services delete ${ENDPOINTS_SERVICE}
Exclua o endereço IP estático:
gcloud compute addresses delete service-ip --region $REGION
A seguir
- Saiba mais sobre autenticação com o Endpoints.
- Saiba mais sobre arquitetura para usar o Pub/Sub em tarefas de longa duração.
- Confira arquiteturas de referência, diagramas e práticas recomendadas do Google Cloud. Confira o Centro de arquitetura do Cloud.