EC2: Parches automáticos para liberar tu agenda
Tags: ec2, automation, security, awtwins
Published: 2024-01-04 00:51:11

"¡Hola de nuevo! En el primer post, exploramos el SSO en AWS para despedirnos de esos engorrosos roles de salto que nos han dado más de un dolor de cabeza. En esta segunda parte, nos adentraremos en otro de los problemas comunes que hemos enfrentado a lo largo de nuestra trayectoria. ¿Cómo abordamos el tema de parchear las EC2 que aún necesitamos mantener? ¡Ups! ¿Pero no estamos todos trabajando con containers y serverless? 😜 ¿Cómo resolver este problema sin dedicar ese tiempo del que nunca parece haber suficiente? En este caso, vamos a hablar de nuestro querido aliado..."
**System Manager**.

Operativa común:
- Conexión manual a las EC2.
- Descarga y revisión de los parches disponibles.
- Creación de una copia de seguridad para una posible recuperación en caso de error.
- Instalación de los parches seleccionados.
- Reinicio de la instancia.
- Verificación del correcto funcionamiento.

Sin duda, un proceso tedioso y "aburrido" con el que nadie quiere lidiar. Para hacerlo más sencillo, AWS nos ofrece un servicio llamado **Patch Manager**, una herramienta que facilita la administración y automatización de actualizaciones de software y parches tanto en instancias EC2 como en entornos locales. Sin embargo, aún así, vamos a presentar una alternativa (estrechamente relacionada) que nos permite gestionar estas actualizaciones de forma más personalizada.
**Documents personalizados de System Manager**👌
En esta ocasión, vamos a crear un documento que ejecute los siguientes pasos:
- Envío de correo para notificar el inicio del proceso de parcheo.
- Actualización del agente de SSM.
- Creación de una AMI (backup) para facilitar la recuperación en caso de error.
- Aplicación de los parches al sistema.
- Envío de correo para notificar la finalización del proceso de parcheo.
- Gestión de errores: si se produce algún error en cualquiera de los pasos, el proceso de parcheo se detendrá y se enviará una notificación correspondiente.

👩‍🏭¡Vamos a ello!👨‍🏭

## Requisitos
Instancias con System Manager
https://docs.aws.amazon.com/systems-manager/latest/userguide/what-is-systems-manager.html
Bucket S3 para almacenar logs, en nuestro caso hemos generado el logs-patch-demo
![1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3yxhny72jbkbc83n1amu.png)
Rol de IAM con los permisos necesarios para ejecutar todas las acciones requeridas. En este ejemplo, y debido a que se trata de una POC (Prueba de Concepto), se han otorgado permisos completos ("full access") sobre los siguientes servicios:
- AmazonEC2FullAccess
- AmazonSNSFullAccess
- AmazonSSMFullAccess
![2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dq8kr9lkd2xntm6gcvjb.png)
![3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vka96p188fdocsk8z3g1.png)
_Recuerda que siempre debemos aplicar los permisos mínimos necesarios, y que el ejemplo proporcionado nunca debe ser utilizado en entornos de producción_

Utilizaremos Amazon SNS para enviar correos electrónicos indicando el inicio, final y cualquier error que pueda surgir. Esto se realizará a través de una suscripción, que especificará el destinatario que recibirá los correos informativos.

![4](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o3w0l9md3p43mngbntwb.PNG)

Resource group al cual aplicaremos el documento. En nuestro caso, será aplicado a todas las instancias EC2 que tengan la etiqueta 'Patch:yes'.

![5](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xycftvfj0shjv0r4z6mp.png)

![6](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ax988dfse1lnejxc8sk2.png)
_En este caso, solo hemos desplegado una instancia, pero podríamos incluir todas las que sean necesarias._

Y por supuesto...💎la joya de la corona💎, el documento personalizado de AWS System Manager:

