

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

# AWS CloudFormation Guard Regeln für Tests
<a name="testing-rules"></a>

Sie können das AWS CloudFormation Guard integrierte Unit-Test-Framework verwenden, um zu überprüfen, ob Ihre Guard-Regeln wie vorgesehen funktionieren. In diesem Abschnitt erfahren Sie, wie Sie eine Unit-Test-Datei schreiben und wie Sie damit Ihre Regeldatei mit dem `test` Befehl testen können.

Ihre Unit-Test-Datei muss eine der folgenden Erweiterungen haben:`.json`,`.JSON`,`.jsn`, `.yaml``.YAML`, oder`.yml`.

**Topics**
+ [Voraussetzungen](#testing-rules-prerequisites)
+ [Überblick über die Guard-Unit-Testdateien](#testing-rules-overview)
+ [Exemplarische Vorgehensweise zum Schreiben einer Unit-Test-Datei für Guard-Regeln](#testing-rules-example)

## Voraussetzungen
<a name="testing-rules-prerequisites"></a>

Schreiben Sie Guard-Regeln, anhand derer Ihre Eingabedaten ausgewertet werden. Weitere Informationen finden Sie unter [Writing Guard-Regeln](writing-rules.md).

## Überblick über die Guard-Unit-Testdateien
<a name="testing-rules-overview"></a>

Guard-Unit-Testdateien sind Dateien im JSON- oder YAML-Format, die mehrere Eingaben und die erwarteten Ergebnisse für Regeln enthalten, die in einer Guard-Regeldatei geschrieben sind. Es kann mehrere Stichproben geben, um unterschiedliche Erwartungen zu bewerten. Wir empfehlen, zunächst auf leere Eingaben zu testen und dann nach und nach Informationen zur Bewertung verschiedener Regeln und Klauseln hinzuzufügen.

Außerdem empfehlen wir, Unit-Testing-Dateien mit dem Suffix `_test.json` oder zu benennen. `_tests.yaml` Wenn Sie beispielsweise eine Regeldatei mit dem Namen haben`my_rules.guard`, geben Sie Ihrer Unit-Test-Datei `my_rules_tests.yaml` einen Namen.

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

Im Folgenden wird die Syntax einer Unit-Test-Datei im YAML-Format gezeigt.

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

### Eigenschaften
<a name="testing-rules-properties"></a>

Im Folgenden sind die Eigenschaften einer Guard-Testdatei aufgeführt.

`input`  <a name="testing-rules-properties-input"></a>
Daten, anhand derer Sie Ihre Regeln testen können. Wir empfehlen, dass Ihr erster Test eine leere Eingabe verwendet, wie im folgenden Beispiel gezeigt.  

```
---
- name: MyTest1
  input {}
```
Fügen Sie für nachfolgende Tests Eingabedaten zum Test hinzu.  
 *Erforderlich*: Ja 

`expectations`  <a name="testing-rules-properties-expectations"></a>
Das erwartete Ergebnis, wenn bestimmte Regeln anhand Ihrer Eingabedaten bewertet werden. Geben Sie eine oder mehrere Regeln an, die Sie zusätzlich zum erwarteten Ergebnis für jede Regel testen möchten. Das erwartete Ergebnis muss eines der folgenden sein:  
+ `PASS`— Bei der Ausführung mit Ihren Eingabedaten werden die Regeln wie folgt ausgewertet`true`.
+ `FAIL`— Bei der Ausführung mit Ihren Eingabedaten werden die Regeln wie folgt ausgewertet`false`.
+ `SKIP`— Wenn die Regel anhand Ihrer Eingabedaten ausgeführt wird, wird sie nicht ausgelöst.

```
expectations:
    rules:
      check_rest_api_is_private: PASS
```
 *Erforderlich*: Ja 

## Exemplarische Vorgehensweise zum Schreiben einer Unit-Test-Datei für Guard-Regeln
<a name="testing-rules-example"></a>

Im Folgenden finden Sie eine Regeldatei mit dem Namen`api_gateway_private.guard`. Mit dieser Regel soll überprüft werden, ob alle in einer CloudFormation Vorlage definierten Amazon API Gateway Gateway-Ressourcentypen nur für den privaten Zugriff bereitgestellt werden. Außerdem wird geprüft, ob mindestens eine Richtlinienerklärung den Zugriff von einer Virtual Private Cloud (VPC) aus erlaubt.

```
#
# 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 AWS Identity and Access Management (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
            }
        }
    }
}
```

In dieser exemplarischen Vorgehensweise wird die Absicht der ersten Regel getestet: Alle bereitgestellten `AWS::ApiGateway::RestApi` Ressourcen müssen privat sein.

1. Erstellen Sie eine Unit-Test-Datei mit dem Namen`api_gateway_private_tests.yaml`, die den folgenden ersten Test enthält. Fügen Sie beim ersten Test eine leere Eingabe hinzu und gehen Sie davon aus, dass die Regel übersprungen `check_rest_api_is_private` wird, da keine `AWS::ApiGateway::RestApi` Ressourcen als Eingaben vorhanden sind.

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

1. Führen Sie den ersten Test in Ihrem Terminal mit dem `test` Befehl aus. Geben Sie für den `--rules-file` Parameter Ihre Regeldatei an. Geben Sie für den `--test-data` Parameter Ihre Unit-Test-Datei an.

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

   Das Ergebnis des ersten Tests ist`PASS`.

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

1. Fügen Sie Ihrer Unit-Test-Datei einen weiteren Test hinzu. Erweitern Sie nun den Test auf leere Ressourcen. Das Folgende ist die aktualisierte `api_gateway_private_tests.yaml` Datei.

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

1. Führen Sie es `test` mit der aktualisierten Unit-Test-Datei aus.

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

   Das Ergebnis für den zweiten Test ist`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. Fügen Sie Ihrer Unit-Test-Datei zwei weitere Tests hinzu. Erweitern Sie die Tests um Folgendes:
   + Eine `AWS::ApiGateway::RestApi` Ressource ohne angegebene Eigenschaften.
**Anmerkung**  
Dies ist keine gültige CloudFormation Vorlage, aber es ist nützlich, um zu testen, ob die Regel auch bei falsch formatierten Eingaben korrekt funktioniert.

     Gehen Sie davon aus, dass dieser Test fehlschlägt, weil die `EndpointConfiguration` Eigenschaft nicht angegeben und daher nicht auf `PRIVATE` gesetzt ist.
   + Eine `AWS::ApiGateway::RestApi` Ressource, die die erste Absicht erfüllt, wenn die `EndpointConfiguration` Eigenschaft auf gesetzt ist, `PRIVATE` aber die zweite Absicht nicht erfüllt, da für sie keine Richtlinienaussagen definiert sind. Erwarten Sie, dass dieser Test bestanden wird.

   Im Folgenden finden Sie die aktualisierte Unit-Test-Datei.

   ```
   ---
   - 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. Führen Sie es `test` mit der aktualisierten Unit-Test-Datei aus.

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

   Das dritte Ergebnis ist`FAIL`, und das vierte Ergebnis ist`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. Kommentieren Sie die Tests 1—3 in Ihrer Unit-Test-Datei aus. Greifen Sie nur für den vierten Test auf den ausführlichen Kontext zu. Im Folgenden finden Sie die aktualisierte Unit-Test-Datei.

   ```
   ---
   #- 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. Überprüfen Sie die Evaluierungsergebnisse, indem Sie den `test` Befehl in Ihrem Terminal ausführen und dabei das `--verbose` Flag verwenden. Ein ausführlicher Kontext ist nützlich, um Bewertungen zu verstehen. In diesem Fall enthält es detaillierte Informationen darüber, warum der vierte Test erfolgreich war und ein `PASS` Ergebnis hatte.

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

   Hier ist die Ausgabe dieses Durchlaufs.

   ```
   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)
   ```

   Die wichtigste Beobachtung aus der Ausgabe ist die Zeile`Clause(Location[file:api_gateway_private.guard, line:22, column:5], Check: Properties.EndpointConfiguration.Types[*] EQUALS String("PRIVATE")), PASS)`, die besagt, dass die Prüfung bestanden wurde. Das Beispiel zeigte auch den Fall, dass ein Array erwartet `Types` wurde, aber ein einziger Wert angegeben wurde. In diesem Fall führte Guard die Auswertung fort und lieferte ein korrektes Ergebnis.

1. Fügen Sie Ihrer Komponententestdatei für eine `AWS::ApiGateway::RestApi` Ressource mit der angegebenen `EndpointConfiguration` Eigenschaft einen Testfall wie den vierten Testfall hinzu. Der Testfall schlägt fehl, anstatt erfolgreich zu sein. Im Folgenden finden Sie die aktualisierte Unit-Test-Datei.

   ```
   ---
   #- 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. Führen Sie den `test` Befehl mit der aktualisierten Unit-Test-Datei mithilfe des `--verbose` Flags aus.

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

   Das Ergebnis ist `FAIL` erwartungsgemäß, da `REGIONAL` es für angegeben wurde`EndpointConfiguration`, aber nicht erwartet wird.

   ```
   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)
   ```

   Die ausführliche Ausgabe des `test` Befehls folgt der Struktur der Regeldatei. Jeder Block in der Regeldatei ist ein Block in der ausführlichen Ausgabe. Der oberste Block ist jede Regel. Wenn es `when` Bedingungen gibt, die gegen die Regel verstoßen, werden sie in einem gleichgeordneten Bedingungsblock angezeigt. Im folgenden Beispiel `%api_gws !empty` wird die Bedingung getestet und sie besteht.

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

   Sobald die Bedingung erfüllt ist, testen wir die Regelklauseln.

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

   `%api_gws`ist eine Blockregel, die dem `BlockClause` Level in der Ausgabe entspricht (Zeile:21). Die Regelklausel besteht aus einer Reihe von Konjunktionsklauseln (AND), wobei jede Konjunktionsklausel eine Menge von Disjunktionen ist. `OR` Die Konjunktion hat eine einzige Klausel,. `Properties.EndpointConfiguration.Types[*] == "PRIVATE"` Daher enthält die ausführliche Ausgabe eine einzige Klausel. Der Pfad `/Resources/apiGw/Properties/EndpointConfiguration/Types/1` zeigt, welche Werte in der Eingabe verglichen werden. In diesem Fall handelt es sich um das Element für den `Types` Index 1.

In können Sie die Beispiele in diesem Abschnitt verwenden[Validierung der Eingabedaten anhand der Guard-Regeln](validating-rules.md), um den `validate` Befehl zu verwenden, um Eingabedaten anhand von Regeln auszuwerten.