BeyondProd: un nuevo enfoque para la seguridad nativa de la nube

Google escribió varios informes en los que explica proyectos desarrollados de forma interna que ayudan a mejorar la seguridad. BeyondProd hace un uso intencional de los conceptos de BeyondCorp: tal como un modelo de seguridad perimetral que ya no funciona para los usuarios finales, tampoco funciona con microservicios. Podemos adaptar el informe original de BeyondCorp y expresar que “Las suposiciones clave de este modelo ya no son válidas: el perímetro ya no es solo la ubicación física [del centro de datos de] de la empresa, y el interior del perímetro ya no es un lugar seguro para alojar [microservicios para] dispositivos informáticos personales y aplicaciones empresariales”.

En este informe, proporcionamos detalles sobre cómo varias piezas de la infraestructura de Google trabajan juntas para proteger las cargas de trabajo, en una arquitectura que ahora se conoce como “nativa de la nube”. Para obtener una descripción general de la seguridad de Google, consulta el informe sobre el diseño de infraestructura de seguridad.

El contenido de este documento corresponde a diciembre de 2019. Este informe representa el statu quo en el momento de su redacción. Es posible que cambien las políticas y los sistemas de seguridad de Google Cloud, ya que mejoramos la protección de nuestros usuarios de forma continua.

Glosario

En este documento, se usan las siguientes definiciones:

  • Un microservicio separa las tareas individuales que una aplicación debe realizar en servicios separados, cada uno de los cuales puede desarrollarse y administrarse de manera independiente con su propia API, lanzamiento, escalamiento y administración de cuotas. En una arquitectura más moderna, una aplicación, como un sitio web, puede ejecutarse como una colección de microservicios en lugar de un único servicio monolítico. Los microservicios son independientes, modulares, dinámicos y efímeros. Pueden distribuirse entre muchos hosts, clústeres o incluso nubes.

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

  • Un trabajo es una instancia única de un microservicio que ejecuta parte de una aplicación.

  • Un microservicio usa una identidad de servicio para autenticarse en otros servicios que se ejecutan en la infraestructura.

  • Una malla de servicios es una capa de infraestructura para la comunicación entre servicios, que puede controlar el tráfico, aplicar políticas y proporcionar supervisión centralizada para las llamadas de servicio. Cuando se utiliza una arquitectura de microservicios, esto le quita la carga de implementar estos controles a los servicios individuales y permite una administración más simple y centralizada en muchos microservicios.

Resumen para directores generales de información

  • La infraestructura de Google implementa cargas de trabajo como microservicios individuales en contenedores y administra estas cargas de trabajo con Borg, nuestro sistema de organización de contenedores. Esta es una inspiración y una plantilla para lo que hoy se conoce como una arquitectura “nativa de la nube”.

  • La infraestructura de Google se diseñó de manera intencional con la seguridad en mente, no se agregó después. Nuestra infraestructura no supone ninguna confianza entre sus servicios.

  • Google protege sus microservicios con una iniciativa llamada BeyondProd. Esta protección incluye cómo se cambia el código y cómo se accede a los datos del usuario en los microservicios. BeyondProd aplica conceptos como: extremos de servicio mutuamente autenticados, seguridad de transporte, terminación en perímetro con balanceo de cargas global y protección de denegación de servicio, procedencia de código de extremo a extremo y zona de pruebas del entorno de ejecución.

  • Pasar de un modelo de seguridad tradicional a un modelo de seguridad nativo de la nube nos obligó a realizar cambios en dos áreas principales: nuestra infraestructura y nuestro proceso de desarrollo. La creación de componentes compartidos en una estructura compartida que abarca y conecta todos los microservicios, también conocida como malla de servicios, facilitó la implementación de cambios y logró una seguridad coherente en todos los servicios.

Motivación

Google se trasladó a contenedores y a la organización de contenedores para lograr un mayor uso de los recursos, compilar aplicaciones de alta disponibilidad y simplificar el trabajo de los desarrolladores de Google. Tuvimos otro motivo por el cual trasladarnos a una infraestructura en contenedores: alinear nuestros controles de seguridad con nuestra arquitectura. Nos resultó evidente que un modelo de seguridad basado en el perímetro no ofrecía suficiente seguridad. Si un atacante ingresara al perímetro, tendría acceso libre dentro de la red. Si bien nos dimos cuenta de que necesitábamos controles de seguridad más fuertes en toda nuestra infraestructura, también queríamos facilitar a los desarrolladores de Google la escritura y la implementación de aplicaciones seguras sin que ellos mismos tuvieran que implementar las características de seguridad.

Pasar de aplicaciones monolíticas a microservicios distribuidos implementados desde contenedores mediante un sistema de organización tuvo beneficios operativos tangibles: administración y escalabilidad más simples. Esta arquitectura nativa de la nube requirió un modelo de seguridad distinto con diferentes herramientas para proteger las implementaciones alineadas con los beneficios de administración y escalabilidad de los microservicios.

