BeyondProd: nuevo modelo de seguridad nativa de la nube

Google ha elaborado varios informes en los que se recoge información sobre diversos proyectos desarrollados internamente que contribuyen a adoptar mejores medidas de seguridad. BeyondProd se basa en los conceptos de BeyondCorp: si un modelo de seguridad perimetral deja de funcionar para los usuarios finales, también deja de ser válido para los microservicios. Por lo tanto, si adaptamos la cita del informe de BeyondCorp original, quedaría así: "Las suposiciones clave de ese modelo han dejado de tener vigencia: el perímetro ya no es solo la ubicación física de la empresa [del centro de datos], ni lo que se encuentra en el interior del perímetro es ya un lugar consagrado y seguro en el que alojar dispositivos de computación personales y aplicaciones empresariales [microservicios]".

En este informe, detallamos la forma en la que varias piezas de la infraestructura de Google colaboran para proteger las cargas de trabajo en una arquitectura que ahora se denomina "nativa de la nube". Para obtener información general sobre la seguridad de Google, consulta el informe Descripción general del diseño de seguridad de la infraestructura de Google.

El contenido incluido en este documento es correcto a fecha de diciembre del 2019 y representa la situación en el momento en que se redactó. Las políticas y sistemas de seguridad de Google Cloud podrían cambiar en el futuro, ya que mejoramos constantemente la protección que ofrecemos a nuestros usuarios.

Glosario

En este documento se utilizan las definiciones expuestas a continuación:

  • Un microservicio divide las tareas concretas que una aplicación debe realizar en distintos servicios. Cada uno de estos servicios puede desarrollarse y gestionarse de manera independiente, con su propia gestión de APIs, lanzamientos, escalados y cuotas. En una arquitectura más moderna, cualquier aplicación (por ejemplo, un sitio web) puede ejecutarse como una colección de microservicios en lugar de como un único servicio monolítico. Los microservicios son independientes, modulares, dinámicos y efímeros. Se pueden distribuir entre muchos hosts, clústeres o incluso nubes diferentes.

  • Una carga de trabajo es una tarea única que completa cualquier aplicación. En una arquitectura de microservicios, una carga de trabajo podría ser uno o varios microservicios.

  • Una tarea es una instancia de un microservicio que ejecuta alguna parte de una aplicación.

  • Todo microservicio utiliza una identidad de servicio para autenticarse ante otros servicios que se ejecutan en la infraestructura.

  • Una malla de servicios es una capa de la infraestructura destinada a las comunicaciones entre servicios. Sus funciones son controlar el tráfico, aplicar políticas y monitorizar de forma centralizada las llamadas de servicio. Cuando se usa una arquitectura de microservicios, se suprime la carga que soporta cada uno de los servicios a la hora de implementar estos controles. Asimismo, se consigue simplificar y centralizar la gestión entre numerosos microservicios.

Resumen para directores de sistemas de información

  • La infraestructura de Google despliega cargas de trabajo en forma de microservicios en contenedores y las gestiona mediante Borg, nuestro sistema de orquestación de contenedores. Este sistema es la inspiración y el modelo en el que se sustenta lo que hoy se conoce como "arquitectura nativa de la nube".

  • La seguridad ha estado en el foco del diseño de la infraestructura de Google desde su concepción. Nuestra infraestructura no presupone la confianza entre sus servicios.

  • Google brinda protección a sus microservicios por medio de una iniciativa denominada BeyondProd. Esta protección abarca la forma en la que el código se modifica y la manera de acceder a los datos de usuario de los microservicios. BeyondProd aplica conceptos como los siguientes: puntos de conexión de servicio autenticados mutuamente, seguridad de transporte, terminación perimetral con balanceo de carga global y protección frente a denegación de servicio, procedencia de código integral y zonas de pruebas de entornos de ejecución.

  • Al pasar de un modelo de seguridad tradicional a uno nativo de la nube tuvimos que hacer cambios en dos áreas fundamentales: nuestra infraestructura y nuestro proceso de programación. La inclusión de componentes compartidos en un tejido común que envuelve y conecta a todos los microservicios (también conocida como "malla de servicios") facilitó el lanzamiento de cambios y la consecución de un grado de seguridad coherente entre servicios.

Motivación

Google empezó a usar un sistema de orquestación de contenedores para lograr un mayor aprovechamiento de los recursos, crear aplicaciones de alta disponibilidad y simplificar el trabajo de los programadores de Google. Al pasar a una infraestructura en contenedores también teníamos otra motivación: alinear nuestros controles de seguridad con nuestra arquitectura. Teníamos claro que un modelo de seguridad basado en perímetros no era lo suficientemente seguro. Si un atacante lograra traspasar el perímetro, podría moverse con total libertad dentro de la red. Aunque constatamos que necesitábamos controles de seguridad más robustos en toda nuestra infraestructura, también queríamos que nuestros programadores pudieran escribir y desplegar aplicaciones seguras fácilmente, sin tener que implementar funciones de seguridad por su cuenta.

El cambio de aplicaciones monolíticas a microservicios distribuidos y desplegados en contenedores por medio de un sistema de orquestación tuvo ventajas operativas evidentes, ya que conseguimos simplificar la gestión y la escalabilidad. Esta arquitectura nativa de la nube precisaba un modelo de seguridad diferente dotado con herramientas diferentes para proteger los despliegues y que estuviera alineado con las ventajas de gestión y escalabilidad de los microservicios.

