Fecha de caducidad 6/4/2021

El 6 de abril de 2021, un certificado TLS comodín caducó de forma inesperada. Es bochornoso que caduque un certificado, pero pensamos que es importante contar lo que ha pasado para que otros puedan aprender de nuestra experiencia y mejorar sus sistemas. Si tú o tu organización empleáis la supervisión de certificados, esto podría servir de recordatorio para buscar carencias en los sistemas.

El certificado que caducó se usaba en muchos servicios internos de Epic, en demasiados, de hecho. A pesar de todos nuestros esfuerzos por supervisar la caducidad de los certificados, no abarcamos por completo todas las áreas en las que estos se usaban. Después de que el certificado caducase y se renovase, se produjeron una serie de acontecimientos inesperados que provocaron que la interrupción del servicio se prolongara. Hay más detalles al respecto en este artículo.

Algunos componentes básicos, como nuestros sistemas de identidad y autenticación, se vieron afectados, y esos servicios están en contacto con muchos otros de nuestro ecosistema global. Se detectaron o notificaron las siguientes incidencias:

  • No se pudo iniciar sesión en cuentas de Epic de todos los productos que usan esa forma de autenticación, incluidos Fortnite, Rocket League, Houseparty, Epic Online Services y la Epic Games Store.
  • Hubo desconexiones de servicios y juegos en directo de todas las plataformas.
  • No se pudieron realizar compras de artículos en el iniciador de Epic Games.
  • Se produjeron comportamientos inesperados en el iniciador de Epic Games, desde contenido que no cargaba hasta la inhabilidad de utilizar el modo sin conexión.
  • Los sitios web de productos y de marketing de Epic Games no estaban disponibles o tuvieron un mal funcionamiento, incluidos los sitios web de Unreal Engine.
  • Varios problemas con diversas herramientas internas afectaron a la capacidad de los empleados de Epic para resolver o gestionar incidencias.

La finalidad de este artículo es proporcionar información detallada de lo que ocurrió, lo que hemos aprendido y las medidas que tomaremos en el futuro.


¿Qué ocurrió?


Se produjeron tres secuencias de acontecimientos importantes:

  1. Un certificado caducado provocó una interrupción del servicio en gran parte de las llamadas de servicio a servicio en el back-end (parte del servidor) interno y en las herramientas de gestión internas.
  2. De forma inesperada, se produjo un aumento significativo de tráfico en el iniciador de Epic Games y una alteración del servicio del iniciador de Epic Games y de las funciones de distribución de contenido.
  3. Se implementó una versión incorrecta del sitio web de la Epic Games Store que hacía referencia a artefactos y activos que no eran válidos como parte de un escalado automático, lo que desmejoró la experiencia de la Epic Games Store.

 

1) Certificado caducado

El 6 de abril a las 12:00 UTC caducó un certificado TLS. Este certificado se usaba para un gran número de comunicaciones internas en el back-end de la plataforma de Epic. Usamos cifrado TLS entre nuestros servicios de back-end para llamadas API de servicios cruzados y nuestras herramientas de gestión internas. Este certificado está destinado a una zona DNS interna que no es pública. 

A las 12:00 UTC, el tráfico entre los sistemas de back-end se detuvo. Seis minutos después, a las 12:06 UTC, se informó del incidente y se inició nuestro proceso de incidencia. Aunque teníamos muchas alertas, también animamos siempre a todos nuestros empleados a que informen de cualquier problema de gran repercusión que detecten. Nuestro equipo de Live Ops (operaciones en vivo), que está disponible las 24 horas del día y todos los días de la semana, y es el encargado de iniciar el proceso de gestión de incidentes, clasificó cada incidente. Cuando recibimos el primer informe interno, nuestros procesos y herramientas de gestión de incidentes crearon de forma automática un canal de Slack y se invitó o se convocó a los grupos correspondientes para que estuvieran al tanto del incidente.

A las 12:12 UTC, confirmamos que había caducado un certificado, algo que ya creíamos que con gran probabilidad podía ser el origen del problema, y comenzamos el proceso de renovación. A las 12:37 UTC, se volvió a emitir el certificado y el certificado actualizado empezó a implementarse en nuestros servicios de back-end. Durante el transcurso de los siguientes 15 minutos, los equilibradores de carga empezaron a implementar el nuevo certificado automáticamente en los terminales internos y tanto nuestras llamadas HTTPS de servicio a servicio como nuestras interfaces de gestión se recuperaron.

