Implemente controles preventivos para Lambda con AWS Config - AWS Lambda

Implemente controles preventivos para Lambda con AWS Config

Es esencial garantizar lo antes posible la conformidad en sus aplicaciones sin servidor durante el proceso de desarrollo. En este tema, abordamos cómo implementar controles preventivos mediante AWS Config. Esto le permite implementar las comprobaciones de conformidad en una fase más temprana del proceso de desarrollo e implementar los mismos controles en sus canalizaciones de CI/CD. Esto también estandariza los controles en un repositorio de reglas administrado de forma centralizada para que pueda aplicarlos de forma coherente en todas sus cuentas de AWS.

Por ejemplo, supongamos que los administradores de conformidad definieron un requisito para garantizar que todas las funciones de Lambda incluyan el seguimiento de AWS X-Ray. Con el modo proactivo de AWS Config, puede realizar comprobaciones de conformidad en los recursos de las funciones de Lambda antes de la implementación, lo que reduce el riesgo de implementar funciones de Lambda mal configuradas y les ahorra tiempo a los desarrolladores al proporcionarles comentarios más rápidos sobre la infraestructura en forma de plantillas de código. La siguiente es una visualización del flujo de los controles preventivos con AWS Config:

AWS CloudFormation requests must pass AWS Config rules before provisioning.

Recuerde el requisito de que todas las funciones de Lambda deben tener habilitado el rastreo. En respuesta, el equipo de la plataforma identifica la necesidad de que una regla específica de AWS Config se ejecute de forma proactiva en todas las cuentas. Esta regla marca cualquier función de Lambda que carezca de una configuración de rastreo de X-Ray configurada como un recurso no conforme. El equipo desarrolla una regla, la empaqueta en un paquete de conformidad y lo implementa en todas las cuentas de AWS para garantizar que todas las cuentas de la organización apliquen estos controles de manera uniforme. Puede escribir la regla en la sintaxis AWS CloudFormation Guard 2.x.x, que adopta la siguiente forma:

rule name when condition { assertion }

A continuación, se muestra un ejemplo de regla de protección que comprueba que las funciones de Lambda tengan activado el rastreo:

rule lambda_tracing_check { when configuration.tracingConfig exists { configuration.tracingConfig.mode == "Active" } }

El equipo de la plataforma toma medidas adicionales al exigir que cada implementación de AWS CloudFormation invoque un enlace de creación previa o actualización. Asumen toda la responsabilidad de desarrollar este enlace y configurar la canalización, reforzar el control centralizado de las reglas de conformidad y mantener su aplicación uniforme en todas las implementaciones. Para desarrollar, empaquetar y registrar un enlace, consulte Desarrollo de enlaces de AWS CloudFormation en la documentación de la interfaz de línea de comandos de CloudFormation (CFN-CLI). Puede usar la CLI de CloudFormation para crear el proyecto del enlace:

cfn init

Este comando le solicita información básica sobre el proyecto del enlace y crea un proyecto que incluye los siguientes archivos:

README.md <hook-name>.json rpdk.log src/handler.py template.yml hook-role.yaml

Como desarrollador de enlaces, debe agregar el tipo de recurso de destino deseado en el archivo de configuración de <hook-name>.json. En la siguiente configuración, se configura un enlace para que se ejecute antes de crear cualquier función de Lambda mediante CloudFormation. También puede agregar controladores similares para las acciones de preUpdate y preDelete.

"handlers": { "preCreate": { "targetNames": [ "AWS::Lambda::Function" ], "permissions": [] } }

También debe asegurarse de que el enlace de CloudFormation tenga los permisos adecuados para llamar a las API de AWS Config. Para ello, actualice el archivo de definición de roles denominado hook-role.yaml. De forma predeterminada, el archivo de definición de roles posee la siguiente política de confianza, que le permite a CloudFormation asumir ese rol.

AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: - hooks.cloudformation.amazonaws.com - resources.cloudformation.amazonaws.com

Para permitir que este enlace llame a las API de configuración, debe agregar los siguientes permisos a la instrucción de política. A continuación, envía el proyecto del enlace mediante el comando cfn submit, y CloudFormation crea un rol para usted con los permisos necesarios.

Policies: - PolicyName: HookTypePolicy PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - "config:Describe*" - "config:Get*" - "config:List*" - "config:SelectResourceConfig" Resource: "*

Luego debe escribir una función de Lambda en un archivo src/handler.py. En este archivo, encontrará los métodos denominados preCreate, preUpdate y preDelete, que ya se crearon al iniciar el proyecto. Su objetivo es escribir una función común y reutilizable que llame a la API de AWS Config StartResourceEvaluation en modo proactivo mediante AWS SDK for Python (Boto3). Esta llamada a la API toma las propiedades del recurso como entrada y evalúa el recurso en función de la definición de la regla.

