Blog de Amazon Web Services (AWS)

Cómo supervisar el cumplimiento Creación de reglas dinámicas con AWS Config Rules, AWS Cloudformation, AWS Lambda y documentos de AWS Systems Manager

Por Guilherme Greco, Arquitecto de Soluciones AWS Brasil y
Kimmy Wu, Arquitecta de Soluciones AWS Brasil

 

Los proyectos exitosos de migración masiva a la nube consideran la necesidad de gobierno y creación de estándares de cumplimiento normativo en materia de seguridad, supervisión, arquitectura y costo.  El cumplimiento de los recursos creados con las reglas pertinentes para su organización da libertad a los equipos de operaciones e infraestructura para crear recursos de forma segura que se evaluarán y alertarán automáticamente en caso de desviación.

Esta entrada de blog muestra las automatizaciones que se pueden utilizar desde una perspectiva de monitoreo, De esta manera, se garantiza que determinadas funciones publicadas en una cuenta de AWS tengan el estándar de cumplimiento definido previamente por la organización.

 

Visión general:

Con las plantillas de Cloudformation,  Plantilla de fundación — foundation.yaml y la plantilla de vigilancia – observancia de la observancia. yaml,  para crear recursos dinámicamente, puede actualizar la plantilla con un determinado parámetro y volver a crear automáticamente las reglas de cumplimiento y la supervisión.

Usaremos reglas de cumplimiento (Reglas de configuración de AWS)  evaluaciones personalizadas y de recursos realizadas a través de AWS Lambda.    Esto se logra a través de eventos iniciados desde AWS Config, que se envían a la función Lambda responsable de evaluar el cumplimiento de los recursos.   Será a través de un documento de System Manager que se realizarán correcciones.

Este escenario es posible gracias a las integraciones entre AWS Config Rule y SSM Documents.  A través de Event Bridge, la automatización propuesta puede eliminar alarmas de instancias que ya no existen o comenzar a ejecutar flujos de automatización utilizando documentos SSM.

Las alarmas de CloudWatch formarán parte del cumplimiento definido por la organización, lo que permitirá reglas de cumplimiento para supervisar en AWS EC2, AWS RDS, AWS Lambda, AWS S3, AWS SNS, AWS SQS, AWS EBS, AWS DynamoDB y AWS Application Load Balancer

En la arquitectura propuesta, tenemos las siguientes reglas de cumplimiento:

  • Regla de cumplimiento 1: verifica que las alarmas creadas sigan el patrón de notificación
  • Regla de cumplimiento 2: comprueba que se han creado alarmas y métricas necesarias para supervisar un recurso (plantilla:  monitoreo de cumplimiento.yaml  )
  • Regla de cumplimiento 3: comprueba si sus alarmas han sido modificadas (plantilla:  monitoreo de cumplimiento.yaml  )
  • Regla de cumplimiento 4: comprueba que se ha eliminado una instancia de EC2 (plantilla:  monitoreo de cumplimiento.yaml  )

Puede elegir la métrica y el límite para cada servicio. Por lo tanto, a través de Infrastructure como código, las reglas de cumplimiento se crearán automáticamente, siguiendo los parámetros introducidos.

Regla de cumplimiento 1: verifica que las alarmas creadas sigan el patrón de notificación

Automation es responsable de garantizar que todas las alarmas sean notificaciones estándar. La plantilla  fundación.yaml  creará características y automatizaciones que utilizará la pila de cumplimiento de alarmas, como la función Lambda y el tema SNS para la notificación predeterminada. Otros recursos que se crearán

  • Tema de notificación estándar de SNS.
  • Función Lambda: Se utilizará para validar el cumplimiento del recurso.
  • Regla de evento de puente de eventos: se utiliza para activar un documento SSM que eliminará alarmas innecesarias para EC2.
  • Documentos SSM.
  • ClearAlarms: Documento SSM que eliminará las alarmas de CloudWatch de las instancias que se han quitado.
  • CreateSNSAction: Documento SSM que creará una acción obligatoria en todas las alarmas que dirijan notificaciones al Tema SNS predeterminado.
  • CloudWatchConfigRule: Regla de cumplimiento que evalúa las alarmas de CloudWatch.

 

