Documentacion Proyecto 2 - Arthaudcom/SeguridadEnLaCloudProyecto1 GitHub Wiki
Proyecto 2 - Seguridad en Cloud
Infraestructura en GCP
Para este segundo proyecto seguimos construyendo sobre lo que ya habíamos hecho en el Proyecto 1, pero esta vez lo llevamos más allá, metiéndole balanceo de carga, dominio personalizado con HTTPS y más capas de seguridad.
Principales diferencias con el Proyecto 1
-
Balanceador de carga HTTP (con round robin)
Creamos tres instancias (app-vm
,app-vm-2
,app-vm-3
) en la zonanorthamerica-south1-a
y desplegamos en todas la misma app que ya habíamos trabajado (FastAPI + React).
Usamos un balanceador de carga HTTP que distribuye el tráfico de forma uniforme (round robin), y configuramos las rutas con una regla predeterminada que apunta al backend serviceblog-service
. -
Dominio personalizado y HTTPS
Asociamos nuestro dominio
proyectocloud.site
al balanceador y habilitamos HTTPS.Configuración aplicada:
- Se realizó la verificación del dominio desde Google Domains, vinculándolo correctamente al proyecto de GCP.
- Se configuró un certificado SSL administrado por Google desde el menú del balanceador HTTP(S), lo cual permitió habilitar HTTPS sin necesidad de gestionar certificados manualmente.
- En el backend service del balanceador, se habilitó la opción "HTTPS to Backend" con redirección automática desde HTTP.
Beneficios obtenidos:
- Todo el tráfico entre el cliente y el balanceador está cifrado mediante TLS, protegiendo así las credenciales, tokens y datos sensibles.
- El uso de un dominio personalizado mejora la confianza del usuario y facilita la integración con servicios externos.
- Se eliminaron posibles advertencias de seguridad en los navegadores (como “Sitio no seguro”) al implementar correctamente el certificado.
-
Reglas de Firewall configuradas
Agregamos varias reglas para controlar el tráfico y restringir el acceso externo no autorizado:
allow-health-checks
: Permite las IPs oficiales de los health checks de Google Cloud.allow-lb-to-vms
: Permite que el balanceador de carga se comunique con las instancias backend.deny-external-http-to-vms
: Bloquea accesos directos HTTP/HTTPS desde Internet a las VMs.allow-http-blog
: Permite tráfico HTTP (puertos 80 y 8000) solo cuando es enviado a través del balanceador.allow-ssh-bastion
: Autoriza conexiones SSH al Bastion Host desde una IP pública específica (acceso restringido).allow-ssh-from-bastion
: Permite que el Bastion se conecte a las VMs internas etiquetadas conssh-access
.deny-all
: Como medida adicional, se añadió una regla por defecto con prioridad baja que bloquea todo el tráfico no expresamente autorizado.
Con estas reglas, se establece una política de acceso mínimamente permisivo, alineada con las buenas prácticas de segmentación y control de tráfico.
-
Cloud Armor
Se configuró una política de seguridad llamada
cloudarmor-policy-blog
, aplicada al backend expuesto a través del balanceador de carga HTTP(S). Esta política tiene como objetivo mitigar amenazas comunes identificadas en el marco del OWASP Top 10, así como limitar el acceso únicamente a regiones y agentes confiables.Las reglas definidas incluyen:
- Bloqueo de IPs específicas consideradas maliciosas, como
192.0.2.1
, utilizada comúnmente en pruebas de ataque. - Prevención de inyecciones SQL (SQLi) mediante la activación de la WAF preconfigurada
sqli-v33-stable
. - Protección contra ataques XSS (Cross-Site Scripting) mediante la WAF
xss-v33-stable
. - Denegación de acceso a agentes de usuario sospechosos, tales como herramientas automatizadas o de prueba de penetración (
sqlmap
,burp
,curl
,wget
,python-requests
). - Restricción geográfica del tráfico entrante, permitiendo únicamente el acceso desde regiones autorizadas como Colombia,Estados Unidos, México, Francia y bloqueando el resto.
Aqui es una prueba con Curl :
- Bloqueo de IPs específicas consideradas maliciosas, como
6. Cloud Web Security Scanner
Se ejecutó un análisis automático con Cloud Web Security Scanner sobre la aplicación (scan-blog-frontend
), configurando autenticación para
acceder
a las rutas protegidas. Se utilizó el formulario de login con credenciales válidas ([email protected]
), lo que permitió escanear páginas internas de la
app.
Resultados:
- 11 URLs rastreadas en 2 minutos y 38 segundos.
- 0 vulnerabilidades encontradas.
Con esta configuración, se validó que tanto las páginas públicas como las protegidas no presentan fallos de seguridad detectables por el escáner.
-
Artifact Registry y Análisis de Vulnerabilidades
Se subieron manualmente las imágenes Docker del backend y frontend a Artifact Registry (región
northamerica-south1
) usandoCloud Build
desde Cloud Shell. Una vez almacenadas, GCP ejecutó automáticamente el análisis de vulnerabilidades (Artifact Analysis) sobre ambas imágenes.- En la imagen del backend se identificó una vulnerabilidad crítica:
- CVE-2023-45853 en
zlib
para Debian 12. - Severidad CRÍTICA, con CVSS 9.8.
- Potencial de ejecución remota sin autenticación.
- CVE-2023-45853 en
Este hallazgo quedó documentado como parte de la priorización de vulnerabilidades para su remediación futura.
Además, el almacenamiento en Artifact Registry permite versionado y trazabilidad completa de las imágenes del proyecto. - En la imagen del backend se identificó una vulnerabilidad crítica:
-
Google Secret Manager e IAM
8. Google Secret Manager e IAM
Se utilizó Secret Manager para almacenar información sensible del proyecto, evitando así que las credenciales estén embebidas directamente en el
código fuente o en archivos .env
.
Secretos configurados:
db-password
: almacena la contraseña de acceso a la base de datos.db-url
: almacena la cadena de conexión completa a la base de datos.
Ambos secretos fueron creados con versionado habilitado, lo que permite gestionar futuras actualizaciones sin perder trazabilidad ni comprometer la seguridad.
Roles y permisos asignados: Para aplicar el principio de mínimo privilegio, se asignaron roles diferenciados:
-
Al equipo de desarrollo se le otorgó el rol
roles/secretmanager.admin
, permitiendo crear, modificar y administrar los secretos. -
A la cuenta de servicio de la aplicación (
backend-service-account
) se le asignaron los siguientes roles :roles/secretmanager.secretAccessor
para acceder a los secretos desde la VM.roles/cloudsql.client
para conectarse a la base de datos.roles/logging.logWriter
yroles/storage.objectViewer
para integración con los registros y objetos relevantes.
-
Adicionalmente, la cuenta de servicio interna de Cloud SQL (
cloudsql-service-account
) dispone de los rolesCloud SQL Client
yCloud SQL Editor
, necesarios para la gestión de la base de datos y su operación dentro del entorno GCP.
Integración con las VMs:
Los secretos fueron recuperados desde la propia VM durante el arranque (startup script), utilizando el contexto de autenticación del servicio. De este
modo, las variables sensibles (DATABASE_URL
, DB_PASSWORD
) fueron inyectadas dinámicamente en tiempo de ejecución, sin dejar rastros en
archivos
persistentes o imágenes Docker.
Rotación de claves: Aunque no se implementó la rotación automática por limitaciones del entorno, se simuló una política de rotación de secretos mediante la creación manual de nuevas versiones en Secret Manager.
Para ello:
- Se creó una nueva versión del secreto
db-password
simulando un cambio de contraseña por motivos de seguridad (p. ej., cada 90 días). - Se configuró el backend para leer siempre la versión más reciente (
latest
) del secreto, evitando así tener que actualizar manualmente la aplicación en cada rotación. - En un entorno real, este proceso podría automatizarse mediante un Cloud Scheduler que invoca periódicamente una Cloud Function encargada de:
- Generar una nueva contraseña segura.
- Crear una nueva versión del secreto.
- Aplicar el nuevo secreto a los servicios que lo utilizan.
- Notificar al equipo de seguridad o registrar el evento.
Este esquema permite mantener un ciclo de rotación regular sin afectar la disponibilidad ni requerir cambios manuales frecuentes.
-
Cifrado de Base de Datos
La base de datos utilizada en la solución ya cuenta con cifrado en reposo activado por defecto, ya que está desplegada como una instancia de Cloud SQL, la cual utiliza claves administradas por Google (Google-managed encryption keys) para proteger los datos almacenados.
Buenas prácticas aplicadas:
- Las credenciales de acceso no están embebidas en el código fuente, sino que se obtienen a través de Secret Manager.
- Se evitaron conexiones desde IP públicas, usando reglas de firewall para limitar el tráfico de entrada.
- Además, la instancia de Cloud SQL fue configurada para ser accesible únicamente mediante IP privada, lo cual refuerza la confidencialidad y el aislamiento de la base de datos frente a accesos externos.
Con estas prácticas, se refuerza la confidencialidad, la integridad y el aislamiento del sistema de almacenamiento de datos.
-
Estrategia de Backup
Aunque no se implementó directamente en GCP por lineamientos del proyecto, se diseñó una estrategia de backup que prioriza la seguridad y la disponibilidad de los datos.
Propuesta:
- Utilizar Cloud Scheduler para ejecutar tareas programadas que realicen copias de seguridad periódicas de la base de datos (por ejemplo, cada 24 horas).
- Estas tareas pueden invocar una Cloud Function.
- Luego enviar los archivos resultantes a un bucket en Cloud Storage con ciclo de vida y cifrado configurado.
- Las copias estarían almacenadas con una política de retención y eliminación automática tras X días. Esta estrategia permite garantizar la recuperación ante fallos sin incurrir en costos innecesarios durante la etapa académica del proyecto.
- Private Google Access
Para reforzar la seguridad de la infraestructura y evitar el uso de direcciones IP públicas innecesarias, se habilitó Private Google Access (PGA) en la subred del VPC utilizado por las instancias del proyecto.
Private Google Access permite que las máquinas virtuales sin dirección IP externa puedan acceder a los servicios de Google Cloud (como Artifact Registry, Cloud SQL, Secret Manager o APIs públicas) utilizando exclusivamente su red interna.
Configuración aplicada:
- Se activó Private Google Access en el subred principal del proyecto (
default
, regiónnorthamerica-south1
). - Las máquinas virtuales que ejecutan el backend (
app-vm
,app-vm-2
,app-vm-3
) fueron configuradas sin dirección IP pública. - La instancia de Cloud SQL también fue modificada: se deshabilitó su dirección IP pública y se habilitó una IP privada, permitiendo la conexión directa desde las VMs internas del proyecto.
- La aplicación accede a la base de datos únicamente mediante la IP privada, evitando así cualquier exposición externa.
Validación de conectividad: Se realizó una prueba de conectividad desde una instancia sin IP pública hacia los servicios de Google Cloud. La respuesta obtenida fue un timeout, lo cual es coherente considerando que la solicitud fue hecha sin autenticación explícita. Esto confirma que el tráfico no intenta salir por una IP externa y que Private Google Access está activo.
Buenas prácticas aplicadas:
- Se evitó el uso de direcciones IP públicas tanto en las VMs como en la base de datos.
- Se habilitó Private Google Access para mantener la funcionalidad sin comprometer la seguridad.
- Se reforzó el aislamiento de la red y se redujo la superficie de ataque potencial, cumpliendo con las recomendaciones de seguridad para entornos cloud en producción.
- Bastion Host y control de acceso SSH
Para limitar la exposición de las máquinas virtuales del backend, se implementó un esquema de acceso indirecto mediante un Bastion Host. Este mecanismo permite conectarse a las VMs internas sin necesidad de exponerlas a Internet, siguiendo las mejores prácticas de seguridad en redes en la nube.
Configuración aplicada:
- Se creó una instancia con el tag
bastion-host
, ubicada en la misma red (default
) y zona (northamerica-south1-a
) que las VMs de la aplicación. - Se asignó una IP pública fija únicamente al Bastion Host.
- Se definieron dos reglas de firewall:
allow-ssh-bastion
: permite el acceso SSH al Bastion desde una dirección IP específica (190.130.103.125/32).allow-ssh-from-bastion
: permite que el Bastion se conecte por SSH a las VMs etiquetadas conssh-access
.
- Para habilitar el acceso SSH, se copió manualmente la clave pública SSH generada en el Bastion dentro del archivo
~/.ssh/authorized_keys
de las máquinas virtuales objetivo.
Validación realizada:
Se accedió exitosamente al Bastion vía navegador y desde allí se estableció una conexión SSH hacia la VM de la aplicación (app-vm
), demostrando el
correcto funcionamiento del canal seguro y restringido.
Buenas prácticas aplicadas:
- Solo el Bastion tiene IP pública; las otras VMs no están expuestas directamente.
- El acceso está restringido por IP y tags de red.
- Se utilizaron claves SSH para autenticar los accesos, evitando el uso de contraseñas.
- Cifrado en tránsito
Además del cifrado en reposo, también se aseguró el cifrado en tránsito de los datos en toda la infraestructura.
Medidas implementadas:
- Se habilitó HTTPS en el balanceador de carga, utilizando un certificado SSL administrado por Google. Esto garantiza que las comunicaciones entre los usuarios y la aplicación estén cifradas mediante TLS.
- Todo el tráfico entre el cliente y el balanceador viaja de forma segura a través de Internet.
- Los flujos internos, entre el balanceador y las máquinas virtuales del backend, también se restringieron mediante reglas de firewall, y las instancias de aplicación se comunican con la base de datos mediante una IP privada, evitando así el paso por la red pública.
- Las reglas de firewall impiden cualquier conexión directa desde el exterior, asegurando que solo los canales autorizados y cifrados estén habilitados.
Estas prácticas garantizan la confidencialidad y la integridad de los datos en tránsito, tanto hacia el exterior como dentro de la red privada del proyecto.
Conclusiones
Esta vez nos enfocamos más en asegurar la infraestructura. Ya no era solo correr la app, sino pensar en cómo escalar, balancear carga y protegerla como se debe.
Aprendimos bastante sobre el manejo de tráfico en GCP, HTTPS con dominios personalizados y cómo usar herramientas como Cloud Armor para mitigar ataques.
Nos gustó que el balanceo de carga funciona bien y todo el tráfico se reparte entre las tres instancias. También nos dio más confianza ver que no había vulnerabilidades detectadas por el scanner.