En este documento, se describe cómo se implementa la seguridad nativa de la nube en Google, denominada BeyondProd: qué implicaciones tiene para la seguridad el traslado hacia la nube nativa, principios de la seguridad nativa de la nube, sistemas creados para abordar estos requisitos y orientación sobre cómo emprender un cambio de este tipo tú mismo.

Seguridad nativa de la nube en Google

Microservicios en contenedores

Desde sus inicios, Google tomó la decisión consciente de aumentar la capacidad de su centro de datos con servidores de bajo costo en lugar de invertir en hardware más costoso y de alta disponibilidad. La filosofía de nuestra confiabilidad era, y aún es, que cualquier parte individual de un sistema debía poder fallar sin afectar la disponibilidad de los servicios visibles para el usuario. Para lograr esta disponibilidad, se requería la ejecución de instancias redundantes de servicios, de manera que las fallas individuales no provocaran interrupciones. Un resultado de esta filosofía fue el desarrollo de contenedores, microservicios y organización de contenedores para administrar de manera escalable la implementación de estos sistemas altamente redundantes y distribuidos.

Una infraestructura en contenedores significa que cada carga de trabajo se implementa como su propio conjunto de contenedores inmutables, móviles y programables. Desarrollamos un sistema de organización de contenedores llamado Borg1 para administrar estos contenedores de forma interna, que todavía usamos a fin de implementar varios miles de millones de contenedores por semana.

Los contenedores hicieron que las cargas de trabajo sean más fáciles de agrupar y reprogramar en las máquinas. Los microservicios facilitaron el desarrollo y la depuración de diferentes partes de una aplicación. Si se usan en combinación, los microservicios y los contenedores permiten dividir las cargas de trabajo en unidades más pequeñas y más administrables para su mantenimiento y detección. Trasladarse hacia una infraestructura en contenedores con una arquitectura de microservicios se conoce como volverse “nativo de la nube”. Los servicios se ejecutan dentro de contenedores implementados por Borg. Esta arquitectura escala las cargas de trabajo según sea necesario. Si hay una demanda alta para una carga de trabajo en particular, es posible que varias máquinas ejecuten copias del mismo servicio en simultáneo para manejar la escala requerida de la carga de trabajo.

Google se destaca por haber tomado en cuenta la seguridad como parte de cada evolución en nuestra arquitectura. El concepto más reciente de seguridad nativa de la nube es comparable a lo que Google usó durante muchos años para proteger nuestra infraestructura. Nuestro objetivo con este proceso de arquitectura y desarrollo de microservicios es abordar los problemas de seguridad lo antes posible en el ciclo de desarrollo y de implementación, cuando los problemas son menos costosos, y hacerlo de manera estandarizada y coherente. El resultado final es que los desarrolladores dediquen menos tiempo a la seguridad y, a su vez, obtengan resultados más seguros.

Migración a una arquitectura nativa de la nube

Las arquitecturas de seguridad modernas fueron más allá del modelo de seguridad tradicional basado en perímetro, en el que un muro protege el perímetro y cualquier usuario o servicio en el interior es totalmente confiable. BeyondCorp fue una respuesta a un cambio en la forma en que trabaja el usuario corporativo moderno. En la actualidad, los usuarios son móviles y por lo general operan fuera del perímetro de seguridad tradicional de una organización, como una cafetería, un avión o cualquier punto intermedio. En BeyondCorp, descartamos la idea de una red corporativa con privilegios y un acceso autorizado basado solo en las credenciales y los atributos de dispositivo y usuario, sin importar la ubicación de red del usuario.

La seguridad nativa de la nube resuelve la misma preocupación respecto de los servicios y los usuarios: no podemos simplemente confiar en un firewall como protección de la red de producción, del mismo modo en que no podemos confiar en un firewall como protección de la red corporativa. De la misma manera en que los usuarios no usan el mismo dispositivo o ubicación física, los desarrolladores no implementan el código en el mismo entorno. Con BeyondProd, los microservicios pueden ejecutarse no solo en un centro de datos con firewall, sino también en nubes públicas, nubes privadas o servicios alojados por terceros, y deben estar protegidos en todas partes.

Del mismo modo en que los usuarios se mueven, usan diferentes dispositivos y se conectan desde distintas ubicaciones, los microservicios también se mueven y se implementan en entornos diferentes y en hosts heterogéneos. Donde BeyondCorp declara que “la confianza del usuario debe depender de características como el estado contextual de los dispositivos y no la capacidad de conectarse a la red corporativa”, BeyondProd afirma que “la confianza del servicio debe depender de características como la procedencia del código y la identidad del servicio, y no de la ubicación en la red de producción, como la identidad del nombre de host o IP”.

Arquitectura nativa de la nube y el desarrollo de aplicaciones

