En este instructivo, se muestra cómo publicar mensajes desde apps para dispositivos móviles o del cliente en Pub/Sub mediante un proxy que controla la lógica de autenticación y autorización en lugar de las credenciales del cliente.
Si bien puedes autenticar mensajes del cliente a Pub/Sub con la Identity and Access Management (IAM), estas credenciales de larga duración nunca caducan. En las apps del cliente, estas credenciales se pueden descubrir mediante técnicas como la separación de aplicaciones y la ingeniería inversa.
En su lugar, puedes descargar la lógica de autenticación y autorización a un proxy que realice las siguientes tareas:
- Autenticar las solicitudes entrantes para validar al usuario
- Reenviar las solicitudes a Pub/Sub junto con los permisos de IAM adecuados
En este instructivo, se muestra cómo implementar un proxy de Pub/Sub en Google Kubernetes Engine (GKE). Este instructivo está dirigido a desarrolladores de aplicaciones y arquitectos de sistemas que definen e implementan el diseño para aplicaciones móviles o del cliente. Se supone que comprendes los conceptos fundamentales de Kubernetes y que estás familiarizado con Cloud Endpoints.
Flujo de solicitudes para este instructivo
Para comprender cómo encaja Pub/Sub en una canalización de transmisión, considera un análisis de flujo de clics. En este caso práctico, te recomendamos que comprendas cómo interactúan los usuarios con la app para dispositivos móviles. Si deseas obtener estas estadísticas, captura la actividad del usuario en tiempo real. En el siguiente diagrama, se muestra el flujo de datos.
Los datos que captura la app se envían a Pub/Sub a través de un proxy. Pub/Sub puede tener suscriptores en sentido descendente, como Dataflow o Dataproc, que agregan los datos para que puedas realizar un análisis significativo.
En el siguiente diagrama, se muestra una vista detallada del flujo de solicitud que sigue este instructivo.
En las siguientes secciones, se explica cómo interactúan los distintos componentes de este diagrama.
Autenticación de usuarios
Las aplicaciones para dispositivos móviles pueden usar varios métodos a fin de autenticar a los usuarios. El flujo de autenticación es específico de tu app. En este instructivo, se muestra una de esas soluciones para autenticar usuarios. Este instructivo está acompañado de una implementación de esta solución.
Solicitudes de la app cliente al proxy de Pub/Sub
El backend de la app genera un token de autenticación de corta duración que el cliente almacena de forma local (por ejemplo, mediante el sistema Android Keystore o los servicios de llavero de iOS). En este instructivo, se usan tokens de ID de OpenID Connect (OIDC) para autenticar la app cliente. Google emite y firma el token de ID de OIDC.
La app del lado del cliente envía una solicitud al proxy de Pub/Sub mediante el token de ID de OIDC. El proxy de Pub/Sub valida el token y reenvía la solicitud a Pub/Sub junto con las credenciales de IAM adecuadas.
Publica mensajes
Una vez que la app cliente se autentica de forma correcta, el proxy de Pub/Sub envía una solicitud de publicación a Pub/Sub. Con la IAM, Pub/Sub ayuda a garantizar que el emisor (el proxy de Pub/Sub) tenga los permisos correspondientes para enviar solicitudes de publicación. En este instructivo, el proxy de Pub/Sub usa la cuenta de servicio predeterminada de Compute Engine para autenticarse con Pub/Sub. La cuenta de servicio predeterminada de Compute Engine tiene la función de IAM de Editor (roles/editor
), que brinda acceso de publicador al proxy de Pub/Sub.
Objetivos
- Crear un clúster de GKE para ejecutar un proxy de Pub/Sub
- Crear un tema de Pub/Sub
- Implementar el proxy de Pub/Sub
- Configurar Endpoints para autenticar solicitudes en el proxy de Pub/Sub
- Verificar que los mensajes se publiquen en Pub/Sub
Costos
En este documento, usarás los siguientes componentes facturables de Google Cloud:
Para generar una estimación de costos en función del uso previsto, usa la calculadora de precios.
Cuando finalices las tareas que se describen en este documento, puedes borrar los recursos que creaste para evitar que continúe la facturación. Para obtener más información, consulta Cómo realizar una limpieza.
Antes de comenzar
-
En la consola de Google Cloud, ve a la página del selector de proyectos.
-
Selecciona o crea un proyecto de Google Cloud.
-
Asegúrate de que la facturación esté habilitada para tu proyecto de Google Cloud.
-
En la consola de Google Cloud, activa Cloud Shell.
En la parte inferior de la consola de Google Cloud, se inicia una sesión de Cloud Shell en la que se muestra una ventana de línea de comandos. Cloud Shell es un entorno de shell con Google Cloud CLI ya instalada y con valores ya establecidos para el proyecto actual. La sesión puede tardar unos segundos en inicializarse.
- Define las variables de entorno que necesitas para este instructivo:
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"
- Habilita las APIs para Cloud Build, Compute Engine,
Google Kubernetes Engine, Artifact Analysis, Container Registry,
Endpoints, Administración de servicios, Control de servicios y
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
Crea un tema de Pub/Sub
En Cloud Shell, crea un tema de Pub/Sub en el que publiques mensajes:
gcloud pubsub topics create $TOPIC
Crea un clúster de GKE
En Cloud Shell, crea un clúster de GKE:
gcloud container clusters create $CLUSTER \ --zone $ZONE \ --scopes "https://www.googleapis.com/auth/cloud-platform"
Obtén credenciales para el clúster en ejecución:
gcloud container clusters get-credentials $CLUSTER \ --zone $ZONE \ --project $PROJECT
Compila una imagen de contenedor
En Cloud Shell, clona el repositorio de código:
git clone https://github.com/GoogleCloudPlatform/solutions-pubsub-proxy-rest
Usa Cloud Build para compilar una imagen de contenedor desde la fuente y, luego, guárdala en Container Registry:
cd solutions-pubsub-proxy-rest && \ gcloud builds submit --tag gcr.io/$PROJECT/pubsub-proxy:v1
Crea una dirección IP externa estática
En Cloud Shell, crea una dirección IP externa estática que luego se asigne al balanceador de cargas del proxy de Pub/Sub:
gcloud compute addresses create service-ip --region $REGION
Almacena la dirección IP estática en una variable de entorno,
PROXY_IP
:PROXY_IP=$(gcloud compute addresses describe service-ip \ --region $REGION --format='value(address)')
Implementa Endpoints
El proxy de Pub/Sub usa Endpoints para autenticar las solicitudes de los usuarios. Endpoints usa el proxy de servicio extensible (ESP) para proporcionar funciones de administración de API como autenticación, supervisión, seguimiento y administración del ciclo de vida de la API. En este instructivo, se usa Endpoints solo para autenticar solicitudes entrantes al proxy de Pub/Sub.
En este instructivo, implementarás el ESP como un archivo adicional con el proxy de Pub/Sub. El ESP intercepta y autentica las solicitudes entrantes antes de reenviarlas al proxy de Pub/Sub.
En Cloud Shell, reemplaza el marcador de posición
[PROJECT_ID]
por el ID de tu proyecto de Google Cloud en el archivoopenapi.yaml
:sed -i -e "s/\[PROJECT_ID\]/$PROJECT/g" openapi.yaml
En el archivo de manifiesto de OpenAPI, reemplaza el marcador de posición
[IP_ADDRESS]
por el valor dePROXY_IP
:sed -i -e "s/\[IP_ADDRESS\]/$PROXY_IP/g" openapi.yaml
Implementa la definición del servicio de OpenAPI en Endpoints:
gcloud endpoints services deploy openapi.yaml
El comando anterior crea lo que se muestra a continuación:
- Un servicio administrado con el nombre que especificaste en el campo de host del archivo
openapi.yaml
(pubtest.endpoints.project-id.cloud.goog
), en el queproject-id
es el ID de tu proyecto de Google Cloud. - Un registro A de DNS que usa el nombre del servicio y la asignación de dirección IP del balanceador de cargas del proxy de Pub/Sub que se define en la extensión
x-google-endpoints
en el archivoopenapi.yaml
.
Durante la implementación, verás una advertencia que puedes ignorar, ya que en este instructivo se usan tokens de ID de OIDC para la autenticación en lugar de claves 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'.
- Un servicio administrado con el nombre que especificaste en el campo de host del archivo
Comprueba si el servicio se implementó de forma correcta:
gcloud endpoints services describe ${ENDPOINTS_SERVICE}
El resultado es similar al siguiente:
[...] 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
En el resultado verás lo siguiente:
project-id
: El ID del proyecto de Google Cloud.
Implementa un proxy
En Cloud Shell, genera un certificado SSL autofirmado para permitir conexiones HTTPS al proxy.
openssl req -x509 -nodes -days 365 \ -newkey rsa:2048 -keyout ./nginx.key \ -out ./nginx.crt \ -subj "/CN=${ENDPOINTS_SERVICE}"
Crea un secreto de Kubernetes mediante el certificado SSL y la clave privada:
kubectl create secret generic nginx-ssl \ --from-file=./nginx.crt \ --from-file=./nginx.key
Reemplaza el marcador de posición
[PROJECT_ID]
en el archivo de manifiesto de la implementación por el ID del proyecto de Google Cloud:sed -i -e "s/\[PROJECT_ID\]/$PROJECT/g" kube/deployment.yaml
Reemplaza el marcador de posición
[IP_ADDRESS]
en el archivo de manifiesto de servicio por el valor dePROXY_IP
:sed -i -e "s/\[IP_ADDRESS\]/$PROXY_IP/g" kube/service.yaml
Implementa el proxy:
kubectl apply -f kube/
Verifica que la implementación sea exitosa:
kubectl rollout status deployment/pubsub-proxy
El resultado es similar al siguiente:
[...] deployment "pubsub-proxy" successfully rolled out
Asegúrate de que dos contenedores (ESP y proxy de Pub/Sub) se estén ejecutando en el Pod:
kubectl get pods $(kubectl get pod \ -l app=pubsub-proxy \ -o jsonpath="{.items[0].metadata.name}") \ -o jsonpath={.spec.containers[*].name}
El resultado es similar al siguiente:
esp pubsub-proxy
Busca el valor de
EXTERNAL-IP
para cambiar de<pending>
a la dirección IP externa estática que creaste antes:kubectl get svc pubsub-proxy -w
El resultado es similar al siguiente:
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 detener la reproducción, presiona
CTRL+C
.Una vez que el proxy de Pub/Sub se implementa de forma correcta, se expone en
https://${ENDPOINTS_SERVICE}/publish
. Es posible que la nueva configuración de DNS tarde algunos minutos en propagarse.Verifica la configuración de DNS:
watch nslookup ${ENDPOINTS_SERVICE}
El resultado es similar al siguiente:
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
En el resultado verás lo siguiente:
gke-load-balancer-ip
: La dirección IP de tu balanceador de cargas de GKE (IP del proxy).
Para detener la reproducción, presiona
CTRL+C
.
Si alguno de los pasos anteriores genera un error, consulta los pasos para solucionar problemas.
Genera un token de autenticación
El siguiente procedimiento para generar un token de autenticación se proporciona como ejemplo. Para tu entorno de producción, necesitas una forma de que los usuarios generen sus propios tokens de autenticación. Por ejemplo, puedes encontrar código de muestra para obtener un token de ID de OIDC de manera programática en la documentación de Identity-Aware Proxy.
Para generar un token de autenticación, haz lo siguiente:
Crea una cuenta de servicio de Google Cloud para la que generes un token de ID de OIDC:
gcloud iam service-accounts create \ $SERVICE_ACCOUNT \ --display-name $SERVICE_ACCOUNT
Obtén la identidad de correo electrónico de la cuenta de servicio:
SA_EMAIL=${SERVICE_ACCOUNT}@${PROJECT}.iam.gserviceaccount.com
Otorga la función de IAM de Creador de tokens de cuentas de servicio (
roles/iam.serviceAccountTokenCreator
) para la cuenta de servicio:gcloud iam service-accounts add-iam-policy-binding $SA_EMAIL \ --member user:$(gcloud config get-value account) \ --role roles/iam.serviceAccountTokenCreator
Mediante la API de credenciales de IAM, genera un token de ID de 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")
El nombre del servicio de Endpoints se especifica en el campo
audience
. La reclamaciónaudience
identifica el destinatario al que está destinado el token.Verifica que el token se haya creado de forma correcta:
echo $TOKEN
El token web JSON (JWT) es similar al siguiente:
eyJhbGciOiJSUzI1NiIsImtpZCI6IjY4NjQyODlm[...].eyJhdWQiOiJwdWJ0ZXN0LmVuZHBvaW50cy52aXR hbC1vY3RhZ29uLTEwOTYxMi5jbG91ZC5nb[...].SjBI4TZjZAlYo6lFKkrvfAcVUp_AJzFKoSsjNbmD_n[...]
Llama a Pub/Sub mediante un proxy
En Cloud Shell, publica un mensaje de prueba:
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"}]}'
El resultado es similar al siguiente:
HTTP/2 200 server: nginx date: Sun, 02 Jun 2019 03:53:46 GMT ...
Comprueba si el mensaje se publicó de forma correcta en el tema de Pub/Sub:
kubectl logs -f --tail=5 deployment/pubsub-proxy -c pubsub-proxy
En los registros de implementación del proxy de Pub/Sub, se muestra el mensaje
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
Soluciona problemas
En Cloud Shell, verifica el estado de ambos contenedores en el Pod del proxy de Pub/Sub:
kubectl describe pods $(kubectl get pod -l app=pubsub-proxy \ -o jsonpath="{.items[0].metadata.name}")
En el resultado del registro, el estado de los contenedores es
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 [...]
Verifica los registros del contenedor para ver si hay otros errores (opcional). Por ejemplo, para verificar los registros del proxy de Pub/Sub, ejecuta el siguiente comando:
kubectl logs -f --tail=10 deployment/pubsub-proxy -c pubsub-proxy
Para obtener ayuda con la solución de problemas, consulta los siguientes documentos:
Limpia
Para evitar que se apliquen cargos a tu cuenta de Google Cloud por los recursos que utilizaste en este instructivo, puedes borrar el proyecto de Google Cloud que creaste para este instructivo o borrar los recursos asociados con este instructivo.
Borra el proyecto de Google Cloud
La manera más fácil de eliminar la facturación es borrar el proyecto que creaste para el instructivo.
- En la consola de Google Cloud, ve a la página Administrar recursos.
- En la lista de proyectos, elige el proyecto que quieres borrar y haz clic en Borrar.
- En el diálogo, escribe el ID del proyecto y, luego, haz clic en Cerrar para borrar el proyecto.
Borra recursos
Si deseas conservar el proyecto de Google Cloud que usaste en este instructivo, borra los recursos individuales:
En Cloud Shell, borra el clúster de GKE:
gcloud container clusters delete $CLUSTER --zone $ZONE --async
Borra el código descargado, los artefactos y otras dependencias:
cd .. && rm -rf solutions-pubsub-proxy-rest
Borra la imagen en 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:{}
Borra el tema de Pub/Sub :
gcloud pubsub topics delete $TOPIC
Borra la cuenta de servicio:
gcloud iam service-accounts delete $SA_EMAIL
Borrar Endpoints:
gcloud endpoints services delete ${ENDPOINTS_SERVICE}
Borra la dirección IP estática:
gcloud compute addresses delete service-ip --region $REGION
¿Qué sigue?
- Obtén más información sobre la autenticación con Endpoints.
- Obtén información sobre la arquitectura para usar Pub/Sub en tareas de larga duración.
- Explora arquitecturas de referencia, diagramas y prácticas recomendadas sobre Google Cloud. Consulta nuestro Cloud Architecture Center.