Implementare i controlli di prevenzione per Lambda con AWS Config - AWS Lambda

Implementare i controlli di prevenzione per Lambda con AWS Config

È essenziale garantire la conformità delle applicazioni serverless il più presto possibile nel processo di sviluppo. In questo argomento, spieghiamo come implementare controlli preventivi utilizzando AWS Config. Ciò ti consente di implementare i controlli di conformità nelle fasi iniziali del processo di sviluppo e di implementare i medesimi controlli nelle pipeline CI/CD. In tal modo è anche possibile standardizzare i controlli in un repository di regole gestito centralmente e, di conseguenza, applicare i controlli in modo coerente in tutti gli account AWS.

Ad esempio, supponiamo che gli amministratori addetti alla conformità abbiano definito un requisito per garantire che tutte le funzioni Lambda includano il tracciamento AWS X-Ray. Con la modalità proattiva di AWS Config, puoi eseguire controlli di conformità sulle risorse delle funzioni Lambda prima dell'implementazione, così da ridurre il rischio di implementare funzioni Lambda configurate in modo errato e da risparmiare tempo agli sviluppatori fornendo loro un feedback più rapido sui modelli di infrastructure as code. Di seguito è riportata una visualizzazione del flusso dei controlli preventivi con AWS Config:

CloudFormation requests must pass AWS Config rules before provisioning.

Immagina che vi sia un requisito per cui il tracciamento deve essere abilitato in tutte le funzioni Lambda. In risposta, il team addetto alla piattaforma identifica la necessità di una regola di AWS Config specifica da eseguire in modo proattivo su tutti gli account. Questa regola contrassegna come risorsa non conforme ogni funzione Lambda priva di una configurazione di tracciamento X-Ray configurata. Il team sviluppa una regola, la inserisce in un pacchetto di conformità e implementa quest'ultimo in tutti gli account AWS per garantire che gli account dell'organizzazione applichino tali controlli in modo uniforme. Puoi scrivere la regola nella sintassi 2.x.x di AWS CloudFormation Guard, che assume la forma seguente:

rule name when condition { assertion }

Di seguito è riportato un esempio di regola Guard che verifica l'abilitazione del tracciamento nelle funzioni Lambda:

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

Il team addetto alla piattaforma intraprende ulteriori azioni imponendo che ogni implementazione di AWS CloudFormation richiami un hook di pre-creazione/aggiornamento. Il team si assume la piena responsabilità dello sviluppo di tale hook e di configurare la pipeline, rafforzando il controllo centralizzato delle regole di conformità e sostenendo l'applicazione coerente in tutte le implementazioni. Per sviluppare, impacchettare e registrare un hook, consulta Sviluppo di hook AWS CloudFormation nella documentazione dell'interfaccia a riga di comando di CloudFormation (CFN-CLI). Puoi utilizzare la CLI CloudFormation per creare il progetto di hook:

cfn init

Questo comando richiede alcune informazioni di base sul progetto hook e crea un progetto contenente i file seguenti:

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

Come sviluppatore di hook, devi aggiungere il tipo di risorsa di destinazione desiderato nel file di configurazione <hook-name>.json. Nella configurazione riportata di seguito, un hook è configurato in modo tale che venga eseguito prima della creazione di qualsiasi funzione Lambda con CloudFormation. Puoi anche aggiungere gestori simili per le azioni preUpdate e preDelete.

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

Devi inoltre assicurarti che l'hook CloudFormation disponga delle autorizzazioni adeguate per effettuare la chiamata alle API AWS Config. Puoi farlo aggiornando il file di definizione del ruolo denominato hook-role.yaml. Il file di definizione del ruolo presenta per impostazione predefinita la seguente policy di attendibilità, che consente a CloudFormation di assumere il ruolo.

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

Per consentire all'hook di effettuare la chiamata alle API di configurazione, devi aggiungere le seguenti autorizzazioni all'istruzione Policy. Quindi devi inviare il progetto di hook utilizzando il comando cfn submit, con cui CloudFormation crea un ruolo per te con le autorizzazioni necessarie.

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

Successivamente, devi scrivere una funzione Lambda in un file src/handler.py. All'interno di tale file, troverai i metodi denominati preCreate, preUpdate e preDelete già creati all'avvio del progetto. L'obiettivo è scrivere una funzione comune e riutilizzabile che effettui la chiamata all'API StartResourceEvaluation di AWS Config in modalità proattiva utilizzando AWS SDK per Python (Boto3). Questa chiamata API accetta le proprietà della risorsa come input e valuta la risorsa rispetto alla definizione della regola.

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.")

Ora puoi effettuare la chiamata alla funzione comune dal gestore per l'hook di pre-creazione. Di seguito è riportato un esempio del gestore:

@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}")

Terminata tale fase, puoi registrare l'hook e configurarlo in modo tale da ascoltare tutti gli eventi di creazione di funzioni AWS Lambda.

Uno sviluppatore prepara il modello di infrastructure as code (IaC) per un microservizio serverless utilizzando Lambda. La preparazione prevede il rispetto degli standard interni, a cui seguono il test e il commit locale del modello nel repository. Ecco un esempio di modello IaC:

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

Nell'ambito del processo CI/CD, quando il modello CloudFormation viene implementato, il servizio CloudFormation richiama l'hook di pre-creazione/aggiornamento subito prima di effettuare il provisioning del tipo di risorsa AWS::Lambda::Function. L'hook utilizza regole AWS Config in esecuzione con modalità proattiva per verificare che la configurazione della funzione Lambda includa quella obbligatoria del tracciamento. La risposta dell'hook determina la fase successiva. Se conforme, l'hook segnala l'esito positivo e CloudFormation procede al provisioning delle risorse. In caso contrario, l'implementazione dello stack CloudFormation ha esito negativo, la pipeline si arresta immediatamente e il sistema registra i dettagli per la successiva revisione. Le notifiche di conformità vengono inviate ai soggetti interessati.

Puoi trovare le informazioni riguardanti l'esito positivo/negativo dell'hook nella console CloudFormation:

Hook success/fail information in the CloudFormation console

Se disponi di log per l'hook CloudFormation abilitati, puoi acquisire il risultato della valutazione dell'hook. Di seguito è riportato un log di esempio relativo a un hook con stato non riuscito, che indica il fatto che nella funzione Lambda non è abilitato X-Ray:

Sample log for a hook with a failed status

Se lo sviluppatore sceglie di modificare l'IaC per aggiornare il valore TracingConfig Mode in Active ed eseguire nuovamente l'implementazione, l'hook viene eseguito correttamente e lo stack procede alla creazione della risorsa Lambda.

CloudFormation console shows successful resource deployment

In tal modo, puoi implementare controlli preventivi con AWS Config in modalità proattiva durante lo sviluppo e l'implementazione di risorse serverless negli account AWS. Integrando regole AWS Config nella pipeline CI/CD, puoi identificare e, facoltativamente, bloccare le implementazioni di risorse non conformi, come funzioni Lambda prive di una configurazione del tracciamento attiva. Ciò garantisce che negli ambienti AWS vengano implementate solo le risorse conformi alle policy di governance più recenti.