Un modelo de seguridad más tradicional, centrado en la seguridad basada en el perímetro, no puede proteger singularmente una arquitectura nativa de la nube. Considera este ejemplo: una aplicación monolítica que utiliza una arquitectura de tres niveles se implementa en un centro de datos corporativo privado que tiene suficiente capacidad para manejar la carga máxima de los eventos críticos. Las aplicaciones con requisitos de red o hardware específicos se implementan de manera intencional en máquinas específicas que por lo general mantienen direcciones IP fijas. Los lanzamientos son poco frecuentes, grandes y difíciles de coordinar, ya que los cambios resultantes afectan simultáneamente a muchas partes de la aplicación. Esto conduce a aplicaciones de muy larga duración que se actualizan con menos continuidad y en las que los parches de seguridad, por lo general, se aplican con menos frecuencia.

Sin embargo, en un modelo nativo de la nube, los contenedores separan los objetos binarios que necesita tu aplicación del sistema operativo host subyacente y permiten que las aplicaciones sean más portátiles. Los contenedores están diseñados para usarse inmutablemente, es decir que no se modifican una vez que se implementan, por lo que se reconstruyen y se vuelven a implementar con frecuencia. Los trabajos escalan para manejar la carga, ya que se implementan trabajos nuevos cuando la carga aumenta y se quitan trabajos existentes cuando la carga disminuye. La reutilización y el uso compartido de hardware y redes es más frecuente, dado que los contenedores se reinician, quitan o reprograman a menudo. El proceso de desarrollo es más coherente y uniforme entre los equipos con un proceso común y estandarizado de compilación y distribución, aunque los equipos administren el desarrollo de sus microservicios de manera independiente. Como resultado, las consideraciones de seguridad (p. ej., revisiones de seguridad, análisis de código y administración de vulnerabilidades) pueden tener lugar más temprano en el ciclo de desarrollo.

Implicaciones para la seguridad

Hablamos mucho sobre cómo el modelo de un interior no confiable, con usuarios de BeyondCorp, también se puede aplicar a microservicios en BeyondProd, pero ¿cómo se ve ese cambio? La Tabla 1 proporciona una comparación entre los aspectos de seguridad de la infraestructura tradicional y sus contrapuntos en una arquitectura nativa de la nube. La tabla también muestra los requisitos necesarios para pasar de una a la otra. El resto de esta sección proporciona más detalles sobre cada fila de la tabla.

Seguridad de la infraestructura tradicional Seguridad nativa de la nube Requisitos implícitos para la seguridad nativa de la nube
Seguridad basada en perímetro (es decir, firewall), con comunicaciones internas consideradas de confianza Seguridad de confianza cero con comunicación de servicio a servicio verificada y sin confianza implícita para los servicios en el entorno Protección de la red en el perímetro (sigue siendo aplicable) sin confianza mutua inherente entre los servicios
Direcciones IP y hardware fijos para ciertas aplicaciones Mayor utilización, reutilización y uso compartido de recursos, incluidas las direcciones IP y el hardware Máquinas confiables que ejecutan código con procedencia conocida
Identidad basada en la dirección IP Identidad basada en el servicio
Los servicios se ejecutan en una ubicación conocida y esperada Los servicios pueden ejecutarse en cualquier lugar del entorno, incluidas las implementaciones híbridas en la nube pública y los centros de datos privados
Requisitos específicos de la seguridad incorporados en cada aplicación y aplicados por separadoRequisitos de seguridad compartidos integrados en las pilas de servicios a partir de una política de aplicación centralizada Cuellos de botella para la aplicación coherente de políticas en todos los servicios
Restricciones limitadas sobre cómo se crean y se revisan los servicios Los requisitos de seguridad se aplican de manera coherente a todos los servicios
Supervisión limitada de los componentes de seguridad Vista centralizada de las políticas de seguridad y cumplimiento de las políticas
Implementaciones especializadas y poco frecuentes Proceso de compilación y lanzamiento estandarizado con cambios más frecuentes en los microservicios individuales Lanzamiento de cambios simple, automatizado y estandarizado
Por lo general, las cargas de trabajo se implementan en hosts físicos o como VM y usan una máquina física o un hipervisor para proporcionar aislamiento Las cargas de trabajo agrupadas y sus procesos se ejecutan en un sistema operativo compartido, que requiere un mecanismo para aislar las cargas de trabajo Aislamiento entre cargas de trabajo que comparten un sistema operativo

Tabla 1: Requisitos implícitos para la seguridad en el traslado a una arquitectura nativa de la nube

Desde la seguridad basada en el perímetro hasta la seguridad de confianza cero