Figura 1: Cumplimiento de las notificaciones

 

La figura 1 describe la automatización que garantiza que todas las alarmas de CloudWatch tengan una acción de notificación para el tema SNS predeterminado. El tema reenviará los mensajes a la suscripción realizada por correo electrónico:

  1. Se crea una nueva alarma de CloudWatch o se cambia una alarma de CloudWatch existente.
  2. Se envía un evento a AWS Config en el que se describen los cambios o la configuración del recurso.
  3. La regla de configuración de AWS evalúa el recurso creado mediante la invocación de la función Lambda.
  4. La función Lambda responde a la regla de configuración con un estado COMPLIANT o NON_COMPLIANT. Si es NON_COMPLIANT, AWS Config Rule activa un documento SSM para realizar la corrección automática. Por lo tanto, CloudWatch Alarm tendrá configurada la acción de notificación.

 Regla de cumplimiento 2: comprueba que se han creado alarmas y métricas necesarias para supervisar un recurso (plantilla:  monitoreo de cumplimiento.yaml  )

Esta parte de la automatización comprueba que se han creado las métricas necesarias para supervisar un recurso.

 

Figura 2: Flujo de automatización para supervisar el cumplimiento de normas cuando se crea un recurso

 

De acuerdo con el diagrama de la Figura 2, tenemos el siguiente flujo:

  1. Se crea una nueva función soportada por la automatización.
  2. Un evento se envía a AWS Config después de la creación.
  3. La regla de configuración de AWS evalúa el recurso creado llamando a un Lambda que comprueba que el recurso tiene todas las métricas relacionadas con la supervisión.
  4. Una función Lambda responde a la regla de configuración con un estado COMPLIANT o NON_COMPLIANT. Si es NON_COMPLIANT, AWS Config activa un documento SSM para realizar la corrección automáticamente, creando alarmas con métricas estándar.

 

Regla de cumplimiento 3: comprueba si sus alarmas han sido modificadas (plantilla:  monitoreo de cumplimiento.yaml  )

La segunda parte de la automatización comprueba si se han modificado las alertas. El valor de umbral predeterminado para cada métrica no es necesario. Sólo las métricas y las alarmas lo son. Esto beneficia a un escenario en el que un servidor en particular puede tener un límite de CPU del 99%.  Por lo tanto, puede actualizar la alarma cambiando el límite al valor deseado. La automatización mantendrá el límite deseado y no habrá inconvenientes. La corrección se produce sólo cuando se elimina o edita una alarma obligatoria y su métrica.

 

Figura 3: Flujo de automatización para supervisar el cumplimiento cuando se modifica una alarma

 

De acuerdo con el diagrama de la Figura 3, tenemos el siguiente flujo:

  1. Se modifica o elimina un Alarm CloudWatch.
  2. El evento se envía al puente de eventos, validando que la alarma no ha sido modificada por el Administrador de sistemas. Esto es necesario para evitar un bucle en la automatización.
  3. Document SSM invoca la API de AWS Config, solicitando una reevaluación del recurso y las alarmas.
  4. Se invoca la función Lambda y analiza las alarmas existentes. Si se requiere la corrección de alarmas, Lambda envía el estado NON_COMPLIANT a Config.
  5. La regla de configuración de AWS invoca un documento SSM, que repone la configuración de las alarmas.

Regla de cumplimiento 4: comprueba que se ha eliminado una instancia de EC2 (plantilla:  monitoreo de cumplimiento.yaml  )

 

Figura 4: Flujo de automatización para supervisar el cumplimiento cuando se elimina un EC2

 

De acuerdo con el diagrama de la Figura 4, tenemos el siguiente flujo:

  1. Se elimina una instancia de EC2.
  2. Se envía un evento al puente de eventos. Una regla invoca el documento SSM.
  3. El documento SSM espera 5 minutos. Este tiempo es necesario para que AWS Config se actualice, sincronizando la información de que la instancia EC2 ya no existe. Esto evita que la automatización se realice en bucle.
  4. Document SSM elimina las alarmas correspondientes a esa instancia.

 Flujo para crear reglas de cumplimiento

El flujo para crear cumplimientos de supervisión para cada servicio será el siguiente:

 

