Como autenticar no Google Cloud usando contas de serviço

Neste tutorial, demonstramos como criar uma conta de serviço do Google Cloud, atribuir papéis para autenticação nos serviços do Google Cloud e usar as credenciais dessa conta em aplicativos em execução no Google Kubernetes Engine (GKE).

Neste exemplo, usaremos o Pub/Sub, mas as instruções podem ser aplicadas a qualquer serviço do Google Cloud. No aplicativo de amostra deste tutorial, uma conta de serviço é usada para a autenticação no Pub/Sub e a inscrição é feita nas mensagens publicadas para um tópico do Pub/Sub de um aplicativo baseado em Python.

Objetivos

Este tutorial inclui as etapas a seguir:

  • Como criar uma conta de serviço.
  • Como atribuir os papéis necessários para a conta de serviço funcionar com o Pub/Sub
  • Como salvar a chave da conta como uma chave secreta do Kubernetes.
  • Como usar a conta de serviço para configurar e implantar um aplicativo

No aplicativo de amostra usado neste tutorial, você assina um tópico do Pub/Sub e imprime as mensagens publicadas na saída padrão. Para configurar o aplicativo com as permissões corretas, use o gcloud command-line tool para publicar as mensagens e inspecione o stream de saída do contêiner para observar se as mensagens são recebidas corretamente.

Como se autenticar com contas de serviço

É possível se autenticar nos serviços do Google Cloud com contas de serviço do GKE usando a Identidade da carga de trabalho, a conta de serviço padrão do Compute Engine ou os secrets.

Usar identidade da carga de trabalho

A identidade da carga de trabalho é a maneira recomendada de se autenticar nos serviços do Google Cloud a partir do GKE. A identidade da carga de trabalho permite configurar contas de serviço do Google Cloud usando recursos do Kubernetes. Se esse método de autenticação for adequado ao seu caso de uso, ele deverá ser sua primeira opção. Este exemplo destina-se a casos de uso em que a identidade da carga de trabalho não é adequada.

Usar a conta de serviço padrão do Compute Engine

Cada nó em um cluster do GKE é uma instância do Compute Engine. Portanto, por padrão, os aplicativos executados em um cluster do GKE tentarão autenticar usando a "conta de serviço padrão do Compute Engine" e herdarão os escopos associados.

Essa conta de serviço padrão pode não ter permissões para usar os serviços do Google Cloud de que você precisa. É possível expandir os escopos da conta de serviço padrão, mas isso pode criar riscos de segurança e não é recomendado.

Gerenciar as credenciais da conta de serviço usando Secrets

Crie uma conta de serviço para seu aplicativo e injete a chave de autenticação como um secret do Kubernetes. Essa opção é o foco deste tutorial.

Por que usar as contas de serviço?

O uso de contas de serviço separadas para aplicativos diferentes oferece os seguintes benefícios:

  • melhor visibilidade e auditoria das solicitações de API feitas no aplicativo;

  • capacidade de revogar chaves para aplicativos específicos, em vez de compartilhar uma conta de serviço e precisar revogar o acesso à API de todos os aplicativos ao mesmo tempo;

  • exposição reduzida, no caso de um possível incidente de segurança em que as credenciais da conta de serviço sejam comprometidas.

Antes de começar

Siga estas etapas para ativar a API do Kubernetes Engine:
  1. Acesse a página do Kubernetes Engine no Console do Google Cloud.
  2. Crie ou selecione um projeto.
  3. Aguarde a ativação da API e dos serviços relacionados. Isso pode levar alguns minutos.
  4. Verifique se o faturamento está ativado para seu projeto na nuvem. Saiba como confirmar se o faturamento está ativado para o projeto.

Instale as ferramentas de linha de comando a seguir usadas neste tutorial:

  • gcloud é usado para criar e excluir clusters do Kubernetes Engine. gcloud está incluído no SDK do Google Cloud.
  • O kubectl é usado para gerenciar o Kubernetes, o sistema de orquestração de cluster usado pelo Kubernetes Engine. É possível instalar kubectl usando gcloud:
    gcloud components install kubectl

Clone o código de amostra do GitHub:

git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
cd kubernetes-engine-samples/cloud-pubsub/deployment

Definir padrões para a ferramenta de linha de comando gcloud

Para poupar tempo, em vez de digitar o ID do projeto e as opções de zona do Compute Engine na ferramenta de linha de comando gcloud, defina os padrões:
gcloud config set project project-id
gcloud config set compute/zone compute-zone

Ative as APIs

Para este tutorial, ative as APIs Pub/Sub e Resource Manager no projeto:

gcloud services enable cloudresourcemanager.googleapis.com pubsub.googleapis.com

criar um cluster de contêiner

Crie um cluster de contêiner chamado pubsub-test para implantar o aplicativo de assinante do Pub/Sub:

gcloud container clusters create pubsub-test

Como criar um tópico do Pub/Sub