En un modelo de seguridad tradicional, las aplicaciones de una organización podrían depender de un firewall externo alrededor de su centro de datos privado para protegerlo contra el tráfico entrante. En un entorno nativo de la nube, un modelo de seguridad basado en el perímetro ya no es suficiente, aunque el perímetro de la red aún debe protegerse como en el modelo de BeyondCorp. Esto no presenta un problema de seguridad nuevo, sino que reconoce que si un firewall no puede proteger por completo la red corporativa, tampoco puede proteger por completo la red de producción. Con un modelo de seguridad de cero confianza, ya no puedes confiar en el tráfico interno de forma implícita, ya que requiere otros controles de seguridad, como autenticación y encriptación. Al mismo tiempo, el cambio hacia los microservicios brinda la oportunidad de reconsiderar el modelo de seguridad tradicional. A medida que dejas de depender de un solo perímetro de red (por ejemplo, un firewall), puedes segmentar aún más la red por servicio. Para llevar esta idea un paso más allá, puedes implementar la segmentación en el nivel de microservicios, sin ninguna confianza inherente entre los servicios. Con los microservicios, el tráfico puede tener niveles de confianza variables con diferentes controles: ya no se compara solo el tráfico interno con el externo.

Desde hardware y direcciones IP fijas hasta recursos compartidos más grandes

En un modelo de seguridad tradicional, las aplicaciones de una organización se implementaban en máquinas específicas y las direcciones IP de esas máquinas cambiaban con poca frecuencia. Esto significaba que las herramientas de seguridad podían confiar en un mapa de arquitectura relativamente estático que vinculaba las aplicaciones de manera predecible. Las políticas de seguridad en herramientas como firewalls podían usar direcciones IP como identificadores.

Sin embargo, en el mundo nativo de la nube, con hosts compartidos y trabajos que cambian con frecuencia, el uso de un firewall para controlar el acceso entre microservicios no funciona. No puedes confiar en el hecho de que una dirección IP específica esté vinculada a un servicio en particular. Como resultado, la identidad se basa en un servicio y no en una dirección IP o nombre de host.

Desde implementaciones de seguridad específicas de la aplicación hasta requisitos de seguridad compartidos integrados en pilas de servicios

En un modelo de seguridad tradicional, las aplicaciones individuales eran responsables de cumplir con sus propios requisitos de seguridad al margen de otros servicios. Estos requisitos incluyen la administración de identidades, la finalización de SSL/TLS y la administración de acceso a los datos. Con frecuencia, esto generaba implementaciones incoherentes o problemas de seguridad no resueltos, ya que estos problemas debían corregirse en muchos lugares y las soluciones eran más difíciles de aplicar.

En el mundo nativo de la nube, los componentes se reutilizan con mucha más frecuencia entre los servicios y hay cuellos de botella que permiten que las políticas se apliquen de manera coherente en todos los servicios. Se pueden aplicar políticas distintas con servicios de seguridad diferentes. Puedes dividir las distintas políticas en microservicios separados (por ejemplo, una política para garantizar el acceso autorizado a datos del usuario y otra a fin de garantizar el uso de conjuntos de cifrado TLS actualizados), en lugar de requerir que cada aplicación implemente servicios de seguridad críticos por separado.

Desde procesos de implementación especializados y poco frecuentes hasta procesos estandarizados con lanzamientos más frecuentes

En un modelo de seguridad tradicional, los servicios compartidos eran limitados. Un código más distribuido, junto con el desarrollo local, hacía difícil determinar el impacto de un cambio que afectaba muchas partes de una aplicación, por lo que los lanzamientos eran poco frecuentes y difíciles de coordinar. Para realizar un cambio, es posible que los desarrolladores necesiten actualizar cada componente directamente (por ejemplo, ingresar mediante SSH en una máquina virtual para actualizar una configuración). En general, esto condujo a aplicaciones de muy larga duración. Desde una perspectiva de seguridad, debido a que el código estaba más distribuido, era más difícil de revisar y era aún más difícil garantizar que cuando se solucionara una vulnerabilidad lo hiciera en todas partes. El traslado a entornos nativos de la nube, donde los lanzamientos son frecuentes y estandarizados, permite que la seguridad se desplace hacia la izquierda2 en el ciclo de desarrollo de software. Esto permite una aplicación de la higiene de seguridad más simple y coherente, incluida la aplicación regular de parches de seguridad.

Desde cargas de trabajo aisladas mediante máquinas físicas o hipervisores hasta cargas de trabajo agrupadas que se ejecutan en la misma máquina y requieren un aislamiento más sólido

En un modelo de seguridad tradicional, las cargas de trabajo se programaban en sus propias instancias, sin recursos compartidos. Una aplicación estaba efectivamente delimitada por su límite de máquina y red, y el aislamiento de la carga de trabajo se aplicaba solo mediante la separación física del host, los hipervisores y los firewalls tradicionales.