Figura 5: Flujo para crear cumplimiento de supervisión

 

    1. Analizar métricas de servicio: identifica la métrica obligatoria para el cumplimiento de los servicios.
    2. Definir qué métricas son obligatorias  : El administrador del entorno define qué métricas de servicio son necesarias para el cumplimiento, creando alarmas dedicadas que se utilizan como regla para la evaluación. De forma predeterminada, la automatización       hasta 3 métricas.
    3. Iniciar la plantilla  : Se ejecutará la plantilla monitoring-compliance.yaml.

Uso de la plantilla de monitoring-compliance.yaml

Para utilizar la plantilla, sólo tiene que descargarla y utilizarla dentro de CloudFormation. La figura 6 describe los siguientes parámetros utilizados en la plantilla:

      • Nombre de la pila:  Nombre de pila. Ex: EC2-obligatorio-alarmas.
      • Lista de los IDs de recursos de AWS Config que se incluyen para esta regla de cumplimiento:  lista de Id. de instancia de EC2 que se eliminarán en la evaluación de conformidad. Este es un parámetro opcional.
      • Nombre del tema que se utilizará para enviar notificaciones:  Nombre del tema SNS que se creó en la pila de cimientos, generado por la plantilla foundation.yaml.
      • Habilitar corrección automática:  verdadero para la corrección automática o false para la no automatización.
      • Espacio de nombres para la métrica de CloudWatch:   Nombre del servicio de AWS que formará parte de la supervisión del cumplimiento. Ex: EC2.

 

Figura 6: Parámetros para crear pila utilizando la plantilla monitoring-compliance.yaml

 

El siguiente paso es identificar los parámetros que definirán cuántas métricas y alarmas existirán para un servicio determinado. En el ejemplo estamos utilizando la instancia EC2, con 2 alarmas obligatorias, siguiendo las métricas CPUUtitilization y StatusCheckFailed_System. No utilizaremos la tercera métrica y por lo tanto no se creará la Alarma 3.

 

Figura 7: Continuación de los parámetros de creación de pila mediante la plantilla monitoring-compliance.yaml

 

 Configuraciones de alarm1:

  • Nombre de la métrica Alarm1: Nombre de métrica obligatoria. Ex: Utilización de CPU.
  • Umbral métrico Alarm1:   Umbral de métricas elegido para Alarma 1. Este será el valor predeterminado que se establecerá para la alarma. Ex: 80.
  • Estadísticas métricas de Alarm1:  Lista de opciones para la estadística. Ex: Máximo.El conjunto de parámetros anterior (Configuraciones de Alarm1) creará el primer patrón de monitoreo para EC2. Cada instancia debe tener una alarma que supervise la métrica (CPUUUtitilization) y envía una notificación al LocalTopic cuando el umbral supera un máximo de 80.Para la alarma 2 se realiza la configuración con los mismos parámetros que la alarma 1, cambiando el nombre a StatusCheckFailed_System y Metric Threshold a 1. La automatización creará 2 acciones: una notificación para el tema predeterminado y una acción para el servicio EC2, recuperando automáticamente la instancia de EC2. Para la alarma 3 simplemente no ingrese el nombre para no realizar su creación.Cuando inicie la plantilla, se creará una pila dedicada para el cumplimiento de EC2. Si es necesario crear cumplimientos para otros servicios, se crea otra pila y el parámetro Namespace for CloudWatch Metric se dirige al servicio.

 Agregar o cambiar métricas obligatorias para un servicio determinado

Para obtener información detallada sobre el cumplimiento, vaya a AWS Config and Rules. Tendremos la regla EC2-con-alarmas-obligatorias. Los nombres predeterminados siempre serán ፦with-mandatory-alarmas <Nombre del Servicio>. Ejemplo: Si se creó una pila de cumplimiento de RDS, tendríamos RDS con alarmas obligatorias.

 

Figura 8: Reglas y parámetros de configuración

 

La figura 8 describe la regla de configuración y sus parámetros, que se introdujeron durante la creación de la pila. Tenemos 4 parámetros, que se ingresaron en el lanzamiento de la pila:

  • WhitelistedResources  : es una lista de características que no formarán parte del cumplimiento. Representa los identificadores únicos de cada recurso que se excluirán de las reglas de validación de conformidad. En este ejemplo utilizamos los ID de las instancias EC2;
  • Alarm1/2/3 Config    :    Un objeto json creado por Cloudformation, siguiendo los parámetros introducidos durante la creación de la pila para alarm1, alarm2 y alarm3;

