Mise en œuvre des contrôles préventifs pour Lambda avec AWS Config - AWS Lambda

Mise en œuvre des contrôles préventifs pour Lambda avec AWS Config

Il est essentiel de garantir la conformité de vos applications sans serveur le plus tôt possible dans le processus de développement. Dans cette rubrique, nous expliquons comment mettre en œuvre des contrôles préventifs à l'aide de AWS Config. Cela vous permet de mettre en œuvre des contrôles de conformité plus tôt dans le processus de développement et de mettre en œuvre les mêmes contrôles dans vos pipelines CI/CD. Cela permet également de standardiser vos contrôles dans un référentiel de règles géré de manière centralisée afin que vous puissiez appliquer vos contrôles de manière cohérente sur l'ensemble de vos comptes AWS.

Supposons, par exemple, que vos administrateurs de conformité aient défini une exigence garantissant que toutes les fonctions Lambda incluent le suivi AWS X-Ray. Grâce au mode proactif AWS Config, vous pouvez effectuer des contrôles de conformité sur les ressources de vos fonctions Lambda avant le déploiement, ce qui réduit le risque de déploiement de fonctions Lambda mal configurées et fait gagner du temps aux développeurs en leur fournissant plus rapidement des informations sur les modèles infrastructure en tant que code. Voici une visualisation du flux pour les contrôles préventifs avec AWS Config :

CloudFormation requests must pass AWS Config rules before provisioning.

Envisagez d'exiger que le suivi soit activé pour toutes les fonctions Lambda. En réponse, l'équipe de la plateforme identifie la nécessité d'une règle AWS Config spécifique pour s'exécuter de manière proactive sur tous les comptes. Cette règle signale toute fonction Lambda dont la configuration de suivi X-Ray n'est pas configurée comme une ressource non conforme. L'équipe développe une règle, l'intègre dans un pack de conformité et déploie le pack de conformité sur tous les comptes afin de garantir que tous les comptes AWS de l'organisation appliquent ces contrôles de manière uniforme. Vous pouvez écrire la règle dans la syntaxe AWS CloudFormation Guard 2.x.x, qui prend la forme suivante :

rule name when condition { assertion }

Voici un exemple de règle Guard qui vérifie que le suivi est activé pour les fonctions Lambda :

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

L'équipe de la plateforme prend des mesures supplémentaires en imposant que chaque déploiement AWS CloudFormation invoque un hook de pré-création/mise à jour. Elle assume l'entière responsabilité du développement de ce hook et de la configuration du pipeline, du renforcement du contrôle centralisé des règles de conformité et du maintien de leur application cohérente dans tous les déploiements. Pour développer, packager et enregistrer un hook, consultez Developing AWS CloudFormation Hooks dans la documentation de l’interface de ligne de commande CloudFormation (CFN-CLI). Vous pouvez utiliser la CLI CloudFormation pour créer le projet hook :

cfn init

Cette commande vous demande des informations de base sur votre projet hook et crée un projet contenant les fichiers suivants :

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

En tant que développeur de hooks, vous devez ajouter le type de ressource cible souhaité dans le fichier <hook-name>.json de configuration. Dans la configuration ci-dessous, un hook est configuré pour s'exécuter avant qu'une fonction Lambda ne soit créée à l'aide de CloudFormation. Vous pouvez également ajouter des gestionnaires preUpdate et des actions preDelete similaires.

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

Vous devez également vous assurer que le hook CloudFormation dispose des autorisations appropriées pour appeler les API AWS Config. Vous pouvez le faire en mettant à jour le fichier de définition de rôle nommé hook-role.yaml. Le fichier de définition de rôle possède la politique de confiance suivante par défaut, qui permet à CloudFormation d'assumer le rôle.

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

Pour permettre à ce hook d'appeler des API de configuration, vous devez ajouter les autorisations suivantes à la déclaration de politique. Vous soumettez ensuite le projet hook à l'aide de la commande cfn submit, dans laquelle CloudFormation crée un rôle pour vous avec les autorisations requises.

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

Ensuite, vous devez écrire une fonction Lambda dans un src/handler.py fichier. Dans ce fichier, vous trouverez les méthodes nommées preCreate, preUpdate et preDelete déjà créées lorsque vous avez lancé le projet. Votre objectif est d'écrire une fonction commune et réutilisable qui appelle l'API AWS Config StartResourceEvaluation en mode proactif avec AWS SDK pour Python (Boto3). Cet appel d'API prend les propriétés des ressources en entrée et évalue la ressource par rapport à la définition de la règle.

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

Vous pouvez maintenant appeler la fonction commune depuis le gestionnaire pour le hook de pré-création. Voici un exemple de gestionnaire :

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

Après cette étape, vous pouvez enregistrer le hook et le configurer pour écouter tous les événements de création de fonctions AWS Lambda.

Un développeur prépare le modèle d'infrastructure en tant que code (IaC) pour un microservice sans serveur à l'aide de Lambda. Cette préparation inclut le respect des normes internes, suivi de tests locaux et de validation du modèle dans le référentiel. Voici un exemple de modèle 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

Dans le cadre du processus CI/CD, lorsque le modèle CloudFormation est déployé, le service CloudFormation appelle le hook de pré-création/mise à jour juste avant le provisionnement du type de ressource AWS::Lambda::Function. Le hook utilise des règles AWS Config exécutées en mode proactif pour vérifier que la configuration de la fonction Lambda inclut la configuration de suivi obligatoire. La réponse du hook détermine l'étape suivante. Si elle est conforme, le hook indique le succès et CloudFormation procède au provisionnement des ressources. Dans le cas contraire, le déploiement de la pile CloudFormation échoue, le pipeline s'arrête immédiatement et le système enregistre les détails pour examen ultérieur. Les notifications de conformité sont envoyées vers les parties prenantes concernées.

Vous trouverez les informations relatives à la réussite ou à l'échec du hook dans la console CloudFormation :

Hook success/fail information in the CloudFormation console

Si les journaux sont activés pour votre hook CloudFormation, vous pouvez capturer le résultat de l'évaluation du hook. Voici un exemple de journal pour un hook dont le statut a échoué, indiquant que X-Ray n'est pas activé sur la fonction Lambda :

Sample log for a hook with a failed status

Si le développeur choisit de modifier le modèle IaC pour mettre à jour la valeur TracingConfig Modesur Active et le redéployer, le hook s'exécute correctement et la pile poursuit la création de la ressource Lambda.

CloudFormation console shows successful resource deployment

Ainsi, vous pouvez mettre en œuvre des contrôles préventifs avec AWS Config en mode proactif lors du développement et du déploiement de ressources sans serveur dans vos comptes AWS. En intégrant des règles AWS Config dans le pipeline CI/CD, vous pouvez identifier et éventuellement bloquer les déploiements de ressources non conformes, tels que les fonctions Lambda dépourvues de configuration de suivi active. Cela garantit que seules les ressources conformes aux dernières politiques de gouvernance sont déployées dans vos environnements AWS.