En el mundo nativo de la nube, las cargas de trabajo se almacenan en contenedores y se agrupan en hosts y recursos compartidos. Como resultado, necesitas contar con un mayor aislamiento entre tus cargas de trabajo. Las cargas de trabajo pueden separarse en microservicios que están aislados unos de otros en parte mediante los controles de red y las tecnologías de las zonas de prueba.

Principios de seguridad

Quisimos fortalecer nuestra seguridad a la par del desarrollo de una arquitectura nativa de la nube, por lo que desarrollamos y optimizamos los siguientes principios de seguridad:

  • Protección de la red en el perímetro, para que las cargas de trabajo estén aisladas de los ataques de red y el tráfico no autorizado de Internet. El enfoque basado en muros no es un concepto nuevo para los nativos de la nube, pero no deja de ser una práctica recomendada de seguridad. En un mundo nativo de la nube, el enfoque perimetral se usa para proteger la mayor infraestructura posible contra el tráfico no autorizado y los posibles ataques de Internet, por ejemplo, ataques de denegación de servicio basados en volumen.

  • No existe una confianza mutua inherente entre los servicios, de modo que solo los emisores conocidos, de confianza y específicamente autorizados puedan utilizar un servicio. Esto evita que los atacantes usen un código que no sea de confianza para acceder a un servicio. En caso de que un servicio sea vulnerado, evita que el atacante realice acciones que le permitan expandir su alcance. Esta desconfianza mutua ayuda a limitar el impacto de una vulneración.

  • Máquinas confiables que ejecutan código con procedencia conocida, de modo que las identidades de servicio estén limitadas a usar solo código y configuraciones autorizadas, y se ejecuten solo en entornos verificados y autorizados.

  • Cuellos de botella para la aplicación coherente de políticas en todos los servicios, por ejemplo, para verificar solicitudes de acceso a datos del usuario, de modo que el acceso del servicio derive de una solicitud validada que provenga de un usuario final autorizado y el acceso del administrador requiera justificación comercial.

  • Lanzamiento de cambios simple, automatizado y estandarizado para facilitar la revisión del impacto sobre la seguridad de los cambios en la infraestructura y permitir la aplicación de parches de seguridad con poco impacto en la producción.

  • Aislamiento entre cargas de trabajo que comparten un sistema operativo, de modo que si se vulnera un servicio, esto no afectará la seguridad de otra carga de trabajo que se ejecuta en el mismo host. Esto limita el “radio de impacto” de un riesgo posible.

Nuestro objetivo es tener una seguridad automatizada que no dependa de las personas en toda nuestra infraestructura. La seguridad debe escalar de la misma manera que los servicios. Los servicios deben ser seguros de forma predeterminada y ser inseguros por excepción. Las intervenciones humanas deben ser excepcionales y no rutinarias, y se deben poder auditar cuando se producen. De esta forma, podemos autenticar un servicio en función del código y la configuración implementados para este, en lugar de las personas que implementaron el servicio.

En conjunto, la implementación de estos principios de seguridad significa que los contenedores y sus microservicios pueden implementarse, comunicarse entre sí y ejecutarse uno al lado del otro sin debilitar las propiedades de una arquitectura nativa de la nube (es decir, administración simple de carga de trabajo, escalamiento autónomo y compresión eficaz). Todo esto se puede lograr sin que los desarrolladores de microservicios individuales se vean afectados por la seguridad y los detalles de implementación de la infraestructura subyacente.

Servicios de seguridad interna de Google