Dado que no hemos establecido el tercer parámetro, esta configuración tiene el valor de MetricName «null».  Eso significa que no habrá una tercera alarma obligatoria.

Se ha creado un documento SSM para remediar las alarmas, siguiendo las normas estipuladas.   Para ver, vaya a AWS Systems Manager   à   Documentos   à   Propiedad de Mí.   Tendremos un Documento con el siguiente nombre ፦Alarmas-Obligatorias- OpsAutomation- <Servicio>, <hash del stack> con los 5 pasos de automatización, como se muestra en la Figura 9.

 

Figura 9: Pasos de automatización en el documento SSM

 

En el paso «VerifyCloudWatchConfig», tenemos una acción «aws:executscript» que invoca un código Python descrito dentro del documento SSM. El código es responsable de recopilar la información de alarma y enviarla al siguiente paso del flujo. Los siguientes pasos tienen acciones de tipo «AWS:ExecuteAWSAPI», que invocan las API de servicio de AWS de forma nativa.

AWS Config Rule validará la supervisión de las instancias existentes. El resultado de la evaluación (COMPLIANT o NON_COMPLIANT) estará disponible en la regla, como se muestra en la Figura 10.

 

Figura 10: Detalles de la regla de configuración

 

Mediante AWS Config Rule, pudimos ver el ID de instancia de EC2 que se ha evaluado, el tipo de servicio (EC2), el resultado de la evaluación (que contiene las métricas que no tienen alarmas para esta instancia) y el estado de la corrección (integración entre la regla de AWS Config y el documento SSM).

Desplácese hasta Administrador de sistemas à Automatización. En «Automations Executions», ejecutaremos el documento:

 

Figura 11 Ejecución del documento SSM

 

Una vez ejecutadas las automatizaciones, tendremos 2 alarmas EC2 en CloudWatch, siguiendo las métricas estipuladas durante la creación de conformidad. La figura 12 muestra un EC2 que se registró en la cuenta, pasó la evaluación de reglas y se ha corregido, creando las alarmas necesarias.

 

Figura 12 Alarmas de CloudWatch

 

Ahora cambiemos los parámetros de la plantilla y agreguemos una nueva regla para ver cómo una infraestructura como código simplifica el proceso. El objetivo es actualizar la regla de AWS Config añadiendo una nueva métrica y, en consecuencia, actualizar el documento de remediación, añadiendo un paso para la validación y corrección de Alarm3.

En Cloudformation à Pilas, seleccione EC2-alarmas-obligatorias à Actualizar à Utilice la plantilla actual. Agregue los siguientes valores en los campos Configuraciones de alarm3:

  • Nombre de la métrica Alarm3: StatusCheckFailed_Instance
  • Umbral métrico de Alarm3: 1
  • Estadísticas métricas de Alarm3: Máximo

Después de la actualización de la pila, tenemos nuevos parámetros (Alarm3) como parte del cumplimiento

 

Figura 13 Regla de configuración y parámetros

 

El documento que se ejecuta para remediar tendrá un paso para verificar y corregir la Alarm3.

 

Figura 14: Pasos de automatización en el documento SSM

 

Dado que la regla de configuración está actualizada y con las 3 alarmas descritas como obligatorias, podemos reevaluar la regla.  Haga clic en AWS Config. à Reglas à EC2 con alarmas obligatorias à Vuelva a valorar. En este punto, AWS Config invocará Lambda, que recibirá los parámetros de las 3 alarmas obligatorias. A través de estos parámetros, se realizará la evaluación, dando como resultado una regla COMPLIANT o NON_COMPLIANT. Como creamos una nueva alarma y la instancia EC2 no tiene Alarm3, se generará un incumplimiento:

 

Figura 15: Resultado de la evaluación de reglas de configuración

 

Todo el flujo de corrección se producirá de nuevo, creando una nueva alarma para el EC2 específico. Desplácese hasta Administrador de sistemas à Automatización. En «Automations Executions», ejecutaremos el documento:

 