En este documento, se describe cómo se implementa en Google la seguridad nativa de la nube, que aquí se denomina BeyondProd. Entre los temas que se incluyen, puedes encontrar información sobre cómo afecta a la seguridad el cambio a un modelo nativo de la nube, cuáles son los principios de seguridad relativos a la seguridad nativa de la nube, cuáles son los sistemas diseñados para abordar estos requisitos y algunos consejos sobre cómo abordar tú mismo cualquier cambio similar.

Seguridad nativa de la nube en Google

Microservicios en contenedores

Ya en sus inicios, Google tomó la decisión consciente de crear su capacidad de centros de datos a partir de servidores genéricos de bajo coste, en vez de invertir en hardware de alta disponibilidad más caro. La filosofía que rige nuestra fiabilidad era, y sigue siendo, la creencia de que todas las piezas de un sistema deberían poder fallar sin que la disponibilidad de los servicios que ven los usuarios se vea afectada. Conseguir este grado de disponibilidad exigió ejecutar instancias redundantes de servicios para que ningún fallo se tradujera en interrupciones. El producto de esta filosofía fue el desarrollo de contenedores, microservicios y orquestación de contenedores para gestionar de forma escalable el despliegue de estos sistemas altamente redundantes y distribuidos.

Una infraestructura en contenedores implica que cada una de las cargas de trabajo se despliega con su propio conjunto de contenedores inmutables, móviles y programables. Para gestionar estos contenedores internamente, desarrollamos un sistema de orquestación de contenedores denominado Borg1, que aún utilizamos en la actualidad para desplegar varios miles de millones de contenedores a la semana.

Gracias a los contenedores, se simplificó la forma de empaquetar binarios y reprogramar cargas de trabajo entre máquinas. Gracias a los microservicios, se simplificaron los procesos de programación y depuración de las distintas secciones de las aplicaciones. La combinación de microservicios y contenedores permite dividir las cargas de trabajo en unidades más pequeñas y fáciles de gestionar con fines de mantenimiento y detección. El cambio a una infraestructura en contenedores con una arquitectura de microservicios se conoce como la "adopción de un modelo nativo de la nube". Los servicios se ejecutan dentro de contenedores que Borg se encarga de desplegar. Esta arquitectura escala las cargas de trabajo según sea necesario: si sube la demanda de una carga en concreto, podrá haber varias máquinas ejecutando copias del mismo servicio para gestionar el nivel de carga de trabajo que se precise.

Google destaca porque ha tenido en cuenta la seguridad en todas las fases evolutivas de su arquitectura. El concepto más moderno de seguridad nativa de la nube se podría comparar con lo que Google ha utilizado durante mucho tiempo para mantener segura su infraestructura. Nuestro objetivo al crear esta arquitectura de microservicios y este proceso de desarrollo es abordar los problemas de seguridad en las fases tempranas del ciclo de desarrollo y despliegue (ya que estos son los momentos en los que la resolución de problemas es menos costosa) y, además, hacerlo de forma normalizada y uniforme. El resultado final es que los programadores dedican menos tiempo preocupándose por la seguridad y, a la vez, consiguen resultados más seguros.

Migración a una arquitectura nativa de la nube

Las arquitecturas de seguridad modernas han dejado atrás el tradicional modelo de seguridad basado en perímetros, en el que un cortafuegos protegía el perímetro y se daba plena confianza a los usuarios o los servicios que estuvieran dentro. BeyondCorp fue una de las respuestas al cambio en la forma de trabajar que ha experimentado el usuario corporativo de hoy en día. En la actualidad, los usuarios son móviles y tienden a operar fuera del perímetro de seguridad convencional de la organización; por ejemplo, desde una cafetería, un avión o cualquier otro lugar. Con BeyondCorp, prescindimos del concepto de una red corporativa con privilegios y accesos autorizados basada únicamente en credenciales y atributos de dispositivo y usuario, y en la que no importa la ubicación de red de los usuarios.

En la seguridad nativa de la red, los servicios se abordan con la misma inquietud que se plantea respecto de los usuarios: en un mundo nativo de la nube, la protección de la red de producción, así como de la red corporativa, no puede depender solo de un cortafuegos. Del mismo modo que no todos los usuarios utilizan la misma ubicación física o el mismo dispositivo, no todos los programadores despliegan código en el mismo entorno. BeyondProd permite que los microservicios, los cuales deben estar seguros en cualquier ubicación, se ejecuten en centros de datos provistos de cortafuegos, pero también en nubes públicas, en nubes privadas o en servicios alojados por terceros.

Del mismo modo que los usuarios se desplazan, utilizan varios dispositivos y se conectan desde ubicaciones diferentes, los microservicios también se desplazan y se despliegan en entornos diferentes entre hosts heterogéneos. Mientras que en BeyondCorp se afirma que "la confianza del usuario debería depender de características tales como el estado contextual de los dispositivos y no de la capacidad de conectarse a la red corporativa", en BeyondProd se indica que "la confianza del servicio debería depender de características tales como la procedencia del código y la identidad del servicio, no de la ubicación dentro de la red de producción (por ejemplo, la identidad basada en la dirección IP o el nombre del host)".