Diseñamos y desarrollamos varias herramientas y servicios internos para proteger la infraestructura nativa de la nube de Google. Los siguientes servicios de seguridad trabajan juntos para abordar los principios de seguridad que se definen en la sección Principios de seguridad:

  • Google Front End (GFE): Termina la conexión con el usuario final y proporciona un punto central para aplicar las prácticas recomendadas de TLS. GFE es una parte importante de nuestra estrategia para proteger los servicios internos contra ataques de denegación de servicio, a pesar de que nuestro énfasis ya no se centra en la seguridad perimetral. GFE es el primer punto de entrada para una conexión de usuario con Google. Una vez dentro de nuestra infraestructura, también es responsable del balanceo de cargas y de redirigir el tráfico entre regiones según sea necesario. En nuestra infraestructura, GFE es el proxy perimetral que dirige el tráfico al microservicio correcto.

  • Seguridad de transporte de la capa de la aplicación (ALTS): se usa para la autenticación, la integridad y la encriptación de RPC. La ALTS es un sistema de encriptación mutuo de autenticación y transporte para los servicios de la infraestructura de Google. Por lo general, las identidades están vinculadas a los servicios en lugar de a un host o un nombre de servidor específico. Esto facilita la replicación sin interrupciones del microservicio, el balanceo de cargas y la reprogramación entre hosts.

  • La autorización binaria para Borg y la Integridad del host se usan a fin de verificar los microservicios y la integridad de la máquina, respectivamente, como se describe a continuación:

    • Autorización binaria de Borg (BAB): Es una verificación de aplicación en el momento de la implementación que garantiza que el código cumpla con los requisitos de seguridad interna antes de implementarse. Las verificaciones de BAB incluyen que un segundo ingeniero revise los cambios, que el código se envíe a nuestro repositorio de código fuente y que se compilen los objetos binarios de manera verificable en una infraestructura dedicada. BAB restringe la implementación de microservicios no autorizados en nuestra infraestructura.
    • Integridad del host (HINT): Verifica la integridad del software del sistema host a través de un proceso de inicio seguro, y tiene el respaldo de hardware de microcontrolador seguro cuando es compatible. Las verificaciones de HINT incluyen la revisión de firmas digitales en el BIOS, el BMC, el bootloader y el kernel del SO.
  • La Política de acceso de servicio y los tickets de contexto del usuario final se usan para restringir el acceso a los datos, como se describe a continuación:

    • Política de acceso de servicio: limita la forma en que se accede a los datos entre servicios. Cuando se envía una RPC de un servicio a otro, la Política de Acceso a los servicios define las políticas de autenticación, autorización y auditoría necesarias para acceder a los datos del servicio receptor. Esto limita la forma en que se accede a los datos, otorga el nivel mínimo de acceso necesario y especifica cómo se puede auditar el acceso. En la infraestructura de Google, la Política de acceso de servicio limita el acceso de un microservicio a los datos de otro microservicio y permite que se realicen análisis globales de los controles de acceso.
    • Tickets de contexto del usuario final (EUC): Un servicio de autenticación de usuario final emite estos tickets, que les proporcionan una identidad de usuario a los servicios, distinta de su identidad de servicio. Estas son credenciales que se pueden reenviar, protegidas por la integridad y emitidas de forma centralizada que certifican la identidad de un usuario final que realizó una solicitud del servicio. Esto reduce la necesidad de confianza entre los servicios, ya que la identidad de par a través de ALTS suele ser insuficiente para otorgar acceso. Estas decisiones de autorización también suelen basarse en la identidad del usuario final.
  • Herramientas de Borg para implementaciones azul-verde3: Estas herramientas son responsables de migrar cargas de trabajo en ejecución cuando se realizan tareas de mantenimiento. Se implementa un nuevo trabajo de Borg además del trabajo existente y un balanceador de cargas mueve gradualmente el tráfico de uno a otro. Esto permite que un microservicio se actualice sin tiempo de inactividad y sin que el usuario lo note. Esta herramienta se usa con el objetivo de aplicar actualizaciones de servicio cuando agregamos características nuevas, así como para aplicar actualizaciones de seguridad críticas sin tiempo de inactividad (por ejemplo, Heartbleed, Spectre y Meltdown). Utilizamos la migración en vivo cuando los cambios afectan la infraestructura de Google Cloud para garantizar que las cargas de trabajo de las VM no se vean afectadas.

  • gVisor para el aislamiento de la carga de trabajo: gVisor usa un kernel de espacio de usuario a fin de interceptar y manejar las llamadas del sistema, lo que reduce la interacción con el host y la superficie de ataque posible. Este kernel proporciona la mayor parte de la funcionalidad necesaria 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 es una de varias herramientas importantes que se usan para aislar entre sí las cargas de trabajo internas y las de clientes de Google Cloud que se ejecutan en el mismo host.

La Tabla 2 asigna cada principio descrito en la sección Principios de seguridad a su herramienta correspondiente usada en Google para implementarlo.

Principio de seguridad Herramienta o servicio de seguridad interno de Google
Protección de la red en el perímetro Google Front End (GFE) para administrar la finalización de TLS y las políticas de tráfico entrante
No hay confianza mutua inherente entre los servicios Seguridad de transporte de la capa de la aplicación (ALTS) para las identidades de servicio y la autenticación, la integridad y la encriptación de RPC
Máquinas confiables que ejecutan código con procedencia conocida Autorización binaria para Borg (BAB), a fin de verificar la procedencia del código

Integridad del host (HINT), para verificar la integridad de la máquina

Cuellos de botella para la aplicación coherente de políticas en todos los servicios Política de acceso de servicio, para limitar la forma en que se accede a los datos entre los servicios

Tickets de contexto de usuario final (EUC), para certificar la identidad del solicitante original

Lanzamiento de cambios simple, automatizado y estandarizado Herramientas de Borg para implementaciones azul-verde
Aislamiento entre cargas de trabajo que comparten un sistema operativo gVisor, para el aislamiento de la carga de trabajo

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

Revisión general

En esta sección, describimos cómo los componentes que analizamos hasta ahora se conectan entre sí para entregar las solicitudes de los usuarios en un mundo nativo de la nube. Usamos dos ejemplos: en el primero, rastreamos una solicitud de datos del usuario típica desde su creación hasta la entrega en su destino y, en el segundo, rastreamos un cambio de código desde el desarrollo hasta la producción. No todas las tecnologías mencionadas aquí se usan en todas las partes de la infraestructura de Google, sino que su uso depende de los servicios y las cargas de trabajo.