El equipo de Live Ops (operaciones en vivo) que clasificó el incidente también lo gestionó en esa etapa (poniéndose en contacto con los empleados e involucrando a las personas adecuadas), y a las 12:38 UTC se inició una llamada por Zoom para coordinar a las personas que habían estado colaborando en Slack. Aunque Slack es una buena herramienta de comunicación, en situaciones urgentes nada supera a la comunicación por vídeo o voz en tiempo real. Se enviaron actualizaciones frecuentemente a las partes interesadas internas sobre el incidente por medio de nuestros procesos y herramientas para mantener a todo el mundo informado de lo que pasaba en cada momento. En ese punto, había 25 personas directamente involucradas y trabajando en el problema, y muchas otras pendientes, como los sectores de asistencia al jugador, comunidad, ingeniería y producción de diferentes áreas y equipos.

Gráfico de los recuentos de solicitudes por minuto de un solo microservicio, con una caída debida al fallo del certificado y una subida en el momento de la recuperación total.

 

Factores asociados


Nuestros servicios de supervisión de certificados no ejercían una supervisión activa de las zonas DNS para esa comunicación interna de servicio a servicio, lo cual fue un descuido por nuestra parte. Nuestro servicio de supervisión de certificados controla espacios de nombres DNS completos, no terminales o certificados individuales, y faltaba la configuración de esa zona interna. Desde entonces, hemos trasladado esa zona a una nueva solución de supervisión que aborda esa carencia. Antes de este incidente, ya habíamos empezado también un proyecto para activar y configurar AWS Config globalmente en todas nuestras cuentas. Con esta configuración a escala global podemos añadir fácilmente una regla de AWS Config con el fin de activar una alarma de protección total para la caducidad de certificados

Las renovaciones automáticas no estaban activadas para ese certificado interno y no se le dio prioridad al trabajo necesario para hacerlo cuando esto se identificó a principios de este año. Contamos con los sistemas y servicios apropiados para facilitar una renovación automática, pero la migración necesaria para poder usar esas funciones no se había completado antes del incidente. Creíamos que, con los sistemas de supervisión con los que contábamos, estábamos más protegidos de los peligros de caducidad de certificados de lo que lo estábamos en realidad. Seguiremos trabajando para que este y otros certificados pasen a tener renovaciones automáticas. Mientras tanto, hemos completado una inspección manual de todos nuestros certificados.

El certificado comodín de servicio a servicio en uso estaba instalado en cientos de servicios de producción diferentes, lo que causó que el impacto fuera muy grande. Utilizamos ACM (AWS Certificate Manager) de AWS para gestionar este certificado, lo cual nos permitió renovarlo e implementarlo rápidamente en cientos de servicios de producción en cuestión de minutos. La fecha de caducidad no está relacionada con ACM de AWS, sino con nuestra gestión o nuestro propio certificado. Trataremos de aislar la "onda expansiva" que pueden causar nuestros certificados y parte de esto consistirá en actualizar nuestros procesos relacionados con el uso de los certificados mediante ACM de AWS.

 

2) Aumento considerable del tráfico en el servicio del iniciador de Epic Games

La mayoría de los servicios se recuperaron de inmediato al renovar el certificado. Sin embargo, los servicios del iniciador de Epic Games permanecieron inoperativos.

A las 12:46 UTC, tras la emisión del certificado, el aumento del índice de solicitudes saturó el servicio del iniciador de Epic Games, un servicio de back-end clave que da soporte al cliente del iniciador de Epic Games. El aumento del índice de solicitudes surgió a raíz de una lógica de reintento inesperada de los clientes que solo suele darse en situaciones de fallo. Hemos efectuado diversas pruebas de resistencia en el iniciador de Epic Games a lo largo de los años, pero esta cantidad de solicitudes nos pilló por sorpresa. El seguimiento de la conexión alcanzó el límite en nuestros servidores y los paquetes se desplomaron junto con los equipos, lo que complicó todavía más la recuperación, pues los equipos de back-end aumentaron el tráfico al 250 %. Los servicios del iniciador de Epic Games sufrieron un error en cascada y una interrupción total, de modo que fue necesario limitar el tráfico al back-end para la recuperación e ir aumentando de nuevo el tráfico paulatinamente en el sistema conforme íbamos aumentando los límites de seguimiento de la conexión simultáneamente.

