

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

# Ressources personnalisées basées sur Lambda
<a name="template-custom-resources-lambda"></a>

Lorsque vous associez une fonction Lambda à une ressource personnalisée, la fonction est appelée chaque fois que la ressource personnalisée est créée, mise à jour ou supprimée. CloudFormation appelle une API Lambda pour appeler la fonction et pour transmettre toutes les données de demande (comme le type de demande et les propriétés des ressources) à la fonction. CloudFormation Combinées à la puissance et à la personnalisation des fonctions Lambda, elles permettent un large éventail de scénarios, tels que la recherche dynamique d' IDs AMI lors de la création d'une pile ou la mise en œuvre et l'utilisation de fonctions utilitaires, telles que les fonctions d'inversion de chaînes de caractères.

Pour une présentation des ressources personnalisées et de leur fonctionnement, consultez [Fonctionnement des ressources personnalisées](template-custom-resources.md#how-custom-resources-work).

**Topics**
+ [Démonstration : créer un mécanisme de délai avec une ressource personnalisée prise en charge par Lambda](walkthrough-lambda-backed-custom-resources.md)
+ [Module `cfn-response`](cfn-lambda-function-code-cfnresponsemodule.md)

# Démonstration : créer un mécanisme de délai avec une ressource personnalisée prise en charge par Lambda
<a name="walkthrough-lambda-backed-custom-resources"></a>

Cette procédure pas à pas vous explique comment configurer et lancer une ressource personnalisée basée sur Lambda à l'aide d'un exemple de modèle. CloudFormation Ce modèle crée un mécanisme de délai qui suspend les déploiements de pile pendant une durée spécifiée. Cela peut être utile lorsque vous devez introduire des délais délibérés pendant l’approvisionnement en ressources, par exemple lorsque vous attendez que les ressources se stabilisent avant de créer des ressources dépendantes.

**Note**  
Alors que les ressources personnalisées soutenues par Lambda étaient auparavant recommandées pour récupérer les AMI IDs, nous recommandons désormais d'utiliser des paramètres. AWS Systems Manager Cette approche rend vos modèles plus réutilisables et plus faciles à maintenir. Pour de plus amples informations, veuillez consulter [Obtenir une valeur en texte brut depuis le magasin de paramètres Systems Manager](dynamic-references-ssm.md). 

**Topics**
+ [Présentation de](#walkthrough-lambda-backed-custom-resources-overview)
+ [Exemple de modèle](#walkthrough-lambda-backed-custom-resources-sample-template)
+ [Démonstration du modèle d’exemple](#walkthrough-lambda-backed-custom-resources-sample-template-walkthrough)
+ [Conditions préalables](#walkthrough-lambda-backed-custom-resources-prerequisites)
+ [Lancement de la pile](#walkthrough-lambda-backed-custom-resources-createfunction-createstack)
+ [Nettoyage des ressources](#walkthrough-lambda-backed-custom-resources-createfunction-cleanup)
+ [Informations connexes](#w2aac11c45b9c24b9c23)

## Présentation de
<a name="walkthrough-lambda-backed-custom-resources-overview"></a>

Le modèle de pile utilisé dans cette démonstration crée une ressource personnalisée basée sur Lambda. Cette ressource personnalisée introduit un délai configurable (60 secondes par défaut) pendant la création de la pile. Le délai se produit pendant les mises à jour de la pile uniquement lorsque les propriétés de la ressource personnalisée sont modifiées.

Le modèle provisionne les ressources suivantes :
+ une ressource personnalisée,
+ une fonction Lambda, et
+ un rôle IAM qui permet à Lambda d'écrire des journaux dans. CloudWatch

Il définit également deux sorties :
+ Le temps réel pendant lequel la fonction a attendu.
+ Un identifiant unique généré lors de chaque exécution de la fonction Lambda.



**Note**  
CloudFormation est un service gratuit, mais Lambda facture en fonction du nombre de requêtes pour vos fonctions et de la durée d'exécution de votre code. Pour plus d’informations sur la tarification Lambda, consultez [Tarification AWS Lambda](https://aws.amazon.com/lambda/pricing/).

## Exemple de modèle
<a name="walkthrough-lambda-backed-custom-resources-sample-template"></a>

Vous pouvez consulter le modèle de ressource personnalisée prise en charge par Lambda avec le mécanisme de délai ci-dessous :

### JSON
<a name="walkthrough-lambda-backed-custom-resources-sample-template-json"></a>

```
{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Resources": {
    "LambdaExecutionRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Statement": [{
            "Effect": "Allow",
            "Principal": { "Service": ["lambda.amazonaws.com"] },
            "Action": ["sts:AssumeRole"]
          }]
        },
        "Path": "/",
        "Policies": [{
          "PolicyName": "AllowLogs",
          "PolicyDocument": {
            "Statement": [{
              "Effect": "Allow",
              "Action": ["logs:*"],
              "Resource": "*"
            }]
          }
        }]
      }
    },
    "CFNWaiter": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Handler": "index.handler",
        "Runtime": "python3.9",
        "Timeout": 900,
        "Role": { "Fn::GetAtt": ["LambdaExecutionRole", "Arn"] },
        "Code": {
          "ZipFile": { "Fn::Join": ["\n", [
            "from time import sleep",
            "import json",
            "import cfnresponse",
            "import uuid",
            "",
            "def handler(event, context):",
            "  wait_seconds = 0",
            "  id = str(uuid.uuid1())",
            "  if event[\"RequestType\"] in [\"Create\", \"Update\"]:",
            "    wait_seconds = int(event[\"ResourceProperties\"].get(\"ServiceTimeout\", 0))",
            "    sleep(wait_seconds)",
            "  response = {",
            "    \"TimeWaited\": wait_seconds,",
            "    \"Id\": id ",
            "  }",
            "  cfnresponse.send(event, context, cfnresponse.SUCCESS, response, \"Waiter-\"+id)"
          ]]}
        }
      }
    },
    "CFNWaiterCustomResource": {
      "Type": "AWS::CloudFormation::CustomResource",
      "Properties": {
        "ServiceToken": { "Fn::GetAtt": ["CFNWaiter", "Arn"] },
        "ServiceTimeout": 60
      }
    }
  },
  "Outputs": {
    "TimeWaited": {
      "Value": { "Fn::GetAtt": ["CFNWaiterCustomResource", "TimeWaited"] },
      "Export": { "Name": "TimeWaited" }
    },
    "WaiterId": {
      "Value": { "Fn::GetAtt": ["CFNWaiterCustomResource", "Id"] },
      "Export": { "Name": "WaiterId" }
    }
  }
}
```

### YAML
<a name="walkthrough-lambda-backed-custom-resources-sample-template-yaml"></a>

```
AWSTemplateFormatVersion: "2010-09-09"
Resources:
  LambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Effect: "Allow"
            Principal:
              Service:
                - "lambda.amazonaws.com"
            Action:
              - "sts:AssumeRole"
      Path: "/"
      Policies:
        - PolicyName: "AllowLogs"
          PolicyDocument:
            Statement:
              - Effect: "Allow"
                Action:
                  - "logs:*"
                Resource: "*"
  CFNWaiter:
    Type: AWS::Lambda::Function
    Properties:
      Handler: index.handler
      Runtime: python3.9 
      Timeout: 900
      Role: !GetAtt LambdaExecutionRole.Arn
      Code:
        ZipFile:
          !Sub |
          from time import sleep
          import json
          import cfnresponse
          import uuid
​
          def handler(event, context):
            wait_seconds = 0
            id = str(uuid.uuid1())
            if event["RequestType"] in ["Create", "Update"]:
              wait_seconds = int(event["ResourceProperties"].get("ServiceTimeout", 0))
              sleep(wait_seconds)
            response = {
              "TimeWaited": wait_seconds,
              "Id": id 
            }
            cfnresponse.send(event, context, cfnresponse.SUCCESS, response, "Waiter-"+id)
  CFNWaiterCustomResource:
    Type: AWS::CloudFormation::CustomResource
    Properties:
      ServiceToken: !GetAtt CFNWaiter.Arn
      ServiceTimeout: 60
Outputs:
  TimeWaited:
    Value: !GetAtt CFNWaiterCustomResource.TimeWaited
    Export:
      Name: TimeWaited
  WaiterId:
    Value: !GetAtt CFNWaiterCustomResource.Id
    Export:
      Name: WaiterId
```

## Démonstration du modèle d’exemple
<a name="walkthrough-lambda-backed-custom-resources-sample-template-walkthrough"></a>

Les extraits suivants expliquent les parties pertinentes du modèle d’exemple afin de vous aider à comprendre comment la fonction Lambda est associée à une ressource personnalisée et à comprendre la sortie.

[AWS::Lambda::Function](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-lambda-function.html)ressource `CFNWaiter`  
La ressource `AWS::Lambda::Function` spécifie le code source de la fonction, le nom du gestionnaire, l’environnement d’exécution et le rôle d’exécution Amazon Resource Name (ARN).  
La propriété `Handler` est définie sur `index.handler` car elle utilise un code source Python. [Pour plus d'informations sur les identifiants de gestionnaire acceptés lors de l'utilisation de codes source de fonctions en ligne, consultez Code. AWS::Lambda::Function ](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-function-code.html#cfn-lambda-function-code-zipfile)  
La propriété `Runtime` est définie sur `python3.9` car le fichier source est un code Python.  
La propriété `Timeout` est définie sur 900 secondes.  
La propriété `Role` utilise la fonction `Fn::GetAtt` pour obtenir l’ARN du rôle d’exécution `LambdaExecutionRole` déclaré dans la ressource `AWS::IAM::Role` du modèle.  
La propriété `Code` définit le code de la fonction en ligne à l’aide d’une fonction Python. La fonction Python du modèle d’exemple effectue les opérations suivantes :  
+ Créer un ID unique à l’aide de l’UUID
+ Vérifier si la demande est une demande de création ou de mise à jour
+ Mettre en veille pendant la durée spécifiée pour `ServiceTimeout` pendant les demandes `Create` ou `Update`
+ Renvoyer le temps d’attente et l’ID unique

### JSON
<a name="walkthrough-lambda-backed-custom-resources-sample-template-lambda-resource-json"></a>

```
...
    "CFNWaiter": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Handler": "index.handler",
        "Runtime": "python3.9",
        "Timeout": 900,
        "Role": { "Fn::GetAtt": ["LambdaExecutionRole", "Arn"] },
        "Code": {
          "ZipFile": { "Fn::Join": ["\n", [
            "from time import sleep",
            "import json",
            "import cfnresponse",
            "import uuid",
            "",
            "def handler(event, context):",
            "  wait_seconds = 0",
            "  id = str(uuid.uuid1())",
            "  if event[\"RequestType\"] in [\"Create\", \"Update\"]:",
            "    wait_seconds = int(event[\"ResourceProperties\"].get(\"ServiceTimeout\", 0))",
            "    sleep(wait_seconds)",
            "  response = {",
            "    \"TimeWaited\": wait_seconds,",
            "    \"Id\": id ",
            "  }",
            "  cfnresponse.send(event, context, cfnresponse.SUCCESS, response, \"Waiter-\"+id)"
          ]]}
        }
      }
    },
...
```

### YAML
<a name="walkthrough-lambda-backed-custom-resources-sample-template-lambda-resource-yaml"></a>

```
...
  CFNWaiter:
    Type: AWS::Lambda::Function
    Properties:
      Handler: index.handler
      Runtime: python3.9 
      Timeout: 900
      Role: !GetAtt LambdaExecutionRole.Arn
      Code:
        ZipFile:
          !Sub |
          from time import sleep
          import json
          import cfnresponse
          import uuid
​
          def handler(event, context):
            wait_seconds = 0
            id = str(uuid.uuid1())
            if event["RequestType"] in ["Create", "Update"]:
              wait_seconds = int(event["ResourceProperties"].get("ServiceTimeout", 0))
              sleep(wait_seconds)
            response = {
              "TimeWaited": wait_seconds,
              "Id": id 
            }
            cfnresponse.send(event, context, cfnresponse.SUCCESS, response, "Waiter-"+id)
...
```

[AWS::IAM::Role](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-iam-role.html)ressource `LambdaExecutionRole`  
La ressource `AWS::IAM:Role` crée un rôle d’exécution pour la fonction Lambda, qui inclut une politique d’assomption de rôle permettant à Lambda de l’utiliser. Il contient également une politique autorisant l'accès aux CloudWatch journaux.

### JSON
<a name="walkthrough-lambda-backed-custom-resources-sample-template-iam-role-json"></a>

```
...
    "LambdaExecutionRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Statement": [{
            "Effect": "Allow",
            "Principal": { "Service": ["lambda.amazonaws.com"] },
            "Action": ["sts:AssumeRole"]
          }]
        },
        "Path": "/",
        "Policies": [{
          "PolicyName": "AllowLogs",
          "PolicyDocument": {
            "Statement": [{
              "Effect": "Allow",
              "Action": ["logs:*"],
              "Resource": "*"
            }]
          }
        }]
      }
    },
...
```

### YAML
<a name="walkthrough-lambda-backed-custom-resources-sample-template-iam-role-yaml"></a>

```
...
  LambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Effect: "Allow"
            Principal:
              Service:
                - "lambda.amazonaws.com"
            Action:
              - "sts:AssumeRole"
      Path: "/"
      Policies:
        - PolicyName: "AllowLogs"
          PolicyDocument:
            Statement:
              - Effect: "Allow"
                Action:
                  - "logs:*"
                Resource: "*"
...
```

[AWS::CloudFormation::CustomResource](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudformation-customresource.html)ressource `CFNWaiterCustomResource`  
La ressource personnalisée est liée à la fonction Lambda avec son ARN à l’aide de `!GetAtt CFNWaiter.Arn`. Elle mettra en œuvre un temps d’attente de 60 secondes pour les opérations de création et de mise à jour, comme défini dans `ServiceTimeout`. La ressource ne sera invoquée pour une opération de mise à jour que si les propriétés sont modifiées.

### JSON
<a name="walkthrough-lambda-backed-custom-resources-sample-template-custom-resource-json"></a>

```
...
    "CFNWaiterCustomResource": {
      "Type": "AWS::CloudFormation::CustomResource",
      "Properties": {
        "ServiceToken": { "Fn::GetAtt": ["CFNWaiter", "Arn"] },
        "ServiceTimeout": 60
      }
    }
  },
...
```

### YAML
<a name="walkthrough-lambda-backed-custom-resources-sample-template-custom-resource-yaml"></a>

```
...
  CFNWaiterCustomResource:
    Type: AWS::CloudFormation::CustomResource
    Properties:
      ServiceToken: !GetAtt CFNWaiter.Arn
      ServiceTimeout: 60
...
```

`Outputs`  
Les `Outputs` de ce modèle sont les `TimeWaited` et les `WaiterId`. La valeur `TimeWaited` utilise une fonction `Fn::GetAtt` pour fournir le temps d’attente réel de la ressource. Le `WaiterId` utilise une fonction `Fn::GetAtt` pour fournir l’ID unique qui a été généré et associé à l’exécution.

### JSON
<a name="walkthrough-lambda-backed-custom-resources-sample-template-output-json"></a>

```
...
  "Outputs": {
    "TimeWaited": {
      "Value": { "Fn::GetAtt": ["CFNWaiterCustomResource", "TimeWaited"] },
      "Export": { "Name": "TimeWaited" }
    },
    "WaiterId": {
      "Value": { "Fn::GetAtt": ["CFNWaiterCustomResource", "Id"] },
      "Export": { "Name": "WaiterId" }
    }
  }
}
...
```

### YAML
<a name="walkthrough-lambda-backed-custom-resources-sample-template-output-yaml"></a>

```
...
Outputs:
  TimeWaited:
    Value: !GetAtt CFNWaiterCustomResource.TimeWaited
    Export:
      Name: TimeWaited
  WaiterId:
    Value: !GetAtt CFNWaiterCustomResource.Id
    Export:
      Name: WaiterId
...
```

## Conditions préalables
<a name="walkthrough-lambda-backed-custom-resources-prerequisites"></a>

Vous devez disposer des autorisations IAM pour utiliser tous les services correspondants, tels que CloudFormation Lambda et.

## Lancement de la pile
<a name="walkthrough-lambda-backed-custom-resources-createfunction-createstack"></a>

**Pour créer la pile**

1. Recherchez le modèle de votre choix (YAML ou JSON) dans la section [Exemple de modèle](#walkthrough-lambda-backed-custom-resources-sample-template) et enregistrez-le sur votre ordinateur sous le nom `samplelambdabackedcustomresource.template`.

1. Ouvrez la CloudFormation console à l'adresse [https://console.aws.amazon.com/cloudformation/](https://console.aws.amazon.com/cloudformation/).

1. Depuis la page **CloudFormation**, choisissez **Piles**, puis **Créer une pile avec de nouvelles ressources (standard)**.

1. Pour la **Condition préalable – Préparer le modèle**, sélectionnez **Choisir un modèle existant**.

1. Pour **Spécifier le modèle**, sélectionnez **Charger un fichier modèle**, puis **Choisir un fichier**.

1. Sélectionnez le fichier de modèle `samplelambdabackedcustomresource.template` que vous avez enregistré précédemment.

1. Choisissez **Suivant**.

1. Pour **Nom de la pile**, saisissez **SampleCustomResourceStack** et sélectionnez **Suivant**.

1. Dans cette procédure détaillée, vous n'avez pas besoin d'ajouter des balises ni de spécifier des paramètres avancés. Dès lors, cliquez sur **Suivant**.

1. Vérifiez que le nom de la pile est correct, puis sélectionnez **Créer**.

La création de votre pile peut prendre plusieurs minutes. CloudFormation Pour surveiller la progression, affichez les événements de la pile. Pour de plus amples informations, veuillez consulter [Afficher les informations relatives à la pile depuis la CloudFormation console](cfn-console-view-stack-data-resources.md).

Si la création de la pile réussit, toutes les ressources de la pile, telles que la fonction Lambda et la ressource personnalisée, ont été créées. Vous avez utilisé avec succès une fonction Lambda et une ressource personnalisée.

[Si la fonction Lambda renvoie une erreur, consultez les journaux de la fonction dans la console CloudWatch Logs.](https://console.aws.amazon.com/cloudwatch/home#logs:) Le nom du flux de journaux est l’ID physique de la ressource personnalisée, qui se trouve dans les ressources de la pile. Pour plus d'informations, consultez la section [Afficher les données du journal](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/Working-with-log-groups-and-streams.html#ViewingLogData) dans le *guide de CloudWatch l'utilisateur Amazon*.

## Nettoyage des ressources
<a name="walkthrough-lambda-backed-custom-resources-createfunction-cleanup"></a>

Supprimez la pile pour nettoyer toutes les ressources que vous y avez créées et pour éviter d’être facturé pour des ressources que vous n’utilisez pas.

**Pour supprimer la pile**

1. Dans la CloudFormation console, choisissez la **SampleCustomResourceStack**pile.

1. Choisissez **Actions**, puis **Supprimer la pile**.

1. Dans le message de confirmation, choisissez **Oui, supprimer**.

Toutes les ressources que vous avez créées seront supprimées.

Maintenant que vous comprenez comment créer et utiliser une ressource personnalisée prise en charge par Lambda, vous pouvez utiliser le modèle et le code d’exemple de cette démonstration pour créer et tester d’autres piles et fonctions.

## Informations connexes
<a name="w2aac11c45b9c24b9c23"></a>
+ [CloudFormation Référence sur les ressources personnalisées](crpg-ref.md)
+ [AWS::CloudFormation::CustomResource](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudformation-customresource.html)

# Module `cfn-response`
<a name="cfn-lambda-function-code-cfnresponsemodule"></a>

Dans votre CloudFormation modèle, vous pouvez spécifier une fonction Lambda comme cible d'une ressource personnalisée. Lorsque vous utilisez la propriété `ZipFile` pour définir le code source de votre [fonction](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-lambda-function.html), vous pouvez charger le module `cfn-response` afin d’envoyer des réponses depuis votre fonction Lambda à une ressource personnalisée. Le module `cfn-response` est une bibliothèque qui simplifie l’envoi de réponses à la ressource personnalisée ayant invoqué votre fonction Lambda. Ce module contient une méthode `send` qui transmet un [objet de réponse](crpg-ref.md#crpg-ref-responses) à une ressource personnalisée au moyen d’une URL présignée Amazon S3 (appelée `ResponseURL`).

Le module `cfn-response` est disponible uniquement lorsque vous utilisez la propriété `ZipFile` pour écrire votre code source. Il n'est pas disponible pour le code source stocké dans des compartiments Amazon S3. Pour le code stocké dans des compartiments , vous devez écrire vos propres fonctions pour envoyer des réponses.

**Note**  
Après l'exécution de la méthode `send`, la fonction Lambda s'arrête. Dès lors, tout ce que vous écrivez après cette méthode est ignoré.

## Chargement du module `cfn-response`
<a name="cfn-lambda-function-code-cfnresponsemodule-loading"></a>

Pour les fonctions Node.js, utilisez la fonction `require()` pour charger le module `cfn-response`. Par exemple, l'exemple de code suivant crée un objet `cfn-response` avec le nom `response` :

```
var response = require('cfn-response');
```

Pour Python, utilisez l'instruction `import` pour charger le module `cfnresponse`, comme illustré dans l'exemple suivant :

**Note**  
Utilisez cette instruction import exacte. CloudFormation n'inclura pas le module de réponse si vous utilisez d'autres variantes de l'instruction d'importation.

```
import cfnresponse
```

## Paramètres de la méthode `send`
<a name="cfn-lambda-function-code-cfnresponsemodule-send-parameters"></a>

Vous pouvez utiliser les paramètres suivants avec la méthode `send`.

`event`  
Champs d'une [demande de ressource personnalisée](crpg-ref.md#crpg-ref-requesttypes).

`context`  
Objet propre aux fonctions Lambda qui vous permet de spécifier à quel moment l'exécution de la fonction et des rappels se termine ou pour accéder aux informations à partir de l'environnement d'exécution Lambda. Pour plus d’informations, consultez [Création de fonctions Lambda avec Node.js](https://docs.aws.amazon.com/lambda/latest/dg/lambda-nodejs.html) dans le *Guide du développeur AWS Lambda *.

`responseStatus`  
Indique si la fonction a été exécutée avec succès. Utilisez les constantes du `cfnresponse` pour spécifier le statut `SUCCESS` pour les exécutions réussies et `FAILED` pour celles qui ont échoué.

`responseData`  
Champ `Data` de l'[objet de réponse](crpg-ref.md#crpg-ref-responses) d'une ressource personnalisée. Les données sont une liste de paires nom-valeur.

`physicalResourceId`  
Facultatif. Identifiant unique de la ressource personnalisée qui appelé la fonction. Par défaut, le module utilise le nom du flux de journal Amazon CloudWatch Logs associé à la fonction Lambda.  
La valeur renvoyée pour un `PhysicalResourceId` peut modifier les opérations de mise à jour des ressources personnalisées. Si la valeur renvoyée est la même, on considère qu'il s'agit d'une mise à jour normale. Si la valeur renvoyée est différente, CloudFormation reconnaît la mise à jour comme un remplacement et envoie une demande de suppression à l'ancienne ressource. Pour de plus amples informations, veuillez consulter [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudformation-customresource.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudformation-customresource.html).

`noEcho`  
Facultatif. Indique s'il faut masquer la sortie de la ressource personnalisée lorsque celle-ci est récupérée à l'aide de la fonction `Fn::GetAtt`. Si cette valeur est définie sur `true`, toutes les valeurs renvoyées sont masquées par des astérisques (\$1\$1\$1\$1\$1), à l'exception des informations stockées dans les emplacements spécifiés ci-dessous. Cette valeur est `false` par défaut.  
L'utilisation de l'attribut `NoEcho` ne masque aucune information stockée dans les lieux suivants :  
+ La section des `Metadata` modèles. CloudFormation ne transforme, ne modifie ni n'expédie aucune information que vous incluez dans `Metadata` cette section. Pour de plus amples informations, veuillez consulter [Métadonnées](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/metadata-section-structure.html).
+ La section de modèle `Outputs` Pour de plus amples informations, veuillez consulter [Sorties](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html)
+ L’attribut `Metadata` d'une définition de ressource. Pour plus d'informations, voir la section consécrée à l'[Attribut `Metadata`](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-attribute-metadata.html).
Nous vous recommandons vivement de ne pas utiliser ces mécanismes pour inclure des informations sensibles, telles que des mots de passe ou des secrets.
Pour plus d’informations sur l’utilisation de `NoEcho` pour masquer les informations sensibles, consultez la bonne pratique [N'incorporez pas d'informations d'identification dans vos modèles](security-best-practices.md#creds).

## Exemples
<a name="cfn-lambda-function-code-cfnresponsemodule-examples"></a>

### Node.js
<a name="cfn-lambda-function-code-zipfile-examplenodejs"></a>

Dans l'exemple Node.js suivant, la fonction Lambda en ligne multiplie une valeur d'entrée par 5. Les fonctions en ligne sont particulièrement utiles pour les fonctions de petite ampleur, car elles vous permettent de spécifier le code source directement dans le modèle au lieu de créer un package et de l'importer dans un compartiment Amazon S3. Cette fonction utilise la méthode `cfn-response` `send` pour renvoyer le résultat à la ressource personnalisée qui l'a appelée.

#### JSON
<a name="cfn-lambda-function-code-zipfile-examplenodejs.json"></a>

```
"ZipFile": { "Fn::Join": ["", [
  "var response = require('cfn-response');",
  "exports.handler = function(event, context) {",
  "  var input = parseInt(event.ResourceProperties.Input);",
  "  var responseData = {Value: input * 5};",
  "  response.send(event, context, response.SUCCESS, responseData);",
  "};"
]]}
```

#### YAML
<a name="cfn-lambda-function-code-zipfile-examplenodejs-yaml"></a>

```
ZipFile: >
  var response = require('cfn-response');
  exports.handler = function(event, context) {
    var input = parseInt(event.ResourceProperties.Input);
    var responseData = {Value: input * 5};
    response.send(event, context, response.SUCCESS, responseData);
  };
```

### Python
<a name="cfn-lambda-function-code-zipfile-examplepython"></a>

Dans l'exemple Python suivant, la fonction Lambda en ligne multiplie un entier par 5.

#### JSON
<a name="cfn-lambda-function-code-zipfile-examplepython.json"></a>

```
"ZipFile" : { "Fn::Join" : ["\n", [
  "import json",
  "import cfnresponse",
  "def handler(event, context):",
  "   responseValue = int(event['ResourceProperties']['Input']) * 5",
  "   responseData = {}",
  "   responseData['Data'] = responseValue",
  "   cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, \"CustomResourcePhysicalID\")"
]]}
```

#### YAML
<a name="cfn-lambda-function-code-zipfile-examplepython.yaml"></a>

```
ZipFile: |
  import json
  import cfnresponse
  def handler(event, context):
    responseValue = int(event['ResourceProperties']['Input']) * 5
    responseData = {}
    responseData['Data'] = responseValue
    cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, "CustomResourcePhysicalID")
```

## Code source du module
<a name="cfn-lambda-function-code-cfnresponsemodule-source"></a>

**Topics**
+ [Code source Node.js asynchrone](#cfn-lambda-function-code-cfnresponsemodule-source-nodejs-async)
+ [Code source Node.js](#cfn-lambda-function-code-cfnresponsemodule-source-nodejs)
+ [Code source Python](#cfn-lambda-function-code-cfnresponsemodule-source-python)

### Code source Node.js asynchrone
<a name="cfn-lambda-function-code-cfnresponsemodule-source-nodejs-async"></a>

Le code suivant représente le module de réponse pour les fonctions Node.js lorsque le gestionnaire est asynchrone. Examinez-le pour comprendre ce que fait le module et pour vous aider à mettre en œuvre vos propres fonctions de réponse.

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: MIT-0

exports.SUCCESS = "SUCCESS";
exports.FAILED = "FAILED";

exports.send = function(event, context, responseStatus, responseData, physicalResourceId, noEcho) {

    return new Promise((resolve, reject) => {
        var responseBody = JSON.stringify({
            Status: responseStatus,
            Reason: "See the details in CloudWatch Log Stream: " + context.logStreamName,
            PhysicalResourceId: physicalResourceId || context.logStreamName,
            StackId: event.StackId,
            RequestId: event.RequestId,
            LogicalResourceId: event.LogicalResourceId,
            NoEcho: noEcho || false,
            Data: responseData
        });

        console.log("Response body:\n", responseBody);

        var https = require("https");
        var url = require("url");

        var parsedUrl = url.parse(event.ResponseURL);
        var options = {
            hostname: parsedUrl.hostname,
            port: 443,
            path: parsedUrl.path,
            method: "PUT",
            headers: {
                "content-type": "",
                "content-length": responseBody.length
            }
        };

        var request = https.request(options, function(response) {
            console.log("Status code: " + parseInt(response.statusCode));
            resolve(context.done());
        });

        request.on("error", function(error) {
            console.log("send(..) failed executing https.request(..): " + maskCredentialsAndSignature(error));
            reject(context.done(error));
        });

        request.write(responseBody);
        request.end();
    })
}
 
function maskCredentialsAndSignature(message) {
    return message.replace(/X-Amz-Credential=[^&\s]+/i, 'X-Amz-Credential=*****')
        .replace(/X-Amz-Signature=[^&\s]+/i, 'X-Amz-Signature=*****');
}
```

### Code source Node.js
<a name="cfn-lambda-function-code-cfnresponsemodule-source-nodejs"></a>

Le code suivant représente le module de réponse pour les fonctions Node.js lorsque le gestionnaire n’est pas asynchrone. Examinez-le pour comprendre ce que fait le module et pour vous aider à mettre en œuvre vos propres fonctions de réponse.

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: MIT-0
 
exports.SUCCESS = "SUCCESS";
exports.FAILED = "FAILED";

exports.send = function(event, context, responseStatus, responseData, physicalResourceId, noEcho) {

    var responseBody = JSON.stringify({
        Status: responseStatus,
        Reason: "See the details in CloudWatch Log Stream: " + context.logStreamName,
        PhysicalResourceId: physicalResourceId || context.logStreamName,
        StackId: event.StackId,
        RequestId: event.RequestId,
        LogicalResourceId: event.LogicalResourceId,
        NoEcho: noEcho || false,
        Data: responseData
    });

    console.log("Response body:\n", responseBody);

    var https = require("https");
    var url = require("url");

    var parsedUrl = url.parse(event.ResponseURL);
    var options = {
        hostname: parsedUrl.hostname,
        port: 443,
        path: parsedUrl.path,
        method: "PUT",
        headers: {
            "content-type": "",
            "content-length": responseBody.length
        }
    };

    var request = https.request(options, function(response) {
        console.log("Status code: " + parseInt(response.statusCode));
        context.done();
    });

    request.on("error", function(error) {
        console.log("send(..) failed executing https.request(..): " + maskCredentialsAndSignature(error));
        context.done();
    });

    request.write(responseBody);
    request.end();
}
```

### Code source Python
<a name="cfn-lambda-function-code-cfnresponsemodule-source-python"></a>

Le code suivant représente le module de réponse pour les fonctions Python :

```
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0
 
from __future__ import print_function
import urllib3
import json
import re

SUCCESS = "SUCCESS"
FAILED = "FAILED"

http = urllib3.PoolManager()


def send(event, context, responseStatus, responseData, physicalResourceId=None, noEcho=False, reason=None):
    responseUrl = event['ResponseURL']

    responseBody = {
        'Status' : responseStatus,
        'Reason' : reason or "See the details in CloudWatch Log Stream: {}".format(context.log_stream_name),
        'PhysicalResourceId' : physicalResourceId or context.log_stream_name,
        'StackId' : event['StackId'],
        'RequestId' : event['RequestId'],
        'LogicalResourceId' : event['LogicalResourceId'],
        'NoEcho' : noEcho,
        'Data' : responseData
    }

    json_responseBody = json.dumps(responseBody)

    print("Response body:")
    print(json_responseBody)

    headers = {
        'content-type' : '',
        'content-length' : str(len(json_responseBody))
    }

    try:
        response = http.request('PUT', responseUrl, headers=headers, body=json_responseBody)
        print("Status code:", response.status)


    except Exception as e:

        print("send(..) failed executing http.request(..):", mask_credentials_and_signature(e))
 
 
def mask_credentials_and_signature(message):
    message = re.sub(r'X-Amz-Credential=[^&\s]+', 'X-Amz-Credential=*****', message, flags=re.IGNORECASE)
    return re.sub(r'X-Amz-Signature=[^&\s]+', 'X-Amz-Signature=*****', message, flags=re.IGNORECASE)
```