Desarrollo nativo de la nube y de aplicaciones

Un modelo de seguridad más tradicional, que base su sistema de seguridad en perímetros, no tiene la capacidad necesaria para proteger una arquitectura nativa de la nube. Analiza este ejemplo: una aplicación monolítica que emplea arquitectura de tres niveles se despliega en un centro de datos corporativo privado cuya capacidad es suficiente para gestionar cargas máximas para eventos críticos. Las aplicaciones con requisitos específicos de hardware o redes se despliegan en máquinas concretas cuyas direcciones IP suelen ser fijas. Los lanzamientos se realizan con poca frecuencia, son voluminosos y es difícil coordinarlos, ya que los cambios resultantes afectan simultáneamente a muchas secciones de la aplicación. Esto se traduce en aplicaciones de muy largo recorrido que se actualizan con menos frecuencia y cuyos parches de seguridad se implementan con menos regularidad.

Sin embargo, en un modelo nativo de la nube, los contenedores desvinculan los binarios que tu aplicación necesita del sistema operativo del host subyacente y dotan a tus aplicaciones de mayor portabilidad. Los contenedores están diseñados para un uso inmutable, por lo que no cambian tras su despliegue, lo que explica que a menudo se vuelvan a crear y a desplegar. Las tareas se escalan para gestionar la carga, de tal forma que se despliegan tareas nuevas cuando la carga se incrementa y se eliminan las que ya existen cuando esta se reduce. Ya que los contenedores se reinician, se eliminan y se reprograman a menudo, el hardware y las redes también se reutilizan y se usan de forma compartida con más frecuencia. Gracias a un proceso normalizado y compartido de compilación y distribución, el proceso de programación gana en coherencia y uniformidad entre los equipos, aunque estos gestionen la programación de sus microservicios de manera independiente. Por lo tanto, los aspectos relativos a la seguridad (por ejemplo, las revisiones de seguridad, los análisis de código y la gestión de vulnerabilidades) se pueden desarrollar en las primeras fases del ciclo de programación.

Implicaciones para la seguridad

Hemos analizado en detalle por qué el modelo de interiores no confiables con usuarios de BeyondCorp también es aplicable a los microservicios de BeyondProd, pero ¿cómo funciona este cambio realmente? En la tabla 1 se comparan algunos aspectos de la seguridad de las infraestructuras tradicionales y sus equivalentes en una arquitectura nativa de la nube. También se exponen los requisitos necesarios para migrar de un modelo a otro. En el resto de esta sección se ofrecen más detalles sobre cada fila de la tabla.

Seguridad de una infraestructura tradicional Seguridad nativa de la nube Requisitos implícitos de la seguridad nativa de la nube
Seguridad basada en perímetros (es decir, un cortafuegos); las comunicaciones internas se consideran de confianza. Seguridad basada en los principios de confianza cero con verificación de comunicaciones entre servicios y sin confianza implícita para los servicios del entorno. Protección de la red en el perímetro (sigue vigente) e inexistencia de confianza mutua inherente entre los servicios.
Direcciones IP y hardware fijos para determinadas aplicaciones. Mayor grado de aprovechamiento, reutilización y uso compartido de recursos, incluidos IP y hardware. Ejecución de código de procedencia conocida por parte de máquinas de confianza.
Identidad basada en direcciones IP. Identidad basada en servicios.
Ejecución de servicios en una ubicación conocida y prevista. Los servicios se pueden ejecutar en cualquier ubicación del entorno, incluidos despliegues híbridos en la nube pública y centros de datos privados.
Integración de requisitos específicos de seguridad en todas las aplicaciones e implementación de estos por separado.Integración de requisitos de seguridad compartidos en pilas de servicios en cumplimiento de una política centralizada de implementaciones. Puntos críticos destinados a lograr una implementación coherente de políticas en los servicios.
Imposición de restricciones limitadas al modo de crear y revisar servicios. Implantación coherente de los requisitos de seguridad en todos los servicios.
Supervisión limitada de los componentes de seguridad. Vista centralizada de las políticas de seguridad y de su cumplimiento.
Lanzamientos especializados y poco frecuentes. Proceso normalizado de compilación y lanzamiento y mayor frecuencia de cambios en microservicios concretos. Simplificación, automatización y normalización del lanzamiento de cambios.
Las cargas de trabajo tienden a desplegarse en forma de máquinas virtuales o en hosts físicos y utilizan máquinas físicas o hipervisores para proporcionar aislamiento. Las cargas de trabajo con paquetes de binarios y los procesos de estas se ejecutan en un sistema operativo compartido, por lo que se precisa un mecanismo que las aísle. Aislamiento entre cargas de trabajo que compartan sistema operativo.

Tabla 1: Requisitos implícitos de seguridad para realizar una migración a una arquitectura nativa de la nube

De seguridad basada en perímetros a seguridad basada en los principios de confianza cero