Figura 16: Ejecución de documento SSM

 

En CloudWatch Alarms, podemos ver la nueva alarma creada automáticamente, formando parte del cumplimiento. Así que tenemos tres alarmas instaladas.

 

Figura 17: Alarmas CloudWatch

 

Detalles sobre el código utilizado en Automatización:

Hay detalles importantes que se pueden encontrar en las plantillas de Cloudformation:

  • Transformación de parámetros en Cloudformation  : Los parámetros introducidos en la plantilla, en campos de cadena, se transforman en json dentro de CloudFormation, en tiempo de ejecución de la pila, actuando como parámetro de AWS Config Rule. El siguiente fragmento muestra la creación dinámica del objeto json con funciones intrínsecas (! Sub y! FindinMap).

 

OpsConfigRule:
    Type: AWS::Config::ConfigRule
    Properties:
      ConfigRuleName: !Sub "${ServiceTobeMonitored}-with-mandatory-alarms"
      InputParameters: 
        Alarm1Config: !Sub
          - |
            {"MetricName": "${Alarm1MetricName}", "MetricThreshold": ${Alarm1Threshold}, "MetricStatistics": "${Alarm1Statistics}", "MetricNamespace": "${namespace}", "MetricDimensions": "${dimension}"}
          - namespace: !FindInMap [NamespaceMapping, !Ref ServiceTobeMonitored, Namespace] 
            dimension: !FindInMap [NamespaceMapping, !Ref ServiceTobeMonitored, Dimension] 
        Alarm2Config: !Sub
          - | 
            {"MetricName": "${Alarm2MetricName}", "MetricThreshold": ${Alarm2Threshold}, "MetricStatistics": "${Alarm2Statistics}", "MetricNamespace": "${namespace}", "MetricDimensions": "${dimension}"}
          - namespace: !FindInMap [NamespaceMapping, !Ref ServiceTobeMonitored, Namespace] 
            dimension: !FindInMap [NamespaceMapping, !Ref ServiceTobeMonitored, Dimension]
            Alarm2MetricName: !If [ CreateAlarm2, !Ref Alarm2MetricName , 'null' ]
        Alarm3Config: !Sub 
          - | 
            {"MetricName": "${Alarm3MetricName}", "MetricThreshold": ${Alarm3Threshold}, "MetricStatistics": "${Alarm3Statistics}", "MetricNamespace": "${namespace}", "MetricDimensions": "${dimension}"}
          - namespace: !FindInMap [NamespaceMapping, !Ref ServiceTobeMonitored, Namespace] 
            dimension: !FindInMap [NamespaceMapping, !Ref ServiceTobeMonitored, Dimension]
            Alarm3MetricName: !If [ CreateAlarm3, !Ref Alarm3MetricName , 'null' ]
        Whitelistedresources: !Ref Whitelistedresources

 

  • Código Python incrustado en el documento SSM  : El caso de uso para el escenario es cuando necesitamos hacer una iteración o algoritmo más complejo en el resultado de una llamada a la API. Como beneficio del código contenido en el propio documento SSM, facilitando la centralización de la automatización.

 

