Autenticar 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 Cloud Platform y usar credenciales de cuentas de servicio en aplicaciones que se ejecutan en GKE.

En este ejemplo, se usa Cloud Pub/Sub, aunque las instrucciones se pueden aplicar a cualquier servicio de Cloud Platform. La aplicación de ejemplo de este instructivo se autentica en Cloud Pub/Sub con 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 Cloud 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. Usa gcloud para publicar mensajes y, también, inspeccionar el flujo de los resultados del contenedor a fin de observar si los mensajes se reciben de forma correcta.

¿Por qué es necesario usar cuentas de servicio?

Cada nodo de un clúster de contenedor es una instancia de Compute Engine. Por lo tanto, las aplicaciones que se ejecutan en un clúster de contenedor heredan, según la configuración predeterminada, los alcances de las instancias de Compute Engine en las que se implementan.

Google Cloud Platform crea de forma automática una cuenta de servicio denominada "Cuenta de servicio predeterminada de Compute Engine", y GKE la asocia con los nodos que crea. Según la configuración del proyecto, la cuenta de servicio predeterminada puede o no tener permisos para usar otras API de Cloud Platform. GKE también asigna algunos niveles de acceso limitados a instancias de procesamiento. No se recomienda actualizar los permisos de la cuenta de servicio predeterminada ni asignar más niveles de acceso a las instancias de procesamiento para autenticarte en otros servicios de Cloud Platform desde los pods que se ejecutan en GKE.

El método recomendado de autenticación en los servicios de Google Cloud Platform desde aplicaciones que se ejecutan en GKE es crear tus propias cuentas de servicio. Lo ideal sería que crearas una cuenta de servicio nueva para cada aplicación que realice solicitudes a las API de Cloud Platform.

Estos son los beneficios de tener cuentas de servicio independientes para aplicaciones diferentes:

  • 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 revocar el acceso a la API de todas las aplicaciones a la vez.

  • 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 tener habilitada la facturación para tu proyecto de Google Cloud Platform. Obtén información sobre cómo confirmar que tienes habilitada la facturación para tu proyecto.

Instala las siguientes herramientas de línea de comandos que se usan en 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

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 los valores predeterminados:
gcloud config set project [PROJECT_ID]
gcloud config set compute/zone [COMPUTE_ENGINE_ZONE]

Habilita la API de Pub/Sub

A fin de seguir este instructivo, debes habilitar la API de Cloud Pub/Sub en el proyecto, ya que la aplicación de muestra la usa para recibir mensajes del tema de Pub/Sub:

Habilita lasAPI

Crea un clúster de 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

Paso 1: Crea un tema de Pub/Sub

En la aplicación de suscripción a Pub/Sub que implementarás, se usa una suscripción denominada echo-read en un tema de Pub/Sub con nombre 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 tu clúster.

apiVersion: pubsub.cnrm.cloud.google.com/v1alpha2
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/v1alpha2
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

Paso 2: Implementa la aplicación de suscripción a Pub/Sub

El siguiente paso es implementar 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, y puedes buscar 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:

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, descárgalo en tu máquina como pubsub.yaml y 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
Resultado:
NAME                      READY     STATUS             RESTARTS   AGE
pubsub-2009462906-1l6bh   0/1       CrashLoopBackOff   1          30s

Puedes ver que el contenedor tiene fallas para iniciarse y que entró en un estado CrashLoopBackOff. Ejecuta lo siguiente para inspeccionar los registros del pod:

kubectl logs -l app=pubsub
Salida:
...
google.gax.errors.RetryError: GaxError(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 la pila y el mensaje de error indican que la aplicación no tiene permisos para consultar el servicio de Cloud Pub/Sub.

Paso 3: Crea credenciales de una cuenta de servicio

Para proporcionar a las aplicaciones que se ejecutan en GKE acceso a los servicios de Google Cloud Platform, debes usar cuentas de servicio.

Console

Para crear una cuenta de servicio, ve a cuentas de servicio en Cloud Console y haz clic en Crear cuenta de servicio:

  1. Especifica un Nombre de cuenta de servicio (por ejemplo, pubsub-app).
  2. En el menú desplegable Función, selecciona "Pub/Sub → Suscriptor".
  3. Haz clic en Crear clave y elige el tipo de clave JSON.
  4. Haz clic en Crear.

Una vez creada la cuenta de servicio, un archivo de claves JSON que contiene las credenciales de la cuenta de servicio se descarga en tu computadora. Debes usar este archivo de claves a fin de configurar la aplicación para autenticarte en la API de Cloud Pub/Sub.

Config Connector

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

apiVersion: iam.cnrm.cloud.google.com/v1alpha1
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/v1alpha1
kind: IAMPolicyMember
metadata:
  name: policy-member-binding
spec:
  member: serviceAccount:pubsub-app@[PROJECT_ID].iam.gserviceaccount.com
  role: roles/pubsub.subscriber
  resourceRef:
    kind: Project
    name: [PROJECT_ID]

Luego, ejecuta el comando siguiente:

kubectl apply -f service-account-policy.yaml

Paso 4: Importa credenciales como un secreto

Kubernetes ofrece el tipo de recurso secreto para almacenar credenciales dentro del clúster del contenedor y usarlas en las aplicaciones implementadas directamente en GKE.

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. Una vez creado el secreto, debes quitar el archivo de claves de tu computadora.

Config Connector

Descarga el recurso siguiente como service-account-key.yaml.

apiVersion: iam.cnrm.cloud.google.com/v1alpha1
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 el comando siguiente:

kubectl apply -f service-account-key.yaml

Paso 5: Configura la aplicación con el secreto

A fin de usar el secreto pubsub-key en tu aplicación, debes modificar la especificación de implementación para realizar las acciones siguientes:

  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:

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 define lo siguiente a fin de que las credenciales estén disponibles para la aplicación:

  • Un volumen denominado google-cloud-key que usa el secreto con el nombre pubsub-key.

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

  • La variable de entorno GOOGLE_APPLICATION_CREDENTIALS configurada como /var/secrets/google/key.json, que contendrá el archivo de credenciales cuando el secreto se active como un volumen en el contenedor.

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, el cliente de Cloud Pub/Sub para Python.

Para implementar este manifiesto, descárgalo en tu máquina como pubsub-with-secret.yaml y ejecuta lo siguiente:

kubectl apply -f pubsub-with-secret.yaml

Una vez implementado de forma correcta, el estado del pod debe mostrarse como Running:

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

Paso 6: Prueba la recepción de 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 resultados. 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.

Limpieza

Sigue estos pasos para evitar que se apliquen cargos a tu cuenta de Google Cloud Platform por los recursos que usaste en este instructivo:

  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

Próximos pasos