Acceso a los datos del usuario

Como se muestra en la Figura 1, cuando GFE recibe una solicitud de un usuario (paso 1), finaliza 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 mediante un servicio central de autenticación de usuario final (EUA) y, si tiene éxito, recibe un ticket de contexto de usuario final (EUC) criptográfico y de corta duración (paso 3).

diagrama

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

A continuación, el frontend de la aplicación realiza una RPC sobre ALTS a un servicio de backend de almacenamiento y reenvía el ticket de EUC en la solicitud de backend (paso 4). El servicio de backend usa la Política de acceso de servicio para garantizar que se cumpla lo siguiente:

  1. La identidad ALTS del servicio de frontend está autorizada para realizar solicitudes al servicio de backend y presentar un ticket de EUC.
  2. La identidad del frontend está protegida por nuestra autorización binaria para Borg (BAB).
  3. El ticket de EUC es válido.

El servicio de backend verifica que el usuario en el ticket de EUC esté autorizado para acceder a los datos solicitados. Si alguna de estas verificaciones falla, se rechaza la solicitud. En muchos casos, hay una cadena de llamadas de backend y cada servicio intermediario realiza una verificación de la Política de acceso de servicio en las RPC entrantes y el ticket de EUC se reenvía en RPC salientes. Si estas verificaciones se aprueban, los datos se devuelven al frontend de la aplicación autorizada y se muestran al usuario autorizado.

Cada máquina cuenta con una credencial ALTS que se aprovisiona a través del sistema HINT y solo se puede desencriptar si HINT verifica que la máquina inició correctamente. La mayoría de los servicios de Google se ejecutan como microservicios sobre Borg y tienen cada uno su propia identidad ALTS. Borgmaster 5 otorga las credenciales ALTS de microservicios a cargas de trabajo basadas en la identidad del microservicio, como se describe en la Figura 1. Las credenciales ALTS a nivel de máquina forman el canal seguro para el aprovisionamiento de credenciales de microservicio, de modo que solo las máquinas que pasaron correctamente el inicio verificado de HINT puedan alojar cargas de trabajo de microservicios.

Cambio de código

Como se muestra en la Figura 2, cuando un Googler realiza un cambio en un microservicio protegido por un BAB adecuado, debe enviarlo a nuestro repositorio de código central, 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 produce un paquete con un certificado de manifiesto de compilación verificable y firmado (paso 1). En el momento de la implementación, BAB valida el certificado firmado de la canalización de compilación para verificar que se haya seguido el proceso (paso 2).

diagrama

Figura 2: Controles de seguridad de la arquitectura nativa de la nube de Google: realizar un cambio de código

Todas las actualizaciones de carga de trabajo se controlan a través de implementaciones azul-verde, ya sea un lanzamiento rutinario o un parche de seguridad de emergencia (paso 3). La carga de GFE equilibra el tráfico hacia la implementación nueva para garantizar la continuidad de las operaciones.

Todas las cargas de trabajo requieren aislamiento. Si la carga de trabajo es menos confiable, por ejemplo, si es de múltiples instancias o el código fuente se origina fuera de Google, puede implementarse en un entorno protegido por gVisor o usar otras capas de aislamiento. Este aislamiento garantiza que si una instancia de la aplicación está en riesgo, ninguna de las otras se verá afectada.

Aplicación de BeyondProd

Un cambio completo

Gracias a la adopción de la nube nativa y una protección adecuada de su infraestructura, Google puede ofrecer propiedades de seguridad muy sólidas para sus cargas de trabajo internas y externas (Google Cloud).

La carga de los desarrolladores individuales para cumplir con los requisitos de seguridad comunes es mínima gracias a la compilación de componentes compartidos. Lo ideal sería que la funcionalidad de seguridad requiriera poca o ninguna integración en cada aplicación individual y, en cambio, se proporcionara como una envoltura que conecta todos los microservicios. Por lo general, esto se denomina malla de servicios. Esto también significa que la seguridad se puede implementar y administrar por separado de las actividades normales de desarrollo o implementación.

El cambio hacia la nube nativa

La transición de Google hacia la nube nativa requirió cambios en dos áreas principales: en nuestra infraestructura y en nuestro proceso de desarrollo. Abordamos estos cambios de forma simultánea, pero podían desvincularse y abordarse de manera independiente.

Cambios en nuestra infraestructura