O aplicativo do assinante Pub/Sub usa uma assinatura chamada echo-read em um tópico do Pub/Sub chamado echo. Crie estes recursos antes de implantar o aplicativo:

Primeiro, crie um tópico do Pub/Sub:

gcloud

gcloud pubsub topics create echo

Config Connector

Observação: esta etapa requer o Config Connector. Siga estas instruções para instalar o Config Connector no cluster.

apiVersion: pubsub.cnrm.cloud.google.com/v1beta1
kind: PubSubTopic
metadata:
  name: echo
Para implantar esse manifesto, faça o download para sua máquina como topic.yaml e execute:
kubectl apply -f topic.yaml

Em seguida, crie uma inscrição:

gcloud

gcloud pubsub subscriptions create echo-read --topic=echo

Config Connector

apiVersion: pubsub.cnrm.cloud.google.com/v1beta1
kind: PubSubSubscription
metadata:
  name: echo-read
spec:
  topicRef:
    name: echo
Para implantar esse manifesto, faça o download para sua máquina como subscription.yaml e execute:
kubectl apply -f subscription.yaml

Como implantar o aplicativo de assinante do Pub/Sub

Em seguida, implante o contêiner do aplicativo para recuperar as mensagens publicadas no tópico do Pub/Sub. Esse aplicativo foi escrito em Python com as bibliotecas de cliente do Google Cloud Pub/Sub. Encontre o código-fonte no GitHub.

No arquivo de manifesto a seguir, você encontra a descrição de uma implantação que executa uma única instância da imagem do Docker desse aplicativo:

# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: pubsub
spec:
  selector:
    matchLabels:
      app: pubsub
  template:
    metadata:
      labels:
        app: pubsub
    spec:
      containers:
      - name: subscriber
        image: gcr.io/google-samples/pubsub-sample:v1

Para implantar esse manifesto, execute:

kubectl apply -f pubsub.yaml

Depois que o aplicativo for implantado, consulte os pods executando:

kubectl get pods -l app=pubsub
Saída:
NAME                      READY     STATUS             RESTARTS   AGE
pubsub-2009462906-1l6bh   0/1       CrashLoopBackOff   1          30s

Observe que o contêiner não é iniciado e está no estado CrashLoopBackOff. Para inspecionar os registros do pod, execute:

kubectl logs -l app=pubsub

Saída:

...
google.gax.errors.RetryError: RetryError(Exception occurred in retry method that
was not classified as transient, caused by <_Rendezvous (StatusCode.PERMISSION_DENIED, scopes.) of RPC that terminated with Request had insufficient authentication>)

O stack trace e a mensagem de erro indicam que o aplicativo não tem permissões para consultar o serviço Pub/Sub.

Como criar credenciais de conta de serviço

Para fornecer ao aplicativo em execução no GKE o acesso aos serviços do Google Cloud, use contas de serviço. As contas de serviço permitem definir um conjunto de permissões de Identity and Access Management (IAM, na sigla em inglês) associadas ao aplicativo.

Console

Para criar uma conta de serviço:

  1. Acesse Contas de serviço no Console do Cloud.

    Acesse Contas de serviço

  2. Clique em + Criar conta de serviço.

  3. Em Detalhes da conta de serviço, insira o Nome da conta de serviço. Por exemplo, pubsub-app.

  4. Opcionalmente, modifique o ID da conta de serviço e adicione uma descrição.

  5. Clique em Criar.

  6. Em Conceder acesso a esta conta de serviço a um projeto, na lista suspensa Selecionar um papel, selecione Assinante do Pub/Sub.

  7. Clique em Continuar e depois em Concluído para criar a conta de serviço.

  8. Na lista de contas de serviço, ao lado da conta de serviço que você criou, clique em Ações > Gerenciar chaves.

  9. Clique em Adicionar chave > Criar nova chave.

  10. Em Tipo de chave, selecione JSON.

  11. Clique em Criar.

Depois que a chave é criada, um arquivo JSON contendo as credenciais da conta de serviço é salvo no seu computador. Use esse arquivo de chave para configurar o aplicativo para autenticação na API Pub/Sub.

Config Connector

Primeiro, faça o download do seguinte recurso como service-account.yaml.

apiVersion: iam.cnrm.cloud.google.com/v1beta1
kind: IAMServiceAccount
metadata:
  name: pubsub-app
spec:
  displayName: Service account for PubSub example

Depois, execute:

kubectl apply -f service-account.yaml

Em seguida, aplique o Papel "Assinante do Pub/Sub" à conta de serviço. Faça o download do recurso a seguir como service-account-policy.yaml. Substitua [PROJECT_ID] pelo ID do seu projeto.

apiVersion: iam.cnrm.cloud.google.com/v1beta1
kind: IAMPolicyMember
metadata:
  name: policy-member-binding
spec:
  member: serviceAccount:pubsub-app@[PROJECT_ID].iam.gserviceaccount.com
  role: roles/pubsub.subscriber
  resourceRef:
    apiVersion: resourcemanager.cnrm.cloud.google.com/v1beta1
    kind: Project
    external: projects/[PROJECT_ID]