En el modelo de seguridad tradicional, la protección de las aplicaciones de una organización frente al tráfico entrante posiblemente dependiera de un cortafuegos externo dispuesto en torno a su centro de datos privado. En un entorno nativo de la nube, aunque sigue siendo necesario proteger el perímetro de red (al igual que en el modelo de BeyondCorp), el modelo de seguridad basado en perímetros ya no es suficiente. Esto no plantea un nuevo problema de seguridad, sino que viene a destapar el hecho de que si un cortafuegos no es capaz de proteger totalmente la red corporativa, tampoco podrá hacerlo con la red de producción. El modelo de seguridad de confianza cero conlleva la pérdida de la confianza implícita en el tráfico interno: requiere otros controles de seguridad, tales como la autenticación y el encriptado. Paralelamente, el cambio hacia los microservicios brinda la oportunidad de reconsiderar la idoneidad del modelo de seguridad tradicional. A medida que te vayas independizando del perímetro de red (por ejemplo, un cortafuegos), podrás ir segmentando aún más la red por servicio. Para desarrollar esta idea, podrías implementar una segmentación a nivel de microservicio, procurando que no haya confianza inherente entre los servicios. Con los microservicios, el tráfico posiblemente experimente niveles variables de confianza según el control que manejes, pues ya no compararás únicamente el tráfico interno con el externo.

De IP y hardware fijos a un mayor uso compartido de recursos

En el modelo de seguridad tradicional, las aplicaciones de las organizaciones se desplegaban en máquinas concretas y sus direcciones IP rara vez cambiaban. Esto suponía que las herramientas de seguridad podían basarse en una asignación arquitectónica relativamente estática que vinculaba aplicaciones de un modo predecible: las políticas de seguridad de herramientas tales como los cortafuegos podían utilizar direcciones IP a modo de identificadores.

Sin embargo, en un mundo nativo de la nube, en el que se comparten hosts y las tareas cambian con frecuencia, el uso de un cortafuegos para controlar accesos entre microservicios deja de tener utilidad. Ya no se puede contar con que una dirección IP concreta vaya a estar asociada a un servicio determinado. Por lo tanto, en lugar de basar la identidad en una dirección IP o en el nombre de un host, esta se vincula a un servicio.

De implementaciones de seguridad específicas de aplicaciones a integración de requisitos de seguridad compartidos en pilas de servicios

En el modelo de seguridad tradicional, cada una de las aplicaciones se encargaba de cumplir sus propios requisitos de seguridad de manera independiente respecto de otros servicios. Entre esos requisitos se encontraban la gestión de identidades, la terminación SSL/TLS y la gestión del acceso a los datos. Esto se traducía a menudo en implementaciones incoherentes o problemas de seguridad pendientes de resolución debido a que debían rectificarse en demasiados lugares, lo que dificultaba la aplicación de correcciones.

En un mundo nativo de la nube, los diversos servicios reutilizan los componentes con mucha más frecuencia, y la existencia de puntos críticos permite la implementación sistemática de políticas entre los servicios. Es posible implementar políticas diferentes a través de servicios de seguridad diferentes. En lugar de exigir a cada una de las aplicaciones que implemente por separado servicios de seguridad críticos, puedes dividir las distintas políticas en microservicios independientes (por ejemplo, una política que garantice el acceso autorizado a datos de usuario y otra que garantice el uso de suites actualizadas de algoritmos de cifrado TLS).

De procesos de lanzamiento especializados y poco frecuentes a procesos normalizados con lanzamientos más frecuentes

En el modelo de seguridad tradicional, el número de servicios compartidos era limitado. La combinación de un código más distribuido y una programación local denotaban la dificultad de determinar las repercusiones de un cambio que afectaba a muchas secciones de una aplicación; por ello, los lanzamientos eran poco frecuentes y difíciles de coordinar. Para hacer cualquier cambio, es posible que los programadores tuvieran que actualizar cada componente directamente (por ejemplo, accediendo a una máquina virtual a través de SSH para actualizar un parámetro). En términos generales, esto dio lugar a aplicaciones de recorrido extremadamente largo. Desde el punto de vista de la seguridad, cuanto más distribuido estaba el código, más difícil era su revisión, y más complicado aún resultaba garantizar que la corrección de cualquier vulnerabilidad se aplicara en todos los sitios donde debía aplicarse. El cambio al modelo nativo de la nube, en el que los lanzamientos son frecuentes y están normalizados, permite a la seguridad realizar cambios en fases tempranas ("shift left"2) del ciclo de la programación de software. Se posibilita así una implementación más sencilla y coherente del mantenimiento de la seguridad, incluida la implantación regular de parches de seguridad.

De cargas de trabajo aisladas mediante máquinas físicas o hipervisores a cargas con paquetes de binarios que se ejecutan en la misma máquina, con la consiguiente necesidad de mayor aislamiento

En el modelo de seguridad tradicional, las cargas de trabajo se programaban en sus propias instancias y no había recursos compartidos. El contorno de la máquina y la red que alojaban la aplicación demarcaban el límite de esta, y la única forma de implementar el aislamiento de la carga de trabajo consistía en recurrir a la separación física de hosts, a hipervisores y a cortafuegos convencionales.

En un mundo nativo de la nube, las cargas de trabajo se crean en contenedores en hosts y recursos compartidos, donde también se sintetizan a modo de paquetes de binarios. Por lo tanto, tienes que contar con un mayor aislamiento entre las cargas de trabajo. Las cargas de trabajo se pueden separar en microservicios, que se aíslan entre sí en parte por medio de controles de red y tecnologías de zonas de pruebas.

Principios de seguridad