def validate_lambda_tracing_config(resource_type, function_properties: MutableMapping[str, Any]) -> ProgressEvent: LOG.info("Fetching proactive data") config_client = boto3.client('config') resource_specs = { 'ResourceId': 'MyFunction', 'ResourceType': resource_type, 'ResourceConfiguration': json.dumps(function_properties), 'ResourceConfigurationSchemaType': 'CFN_RESOURCE_SCHEMA' } LOG.info("Resource Specifications:", resource_specs) eval_response = config_client.start_resource_evaluation(EvaluationMode='PROACTIVE', ResourceDetails=resource_specs, EvaluationTimeout=60) ResourceEvaluationId = eval_response.ResourceEvaluationId compliance_response = config_client.get_compliance_details_by_resource(ResourceEvaluationId=ResourceEvaluationId) LOG.info("Compliance Verification:", compliance_response.EvaluationResults[0].ComplianceType) if "NON_COMPLIANT" == compliance_response.EvaluationResults[0].ComplianceType: return ProgressEvent(status=OperationStatus.FAILED, message="Lambda function found with no tracing enabled : FAILED", errorCode=HandlerErrorCode.NonCompliant) else: return ProgressEvent(status=OperationStatus.SUCCESS, message="Lambda function found with tracing enabled : PASS.")

Ahora puede llamar a la función común desde el controlador del enlace de creación previa. El siguiente es un ejemplo del controlador:

@hook.handler(HookInvocationPoint.CREATE_PRE_PROVISION) def pre_create_handler( session: Optional[SessionProxy], request: HookHandlerRequest, callback_context: MutableMapping[str, Any], type_configuration: TypeConfigurationModel ) -> ProgressEvent: LOG.info("Starting execution of the hook") target_name = request.hookContext.targetName LOG.info("Target Name:", target_name) if "AWS::Lambda::Function" == target_name: return validate_lambda_tracing_config(target_name, request.hookContext.targetModel.get("resourceProperties") ) else: raise exceptions.InvalidRequest(f"Unknown target type: {target_name}")

Luego de este paso, puede registrar el enlace y configurarlo para que escuche todos los eventos de creación de las funciones de AWS Lambda.

Un desarrollador prepara la plantilla de infraestructura como código (IaC) para un microservicio sin servidor mediante Lambda. Esta preparación incluye el cumplimiento de los estándares internos, y está seguida de pruebas locales y el envío de la plantilla al repositorio. A continuación, se muestra una plantilla de IaC de ejemplo:

MyLambdaFunction: Type: 'AWS::Lambda::Function' Properties: Handler: index.handler Role: !GetAtt LambdaExecutionRole.Arn FunctionName: MyLambdaFunction Code: ZipFile: | import json def handler(event, context): return { 'statusCode': 200, 'body': json.dumps('Hello World!') } Runtime: python3.13 TracingConfig: Mode: PassThrough MemorySize: 256 Timeout: 10

Como parte del proceso de CI/CD, cuando se implementa la plantilla de CloudFormation, el servicio de CloudFormation invoca el enlace de creación previa o actualización justo antes de aprovisionar el tipo de recurso de AWS::Lambda::Function. El enlace utiliza reglas de AWS Config que se ejecutan en modo proactivo para comprobar si la configuración de la función de Lambda incluye la configuración de rastreo obligatoria. La respuesta del enlace determina el siguiente paso. Si es compatible, el enlace indica que se ha realizado correctamente y CloudFormation procede a aprovisionar los recursos. De lo contrario, se produce un error en la implementación de la pila de CloudFormation, la canalización se detiene inmediatamente y el sistema registra los detalles para su posterior revisión. Las notificaciones de conformidad se envían a las partes interesadas pertinentes.

Puede encontrar la información sobre el éxito o el error del enlace en la consola de CloudFormation:

Hook success/fail information in the AWS CloudFormation console

Si tiene los registros habilitados para su enlace de CloudFormation, puede capturar el resultado de la evaluación del enlace. Este es un ejemplo de registro de un enlace con un estado de error, que indica que la función de Lambda no tiene activado X-Ray:

Sample log for a hook with a failed status

Si el desarrollador decide cambiar la IaC para actualizar el valor TracingConfig Mode a Active y volver a implementarlo, el enlace se ejecuta correctamente y la pila continúa con la creación del recurso de Lambda.

AWS CloudFormation console shows successful resource deployment

De esta forma, puede implementar controles preventivos con AWS Config en modo proactivo al desarrollar e implementar recursos sin servidor en sus cuentas de AWS. Al integrar las reglas de AWS Config en la canalización de CI/CD, puede identificar y, opcionalmente, bloquear las implementaciones de recursos no conformes, como las funciones de Lambda que carecen de una configuración de rastreo activo. Esto garantiza que en sus entornos de AWS solo se implementen los recursos que cumplen con las políticas de gobernanza más recientes.