Autentícate en Google Cloud Platform con cuentas de servicio

En este instructivo, se muestra cómo crear una cuenta de servicio de Google Cloud, asignar funciones para autenticarte en los servicios de Google Cloud y usar las credenciales de la cuenta de servicio en las aplicaciones que se ejecutan en Google Kubernetes Engine (GKE).

En este ejemplo, se usa Pub/Sub, aunque las instrucciones se pueden aplicar a cualquier servicio de Google Cloud. La aplicación de ejemplo de este instructivo se autentica en Pub/Sub mediante una cuenta de servicio y se suscribe a los mensajes publicados en un tema de Pub/Sub desde una aplicación basada en Python.

Objetivos

En este instructivo se analizan los siguientes pasos:

  • Cómo se crea una cuenta de servicio.
  • Cómo se asignan las funciones necesarias para que la cuenta de servicio funcione con Pub/Sub.
  • Cómo se guarda la clave de la cuenta como un secreto de Kubernetes,
  • Cómo se usa la cuenta de servicio para implementar y configurar una aplicación

La aplicación de muestra que se usa en este instructivo se suscribe a un tema de Pub/Sub y, también, imprime los mensajes publicados en los resultados estándar. Debes configurar la aplicación con los permisos correctos, usar gcloud command-line tool para publicar mensajes e inspeccionar el flujo de salida del contenedor a fin de observar si los mensajes se reciben de forma correcta.

Autentícate con cuentas de servicio

Puedes autenticarte en los servicios de Google Cloud con cuentas de servicio internas a GKE mediante Workload Identity, la cuenta de servicio predeterminada de Compute Engine o los objetos Secret.

Usa Workload Identity

Workload Identity es la forma recomendada para autenticarse en los servicios de Google Cloud desde GKE. Workload Identity te permite configurar las cuentas de servicio de Google Cloud mediante recursos de Kubernetes. Si este método de autenticación se ajusta a tu caso de uso, debe ser tu primera opción. Este ejemplo tiene como objetivo describir casos de uso en los que Workload Identity no es una buena opción.

Usa la cuenta de servicio predeterminada de Compute Engine

Cada nodo en un clúster de GKE es una instancia de Compute Engine. Por lo tanto, las aplicaciones que se ejecutan en un clúster de GKE intentarán autenticarse de forma predeterminada con la “cuenta de servicio predeterminada de Compute Engine” y heredar los permisos asociados.

Es posible que esta cuenta de servicio predeterminada no tenga permisos para usar los servicios de Google Cloud que necesitas. Es posible expandir los permisos de la cuenta de servicio predeterminada, pero esa acción puede generar riesgos de seguridad y no se recomienda.

Administra las credenciales de la cuenta de servicio mediante objetos Secret

Puedes crear una cuenta de servicio para tu aplicación y, luego, insertar la clave de autenticación como un secreto de Kubernetes. Este instructivo se enfoca en esta opción.

¿Por qué es necesario usar cuentas de servicio?

El uso de cuentas de servicio independientes para diferentes aplicaciones proporciona los siguientes beneficios:

  • Mejor visibilidad y auditoría de las solicitudes a la API que realiza la aplicación

  • La capacidad de revocar claves de aplicaciones particulares, en lugar de compartir una cuenta de servicio y tener que revocar el acceso a la API de todas las aplicaciones al mismo tiempo

  • Exposición reducida en el caso de un incidente de seguridad posible en el que las credenciales de la cuenta de servicio se vuelvan vulnerables.

Antes de comenzar

Sigue los pasos que se indican a continuación para habilitar la API de Kubernetes Engine:
  1. Consulta la página de Kubernetes Engine en Google Cloud Console.
  2. Crea o selecciona un proyecto.
  3. Espera a que la API y los servicios relacionados se habiliten. Esto puede tardar varios minutos.
  4. Asegúrate de que la facturación esté habilitada para tu proyecto de Cloud. Descubre cómo confirmar que tienes habilitada la facturación en un proyecto.