Comenzamos por crear una base sólida de identidad, autenticación y autorización de servicios. Tener una base de identidades de servicio confiable nos permitió implementar funciones de seguridad de nivel superior que dependen de la validación de estas identidades, como Políticas de Acceso a los Servicios y tickets de EUC. A fin de facilitar la transición de los servicios nuevos y los existentes, ALTS se proporcionó en un principio como una biblioteca con un único daemon auxiliar. Este daemon se ejecutaba en el host al que llamaban todos los servicios y con el tiempo evolucionó como una biblioteca con credenciales de servicio. La biblioteca de ALTS se integró sin problemas en la biblioteca principal de RPC, y esto facilitó su amplia adopción, sin una carga significativa para los equipos de desarrollo individuales. El lanzamiento de ALTS era un requisito previo para implementar las Políticas de Acceso a los Servicios y los tickets de EUC.

Cambios en nuestros procesos de desarrollo

Establecer un proceso sólido de compilación y revisión de código fue fundamental para Google. Esto nos permitió garantizar la integridad de los servicios que se están ejecutando y que las identidades que usa ALTS son significativas. Establecimos un proceso de compilación central en el que pudimos comenzar a aplicar requisitos, como una revisión de código de dos personas y pruebas automatizadas en el momento de la compilación y la implementación. (Consulta el informe de autorización binaria para Borg a fin de obtener más información sobre la implementación).

Una vez implementados los conceptos básicos, comenzamos a abordar la necesidad de ejecutar código externo y no confiable en nuestros entornos. Para lograr este objetivo, comenzamos a trabajar con zonas de pruebas: primero con ptrace y, luego, con gVisor. Del mismo modo, las implementaciones azul-verde proporcionaron un beneficio significativo en términos de confiabilidad y seguridad (p. ej., la aplicación de parches).

Descubrimos con rapidez que era más fácil si un servicio comenzaba por registrar incumplimientos de política en lugar de bloquearlos. El beneficio de este enfoque era doble. Primero, le dio a los propietarios del servicio la oportunidad de probar el cambio y medir el impacto (si lo hubiera) que tendría el traspaso a un entorno nativo de la nube en su servicio. En segundo lugar, nos permitió corregir cualquier error, así como identificar cualquier funcionalidad adicional que pudiéramos proporcionar a los equipos de servicio. Por ejemplo, cuando un servicio se incorpora a BAB, los propietarios del servicio habilitan el modo de solo auditoría. Esto los ayuda a identificar código o flujos de trabajo que no cumplen con sus requisitos. Una vez que abordan los problemas marcados por el modo de solo auditoría, los propietarios del servicio cambian al modo de aplicación. En gVisor, logramos esto mediante la ejecución de cargas de trabajo en zonas de prueba, incluso con brechas de compatibilidad en las capacidades de la zona de pruebas, y luego resolvimos estas brechas sistemáticamente para mejorar la zona de pruebas.

Beneficios de realizar el cambio

De la misma manera en que BeyondCorp nos ayudó a evolucionar más allá de un modelo de seguridad basado en el perímetro, BeyondProd representa un salto similar en nuestro enfoque de seguridad de producción. El enfoque de BeyondProd describe una arquitectura de seguridad nativa de la nube que supone que no hay confianza entre servicios, proporciona aislamiento entre las cargas de trabajo, verifica que solo se implementen aplicaciones compiladas de forma central, automatiza la administración de vulnerabilidades y aplica controles de acceso sólidos a datos críticos. La arquitectura de BeyondProd llevó a Google a innovar varios sistemas nuevos para cumplir con estos requisitos.

Con frecuencia, la seguridad se deja para último momento, cuando ya se tomó la decisión de migrar a una arquitectura nueva. Si involucras a tu equipo de seguridad con anticipación y te enfocas en los beneficios del modelo de seguridad nuevo, como una administración de parches más simple y controles de acceso más estrictos, la arquitectura nativa de la nube puede proporcionar beneficios significativos para los equipos de seguridad y de desarrollo de aplicaciones. Cuando aplicas los principios de seguridad descritos en este documento a la infraestructura nativa de la nube, puedes fortalecer la implementación de las cargas de trabajo, cómo se protegen sus comunicaciones y cómo afectan a otras cargas de trabajo.

Notas

1 Borg es el sistema de administración de clústeres de Google para programar y ejecutar cargas de trabajo a gran escala. Borg fue el primer sistema de administración de contenedores unificado de Google y la inspiración para Kubernetes.

2 “Desplazamiento hacia la izquierda” hace referencia a pasos anteriores en el ciclo de desarrollo de software y puede incluir pasos como codificar, compilar, probar, validar e implementar. Por lo general, los diagramas de ciclo de vida se dibujan de izquierda a derecha, por lo que la izquierda se refiere a un paso anterior.

3 Una implementación azul-verde es una forma de implementar un cambio en una carga de trabajo sin afectar el tráfico entrante, de modo que los usuarios finales no experimenten ningún tiempo de inactividad cuando acceden 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 sobre la encriptación en tránsito.

5 Borgmaster es el controlador centralizado de Borg. Administra la programación de los trabajos y se comunica con los trabajos en ejecución para obtener información sobre su estado.