```
description: Parcheo automatizado
schemaVersion: '0.3'
assumeRole: '{{Rol}}'
parameters:
  TopicArn:
    type: String
    description: (Required) ARN del SNS para enviar eventos.
  Instance:
    type: String
    description: (Required) ID de Instancia EC2.
  Rol:
    type: String
    description: (Required) Rol de IAM con permisos.
  BucketName:
    type: String
    description: (Required) Nombre del bucket donde almacenaremos los logs.
mainSteps:
  - name: Iniciopatch
    action: aws:executeAwsApi
    nextStep: ActualizacionAgenteSSM
    isEnd: false
    onFailure: Abort
    inputs:
      Service: sns
      Api: Publish
      TopicArn: '{{TopicArn}}'
      Message: Empezamos el parcheo de {{Instance}}
  - name: ActualizacionAgenteSSM
    action: aws:runCommand
    maxAttempts: 1
    timeoutSeconds: 3600
    nextStep: CreacionAMI
    isEnd: false
    onFailure: step:Errorpatch
    inputs:
      DocumentName: AWS-UpdateSSMAgent
      InstanceIds:
        - '{{Instance}}'
  - name: CreacionAMI
    action: aws:createImage
    maxAttempts: 3
    nextStep: ParcheoInstancia
    isEnd: false
    onFailure: step:Errorpatch
    inputs:
      InstanceId: '{{Instance}}'
      ImageName: AMI generada el {{global:DATE_TIME}} sobre {{Instance}}
      NoReboot: true
      ImageDescription: AMI generada por parcheo en {{global:DATE_TIME}} para {{Instance}}
  - name: ParcheoInstancia
    action: aws:runCommand
    maxAttempts: 1
    timeoutSeconds: 5400
    nextStep: Finalpatch
    isEnd: false
    onFailure: step:Errorpatch
    inputs:
      DocumentName: AWS-RunPatchBaseline
      InstanceIds:
        - '{{Instance}}'
      OutputS3BucketName: '{{BucketName}}'
      Parameters:
        Operation: Install
        RebootOption: RebootIfNeeded
  - name: Finalpatch
    action: aws:executeAwsApi
    isEnd: true
    onFailure: step:Errorpatch
    inputs:
      Service: sns
      Api: Publish
      TopicArn: '{{TopicArn}}'
      Message: Finalizamos el parcheo de {{ Instance }}
  - name: Errorpatch
    action: aws:executeAwsApi
    isEnd: true
    inputs:
      Service: sns
      Api: Publish
      TopicArn: '{{TopicArn}}'
      Message: El parcheo no ha finalizado correctamente, revisar el estado
outputs:
  - CreacionAMI.ImageId

```

Mientras preparamos el post, hemos notado que actualmente existe la opción de visualizar de manera gráfica las acciones que llevaremos a cabo mediante el documento. Esta función ciertamente resulta de gran ayuda para comprender mejor las operaciones que realizaremos.

![7](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/glzs6dkwgg9mf0batyyi.png)


Como mencionamos anteriormente, el documento está configurado para enviar un correo indicando el inicio del proceso de parcheo, actualizar el agente de System Manager, crear una AMI de la EC2, aplicar los parches a la instancia y enviar un correo notificando la finalización del proceso de parcheo. Todo esto se realizará de manera automatizada, sin necesidad de supervisión. ¡Fantástico! 👌
Ahora, podrías estar pensando, "¡perfecto! Pero, ¿cómo ejecuto este documento para no tener que estar pendiente de cuándo debo parchear los sistemas?" Para abordar esta inquietud, vamos a profundizar en "**Maintenance Windows**", un servicio que permite programar y gestionar centralizadamente las tareas de mantenimiento y actualizaciones en los recursos de AWS.
Para comenzar, crearemos una nueva ventana de mantenimiento:

![8](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iatjtwj5fl6zwm31plqu.png)

![9](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q28y63usaysc7h6s6i1h.png)
🚨_Para ejecutar la ventana de mantenimiento en el grupo de instancias al que queremos aplicarlo, es necesario registrar dicho grupo dentro de la ventana._🚨

![10](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wyz0zfrpxjok3moixy9p.png)
![11](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0qnjzp2kq52hbu6sygnr.png)

Seleccionamos la sección "Task" y creamos una nueva tarea que haga referencia a nuestro documento.

![12](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cvgt81821lhhw5tq1xfo.png)

![13](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5viyzql65t7l0u7hjmz4.png)