Instala las siguientes herramientas de línea de comandos de este instructivo:

  • gcloud se usa para crear y borrar clústeres de Kubernetes Engine. gcloud se incluye en el SDK de Google Cloud.
  • kubectl se usa para administrar Kubernetes, el sistema de organización de clústeres que emplea Kubernetes Engine. Puedes instalar kubectl con gcloud:
    gcloud components install kubectl

Clona el código de ejemplo desde GitHub:

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

Establece valores predeterminados para la herramienta de línea de comandos de gcloud

Para ahorrar tiempo cuando escribes las opciones del ID del proyecto y la zona de Compute Engine en la herramienta de línea de comandos de gcloud, puedes establecer valores predeterminados:
gcloud config set project project-id
gcloud config set compute/zone compute-zone

Habilite las API

Para este instructivo, habilita la API de Pub/Sub y la API de Resource Manager en tu proyecto:

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

Crea un cluster del contenedor

Crea un clúster de contenedor con el nombre pubsub-test para implementar la aplicación de suscripción a Pub/Sub:

gcloud container clusters create pubsub-test

Crea un tema de Pub/Sub

La aplicación de suscriptor de Pub/Sub usa una suscripción llamada echo-read en un tema de Pub/Sub llamado echo. Crea estos recursos antes de implementar la aplicación.

Primero, crea un tema Pub/Sub:

gcloud

gcloud pubsub topics create echo

Config Connector

Nota: En este paso, se necesita Config Connector. Sigue las instrucciones de instalación para instalar Config Connector en el clúster.

apiVersion: pubsub.cnrm.cloud.google.com/v1beta1
kind: PubSubTopic
metadata:
  name: echo
Para implementar este manifiesto, descárgalo en tu máquina como topic.yaml y ejecuta lo siguiente:
kubectl apply -f topic.yaml

Luego, crea una suscripción:

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 implementar este manifiesto, descárgalo en tu máquina como subscription.yaml y ejecuta lo siguiente:
kubectl apply -f subscription.yaml

Implementa una aplicación de suscriptor de Pub/Sub

A continuación, implementa el contenedor de la aplicación para recuperar los mensajes publicados en el tema de Pub/Sub. Esta aplicación se escribe en Python mediante las bibliotecas cliente de Google Cloud Pub/Sub. Puedes encontrar el código fuente en GitHub.

En el siguiente archivo de manifiesto, se describe una implementación que ejecuta una instancia única de la imagen de Docker de esta aplicación:

# 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 implementar este manifiesto, ejecuta lo siguiente:

kubectl apply -f pubsub.yaml

Una vez implementada la aplicación, ejecuta lo siguiente para consultar los pods:

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

Puedes ver que el contenedor no lograr iniciar y se encuentra en estado CrashLoopBackOff. Ejecuta lo siguiente para inspeccionar los registros del pod:

kubectl logs -l app=pubsub

Salida:

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

El seguimiento de pila y el mensaje de error indican que la aplicación no tiene permisos para consultar el servicio de Pub/Sub.

Crea credenciales de la cuenta de servicio

Para permitir que tu aplicación que se ejecuta en GKE acceda a los servicios de Google Cloud, usa cuentas de servicio. Las cuentas de servicio te permiten definir un conjunto de permisos de administración de identidades y accesos (IAM) asociados con tu aplicación.

Console

Para crear una cuenta de servicio:

  1. Ve a Cuentas de servicio en Cloud Console.

    Ir a Cuentas de servicio

  2. Haz clic en  Crear cuenta de servicio.

  3. En Detalles de la cuenta de servicio, ingresa un Nombre de cuenta de servicio (por ejemplo, pubsub-app).

  4. De manera opcional, modifica el ID de cuenta de servicio y agrega una descripción.

  5. Haga clic en Crear.

  6. En Otorga a esta cuenta de servicio acceso a un proyecto, en la lista desplegable Seleccionar una función, selecciona Suscriptor de Pub/Sub.

  7. Haz clic en Continuar y, luego, en Listo para crear la cuenta de servicio.

  8. En la lista de cuentas de servicio, junto a la cuenta de servicio que creaste, haz clic en Acciones> Administrar claves.

  9. Haz clic en AGREGAR CLAVE -> Crear nueva clave.

  10. En Tipo de clave, selecciona JSON.

  11. Haga clic en Crear.

