Este es el tercer blog de una serie que cubre diversos aspectos de lo que nos llevó construir y operar nuestro servicio SaaS :
Mi blog inicial proporcionó algunos antecedentes sobre las necesidades que nos llevaron a construir una nueva plataforma para nubes distribuidas. Al utilizar esta plataforma, nuestros clientes crean un conjunto complejo y diverso de aplicações , como fabricación inteligente, análisis forense de video para seguridad pública, comercio algorítmico y redes de telecomunicaciones 5G.
Dado que muchas de estas aplicações son de misión crítica, nuestros clientes esperan que no solo ofrezcamos seguridad de múltiples capas, sino que también tengamos la capacidad de realizar mejoras continuas para mantener seguros sus clústeres distribuidos. Este blog específico abordará los desafíos de proteger la infraestructura, las aplicações y los datos en múltiples clústeres.
Como se mencionó anteriormente, el problema de proteger el acceso de los usuarios a las aplicações (por ejemplo, el acceso a nuestras cuentas bancarias o nuestros correos electrónicos) es bien comprendido. Sin embargo, no es tan sencillo hacer lo mismo para el acceso de aplicación a aplicación o de aplicación a datos, ya que no hay ninguna persona involucrada en el proceso de verificación.
Para que una aplicação acceda a otro recurso de manera segura (por ejemplo, datos almacenados en un almacén de objetos o realice una llamada API a otra aplicação, etc.), debe suceder lo siguiente:
Como parte del proceso de autenticación, la aplicação solicitante puede presentar su identidad en forma de un certificado PKI o un secreto (por ejemplo, una contraseña) o una clave. Hay dos cuestiones que deben abordarse cuando se utilizan secretos o una clave para la identidad:
Realizar estas operaciones de seguridad (para la interacción entre aplicaciones) de manera confiable y repetible es un problema no trivial. Hay muchas razones por las que esto no es trivial:
Como resultado, proteger la infraestructura, las aplicações y los datos en un entorno dinámico es un problema muy desafiante. Si bien los proveedores de la nube han estado a la altura de este desafío y han proporcionado muchas herramientas para lidiar con estos problemas, integrarlos y mantenerlos no es fácil por las siguientes razones:
Si bien muchas empresas son un único proveedor de nube y puede ser suficiente para ellas invertir recursos en gestionar y mejorar las primitivas de seguridad de ese proveedor, operamos en un entorno heterogéneo (nube híbrida y borde) y tuvimos que crear una nueva solución para resolver estos problemas.
Nuestro equipo tuvo la tarea de brindar seguridad a las aplicações, la infraestructura y los datos que puedan residir en una infraestructura distribuida como se muestra en la Figura 1.
Como resultado, nuestro equipo de plataforma decidió crear nuevos servicios de software que integraran los siguientes cuatro aspectos para brindar seguridad de la plataforma en el borde, cualquier nube y nuestros PoP de red:
La identidad es una cuestión fundamental ya que muchos desafíos de seguridad pueden abordarse más fácilmente una vez que se resuelve el problema de identidad. Sin embargo, para resolver el problema de la identidad, necesitamos definir qué queremos decir con ella y cómo emitirla de manera confiable. A los fanáticos de las criptomonedas les gusta darle su propio toque a todo, y la definición de identidad no es una excepción:
El conjunto único y completo de características infalsificables y criptográficamente verificables , certificadas criptográficamente a través de un protocolo no delegado y seguro por una autoridad confiable, que conforman lo que se conoce o se considera que es una persona o cosa.
En esencia, lo que se necesita es una identidad infalsificable y criptográficamente verificable, entregada de forma segura. Emitir dicha identidad es un desafío por dos razones: 1) arranque de la identidad y 2) raíz de confianza
Hay algunos enfoques que se discuten a menudo en relación con la identidad: SPIFFE y Hashicorp Vault. Queremos aclarar que SPIFFE es un esquema de nombres que podría usarse en nuestro sistema como un documento de identidad (certificado X.509); sin embargo, el formato no es adecuado para algunos atributos de identidad que contienen datos binarios. Si bien Vault se puede utilizar para emitir un documento de identidad, no resuelve los desafíos del bootstrapping de identidad y los problemas de raíz de confianza:
Por ejemplo, cuando se lanza una máquina virtual en AWS, se le proporciona una identidad de arranque y el servicio de metadatos de AWS actúa como raíz de confianza. El documento de identidad (firmado por AWS con su propia clave criptográfica) se parece a esto:
Si bien instanceId puede indicar la identidad única de la instancia de aplicação que se lanzó, debe estar encadenado a algún nombre conocido (myserver.acmecorp.com) que otras aplicações usarán para comunicarse con esta instancia en particular. Como resultado, incluso este documento de identidad de arranque de AWS es insuficiente, pero se puede utilizar para emitir otra identidad que las aplicações puedan usar para comunicarse con otra aplicação.
Como se mencionó anteriormente, para nosotros era fundamental ofrecer una identidad que permita a las aplicações comunicarse y compartir información entre proveedores de nube y/o ubicaciones de borde (Figura 2). Esto significó que teníamos que construir un sistema tanto para el arranque de identidad como para la raíz de confianza que funcionara en todos estos entornos.
Dado que utilizamos Kubernetes para administrar y orquestar aplicações (tanto microservicios como máquinas virtuales), esto significó que el arranque de una identidad única para cada pod lanzado tuvo que estar vinculado al proceso de creación de pods de Kubernetes. La figura 3 muestra cómo nos conectamos al proceso de creación de pods utilizando el mecanismo de webhook de K8s. Este webhook, llamado Voucher, inyecta un sidecar de seguridad, llamado Wingman , en todos los Pods creados en el clúster y también proporciona la información firmada criptográficamente necesaria que puede usarse como raíz de confianza . Este webhook proporciona un token firmado de corta duración que Wingman utiliza para solicitar un certificado X.509 a la autoridad de identidad en el backend SaaS de Volterra.
La Autoridad de Identidad hace cumplir las reglas de acuñación de la identidad de manera tal de minimizar el “radio de explosión” en caso de que uno de los grupos K8 se vea comprometido. Muchas otras soluciones que dependen de una CA raíz común o de una federación de clústeres K8 no pueden limitar el radio de explosión, lo que fue un factor importante en nuestra decisión de diseño.
Para un Pod determinado en K8s, los atributos pueden cambiar después de la creación del Pod; por ejemplo, un Pod se puede adjuntar a un nuevo servicio después de su creación. Esto significaba que los certificados de identidad tenían que actualizarse con el nuevo servicio. Wingman vigila continuamente el Voucher que rastrea el servidor API de K8s para detectar cualquier actualización de este tipo.
Este mecanismo proporciona una identidad global única y universal a cada instancia de aplicação que se ejecuta en nuestra plataforma, independientemente de si se trata de nuestra propia carga de trabajo o de la carga de trabajo del cliente. Esta identidad única y sidecar (Wingman) se utilizan luego para proteger todas las comunicaciones, accesos y claves/secretos en un sistema distribuido.
Tener una identidad única por Pod es un gran comienzo ya que facilita la tarea de implementar la autenticación mutua entre los servicios que se comunican. Nuestra infraestructura subyacente se compone de muchos servicios diferentes que se ejecutan en diferentes protocolos como gRPC, REST, IPSec, BGP, etc. Desde el principio, el equipo se propuso como objetivo lograr autenticación mutua y seguridad de comunicación (canal cifrado) para todas las partes que se comunican, independientemente del protocolo. Esto también significaba que no podíamos vincular nuestra identidad a una solución (por ejemplo, Istio) que se limita a un conjunto particular de protocolos (por ejemplo, HTTP/TCP vs. Basado en IP).
Dado que nuestra plataforma también permite a los clientes ejecutar cargas de trabajo de su elección, esperamos que estas cargas de trabajo puedan ejecutar una variedad de protocolos y la plataforma no debería limitar su capacidad al proporcionar una identidad que esté limitada a un conjunto particular de protocolos. En cambio, la autenticación se desacopla de la identidad (a través de Wingman) y esto hace posible la conexión a varias tecnologías de malla de servicios. Nuestro sidecar/plano de datos de malla de servicio (cubierto en un blog anterior) utiliza esta identidad para brindar mTLS para las cargas de trabajo de los clientes.
Dado que muchos de nuestros propios servicios de infraestructura se escribieron utilizando Volterra Golang Service Framework (que se analizará en un blog futuro), decidimos desarrollar la lógica de consumo de identidad (de Wingman) directamente en el marco. Esto ha ayudado a nuestros desarrolladores a proteger sus comunicaciones de servicio a servicio de forma inmediata, sin depender del sidecar de malla de servicio para mTLS.
El siguiente paso lógico después de lograr un canal seguro autenticado mutuamente es la Autorización, un proceso para que el receptor de la solicitud (servidor) determine si permite o no la solicitud que proviene del llamador identificado (cliente). Las razones para no permitir la solicitud podrían ser muchas: limitaciones de cuota, permisos, etc. Dado que estos motivos y sus umbrales cambian dinámicamente, un conjunto de reglas codificadas (políticas) para la autorización no era viable para nuestra plataforma.
Decidimos utilizar el motor de Open Policy Agent como punto de partida y construimos un contenedor para la autorización dentro del sidecar de Wingman. Este código contenedor recupera dinámicamente las políticas relevantes y las mantiene activas para una evaluación rápida. De manera similar a la autenticación, disociar el motor de autorización de la identidad (y la autenticación) nos ha permitido aplicar políticas de autorización en múltiples etapas del procesamiento de solicitudes, incluso en lo profundo de la lógica empresarial y no inmediatamente después de la autenticación.
Dado que Wingman se inserta en todas las cargas de trabajo, incluidas las del cliente, nuestra plataforma proporciona un motor de autorización como función incorporada. Aunque Open Policy Agent (OPA) está construido sobre un lenguaje poderoso llamado Rego, queríamos ocultar su complejidad a nuestros desarrolladores y clientes. Todas las políticas de nuestra plataforma también se pueden definir utilizando una estructura de políticas mucho más fácil de entender e intuitiva que no requiere que los usuarios (DevOps) aprendan Rego y, por lo tanto, evitan errores. De manera similar a la configuración de autenticación, nuestro Golang Service Framework se conectó al motor de autorización de Wingman llamando automáticamente a Wingman para solicitar autorización y ocultando la complejidad de la autorización a los desarrolladores.
Al utilizar una identidad única (emitida mediante Wingman) para la autenticación y un motor de políticas programable (dentro de Wingman) para la autorización, podemos proteger la comunicación mediante mTLS y controlar cada acceso mediante una política sólida y programable.
Todos los días, los ingenieros cometen errores involuntarios al almacenar claves y contraseñas en su código y, de alguna manera, estos llegan al código público o a repositorios de artefactos. Gestionar secretos es difícil y, sin un conjunto de herramientas fácil de usar y un proceso bien definido, se espera que los desarrolladores sigan el camino más corto. Como resultado, desde el comienzo de la empresa, la misión de nuestro equipo de seguridad de plataforma (diferente de la seguridad de red y aplicaciones) fue garantizar que los desarrolladores no tengan que hacer preguntas como "¿Dónde guardo los secretos: el código fuente , los artefactos o...?".
Evaluamos dos enfoques comunes que estaban disponibles para la gestión de secretos cuando comenzamos a construir nuestra plataforma, y ambos tenían ciertas deficiencias:
En nuestro caso, al ser un servicio SaaS, tuvimos que idear un método más sólido para proteger los secretos de nuestros clientes, ya que cualquier compromiso no debería revelar sus secretos.
Como resultado, decidimos implementar una nueva técnica que llamamos Volterra Blindfold (marca registrada), que funciona junto con nuestro sidecar de seguridad, Wingman, como se muestra en la Figura 4. Este enfoque permite al propietario del secreto bloquearlo (cifrarlo) de tal manera que nunca sea revelado en forma clara a ninguna parte no deseada (incluido el servidor de descifrado). El secreto ni siquiera se almacena en un servidor de descifrado central y este diseño, en algunos aspectos, simplifica drásticamente el diseño del servidor.
Proporcionamos a los usuarios una herramienta que se puede usar en un entorno completamente fuera de línea para cifrar el secreto (S) que luego se puede distribuir; por ejemplo, el secreto se puede almacenar con la carga de trabajo y cargar en el registro. Una vez logrado esto, es necesario realizar los siguientes pasos:
Esto garantiza que el plano de control centralizado nunca tenga acceso al secreto en claro (S) y también que el secreto solo esté disponible en la memoria de tiempo de ejecución del Pod mientras dure el acceso. Además, se puede aplicar la política de acceso para definir quién tiene acceso a un secreto. La política se puede definir en función de los atributos de identidad, como el nombre de la aplicação , la ubicación, el nivel de cumplimiento, etc. De esta manera se puede separar cualquier subconjunto complejo de cargas de trabajo y lograr un control de acceso preciso. La política está criptográficamente entretejida en el proceso de cifrado, cegamiento, descifrado y desenmascaramiento: es computacionalmente inviable frustrar la intención de la política.
Al utilizar nuestra exclusiva técnica Blindfold para bloquear cada secreto y Wingman para revelar cada secreto según una política y una identidad infalsificable, podemos superar los problemas con las soluciones existentes y brindar administración de secretos en un entorno distribuido sin preocuparnos nunca por comprometer la mina de oro central.
Aunque los secretos y la gestión de claves pueden parecer dos nombres diferentes para el mismo problema, existen diferencias sutiles (pero importantes en la práctica) entre ambos dependiendo de a quién le pregunte y de cómo se quieran implementar las soluciones.
Secreto se refiere a cualquier información que se supone que es secreta y no está disponible para partes no autorizadas. En cierto modo, las claves criptográficas son un caso específico de secretos. La gestión de claves, por otro lado, generalmente se refiere a un sistema que almacena de forma segura material de claves criptográficas confidenciales y controla el uso de dicho material. En algunos casos, el sistema de gestión de claves puede entregar bytes sin procesar de la clave a partes autorizadas y, por lo tanto, puede confundirse con un sistema de gestión de secretos. Sin embargo, en la mayoría de los casos, el sistema de gestión de claves no entrega bytes sin procesar del material de la clave y, en su lugar, realiza operaciones para solicitantes autorizados y envía únicamente el resultado de la operación. Muchos sistemas de administración de claves también están respaldados por almacenamiento de hardware (por ejemplo, HSM) para el material de la clave, de modo que la clave nunca queda expuesta de forma clara al software.
En entornos distribuidos, incluso para un único proveedor de nube, el problema de gestionar, sincronizar y rotar claves criptográficas es muy desafiante y las soluciones actuales son propensas a errores, ineficientes e incluso inseguras. Por ejemplo, si uno usa 3 regiones de AWS hoy y quiere usar la misma clave criptográfica en las 3 regiones, tendrá que sincronizar y rotar las claves manualmente. El problema se vuelve aún peor cuando el entorno se extiende por múltiples proveedores de nube (públicos y/o privados). Incluso después de todo esto dicho y hecho, los propietarios de las aplicação todavía tienen que escribir código complejo para utilizar estas capacidades de KMS.
Nuestra plataforma oculta todas las complejidades de la administración de claves de la aplicação al hacer que Wingman sidecar haga todo el trabajo pesado y proporcione interfaces simples a la aplicação para realizar las solicitudes de administración de claves, incluido el cifrado, descifrado, HMAC, verificación de HMAC, firma digital, verificación de firma, obtención de clave (cuando esté permitido), etc. Esto hace que la gestión de claves no sea en absoluto una tarea desalentadora para nuestros propios servicios de infraestructura, así como para las cargas de trabajo de los clientes.
El siguiente diagrama (Figura 5) muestra cómo funciona el KMS de Volterra en distintos entornos y ayuda a las cargas de trabajo a descargar sus operaciones de gestión de claves y cifrado al sidecar Wingman. Dependiendo de la configuración, Wingman puede almacenar en caché claves y actualizar el caché sin que la aplicação lo sepa. El factor que lo permite es la identidad universal e infalsificable que presentamos anteriormente. Dado que cada Pod, independientemente de su ubicación, obtiene una identidad única global, es fácil para el sistema Volterra KMS aplicar políticas de acceso a claves criptográficas y operaciones específicas como cifrado, descifrado, HMAC, verificación de HMAC, firma digital y verificación de firma de una manera muy precisa.
Dado que todas las claves se administran a través del backend SaaS de Volterra, las cargas de trabajo que se ejecutan en entornos heterogéneos no tienen que lidiar con la sincronización, rotación y revocación de claves, etc.; solo tienen que conocer las API simples de Wingman para todas sus necesidades de seguridad de datos en reposo.
¡Usando una plataforma de seguridad de múltiples capas, hemos podido ofrecer una solución integral a tres problemas críticos de una manera completamente nueva! Nuestro sistema es capaz de crear de forma segura una identidad universal que no sufre el problema de las “ tortugas hasta el final ”, administrar secretos que pueden almacenarse y distribuirse sin preocuparse nunca por el problema de la mina de oro y brindar administración de claves para facilitar la seguridad de los datos en reposo en un entorno distribuido. Esto ha supuesto los siguientes beneficios para nuestros equipos internos y nuestros clientes:
Esta serie de blogs cubrirá diversos aspectos de lo que nos llevó construir y operar nuestro servicio SaaS distribuido globalmente con muchos clústeres de aplicação en la nube pública, nuestros PoP de red privada y sitios de borde. El siguiente tema será Seguridad de aplicação y redes …
Estamos buscando algunos desarrolladores y arquitectos de soluciones voluntarios que nos ayuden a llevar esta capacidad a una comunidad más amplia como un proyecto de código abierto. Comuníquese directamente con asingla@volterra.io si está interesado en ser parte de algo divertido.