Los enormes archivos de superficie de los clientes del iniciador de Epic Games empezaron a generar decenas de millones de conexiones con el servicio de back-end del iniciador de Epic Games y los componentes de los sistemas del iniciador se deterioraron por dicha carga. Tuvimos que drenar el tráfico al back-end para que pudiera recuperarse. Por norma, tenemos capacidad de ráfaga disponible para este servicio, pero no fue suficiente para soportar 28 veces la carga que observamos al comienzo de la interrupción.

Gráfico de los recuentos de solicitudes por minuto del equilibrador de carga de back-end del iniciador de Epic Games. El tráfico aumentó 28 veces al principio y la ráfaga final, a las 15:12 UTC, era 40 veces superior al índice normal.


El recuento de solicitudes era más de 28 veces superior a lo normal, y el número total de conexiones al servicio back-end del iniciador de Epic Games colapsó el espacio de seguimiento de la conexión disponible, lo que provocó la pérdida de paquetes y el deterioro de la conectividad de los nodos de back-end. Nuestra carga de conexión de back-end fue 3200 veces superior a la habitual. El aumento de conexiones TCP fue muy superior a la cantidad de solicitudes.

Gráfico de los recuentos de conexiones nuevas por minuto del equilibrador de carga de back-end del iniciador de Epic Games con un aumento de las conexiones 3200 veces superior al máximo habitual.

 

Factores asociados


El certificado TLS que caducó creó una interrupción que dio lugar a un comportamiento inesperado en el cliente del iniciador. Tras investigarlo, descubrimos que el reintento del cliente estaba usando una lógica de reintento lineal en lugar del retroceso exponencial que esperábamos. Un error adicional inesperado provocó, además, que las solicitudes de millones de clientes del iniciador de Epic Games siguieran un patrón de reintento constante e interminable hasta recibir una respuesta satisfactoria. Estos dos errores en la base de instalación del cliente generaron un patrón de llamada imprevisto y accidental. Estábamos recibiendo ataques de denegación de servicio (DDoS) de nuestros propios clientes y nos pusimos a trabajar a toda velocidad para corregir estos errores con una actualización del iniciador de Epic Games. 

Un factor asociado e interesante de este apartado del incidente fue la duración de la interrupción inicial. Cuanto más durara la interrupción inicial, más probabilidades habría de que hubiera más clientes utilizando la lógica de reintento defectuosa y solicitando nuestro back-end constantemente. Si la interrupción inicial hubiera durado menos tiempo, no habríamos podido acumular suficientes clientes solicitando el reintento constantemente para saturar el sistema; solo una interrupción de tal duración podría haber generado lo que ocurrió. Resolveremos esto haciendo cambios en el patrón de llamada.

Nuestra alarma de seguimiento de la conexión no se comprendió correctamente. La alarma se activó durante un incidente en el servicio del iniciador de Epic Games y, pese a que varios equipos están familiarizados con el significado de esta alarma, la descripción y la notificación de esta no fueron lo bastante esclarecedoras, y no fuimos capaces de ver que esta situación provocaría pérdida de paquetes en cualquier conexión que hicieran los servidores, incluida la conectividad a un clúster de Redis interno. Fue un momento estresante para el equipo que estaba investigando qué podía estar sucediendo, ya que la conectividad al clúster de Redis se deterioró. Nuestros mecanismos de caché parecían tener parte de culpa. Más tarde, descubrimos que se debía a que la tabla de seguimiento de la conexión estaba llena, y esto provocaba la pérdida de paquetes, con cientos de miles de conexiones en uso. Después, subimos los límites de seguimiento de la conexión a más de un millón por nodo, pero los aumentos del seguimiento de la conexión en nuestra infraestructura no son instantáneos y tardaron un poco. Vamos a esforzarnos para hacer que la alarma sea más clara, ya que, de lo contrario, sufriremos problemas de redes importantes. 