Con el desarrollo de una arquitectura nativa de la nube, pretendíamos reforzar de forma simultánea toda nuestra seguridad; así que desarrollamos y optimizamos los siguientes principios de seguridad:

  • Protección de redes en el perímetro, de forma que las cargas de trabajo queden aisladas de los ataques a la red y del tráfico no autorizado procedente de Internet. El enfoque basado en cortafuegos, aunque no es un concepto novedoso para el modelo nativo de la nube, sigue formando parte de las prácticas recomendadas en materia de seguridad. En un mundo nativo de la nube, el enfoque perimetral sirve para proteger tantos componentes de la infraestructura como sea posible frente al tráfico no autorizado y posibles ataques procedentes de Internet (por ejemplo, ataques de denegación de servicio por volumen).

  • Inexistencia de confianza mutua inherente entre servicios, de tal forma que solo pueden hacer uso del servicio las llamadas conocidas, de confianza y portadoras de una autorización específica. Se impide así que los atacantes utilicen código no confiable para acceder a los servicios. Si un servicio sufre una vulneración, este principio evita que el atacante lleve a cabo acciones que le permitan ampliar su alcance. Esta desconfianza mutua contribuye a limitar el alcance de cualquier posible vulneración.

  • Ejecución por parte de máquinas de confianza de código cuya procedencia sea conocida, de forma que se obligue a las identidades de servicio a utilizar solo código y configuraciones autorizados, así como a ejecutarse solo en entornos autorizados y verificados.

  • Puntos críticos destinados a lograr una implementación coherente de políticas en los servicios. Por ejemplo, un punto crítico que sirva para verificar solicitudes de acceso a datos de usuario, de tal forma que el acceso a cualquier servicio proceda de una solicitud validada proveniente de un usuario final que cuente con autorización y que el acceso de administrador requiera una justificación empresarial.

  • Simplificación, automatización y normalización del lanzamiento de cambios, de tal forma que se pueda revisar con facilidad cómo los cambios en la infraestructura repercuten en la seguridad y para que se puedan lanzar los parches de seguridad ocasionando el mínimo impacto posible en la producción.

  • Aislamiento entre cargas de trabajo que compartan sistema operativo, de tal forma que sea imposible que la vulneración de cualquier servicio afecte a la seguridad de otra carga que se ejecute en el mismo host. Se limita así el alcance de cualquier posible vulneración.

La meta que perseguimos en toda nuestra infraestructura es contar con una seguridad automatizada que no dependa de personas. La seguridad debería escalarse en la misma medida que lo hagan los servicios. Los servicios deberían ser seguros de manera predeterminada e inseguros de manera excepcional: las acciones humanas deberían ser una excepción, no una rutina, además de auditables cada vez que ocurran. De ese modo, podremos autenticar un servicio en función del código y la configuración desplegados para el servicio, en lugar de las personas que lo desplegaron.

La implementación de estos principios de seguridad en su conjunto equivale a que los contenedores y los microservicios que se ejecutan en el interior de estos pueden desplegarse, comunicarse entre sí y ejecutarse en paralelo sin debilitar las propiedades de cualquier arquitectura nativa de la nube (es decir, la gestión sencilla de las cargas de trabajo, el escalado sin operaciones y el empaquetado de binarios eficaz). Todo esto se puede lograr sin que los detalles de seguridad e implementación de la infraestructura subyacente supongan una carga para los programadores de los microservicios.

Servicios de seguridad internos de Google