Depois, execute:

kubectl apply -f service-account-policy.yaml

Como importar credenciais como um secret

Agora que você tem a chave da conta de serviço, você precisa de uma maneira de carregá-la no contêiner. Sua primeira ideia pode ser adicionar uma etapa no Dockerfile, mas as chaves da conta de serviço são arquivos sensíveis à segurança que não devem ser salvos em imagens de contêiner.

Em vez disso, o Kubernetes oferece o tipo de recurso Secret para ativar com segurança arquivos particulares dentro de pods no tempo de execução.

kubectl

Para salvar o arquivo de chave JSON como um Secret chamado pubsub-key, execute o seguinte comando com o caminho para o arquivo de credenciais da conta de serviço baixado:

kubectl create secret generic pubsub-key --from-file=key.json=PATH-TO-KEY-FILE.json

Esse comando cria um Secret chamado pubsub-key que tem um arquivo key.json com o conteúdo da chave privada que você fez o download do Console do GCP. Após criar o secret, remova o arquivo de chave do seu computador.

Config Connector

Faça o download do recurso a seguir como service-account-key.yaml.

apiVersion: iam.cnrm.cloud.google.com/v1beta1
kind: IAMServiceAccountKey
metadata:
  name: pubsub-key
spec:
  publicKeyType: TYPE_X509_PEM_FILE
  keyAlgorithm: KEY_ALG_RSA_2048
  privateKeyType: TYPE_GOOGLE_CREDENTIALS_FILE
  serviceAccountRef:
    name: pubsub-app

Depois, execute:

kubectl apply -f service-account-key.yaml

Como configurar o aplicativo com o secret

Para usar o secret pubsub-key no aplicativo, modifique a especificação de implantação para:

  1. Defina um volume com o secret.
  2. Ative o volume do secret para o contêiner de aplicativo.
  3. Defina a variável de ambiente GOOGLE_APPLICATION_CREDENTIALS de modo que ela aponte para o arquivo da chave no volume montado da chave secreta.

O arquivo de manifesto atualizado ficará parecido com este:

# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: pubsub
spec:
  selector:
    matchLabels:
      app: pubsub
  template:
    metadata:
      labels:
        app: pubsub
    spec:
      volumes:
      - name: google-cloud-key
        secret:
          secretName: pubsub-key
      containers:
      - name: subscriber
        image: gcr.io/google-samples/pubsub-sample:v1
        volumeMounts:
        - name: google-cloud-key
          mountPath: /var/secrets/google
        env:
        - name: GOOGLE_APPLICATION_CREDENTIALS
          value: /var/secrets/google/key.json

Neste arquivo de manifesto, os seguintes campos estão definidos para que as credenciais fiquem disponíveis para o aplicativo:

  • Um volume chamado google-cloud-key que usa o secret denominado pubsub-key.

  • Um volume montado que disponibiliza o google-cloud-key no diretório /var/secrets/google dentro do contêiner.

  • Uma variável de ambiente GOOGLE_APPLICATION_CREDENTIALS definida como /var/secrets/google/key.json, que contém o arquivo de credenciais após o secret ser ativado para o contêiner como um volume.

Observe que a variável de ambiente GOOGLE_APPLICATION_CREDENTIALS é reconhecida automaticamente pelas bibliotecas de cliente do Google Cloud que, nesse caso, é o cliente do Pub/Sub para Python.

Para implantar esse manifesto, execute:

kubectl apply -f pubsub-with-secret.yaml

Verifique se o status do pod é Running:

kubectl get pods -l app=pubsub
Saída:
NAME                     READY     STATUS    RESTARTS   AGE
pubsub-652482369-2d6h2   1/1       Running   0          29m

Como testar o recebimento de mensagens do Pub/Sub

Agora que você configurou o aplicativo, publique uma mensagem no tópico do Pub/Sub chamado echo:

gcloud pubsub topics publish echo --message="Hello, world!"

Em alguns segundos, a mensagem é recebida pelo aplicativo e exibida no stream de saída. Para inspecionar os registros do pod implantado, execute:

kubectl logs -l app=pubsub
Saída:
Pulling messages from Pub/Sub subscription...
[2017-06-19 12:31:42.501123] ID=130941112144812 Data=Hello, world!

Você configurou com sucesso a autenticação de um aplicativo no GKE na API do Pub/Sub usando credenciais de conta de serviço.

Limpeza

Para evitar cobranças na sua conta do Google Cloud pelos recursos usados no tutorial, exclua o projeto que os contém ou mantenha o projeto e exclua os recursos individuais.

  1. Remova a inscrição e o tópico do Pub/Sub:

    gcloud pubsub subscriptions delete echo-read
    gcloud pubsub topics delete echo
  2. Exclua o cluster de contêiner:

    gcloud container clusters delete pubsub-test

Próximas etapas