El aumento de la capacidad provocó que hubiera nodos nuevos que alcanzaron al instante los límites de seguimiento de la conexión. Puesto que nuestros equipos estaban saturados por las conexiones, lo que provocó una importante pérdida de paquetes, teníamos que reducir el tráfico general en los equipos y aumentar poco a poco el tráfico permitido. Primero, intentamos utilizar el WAF (Web Application Firewall) de AWS para limitarnos a un subconjunto de tráfico entrante, pero nuestra configuración no limitó suficiente tráfico. El problema no estaba relacionado con el WAF de AWS, sino con nuestro conjunto de regla especificado. Debido a las limitaciones de tiempo, luego empleamos las masas objetivo del equilibrador de carga de AWS para mover el tráfico, lo cual, sumado al aumento de nuestros límites de seguimiento de la conexión, funcionó. El uso del WAF en esta situación retrasó la recuperación de los servicios del iniciador de Epic Games, pero no fue culpa de AWS. Desarrollaremos un proceso estándar para cargar el tráfico perdido en situaciones críticas como esta utilizando el WAF de AWS, masas objetivo del equilibrador de carga u otras tecnologías de AWS.

 

3) Activos inválidos del sitio web de la Epic Games Store

A las 15:12 UTC, nuestro certificado se renovó y el servicio del iniciador de Epic Games se recuperó, así que procedimos a desbloquear todos los clientes que intentaban acceder a la Epic Games Store. Debido a la duración de la interrupción, hubo muchos más clientes de lo habitual solicitando contenido de la Epic Games Store, pero, poco a poco, se fue normalizando la situación. Empezamos a evaluar cualquier impacto reminiscente alrededor de las 15:30 UTC.

Al principio todo parecía normal, pero empezamos a recibir informes internos de problemas de formato y errores en la tienda que pudimos confirmar y reproducir. Tras investigar los detalles, descubrimos que el cliente web (la forma en la que el usuario interactúa con la tienda navegando en epicgames.com) intentaba obtener un ID de activo único que no aparecía en nuestra CDN. Comprobamos las versiones de contenedores implementadas en todos los equipos, y eran todas las mismas, pero, de ser así, ¿cómo es que la misma versión de la aplicación estaba devolviendo diferentes valores de activos estáticos? 

Algo no iba bien. Esta parte del incidente fue muy confusa, pero, al final, resultó que muchas de las señales que teníamos disponibles (como versiones implementadas) eran falsas. Conseguimos correlacionar el tráfico en el back-end de la Epic Games Store a un incremento de 403 en nuestra CDN, lo que nos dio pie a investigar en mayor profundidad las nuevas instancias. Tras realizar un "curling" con el contenido local en las nuevas instancias, descubrimos que el contenido devuelto no era válido. Pudimos rastrearlo hasta descubrir que un contenedor desencadenaba de forma inesperada un nuevo flujo de trabajo de CI/CD. Esto se creó el día anterior y, por lo demás, no tenía nada que ver con lo que nos habíamos encontrado hasta ahora durante el incidente. Los resultados nos sorprendieron bastante, pero, tras haber descubierto este hecho, conseguimos recuperar rápidamente la versión del contenedor, cerrar las instancias inválidas y restablecer el tráfico.

Este error podría haberse presentado durante cualquier gran aumento de tráfico que hubiera ocurrido durante este periodo, pero, como normalmente mantenemos suficiente espacio libre en nuestros equipos, el error no salió a la luz hasta que tuvo lugar el gran aumento de tráfico en la Epic Games Store que produjo el iniciador de Epic Games.

 

Factores asociados


El fallo del certificado causó problemas con el iniciador de Epic Games, que, hasta su recuperación, creó un sinfín de solicitudes en la Epic Games Store, lo que llevó a un aumento del tráfico en los sistemas de la Epic Games Store. Esta situación es normal y esperable.

Las señales y datos sobre el estado de las versiones en nuestras aplicaciones nos llevaron a creer erróneamente que la implementación se había realizado de forma uniforme en nuestros equipos. Hemos cambiado nuestro plan de versiones para evitar este error de diagnóstico en el futuro.

Un cambio reciente en el canal de CI/CD de la Epic Games Store tenía un error de configuración que hacía que el artefacto de la aplicación se actualizara de forma inesperada. Este error se ha corregido con una modificación de nuestro canal de CI/CD, y se han revertido los cambios inesperados. Este cambio en el plan de versiones nos protegerá si volviera a suceder lo mismo.