Para proteger la infraestructura nativa de la nube de Google, hemos diseñado y desarrollado diferentes herramientas y servicios internos. Los servicios de seguridad que enumeramos a continuación funcionan de forma cooperativa para abordar las directrices definidas en la sección Principios de seguridad:

  • Google Front End (GFE): se encarga de terminar las conexiones procedentes del usuario final y proporciona un punto centralizado para implementar las prácticas recomendadas en materia de TLS. A pesar de que hemos dejado de hacer hincapié en la seguridad basada en perímetros, GFE sigue siendo una parte importante de nuestra estrategia de protección de los servicios internos frente a los ataques de denegación de servicio. GFE es el primer punto de entrada a Google de cualquier conexión de usuario; una vez que este accede a nuestra infraestructura, GFE también se encarga del balanceo de carga y del redireccionamiento del tráfico entre regiones según sea necesario. En nuestra infraestructura, GFE es el proxy perimetral que enruta el tráfico al microservicio pertinente.

  • Seguridad de transporte en la capa de la aplicación (ALTS): se emplea con fines de autenticación, integridad y encriptado de RPC. ALTS es un sistema de encriptado durante el transporte y autenticación mutua para los servicios de la infraestructura de Google. Las identidades están, por lo general, vinculadas a los servicios en lugar de a un nombre de servidor o host específicos. Se aporta así fluidez a la replicación de microservicios, al balanceo de carga y a la reprogramación entre hosts.

  • La autorización binaria para Borg y la integridad de hosts sirven para verificar la integridad de microservicios y máquinas, respectivamente:

    • Autorización binaria para Borg (BAB): mecanismo de comprobación del cumplimiento en el momento del despliegue que se asegura de que el código cumpla los requisitos de seguridad internos antes de ser desplegado. BAB comprueba, por ejemplo, que un segundo ingeniero revisa los cambios, que el código se envía a nuestro repositorio de código fuente y que los binarios se compilan de forma verificable en infraestructuras dedicadas. En nuestra infraestructura, BAB restringe el despliegue de microservicios que no cuenten con autorización.
    • Integridad de hosts (HINT): verifica la integridad del software de sistemas de hosts a través de un proceso de arranque seguro y, cuando existe compatibilidad, tiene el respaldo de un hardware seguro de microcontrolador. HINT comprueba, por ejemplo, si se incluye la verificación de firmas digitales en el BIOS, el BMC, el bootloader y el kernel del sistema operativo.
  • La política de acceso a servicios y las incidencias contextuales de usuarios finales sirven para restringir el acceso a los datos:

    • Política de acceso a servicios: limita la forma de acceder a datos entre los servicios. Cada vez que se envía una RPC de un servicio a otro, la política de acceso a servicios define las políticas de autenticación, autorización y auditoría que se necesitan para acceder a los datos del servicio receptor. De este modo, se restringe la forma de acceso a los datos, se concede el nivel mínimo de acceso necesario y se especifican las opciones de auditar ese acceso. En la infraestructura de Google, la política de acceso a servicios limita el acceso de un microservicio a los datos de otro y permite realizar análisis globales de controles de acceso.
    • Incidencias contextuales de usuarios finales (EUC): un servicio de autenticación de usuarios finales emite estas incidencias, que prestan servicios con una identidad de usuario que es independiente de su identidad de servicio. Se trata de credenciales protegidas por integridad, emitidas de forma centralizada y susceptibles de reenvío que certifican la identidad del usuario final que haya solicitado el servicio. Se reduce así la necesidad de que haya confianza entre servicios, ya que la identidad de emparejamiento a través de ATLS no suele ser suficiente para conceder acceso y tales decisiones de autorización tienden a basarse también en la identidad del usuario final.
  • Herramientas de Borg para despliegues azul-verde:3 este conjunto de herramientas se encarga de migrar cargas de trabajo en ejecución cuando se realizan tareas de mantenimiento. Se despliega una nueva tarea de Borg, además de la que ya existe, y un balanceador de carga va traspasando tráfico de una a otra. Se posibilita así la actualización de un microservicio sin que haya periodo inactivo alguno y sin que el usuario se dé cuenta. Estas herramientas sirven para aplicar mejoras a los servicios cada vez que les añadimos nuevas funciones, así como para aplicar actualizaciones de seguridad críticas sin que haya periodos inactivos (por ejemplo, para los errores heartbleed y las vulnerabilidades Spectre/Meltdown). En cuanto a los cambios que afectan a la infraestructura de Google Cloud, empleamos un proceso de migración activa para asegurarnos de que no afecten a las cargas de trabajo de las máquinas virtuales.

  • La herramienta que utilizamos para aislar cargas de trabajo es gVisor. Esta utiliza un kernel de espacio de usuario para interceptar y gestionar syscalls, con lo que se reducen la interacción con el host y la posible superficie de ataque. Este kernel proporciona la mayor parte de la funcionalidad que se necesita para ejecutar una aplicación y limita la superficie del kernel del host a la que puede acceder la aplicación. En la infraestructura de Google, gVisor figura entre las varias herramientas importantes que se utilizan para aislar entre sí las cargas de trabajo internas y las de clientes de Google Cloud que se ejecutan en el mismo host.

En la tabla 2, se asigna cada uno de los principios de seguridad descritos en la sección del mismo nombre a la herramienta correspondiente que utilizamos para implementarlo.

Principio de seguridad Herramienta o servicio de seguridad internos de Google
Protección de la red en el perímetro Google Front End (GFE), para gestionar la terminación de TLS y las políticas de tráfico entrante
Inexistencia de confianza mutua inherente entre los servicios Seguridad de transporte en la capa de la aplicación (ALTS), para las identidades de servicio y para la autenticación, la integridad y el encriptado de RPC
Ejecución de código de procedencia conocida por parte de máquinas de confianza Autorización binaria para Borg (BAB), para verificar la procedencia del código

Integridad de hosts (HINT), para verificar la integridad de las máquinas

Puntos críticos destinados a lograr una implementación coherente de políticas en los servicios Política de acceso a servicios, para limitar la forma de acceder a datos entre los servicios

Incidencias contextuales de usuarios finales (EUC), para certificar la identidad del solicitante original

Simplificación, automatización y normalización de la implementación de cambios Herramienta de Borg, para realizar despliegues azul-verde
Aislamiento entre cargas de trabajo que compartan sistema operativo gVisor, para aislar cargas de trabajo

Tabla 2: Principios y herramientas de seguridad para implementar la seguridad nativa de la nube en Google

Visión de conjunto

En esta sección, describimos cómo se acoplan los componentes analizados hasta ahora para entregar las solicitudes de usuario en un mundo nativo de la nube. Para ello utilizamos dos ejemplos: en el primero, rastreamos una solicitud de datos de usuario típica desde su creación hasta su entrega en destino y, en el segundo, rastreamos un cambio de código desde la programación hasta la producción. No todas las tecnologías mencionadas aquí se utilizan en todas las partes de la infraestructura de Google, sino que ello depende de los servicios y las cargas de trabajo.

Acceso a datos de usuario

