GCP CloudRun en acción
Integrando Secret Manager
En esta serie de capítulos pondremos a prueba la versatilidad que ofrece CloudRun, de Google Cloud Platform.
CloudRun es una plataforma de cómputo de la familia Serverless, que permite desplegar aplicaciones dentro de contenedores completamente administrados. Una de las características más significativas es que no tienes que dedicarle esfuerzo a administrar el cluster y además sólo pagas por uso.
Veamos una tabla comparativa entre algunas alternativas de cómputo que existen para desplegar aplicaciones, con el fin de que apreciemos los beneficios de CloudRun y nos dé una idea de cuándo utilizarlo.
A continuación vamos a describir un escenario para poder dar contexto a la solución que implementaremos.
La problemática:
Tenemos una base de datos para un ecommerce, la cual almacena información de los clientes y sus compras. Al final de cada mes hay miles de registros lo que hace cada vez más ineficientes las búsquedas de información. Ademas los costos de almacenamiento aumentan día a día.
Requerimiento:
Implementar una aplicación que cada cierto tiempo borre las órdenes de compra confirmadas que tienen una antigüedad mayor a x días (Tú podrías implementar un mecanismo de respaldo previo de esas órdenes antes de eliminarlas de la base de datos).
Elección del producto:
Para el análisis y elección del/los producto/s que vamos a utilizar, nos vamos a enfocar en 3 puntos importantes:
1.- Costo: Dado que el proceso de borrado de información no es frecuente, quizás una vez al mes o a la semana, no necesitamos mantener disponible esta funcionalidad 7*24. Para ahorrar, además queremos pagar solo por el “uso”.
2.- Administración: Dado que no se justifica tener un administrador de la infraestructura, optaremos por privilegiar un producto autoadministrado por GCP. Esto nos permitirá además enfocar los esfuerzos en el desarrollo.
3.- Despliegue: Dado que queremos disponer de esta solución lo más rápido posible en Producción, privilegiaremos un producto que tenga un fácil acople a un flujo de integración y despliegue continuo (pipeline)
Los candidatos naturales que nos permitirían tener activa nuestra aplicación solo el tiempo que necesitemos usarla, lo cual también nos permitirá ahorrar en costos, serían CloudRun (se activa cuando la utilicemos y se desactiva cuando termina su ejecución) y AppEngine Standard (escala a 0). Seleccionaremos en esta oportunidad CloudRun dado que es un producto reciente de GCP que queremos experimentar y nos puede dar la versatilidad que necesitamos para implementar la solución completa, considerando los 3 puntos mencionados anteriormente.
Solución
En este capitulo abordaremos la primera problemática que consiste en implementar un componente sencillo que sea capaz de utilizar los datos de configuración que sean sensibles de forma segura.
En los próximos capítulos iremos abordando la solución completa
Vamos por este desafío!
Requisitos Técnicos
Gradle: 6.3+
Google Cloud Platform
- Una cuenta personal de Google Cloud
- SDK de Google Cloud
Recuerda autenticarte con tu cuenta personal antes de iniciar el proceso. Para esto, debes abrir un terminal y debes ejecutar:
$ gcloud auth login
Chequear tu proyecto GCP por defecto
Antes de partir te recomiendo que revises cual es tu proyecto GCP por defecto que tienes configurado en tu ambiente.
$ gcloud config get-value project
Si no es el proyecto GCP que tu requieres, debes configurarlo:
$ gcloud config set project [GCP_PROJECT_ID]
Por ejemplo:
$ gcloud config set project architect-poc
Cuenta de servicio GCP
Debemos crear una cuenta de servicio especializada que nos permita tener acceso a todos los recursos necesarios.
Para que la aplicación pueda acceder a los secretos que estarán resguardados en Secret Manager, debemos asignarle a nuestra cuenta de servicio los siguientes roles:
- Secret Manager Admin
- Secret Manager Secret Accessor
Para que tengamos acceso a Cloud Storage, el cual será necesario cuando subamos la imagen de nuestra aplicación, debemos asignarle a nuestra cuenta de servicio el siguiente rol:
- Storage Object Admin
Debes seguir los siguientes pasos en la consola de GCP:
Incluir los roles Secret Manager Admin y Secret Manager Secret Accessor
Además, debes incluir el rol Storage Object Admin para que podamos subir la imagen en un bucket de Cloud Storage.
Haz click en [DONE]
Tu cuenta de servicio se debería ver así:
Pincha sobre tu cuenta de servicio
Crea una nueva Key [Create New Key]
Haz click en [CREATE]
Se descargará en tu computador un archivo con extensión json. Muévelo en tu computador a una ruta conocida, la que utilizarás más adelante para configurar una variable de entorno.
Diseño de la solución
La solución consiste en un microservicio que implementará la funcionalidad de limpiar los datos antiguos de una tabla especifica de la base de datos. Los datos sensibles no los configuraremos dentro de la aplicación sino que serán externalizados para una mayor flexibilidad y seguridad.
Esta aplicación se desplegará y ejecutará sobre CloudRun y estará integrada con Secret Manager, para otorgar un mayor nivel de seguridad a nuestros datos sensibles.
Para el empaquetado de la solución usaremos CloudBuild. En el siguiente diagrama se muestran los componentes GCP involucrados en la solución y sus interacciones.
En esta primera versión, el objetivo es implementar un microservicio que se despliegue en CloudRun y que sea capaz de obtener los valores sensibles que están guardados en Secret Manager.
Productos GCP
CloudRun: Plataforma de cómputo serverless autoadministrada
CloudBuild: Herramienta para crear y desplegar la imagen
Container Registry: Herramienta para gestionar las imágenes
Secret Manager: Herramienta para resguardar nuestros datos sensibles
Implementación de la solución
1.- Crear proyecto base
Utilizaremos Springboot.
Puedes armar tu propio proyecto base o descargar el proyecto de referencia de este artículo.
2.- Crear Secretos
Para configurar la información sensible de nuestra aplicación, utilizaremos Secret Manager de GCP. Para este fin, se deben realizar los siguientes pasos:
Acceder a Secret Manager
Habilitar la API
Crear Mi Primer Secreto. Presionar “CREATE SECRET”
Asignar el nombre y valor de cada secreto
En este caso, vamos a crear 2 secretos:
+============+==============+========+=======+
| Name | Secret Value | Labels | |
+============+==============+========+=======+
| | | Key | Value |
+------------+--------------+--------+-------+
| CL_DB_USER | democl | tenant | cl |
+------------+--------------+--------+-------+
| CL_DB_PWD | democl2020 | tenant | cl |
+------------+--------------+--------+-------+
Estos secretos los vamos a utilizar a lo largo de toda la serie.
3.- Implementar la solución
Los aspectos más relevantes del código son:
Librería Secret Manager
build.gradle
dependencies {
compile group: 'com.google.cloud',
name: 'google-cloud-secretmanager',
version: '1.0.1'
}
Acceso a los secretos
Debes crear un método para acceder y obtener los secretos de Secret Manager.
public void accessSecretVersion() {private String versionId = 1.0private String projectId = “TU_PROYECTO_GCP”ProjectName projectName = ProjectName.of(projectId);
SecretManagerServiceClient client = SecretManagerServiceClient.create();SecretManagerServiceClient.ListSecretsPagedResponse pagedResponse = client.listSecrets(projectName);// List all secrets.pagedResponse.iterateAll().forEach(secret -> { //Get Secret Name String secretName = secret.getName().substring(secret.getName().lastIndexOf(“/”)+1); //Get Secret Values SecretVersionName secretVersionName = SecretVersionName.of(projectId, secretName, versionId); AccessSecretVersionResponse response = client.accessSecretVersion(secretVersionName); System.out.println(“My secrets: “ + secretName + “|” + response.getPayload().getData().toStringUtf8());});}
Los nombres de los secretos tienen una nomenclatura que forma una url (por ejemplo, projects/1044744622990/secrets/CL_DB_PWD). Por lo tanto, si queremos usar el nombre original del secreto debemos parsearlo previamente. Una vez obtenidos los secretos desde tu aplicación, ya los puedes usar libremente.
Antes de subir tu aplicación a GCP puedes probarla localmente.
Abre un terminal y sigue los siguientes pasos
- Compilar la aplicación
$ gradle build
- Ejecutar la aplicación
$ java -jar build/libs/[JAR_NAME].jar
Por ejemplo:
$ java -jar build/libs/clean-0.0.1-SNAPSHOT.jar
Nota: La sentencia System.out implementada en el fragmento de código, es solo un ejemplo local para validar el valor de los secretos que estamos leyendo, sin embargo No es una buena práctica dado que los secretos son información de naturaleza sensible. Por lo tanto, no subas el código a tu repositorio con esa instrucción. En su defecto, puedes utilizar el modo debug de tu IDE favorito para revisar los valores de los secretos en tiempo de desarrollo.
4.- Configurar variables de entorno
Previo a la compilación del componente debes configurar las siguientes variables de entorno:
$ export GOOGLE_APPLICATION_CREDENTIALS=[PATH_TO_JSON]/[JSON_FILE_NAME].json$ export PROJECT_ID=[GCP_PROJECT_ID]
Por ejemplo:
$ export GOOGLE_APPLICATION_CREDENTIALS=/Users/oliver/Documents/google-auth/cloudrunsa.json$ export PROJECT_ID=architect-poc
5.- Generar y subir la imagen
Para generar la imagen de tu componente debemos tener el siguiente archivo configurado:
Dockerfile
FROM openjdk:8-jdk-slim
ARG JAR_FILE=build/libs/clean-0.0.1-SNAPSHOT.jar
COPY ${JAR_FILE} /app.jar
ENTRYPOINT [“java”, “-Djava.security.edg=file:/dev/./urandom”,”-jar”,”/app.jar”]
Luego, debemos ejecutar el siguiente comando:
$ gcloud builds submit --tag gcr.io/[GCP_PROJECT_ID]/[IMAGE_NAME]
Por ejemplo:
$ gcloud builds submit --tag gcr.io/architect-poc/clean
Aquí estamos usando Cloud Build para generar la imagen y subirla a GCR.
El proceso te indicará el estado SUCCESS en caso de éxito.
Si no has activado previamente la API de CloudBuild, te lo pedirá al final de la ejecución del proceso. Dale “Y”.
Verifica además que la API de Cloud Storage esté habilitada.
La habilitación de API lo puedes efectuar desde APIs & Services
6- Desplegar la imagen en CloudRun
Usando la consola GCP
Ve a la consola de GCP, opción [Cloud Run]
Click en [CREATE SERVICE]
Agrega un nombre a tu servicio. En este caso “data-clean-service”. Chequea [Allow unauthenticated invocations].
Dale [NEXT]
Selecciona una imagen. Dale [SELECT]
Una vez seleccionada la imagen a tu derecha, dale [SELECT]
Dale [Show Advanced Settings]
Cambia el máximo de instancias a un número razonable. Además, y muy importante, vincula la cuenta de servicio (Service account) que creamos en los pasos anteriores. En nuestro caso, dataclean-secrets.
Ve al tab [VARIABLES] y crea la variable de entorno PROJECT_ID y en el valor coloca el nombre de tu proyecto GCP.
Luego dale [CREATE]
Finalmente se desplegará tu servicio [REVISIONS]. Quedará con un check Verde.
Revisa el LOGS para ver la primera ejecución de tu aplicación.
Si quieres probarlo desde POSTMAN, copia la URL que te ofrece Cloud Run y arma tu llamada http, sumándole el path que expone tu servicio rest (en este caso nuestro path será “/dataclean”):
https://data-clean-service-fb46zlhboq-uc.a.run.app/dataclean
Nota: La aplicación exige dos cosas para ser invocada correctamente:
Verbo Http
DELETEHeaders Http:
key: X-TENANT-ID
value: CL
El parámetro X-TENANT-ID lo explicaremos en los próximos capítulos.
POSTMAN
Usando la linea de comando
En vez de desplegar tu imagen manualmente desde la consola GCP, lo puedes hacer ejecutando la siguiente linea de comando de Cloud Build:
$ gcloud run deploy --image gcr.io/[GCP_PROJECT_ID]/[IMAGE_NAME] --platform managed
Por ejemplo:
$ gcloud run deploy --image gcr.io/architect-poc/clean --platform managed
Espero que te haya gustado este desafío y lo hayas podido seguir y entender.
En el próximo episodio veremos cómo integrar CloudRun con una base de datos CloudSql, para ir completando nuestra solución.
Nos vemos en la próxima aventura GCP.
Código Fuente:
https://github.com/oliverfierro77/gcp-cloudrun-secrets