![14](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yzs2tcav0f3z0ih4a82m.png)
Habiendo alcanzado este punto, es el momento de proporcionar las variables que mencionamos al principio como requisitos:

- TopicArn: Arn del SNS generado.
- Rol: Rol de IAM con los permisos necesarios.
- BucketName: Nombre del bucket donde se almacenarán los logs.

![15](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yogznb26c3s6yibppv5z.png)
![16](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jikteneer0dqyxl7kfsj.png)
_En este caso, el rol no es necesario proporcionarlo en esta última opción, ya que se asume dentro del propio documento._ 

## ¡Ha llegado el momento más esperado... es hora de probarlo!

Para garantizar la ejecución de la tarea, hemos modificado el cron de la ventana de mantenimiento para que se ejecute a una hora específica: 23:12 PM (¡Sí, así somos! ¡Con una Coca-Cola en la mano y listos para compartir! 🎉)
![17](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1qrtc12wq0qvjtk2rxoi.png)

Podemos seguir el progreso de la tarea en la pestaña "History" de la propia ventana.
![18](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/idnfr3c2pm005pw06227.png)
Para ver la ejecución paso a paso, podemos seleccionar "View details", lo cual nos mostrará el proceso de parcheo en detalle, paso por paso.
![19](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f95bszgnmverocaxrx7k.png)
![20](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7vy5524oodrkuf2uiddg.png)
En cada paso, es posible obtener los resultados y visualizar los logs correspondientes. En el caso de la actualización del agente de System Manager, el resultado es el siguiente.
![21](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n14k0wbfq37zffn0crb5.png)

Una vez ejecutado y completado sin errores (en caso de recibir errores, se recibiría un correo indicando el error y se podrían ver los detalles en esta sección de manera detallada), procedemos a validar que tenemos registros en S3 y que la imagen se ha generado sin problemas.
**S3**
Al llevar a cabo el parcheo de la instancia, AWS genera una estructura de carpetas dentro de S3 donde se almacenan tanto los registros de resultado como los de error:
![22](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mfcwfo7lf8rg93jyx2cv.png)
_En este caso, las horas de los logs no coinciden debido a que se ejecutó en múltiples ocasiones durante la creación del documento. Verificamos que las imágenes se han generado correctamente durante las ejecuciones._
![23](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0o1op376sh5z9lox5g66.png)
**SNS**
En el caso de las notificaciones por correo electrónico, se ha seleccionado una cuenta de Gmail como destino para la POC.
![24](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9zury318fy54q9z54i5e.png)

Antes de finalizar el post, nos gustaría proporcionar algunos ejemplos donde este tipo de solución puede aplicarse:

- Parar y arrancar instancias o RDS de forma automatizada.
- Parchear sistemas con aplicaciones que requieran detención o inicio controlado.
- Actualizar paquetes personalizados o realizar customizaciones en instancias.

**Información adicional**

En este caso, hemos utilizado una cuenta única para la POC. Sin embargo, es importante destacar que estos documentos pueden ser compartidos entre cuentas, lo que permite realizar la ejecución de manera centralizada. ¡Mola! ¿no? 👀

Además, es relevante tener en cuenta que el documento ofrece una amplia gama de variables. Por ejemplo, podemos elegir reiniciar la instancia al finalizar el parcheo (tal como se ha ejemplificado), pero también podríamos incluir acciones como el apagado de servicios antes del parcheo, la ejecución de scripts, y muchas otras opciones.

¡Sin duda, esta es una solución muy personalizable que estamos seguros será de gran utilidad en diversas situaciones, simplificando las operaciones y liberando tiempo para seguir aprendiendo y enfrentando nuevos retos!

¿Te has preguntado si este flujo automatizado podría convertirse en una infraestructura como código con Terraform? ¡La respuesta es sí!¿Le damos caña?💯

¡Y eso es todo por hoy! Esperamos que hayas disfrutado de este post sobre automatización. ¿Te ha parecido interesante? ¡Nos encantaría conocer tu opinión! Déjanos tus comentarios, reacciones o preguntas. ¡Estamos ansiosos por saber qué piensas! 🙏