Después de crear la clave, se descarga en tu computadora un archivo JSON con las credenciales de la cuenta de servicio. Debes usar este archivo de claves a fin de configurar la aplicación para autenticarte en la API de Pub/Sub.

Config Connector

Primero, descarga el recurso siguiente como service-account.yaml.

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

Luego, ejecuta el comando siguiente:

kubectl apply -f service-account.yaml

A continuación, aplica la Función del “Suscriptor de Pub/Sub” a la cuenta de servicio. Descarga el recurso siguiente como service-account-policy.yaml. Reemplaza [PROJECT_ID] por el ID del proyecto.

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]

Luego, ejecuta lo siguiente:

kubectl apply -f service-account-policy.yaml

Importa credenciales como un objeto Secret

Ahora que tienes la clave de la cuenta de servicio, necesitas una forma de cargarla en tu contenedor. Tu primera idea podría ser agregar un paso en el Dockerfile, pero las claves de la cuenta de servicio son archivos sensibles a la seguridad que no se deben guardar en imágenes de contenedor.

En su lugar, Kubernetes ofrece el tipo de recurso Secreto para activar de forma segura los archivos privados dentro de los Pods en el entorno de ejecución.

kubectl

Para guardar el archivo de claves JSON como un secreto con el nombre pubsub-key, ejecuta el comando siguiente con la ruta al archivo de las credenciales de la cuenta de servicio descargado:

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

Con este comando, se crea un secreto con el nombre pubsub-key que tiene un archivo key.json con los contenidos de la clave privada que descargaste de Cloud Console. Después de crear el objeto Secret, quita el archivo de claves de tu computadora.

Config Connector

Descarga el recurso siguiente 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

Luego, ejecuta lo siguiente:

kubectl apply -f service-account-key.yaml

Cómo configurar la aplicación con el objeto Secret

A fin de usar el objeto Secret pubsub-key en tu aplicación, modifica la especificación de la implementación para realizar lo siguiente:

  1. Definir un volumen con el secreto
  2. Activar el volumen del secreto en el contenedor de la aplicación
  3. Configurar la variable de entorno GOOGLE_APPLICATION_CREDENTIALS para señalar el archivo de claves en la activación del volumen del secreto

El archivo de manifiesto actualizado se verá como el siguiente:

# 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

En este archivo de manifiesto, se definen los siguientes campos a fin de que las credenciales estén disponibles para la aplicación:

  • Un volumen denominado google-cloud-key que usa el objeto Secret con el nombre pubsub-key

  • Una activación de volumen que hace que google-cloud-key esté disponible en el directorio /var/secrets/google dentro del contenedor

  • Una variable de entorno GOOGLE_APPLICATION_CREDENTIALS configurada como /var/secrets/google/key.json, que contiene el archivo de credenciales después de que el secreto se active en el contenedor como un volumen

Ten en cuenta que las bibliotecas cliente de Google Cloud reconocen de forma automática la variable de entorno GOOGLE_APPLICATION_CREDENTIALS. En este caso, es el cliente de Pub/Sub para Python.

Para implementar este manifiesto, ejecuta lo siguiente:

kubectl apply -f pubsub-with-secret.yaml

Verifica que el estado del pod sea Running:

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

Prueba la recepción de los mensajes de Pub/Sub

Ahora que ya configuraste la aplicación, publica un mensaje para el tema de Pub/Sub con el nombre echo:

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

En pocos segundos, la aplicación debe tomar el mensaje para después imprimirlo en el flujo de salida. Para inspeccionar los registros desde el pod implementado, ejecuta lo siguiente:

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

Configuraste correctamente una aplicación en GKE para autenticarte en la API de Pub/Sub con las credenciales de la cuenta de servicio.

Realice una limpieza

Para evitar que se apliquen cargos a tu cuenta de Google Cloud por los recursos usados en este instructivo, borra el proyecto que contiene los recursos o conserva el proyecto y borra los recursos individuales.

  1. Limpia la suscripción y el tema de Pub/Sub:

    gcloud pubsub subscriptions delete echo-read
    gcloud pubsub topics delete echo
  2. Borra el clúster del contenedor:

    gcloud container clusters delete pubsub-test

¿Qué sigue?