Como se muestra en la figura 1, cuando GFE recibe la solicitud de un usuario (paso 1), este servicio termina la conexión TLS y reenvía la solicitud al frontend del servicio correspondiente mediante ALTS4 (paso 2). El frontend de la aplicación autentica la solicitud del usuario mediante un servicio de autenticación de usuarios finales (EUA) centralizado y, si es correcta, recibe una incidencia contextual de usuarios finales (EUC) criptográfica de corta duración (paso 3).

diagrama

Figura 1: Controles de seguridad de la arquitectura nativa de la nube de Google: acceso a datos de usuario

A continuación, el frontend de la aplicación hace una RPC a través de ALTS a un servicio de backend de almacenamiento y reenvía la incidencia EUC en la solicitud de backend (paso 4). El servicio de backend utiliza la política de acceso a servicios para asegurarse de que se cumpla lo siguiente:

  1. La identidad ALTS del servicio de frontend tiene autorización para realizar solicitudes al servicio de backend y presentar una incidencia EUC.
  2. La identidad del frontend está protegida por nuestra autorización binaria para Borg (BAB).
  3. La incidencia EUC es válida.

El servicio de backend comprueba entonces que el usuario de la incidencia EUC tenga la autorización para acceder a los datos solicitados. Si alguna de estas comprobaciones fracasa, se rechaza la solicitud. En muchos casos, hay una cadena de llamadas de backend, cada uno de los servicios intermediarios somete a las RPC entrantes a una verificación de política de acceso a servicios y la incidencia EUC se reenvía con RPC salientes. Si estas comprobaciones prosperan, los datos se devuelven al frontend de la aplicación autorizada y se entregan al usuario autorizado.

Cada una de las máquinas cuenta con una credencial ALTS que se aprovisiona a través del sistema HINT, y que solo se puede desencriptar si HINT ha verificado que la máquina se inició correctamente. La mayoría de los servicios de Google se ejecutan en forma de microservicios sobre Borg, cada uno de los cuales tiene su propia identidad ALTS. El borgmaster5 otorga estas credenciales ALTS de microservicios a cargas de trabajo en función de la identidad del microservicio, como se describe en la figura 1. Las credenciales ALTS de nivel de máquina forman el canal seguro destinado a aprovisionar credenciales de microservicios, de modo que solo las máquinas que hayan superado el inicio verificado por HINT puedan alojar cargas de trabajo de microservicios.

Cambios en el código

Como se muestra en la figura 2, cada vez que un Googler hace un cambio en un microservicio protegido por una BAB cuya solidez esté acreditada, el cambio debe enviarse a nuestro repositorio central de código, que aplica una revisión de código. Una vez aprobado, el cambio se envía al sistema de compilación central y confiable, que genera un paquete que incluye un certificado de archivo de manifiesto de compilación verificable y firmado (paso 1). En el momento del despliegue, BAB verifica que se haya seguido este proceso validando el certificado firmado procedente del flujo de procesamiento de compilación (paso 2).

diagrama

Figura 2: Controles de seguridad de la arquitectura nativa de la nube de Google: cambios en el código

Todas las actualizaciones de las cargas de trabajo se gestionan a través de despliegues azul-verde, ya se trate de un lanzamiento rutinario o de un parche de seguridad urgente (paso 3). GFE balancea la carga del tráfico de modo que vaya dirigido al nuevo despliegue para garantizar la continuidad de las operaciones.

Todas las cargas de trabajo precisan aislamiento. Si la carga de trabajo es menos confiable —porque, por ejemplo, la carga tenga varios propietarios o la procedencia del código fuente sea ajena a Google—, se puede desplegar en un entorno protegido por gVisor, o se pueden usar otras capas de aislamiento. Este aislamiento garantiza que, en caso de que una de las instancias de la aplicación sufra una vulneración, las demás instancias no se vean afectadas.

Implementación de BeyondProd

Un cambio total

Gracias a la conversión a una arquitectura nativa de la nube y a la creación de medidas de seguridad para dicha infraestructura, Google está en condiciones de ofrecer propiedades de seguridad muy sólidas para sus cargas de trabajo internas y externas (Google Cloud).

La creación de componentes compartidos permite minimizar la carga que soportan los programadores al tener que cumplir requisitos de seguridad comunes. En un escenario ideal, la funcionalidad de seguridad apenas debería exigir integración en cada aplicación y habría de proporcionarse como un tejido que envolviera y conectara todos los microservicios. Esta es una característica que conocemos como "malla de servicios". Esto significa, además, que la seguridad se puede gestionar e implementar por separado a partir de actividades rutinarias de programación y despliegue.

Cambio hacia el modelo nativo de la nube

La transición de Google hacia el modelo nativo de la nube requirió cambios en dos áreas principales: nuestra infraestructura y nuestro proceso de programación. Aunque los abordamos simultáneamente, estos cambios se podrían haber desvinculado y abordado de manera independiente.

Cambio de nuestra infraestructura