Cronología

  • 12:00 UTC - Caduca el certificado interno
  • 12:06 UTC - Se informa del incidente y comienza la gestión de este
  • 12:15 UTC - Se prepara el primer mensaje al cliente
  • 12:21 UTC - Distintos equipos confirman multitud de errores a gran escala en el servicio
  • 12:25 UTC - Se confirma el comienzo del proceso de sustitución del certificado
  • 12:37 UTC - Se confirma que se ha vuelto a emitir el certificado
  • 12:46 UTC - Se confirma la recuperación de algunos servicios
  • 12:54 UTC - Se descubre que hay un problema de seguimiento de la conexión en el servicio del iniciador de Epic Games
  • 13:41 UTC - Se reinician los nodos de servicio del iniciador de Epic Games
  • 15:05 UTC - Se aumenta el límite de seguimiento de la conexión del servicio del iniciador de Epic Games
  • 15:12 UTC - Primeras señales de recuperación del servicio del iniciador de Epic Games
  • 15:34 UTC - Aumento de tráfico en el servicio web de la Epic Games Store
  • 15:59 UTC - Primeros informes de recursos activos faltantes en la Epic Games Store
  • 16:57 UTC - Se descubre un error por versiones incompatibles del servicio web de la Epic Games Store
  • 17:22 UTC - Se corrige la versión del servicio web de la Epic Games Store
  • 17:35 UTC - Recuperación total


¿Y qué sucede ahora?

En las secciones de arriba, hemos explicado la situación que llevó a las sorpresas y, al final, a la interrupción del servicio el pasado 6 de abril. Hemos mencionado los pasos que fuimos siguiendo junto a los factores asociados, pero también los resumiremos aquí. 

Estos errores no tienen una única causa. Un cúmulo de factores, tanto tecnológicos como de organización, contribuyeron a que ocurriese todo lo que pasó. Las dimensiones y duración de la interrupción no solo nos ayudaron a descubrir errores explícitos en nuestros sistemas (que trabajaremos para corregir), sino también a replantearnos algunos aspectos de nuestros procesos internos, especialmente los relativos a la gestión de certificados. 

Aunque ya nos hemos movilizado para ocuparnos de este aspecto con nuestro nuevo sistema de supervisión de certificados y también hemos auditado todos los certificados de los que tenemos constancia, analizaremos en profundidad cualquier posible carencia de nuestro sistema de supervisión de certificados e incorporaremos más herramientas de corrección, como la implantación de supervisión de AWS Config para todos los certificados basados en ACM de AWS. También trataremos de reducir la "onda expansiva" de todos los certificados en caso de que estos fallen.

Vamos a investigar más detenidamente los patrones de llamada de cliente de nuestro iniciador de Epic Games y arreglaremos de forma urgente algunos de los errores que hemos identificado. Además, mejoraremos nuestra capacidad para reaccionar antes situaciones de aumento considerable de tráfico. Con el aumento permanente de tablas de seguimiento de la conexión en nuestros equipos, deberíamos ser capaces de lidiar con una cantidad similar de carga sin sufrir grandes pérdidas de paquetes. Si administras flotas de equipos a gran escala, puede que esto te sirva de recordatorio para comprobar las alarmas y los límites de tu tabla de seguimiento de la conexión si utilizas esta funcionalidad netfilter. También queremos ayudarte a recodar que se debe comprobar la lógica de reintento de tus clientes y, sobre todo, cómo se pueden comportar en conjunto tras una interrupción prolongada del servicio.

En la Epic Games Store, hemos implementado una solución que debería evitar la modificación de objetos de aplicaciones en directo y, además, hemos descubierto y arreglado un error en nuestro sistema de generación de activos.

Esperamos que este informe del incidente te haya servido para conocer mejor lo ocurrido el pasado 6 de abril. Confiamos en que estos detalles hayan arrojado algo de luz sobre lo que hemos aprendido y mejorado, y que ayuden a otras organizaciones a evitar errores similares.


¡Únete a nuestro equipo!

Nuestro equipo de ingeniería de confiabilidad ha redactado este artículo con la ayuda de los muchos otros equipos de ingenieros que trabajan en Epic.

¿Te interesan este tipo de problemas? ¿Te encantan los videojuegos y los servicios de juegos? Epic está en búsqueda permanente de talento y contratamos a todo tipo de especialistas en todo el mundo. Si quieres ver las ofertas laborales disponibles, visita el portal de empleo de Epic Games.

¿Este artículo te ha resultado interesante o te ha servido de ayuda? Cuéntanoslo en [email protected].