

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.

# AWS CloudFormation Guard Règles de test
<a name="testing-rules"></a>

Vous pouvez utiliser le cadre de test unitaire AWS CloudFormation Guard intégré pour vérifier que vos règles Guard fonctionnent comme prévu. Cette section explique comment écrire un fichier de test unitaire et comment l'utiliser pour tester votre fichier de règles à l'aide de la `test` commande.

Votre fichier de test unitaire doit avoir l'une des extensions suivantes : `.json``.JSON`,`.jsn`,`.yaml`,`.YAML`, ou`.yml`.

**Topics**
+ [Conditions préalables](#testing-rules-prerequisites)
+ [Vue d'ensemble des fichiers de tests unitaires Guard](#testing-rules-overview)
+ [Procédure pas à pas de rédaction d'un fichier de test unitaire des règles Guard](#testing-rules-example)

## Conditions préalables
<a name="testing-rules-prerequisites"></a>

Rédigez des règles de garde pour évaluer vos données d'entrée. Pour de plus amples informations, veuillez consulter [Règles de Writing Guard](writing-rules.md).

## Vue d'ensemble des fichiers de tests unitaires Guard
<a name="testing-rules-overview"></a>

Les fichiers de test unitaire Guard sont des fichiers au format JSON ou YAML qui contiennent plusieurs entrées et les résultats attendus pour les règles écrites dans un fichier de règles Guard. Il peut y avoir plusieurs échantillons pour évaluer les différentes attentes. Nous vous recommandons de commencer par tester les entrées vides, puis d'ajouter progressivement des informations pour évaluer les différentes règles et clauses.

Nous vous recommandons également de nommer les fichiers de tests unitaires en utilisant le suffixe `_test.json` ou`_tests.yaml`. Par exemple, si vous avez un fichier de règles nommé`my_rules.guard`, nommez votre fichier de tests unitaires`my_rules_tests.yaml`.

### Syntaxe
<a name="testing-rules-syntax"></a>

Ce qui suit montre la syntaxe d'un fichier de test unitaire au format YAML.

```
---
- name: <TEST NAME>
  input:
     <SAMPLE INPUT>
   expectations:
     rules:
       <RULE NAME>: [PASS|FAIL|SKIP]
```

### Propriétés
<a name="testing-rules-properties"></a>

Voici les propriétés d'un fichier de test Guard.

`input`  <a name="testing-rules-properties-input"></a>
Des données pour tester vos règles. Nous recommandons que votre premier test utilise une entrée vide, comme illustré dans l'exemple suivant.  

```
---
- name: MyTest1
  input {}
```
Pour les tests suivants, ajoutez les données d'entrée à tester.  
 *Obligatoire* : oui 

`expectations`  <a name="testing-rules-properties-expectations"></a>
Le résultat attendu lorsque des règles spécifiques sont évaluées par rapport à vos données d'entrée. Spécifiez une ou plusieurs règles que vous souhaitez tester en plus du résultat attendu pour chaque règle. Le résultat attendu doit être l'un des suivants :  
+ `PASS`— Lorsqu'elles sont exécutées par rapport à vos données d'entrée, les règles sont évaluées à`true`.
+ `FAIL`— Lorsqu'elles sont exécutées par rapport à vos données d'entrée, les règles sont évaluées à`false`.
+ `SKIP`— Lorsqu'elle est exécutée sur vos données d'entrée, la règle n'est pas déclenchée.

```
expectations:
    rules:
      check_rest_api_is_private: PASS
```
 *Obligatoire* : oui 

## Procédure pas à pas de rédaction d'un fichier de test unitaire des règles Guard
<a name="testing-rules-example"></a>

Voici un fichier de règles nommé`api_gateway_private.guard`. Le but de cette règle est de vérifier si tous les types de ressources Amazon API Gateway définis dans un CloudFormation modèle sont déployés pour un accès privé uniquement. Il vérifie également si au moins une déclaration de politique autorise l'accès depuis un cloud privé virtuel (VPC).

```
#
# Select all AWS::ApiGateway::RestApi resources
#     present in the Resources section of the template. 
#
let api_gws = Resources.*[ Type == 'AWS::ApiGateway::RestApi']

#
# Rule intent:         
# 1) All AWS::ApiGateway::RestApi resources deployed must be private.                                            
# 2) All AWS::ApiGateway::RestApi resources deployed must have at least one Gestion des identités et des accès AWS (IAM) policy condition key to allow access from a VPC.
#
# Expectations:        
# 1) SKIP when there are no AWS::ApiGateway::RestApi resources in the template.  
# 2) PASS when:
#     ALL AWS::ApiGateway::RestApi resources in the template have the EndpointConfiguration property set to Type: PRIVATE. 
#     ALL AWS::ApiGateway::RestApi resources in the template have one IAM condition key specified in the Policy property with aws:sourceVpc or :SourceVpc.    
# 3) FAIL otherwise.                                                                                  
#
#

rule check_rest_api_is_private when %api_gws !empty {      
    %api_gws {
        Properties.EndpointConfiguration.Types[*] == "PRIVATE"                             
    }  
}       

rule check_rest_api_has_vpc_access when check_rest_api_is_private {
    %api_gws {
        Properties {
            #
            # ALL AWS::ApiGateway::RestApi resources in the template have one IAM condition key specified in the Policy property with 
            #     aws:sourceVpc or :SourceVpc
            #           
            some Policy.Statement[*] {
                Condition.*[ keys == /aws:[sS]ource(Vpc|VPC|Vpce|VPCE)/ ] !empty
            }
        }
    }
}
```

Cette procédure pas à pas teste l'intention de la première règle : toutes les `AWS::ApiGateway::RestApi` ressources déployées doivent être privées.

1. Créez un fichier de test unitaire appelé `api_gateway_private_tests.yaml` qui contient le test initial suivant. Lors du test initial, ajoutez une entrée vide et attendez-vous à ce que la règle `check_rest_api_is_private` soit ignorée car il n'y a aucune `AWS::ApiGateway::RestApi` ressource en entrée.

   ```
   ---
   - name: MyTest1
     input: {}
     expectations:
       rules:
         check_rest_api_is_private: SKIP
   ```

1. Exécutez le premier test dans votre terminal à l'aide de la `test` commande. Pour le `--rules-file` paramètre, spécifiez votre fichier de règles. Pour le `--test-data` paramètre, spécifiez votre fichier de test unitaire.

   ```
   cfn-guard test --rules-file api_gateway_private.guard --test-data api_gateway_private_tests.yaml
   ```

   Le résultat du premier test est`PASS`.

   ```
   Test Case #1
   Name: "MyTest1"
     PASS Rules:
       check_rest_api_is_private: Expected = SKIP, Evaluated = SKIP
   ```

1. Ajoutez un autre test à votre fichier de tests unitaires. Maintenant, étendez les tests pour inclure les ressources vides. Le `api_gateway_private_tests.yaml` fichier mis à jour est le suivant.

   ```
   ---
   - name: MyTest1
     input: {}
     expectations:
       rules:
         check_rest_api_is_private: SKIP
   - name: MyTest2
     input:
        Resources: {}
     expectations:
       rules:
         check_rest_api_is_private: SKIP
   ```

1. Exécutez `test` avec le fichier de test unitaire mis à jour.

   ```
   cfn-guard test --rules-file api_gateway_private.guard --test-data api_gateway_private_tests.yaml
   ```

   Le résultat du deuxième test est`PASS`.

   ```
   Test Case #1
   Name: "MyTest1"
     PASS Rules:
       check_rest_api_is_private: Expected = SKIP, Evaluated = SKIP
   Test Case #2
   Name: "MyTest2"
     PASS Rules:
       check_rest_api_is_private: Expected = SKIP, Evaluated = SKIP
   ```

1. Ajoutez deux autres tests à votre fichier de tests unitaires. Étendez les tests pour inclure les éléments suivants :
   + `AWS::ApiGateway::RestApi`Ressource dont aucune propriété n'est spécifiée.
**Note**  
Ce CloudFormation modèle n'est pas valide, mais il est utile pour vérifier si la règle fonctionne correctement, même pour des entrées mal formées.

     Attendez-vous à ce que ce test échoue car la `EndpointConfiguration` propriété n'est pas spécifiée et n'est donc pas définie sur`PRIVATE`.
   + `AWS::ApiGateway::RestApi`Ressource qui répond à la première intention avec la `EndpointConfiguration` propriété définie sur, `PRIVATE` mais ne satisfait pas à la seconde, car aucune déclaration de politique n'est définie pour elle. Attendez-vous à ce que ce test soit réussi.

   Le fichier de test unitaire mis à jour est le suivant.

   ```
   ---
   - name: MyTest1
     input: {}
     expectations:
       rules:
         check_rest_api_is_private: SKIP
   - name: MyTest2
     input:
        Resources: {}
     expectations:
       rules:
         check_rest_api_is_private: SKIP
   - name: MyTest3
     input:
       Resources: 
         apiGw:
           Type: AWS::ApiGateway::RestApi
     expectations:
       rules:
         check_rest_api_is_private: FAIL
   - name: MyTest4
     input:
       Resources: 
         apiGw:
           Type: AWS::ApiGateway::RestApi
           Properties:
             EndpointConfiguration:
               Types: "PRIVATE"
     expectations:
       rules:
         check_rest_api_is_private: PASS
   ```

1. Exécutez `test` avec le fichier de test unitaire mis à jour.

   ```
   cfn-guard test --rules-file api_gateway_private.guard --test-data api_gateway_private_tests.yaml \
   ```

   Le troisième résultat est`FAIL`, et le quatrième résultat l'est`PASS`.

   ```
   Test Case #1
   Name: "MyTest1"
     PASS Rules:
       check_rest_api_is_private: Expected = SKIP, Evaluated = SKIP
   
   Test Case #2
   Name: "MyTest2"
     PASS Rules:
       check_rest_api_is_private: Expected = SKIP, Evaluated = SKIP
   
   Test Case #3
   Name: "MyTest3"
     PASS Rules:
       check_rest_api_is_private: Expected = FAIL, Evaluated = FAIL
   
   Test Case #4
   Name: "MyTest4"
     PASS Rules:
       check_rest_api_is_private: Expected = PASS, Evaluated = PASS
   ```

1. Commentez les tests 1 à 3 dans votre fichier de tests unitaires. Accédez au contexte détaillé pour le quatrième test uniquement. Le fichier de test unitaire mis à jour est le suivant.

   ```
   ---
   #- name: MyTest1
   #  input: {}
   #  expectations:
   #    rules:
   #      check_rest_api_is_private_and_has_access: SKIP
   #- name: MyTest2
   #  input:
   #     Resources: {}
   #  expectations:
   #    rules:
   #      check_rest_api_is_private_and_has_access: SKIP
   #- name: MyTest3
   #  input:
   #    Resources: 
   #      apiGw:
   #        Type: AWS::ApiGateway::RestApi
   #  expectations:
   #    rules:
   #      check_rest_api_is_private_and_has_access: FAIL
   - name: MyTest4
     input:
       Resources: 
         apiGw:
           Type: AWS::ApiGateway::RestApi
           Properties:
             EndpointConfiguration:
               Types: "PRIVATE"
     expectations:
       rules:
         check_rest_api_is_private: PASS
   ```

1. Vérifiez les résultats de l'évaluation en exécutant la `test` commande dans votre terminal à l'aide de l'`--verbose`indicateur. Le contexte verbeux est utile pour comprendre les évaluations. Dans ce cas, il fournit des informations détaillées sur les raisons pour lesquelles le quatrième test a réussi et a donné un `PASS` résultat.

   ```
   cfn-guard test --rules-file api_gateway_private.guard --test-data api_gateway_private_tests.yaml \
     --verbose
   ```

   Voici le résultat de cette exécution.

   ```
   Test Case #1
   Name: "MyTest4"
     PASS Rules:
       check_rest_api_is_private: Expected = PASS, Evaluated = PASS
   Rule(check_rest_api_is_private, PASS)
       |  Message: DEFAULT MESSAGE(PASS)
       Condition(check_rest_api_is_private, PASS)
           |  Message: DEFAULT MESSAGE(PASS)
           Clause(Clause(Location[file:api_gateway_private.guard, line:20, column:37], Check: %api_gws NOT EMPTY ), PASS)
               |  From: Map((Path("/Resources/apiGw"), MapValue { keys: [String((Path("/Resources/apiGw/Type"), "Type")), String((Path("/Resources/apiGw/Properties"), "Properties"))], values: {"Type": String((Path("/Resources/apiGw/Type"), "AWS::ApiGateway::RestApi")), "Properties": Map((Path("/Resources/apiGw/Properties"), MapValue { keys: [String((Path("/Resources/apiGw/Properties/EndpointConfiguration"), "EndpointConfiguration"))], values: {"EndpointConfiguration": Map((Path("/Resources/apiGw/Properties/EndpointConfiguration"), MapValue { keys: [String((Path("/Resources/apiGw/Properties/EndpointConfiguration/Types"), "Types"))], values: {"Types": String((Path("/Resources/apiGw/Properties/EndpointConfiguration/Types"), "PRIVATE"))} }))} }))} }))
               |  Message: (DEFAULT: NO_MESSAGE)
       Conjunction(cfn_guard::rules::exprs::GuardClause, PASS)
           |  Message: DEFAULT MESSAGE(PASS)
           Clause(Clause(Location[file:api_gateway_private.guard, line:22, column:5], Check: Properties.EndpointConfiguration.Types[*]  EQUALS String("PRIVATE")), PASS)
               |  Message: (DEFAULT: NO_MESSAGE)
   ```

   La principale observation de la sortie est la ligne`Clause(Location[file:api_gateway_private.guard, line:22, column:5], Check: Properties.EndpointConfiguration.Types[*] EQUALS String("PRIVATE")), PASS)`, qui indique que le contrôle a été réussi. L'exemple a également montré le cas où l'on s'`Types`attendait à ce qu'il s'agisse d'un tableau, mais où une seule valeur a été donnée. Dans ce cas, Guard a poursuivi son évaluation et a fourni un résultat correct.

1. Ajoutez un scénario de test tel que le quatrième scénario de test à votre fichier de test unitaire pour une `AWS::ApiGateway::RestApi` ressource dont la `EndpointConfiguration` propriété est spécifiée. Le scénario de test échouera au lieu de réussir. Le fichier de test unitaire mis à jour est le suivant.

   ```
   ---
   #- name: MyTest1
   #  input: {}
   #  expectations:
   #    rules:
   #      check_rest_api_is_private_and_has_access: SKIP
   #- name: MyTest2
   #  input:
   #     Resources: {}
   #  expectations:
   #    rules:
   #      check_rest_api_is_private_and_has_access: SKIP
   #- name: MyTest3
   #  input:
   #    Resources: 
   #      apiGw:
   #        Type: AWS::ApiGateway::RestApi
   #  expectations:
   #    rules:
   #      check_rest_api_is_private_and_has_access: FAIL
   #- name: MyTest4
   #  input:
   #    Resources: 
   #      apiGw:
   #        Type: AWS::ApiGateway::RestApi
   #        Properties:
   #          EndpointConfiguration:
   #            Types: "PRIVATE"
   #  expectations:
   #    rules:
   #      check_rest_api_is_private: PASS
   - name: MyTest5
     input:
       Resources: 
         apiGw:
           Type: AWS::ApiGateway::RestApi
           Properties:
             EndpointConfiguration:
               Types: [PRIVATE, REGIONAL]
     expectations:
       rules:
         check_rest_api_is_private: FAIL
   ```

1. Exécutez la `test` commande avec le fichier de test unitaire mis à jour à l'aide de l'`--verbose`indicateur.

   ```
   cfn-guard test --rules-file api_gateway_private.guard --test-data api_gateway_private_tests.yaml \
    --verbose
   ```

   Le résultat est `FAIL` conforme aux attentes car `REGIONAL` il est spécifié `EndpointConfiguration` mais n'est pas attendu.

   ```
   Test Case #1
   Name: "MyTest5"
     PASS Rules: 
       check_rest_api_is_private: Expected = FAIL, Evaluated = FAIL
   Rule(check_rest_api_is_private, FAIL)
       |  Message: DEFAULT MESSAGE(FAIL)
       Condition(check_rest_api_is_private, PASS) 
           |  Message: DEFAULT MESSAGE(PASS)
           Clause(Clause(Location[file:api_gateway_private.guard, line:20, column:37], Check: %api_gws NOT EMPTY ), PASS)
               |  From: Map((Path("/Resources/apiGw"), MapValue { keys: [String((Path("/Resources/apiGw/Type"), "Type")), String((Path("/Resources/apiGw/Properties"), "Properties"))], values: {"Type": String((Path("/Resources/apiGw/Type"), "AWS::ApiGateway::RestApi")), "Properties": Map((Path("/Resources/apiGw/Properties"), MapValue { keys: [String((Path("/Resources/apiGw/Properties/EndpointConfiguration"), "EndpointConfiguration"))], values: {"EndpointConfiguration": Map((Path("/Resources/apiGw/Properties/EndpointConfiguration"), MapValue { keys: [String((Path("/Resources/apiGw/Properties/EndpointConfiguration/Types"), "Types"))], values: {"Types": List((Path("/Resources/apiGw/Properties/EndpointConfiguration/Types"), [String((Path("/Resources/apiGw/Properties/EndpointConfiguration/Types/0"), "PRIVATE")), String((Path("/Resources/apiGw/Properties/EndpointConfiguration/Types/1"), "REGIONAL"))]))} }))} }))} }))
               |  Message: DEFAULT MESSAGE(PASS)
       BlockClause(Block[Location[file:api_gateway_private.guard, line:21, column:3]], FAIL)
           |  Message: DEFAULT MESSAGE(FAIL)
           Conjunction(cfn_guard::rules::exprs::GuardClause, FAIL)
               |  Message: DEFAULT MESSAGE(FAIL)
               Clause(Clause(Location[file:api_gateway_private.guard, line:22, column:5], Check: Properties.EndpointConfiguration.Types[*]  EQUALS String("PRIVATE")), FAIL)
                   |  From: String((Path("/Resources/apiGw/Properties/EndpointConfiguration/Types/1"), "REGIONAL"))
                   |  To: String((Path("api_gateway_private.guard/22/5/Clause/"), "PRIVATE"))
                   |  Message: (DEFAULT: NO_MESSAGE)
   ```

   La sortie détaillée de la `test` commande suit la structure du fichier de règles. Chaque bloc du fichier de règles est un bloc de la sortie détaillée. Le bloc le plus élevé correspond à chaque règle. S'il existe `when` des conditions contraires à la règle, elles apparaissent dans un bloc de conditions frère. Dans l'exemple suivant, la condition `%api_gws !empty` est testée et elle passe.

   ```
   rule check_rest_api_is_private when %api_gws !empty {
   ```

   Une fois la condition remplie, nous testons les clauses des règles.

   ```
   %api_gws {
       Properties.EndpointConfiguration.Types[*] == "PRIVATE"                      
   }
   ```

   `%api_gws`est une règle de blocage qui correspond au `BlockClause` niveau de la sortie (ligne : 21). La clause de règle est un ensemble de clauses de conjonction (AND), chaque clause de conjonction étant un ensemble de disjonctions. `OR` La conjonction comporte une seule clause,`Properties.EndpointConfiguration.Types[*] == "PRIVATE"`. Par conséquent, la sortie détaillée affiche une seule clause. Le chemin `/Resources/apiGw/Properties/EndpointConfiguration/Types/1` indique quelles valeurs de l'entrée sont comparées. Dans ce cas, il s'agit de l'élément à `Types` indexer à 1.

Dans[Validation des données d'entrée par rapport aux règles Guard](validating-rules.md), vous pouvez utiliser les exemples de cette section pour utiliser la `validate` commande afin d'évaluer les données d'entrée par rapport aux règles.