Comenzamos levantando una sólida base de identidad, autenticación y autorización de servicios. Los cimientos que construimos a modo de identidades de servicio confiables nos permitieron implementar funciones de seguridad de nivel superior que dependieran de la validación de estas identidades, como la política de acceso a servicios y las incidencias EUC. Con el objetivo de agilizar esta transición para los servicios nuevos y actuales, el sistema ALTS se proporcionó inicialmente como biblioteca con un único daemon auxiliar. Este daemon se ejecutaba en el host al que llamaban todos los servicios y con el tiempo evolucionó hasta convertirse en una biblioteca que utilizaba credenciales de servicios. La biblioteca de ALTS se integró a la perfección en la biblioteca principal de RPC, lo que facilitó su amplia adopción, y no impuso una carga significativa a equipos de programación concretos. El lanzamiento de ALTS era un requisito previo para lanzar los servicios de política de acceso a servicios y de incidencias EUC.

Cambio de nuestros procesos de programación

Para Google fue crucial establecer un proceso sólido de compilación y revisión de código. Esto nos permitió garantizar la integridad de los servicios en ejecución y el sentido de las identidades utilizadas por ALTS. Establecimos un proceso de compilación centralizado que nos permitía comenzar a aplicar requisitos, como la revisión de código por dos personas y la realización automatizada de pruebas en las fases de compilación y despliegue. Consulta el informe Autorización binaria para Borg si quieres más información sobre el despliegue.

Tras levantar la estructura básica, comenzamos a abordar la necesidad de ejecutar código externo y no confiable en nuestros entornos. Para ello, comenzamos a trabajar creando zonas de pruebas: primero con ptrace; luego, con gVisor. Del mismo modo, los despliegues azul-verde aportaron una ventaja notable en términos de seguridad (por ejemplo, en la aplicación de parches) y fiabilidad.

No tardamos en darnos cuenta de que todo se simplificaba si los servicios se iniciaban registrando infracciones de políticas en lugar de bloqueándolas. La ventaja de este enfoque fue doble: en primer lugar, les brindaba a los propietarios de servicios la oportunidad de probar el cambio y medir el impacto (si lo hubiera) que tendría en su servicio la migración a un entorno nativo de la nube; en segundo lugar, nos permitió corregir errores, así como identificar cualquier funcionalidad complementaria que fuera necesario proporcionar a los equipos de servicio. Por ejemplo, cuando un servicio se incorpora a BAB, los propietarios de servicios habilitan el modo de solo auditoría. Esto les facilita la identificación de código o flujos de trabajo que no cumplan con sus requisitos. Una vez que abordan los problemas indicados por el modo de solo auditoría, los propietarios de servicios se pasan al modo de cumplimiento. En gVisor esto lo logramos, en primer lugar, demarcando zonas de pruebas y asignándoles cargas de trabajo, a pesar de que ello comportara carencias de compatibilidad; y, en segundo lugar, resolviendo estas carencias sistemáticamente para mejorar la zona de pruebas.

Ventajas del cambio

Del mismo modo que BeyondCorp nos ayudó a evolucionar y superar un modelo de seguridad basado en perímetros, BeyondProd representa un salto similar en nuestro enfoque sobre la seguridad de la producción. El enfoque de BeyondProd describe una arquitectura de seguridad nativa de la nube que no presupone la confianza entre servicios, proporciona aislamiento entre las cargas de trabajo, verifica que solo se desplieguen aplicaciones compiladas de manera centralizada, automatiza la gestión de vulnerabilidades e implementa sólidos controles de acceso a datos críticos. La arquitectura de BeyondProd dio pie a que Google innovara creando varios sistemas para cumplir con estos requisitos.

Con demasiada frecuencia, la seguridad se deja para el último momento, cuando ya se ha tomado la decisión de migrar a una nueva arquitectura. La implicación de tu equipo de seguridad en las fases iniciales de implantación de una arquitectura nativa de la nube y la priorización de las ventajas de este nuevo modelo de seguridad —por ejemplo, la simplificación de la gestión de parches y el endurecimiento de los controles de acceso— posiblemente aporten ventajas significativas a los equipos de seguridad y de desarrollo de aplicaciones. La aplicación de los principios de seguridad descritos en este documento a tu infraestructura nativa de la nube permite reforzar el despliegue de tus cargas de trabajo y las medidas de protección de las comunicaciones de dichas cargas, así como controlar las repercusiones de estas medidas en otras cargas.

Notas

1 Borg es el sistema de gestión de clústeres de Google y está concebido para programar y ejecutar cargas de trabajo a gran escala. Borg fue el primer sistema de gestión de contenedores unificado de Google y sirvió de inspiración a los creadores de Kubernetes.

2 La expresión en inglés "shifting left" (literalmente, "desplazarse a la izquierda") hace referencia a hacer cambios en las fases tempranas del ciclo de programación de software, entre los que se pueden incluir la codificación, la compilación, la realización de pruebas, la validación y el despliegue. Los diagramas de ciclo de vida se dibujan generalmente de izquierda a derecha, por lo que la izquierda se refiere a las fases que se hacen antes.

3 Un despliegue azul-verde es una forma de lanzar un cambio en una carga de trabajo sin afectar al tráfico entrante, de modo que los usuarios finales no experimenten periodos de inactividad al acceder a la aplicación.

4 Para comprender mejor cómo se enruta el tráfico dentro de la infraestructura de Google desde GFE hasta un servicio, consulta la sección ¿Cómo se enruta el tráfico? de nuestro informe "Encriptado en tránsito".

5El borgmaster es el controlador centralizado perteneciente a Borg. Se encarga de gestionar la programación de tareas y de comunicarse con las que estén en ejecución acerca de su estado.