OpsAutomationDocument:
    Type: 'AWS::SSM::Document'
    Properties: 
      DocumentType: Automation
      Content:
        schemaVersion: "0.3"
        assumeRole: "{{ AutomationAssumeRole }}"
        description: SSM Document
        mainSteps:
          - name: VerifyCloudWatchConfig
            action: 'aws:executeScript'
            inputs:
              Runtime: python3.6
              Handler: script_handler
              Script: |-
                import json, boto3, string
                client_cw = boto3.client('cloudwatch')
                client_config = boto3.client('config')
                def get_resource_history(events):
                  response = client_config.get_resource_config_history(
                      resourceType=events['ConfigServiceName'],
                      resourceId=events['ResourceId'])
                  return response
                def script_handler(events, context):
                  print(events)
                  temp_dict = {}
                  results = {}
                  response = get_resource_history(events)
                  if events['ConfigServiceName'] == 'AWS::RDS::DBInstance' or events['ConfigServiceName'] == 'AWS::SNS::Topic':
                    resourceId_cw = response['configurationItems'][0]['resourceName']
                  elif events['ConfigServiceName'] == 'AWS::ElasticLoadBalancingV2::LoadBalancer':
                    print('this is the response %s' % response)
                    alb_resource_name = response['configurationItems'][0]['resourceId']
                    resourceId_cw = alb_resource_name.split('/')[1]+'/'+alb_resource_name.split('/')[2]+'/'+alb_resource_name.split('/')[3]
                  else:
                    resourceId_cw = events['ResourceId']
                  del events['ResourceId']
                  del events['ConfigServiceName']
                  for key in events:
                    temp_dict = json.loads(events[key])
                    if temp_dict['MetricName'] == 'null':
                      del key
                  for key in events:
                    temp_dict = json.loads(events[key])
                    metric = temp_dict['MetricName']
                    namespace = temp_dict['MetricNamespace']
                    dimension = temp_dict['MetricDimensions']
                    alarm_name = f'{resourceId_cw}-{metric}'
                    try:
                        response = client_cw.describe_alarms_for_metric(
                            MetricName=metric,
                            Namespace=namespace,
                            Dimensions=[{'Name': dimension,'Value': resourceId_cw}]
                        )
                        if len(response['MetricAlarms']) == 0:
                          results[key] = json.loads(events[key])
                          for key in results: 
                            results[key]['MetricThreshold'] = int(results[key]['MetricThreshold'])
                        else:
                          for i in response['MetricAlarms']: 
                            if i['AlarmName'] == alarm_name:
                              results[key] = {'MetricName': i['MetricName'],
                                  'MetricThreshold': int(i['Threshold']),
                                  'MetricStatistics': i['Statistic'],
                                  'MetricNamespace': i['Namespace'],
                                  'MetricDimensions': i['Dimensions'][0]['Name']}
                            else:
                              results[key] = json.loads(events[key])
                    except Exception as e:
                        print('Error %s' % (e)) 
                  results['ResourceId_CW'] = resourceId_cw
                  return results
              InputPayload:
                Alarm1Config: '{{ Alarm1Config }}'
                Alarm2Config: '{{ Alarm2Config }}'
                Alarm3Config: '{{ Alarm3Config }}'
                ResourceId: '{{ ResourceId }}'
                ConfigServiceName: '{{ ConfigServiceName }}'

 

En el ejemplo anterior, creamos una Automatización de tipo AWS:ExecuteScript. La automatización invoca el código de Python a través de Parámetros de entrada y volverá al siguiente paso los Parámetros de salida:

  • Parámetros de entrada: InputPayLoad (Alarm1Config, Alarm2Config, Alarm3Config y ConfigServiceName).
  • Parámetros de salida: En Output devuelve un objeto json, que mediante el uso de filtros en Salida, puede reenviar los valores a los siguientes pasos del flujo de automatización

 

Conclusión

El cumplimiento como código es una práctica importante para automatizar las arquitecturas y estándares de referencia. El gobierno automatizado basado en código beneficia a las organizaciones que necesitan monitoreo para garantizar sus estándares.

Los servicios utilizados crean este objetivo, integrando de forma nativa y permitiendo personalizaciones en lenguaje de notación o lenguaje de programación. Las reglas de configuración de AWS pueden tener reglas de configuración personalizadas con evaluaciones e integración con Lambda, Event Bridge, supervisa y desencadena acciones a través de eventos específicos. Los documentos SSM tienen varias opciones de personalización a través de llamadas a API o código incrustado.

Los códigos de implementación anteriores están disponibles en GitHub . Se puede cambiar según sea necesario.

 

Este artículo fue traducido del Blog de AWS en Portugués

 


Sobre os autores

Guilherme es Arquitecto de Soluciones en AWS, centrado en el segmento financiero. Con 18 años de experiencia en infraestructura y arquitectura, Guilherme ha ayudado a los clientes de AWS a tener éxito en sus viajes a la nube desde 2018, desde la creación de una base sólida hasta las migraciones de soluciones empresariales.

 

 

 

 

Kimmy Wu es Arquitecta de Soluciones y responsable de ayudar a los clientes a crear cargas de trabajo que les permitan avanzar en su proceso de transformación digital en la nube de AWS.