

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

# AWS CloudFormation Guard Reglas de prueba
<a name="testing-rules"></a>

Puede utilizar el marco de pruebas unitarias AWS CloudFormation Guard integrado para comprobar que las reglas de Guard funcionan según lo previsto. En esta sección se proporciona un tutorial sobre cómo escribir un archivo de pruebas unitarias y cómo usarlo para probar el archivo de reglas con el `test` comando.

El archivo de prueba unitaria debe tener una de las siguientes extensiones: `.json``.JSON`,`.jsn`, `.yaml``.YAML`, o`.yml`.

**Topics**
+ [Requisitos previos](#testing-rules-prerequisites)
+ [Descripción general de los archivos de pruebas de las unidades Guard](#testing-rules-overview)
+ [Tutorial sobre cómo escribir un archivo de pruebas unitarias con las reglas de Guard](#testing-rules-example)

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

Escribe reglas de Guard para evaluar tus datos de entrada con ellas. Para obtener más información, consulte [Reglas de Writing Guard](writing-rules.md).

## Descripción general de los archivos de pruebas de las unidades Guard
<a name="testing-rules-overview"></a>

Los archivos de pruebas unitarias de Guard son archivos con formato JSON o YAML que contienen múltiples entradas y los resultados esperados de las reglas escritas en un archivo de reglas de Guard. Puede haber varios ejemplos para evaluar diferentes expectativas. Le recomendamos que comience por comprobar si hay entradas vacías y, a continuación, vaya añadiendo información de forma progresiva para evaluar las distintas reglas y cláusulas.

Además, le recomendamos que nombre los archivos de pruebas unitarias con el sufijo `_test.json` o`_tests.yaml`. Por ejemplo, si tiene un nombre para un archivo de reglas`my_rules.guard`, asígnele un nombre al archivo `my_rules_tests.yaml` de pruebas unitarias.

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

A continuación se muestra la sintaxis de un archivo de pruebas unitarias en formato YAML.

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

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

A continuación se muestran las propiedades de un archivo de prueba de Guard.

`input`  <a name="testing-rules-properties-input"></a>
Datos con los que poner a prueba tus reglas. Recomendamos que la primera prueba utilice una entrada vacía, como se muestra en el siguiente ejemplo.  

```
---
- name: MyTest1
  input {}
```
Para las pruebas posteriores, añada los datos de entrada a la prueba.  
 *Obligatorio*: sí 

`expectations`  <a name="testing-rules-properties-expectations"></a>
El resultado esperado cuando se evalúan reglas específicas en función de los datos de entrada. Especifique una o varias reglas que desee probar además del resultado esperado para cada regla. El resultado esperado debe ser uno de los siguientes:  
+ `PASS`— Cuando se comparan con los datos de entrada, las reglas se evalúan como `true`
+ `FAIL`— Cuando se comparan con los datos de entrada, las reglas se evalúan como `false`
+ `SKIP`— Cuando se ejecuta con los datos de entrada, la regla no se activa.

```
expectations:
    rules:
      check_rest_api_is_private: PASS
```
 *Obligatorio*: sí 

## Tutorial sobre cómo escribir un archivo de pruebas unitarias con las reglas de Guard
<a name="testing-rules-example"></a>

El siguiente es un archivo de reglas llamado`api_gateway_private.guard`. El objetivo de esta regla es comprobar si todos los tipos de recursos de Amazon API Gateway definidos en una CloudFormation plantilla se implementan únicamente para acceso privado. También comprueba si al menos una declaración de política permite el acceso desde una nube privada virtual (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 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
            }
        }
    }
}
```

Este tutorial pone a prueba el propósito de la primera regla: todos los `AWS::ApiGateway::RestApi` recursos desplegados deben ser privados.

1. Cree un archivo de pruebas unitarias denominado `api_gateway_private_tests.yaml` que contenga la siguiente prueba inicial. Con la prueba inicial, agrega una entrada vacía y espera que la regla `check_rest_api_is_private` se omita porque no hay `AWS::ApiGateway::RestApi` recursos como entradas.

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

1. Ejecuta la primera prueba en tu terminal con el `test` comando. Para el `--rules-file` parámetro, especifique su archivo de reglas. Para el `--test-data` parámetro, especifique el archivo de pruebas unitarias.

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

   El resultado de la primera prueba es`PASS`.

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

1. Añada otra prueba a su archivo de pruebas unitarias. Ahora, amplíe las pruebas para incluir los recursos vacíos. El siguiente es el `api_gateway_private_tests.yaml` archivo actualizado.

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

1. Ejecute `test` con el archivo de pruebas unitarias actualizado.

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

   El resultado de la segunda prueba es`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. Añada dos pruebas más a su archivo de pruebas unitarias. Amplíe las pruebas para incluir lo siguiente:
   + Un `AWS::ApiGateway::RestApi` recurso sin propiedades especificadas.
**nota**  
No es una CloudFormation plantilla válida, pero es útil para comprobar si la regla funciona correctamente incluso con entradas con formato incorrecto.

     Es de esperar que esta prueba falle porque la `EndpointConfiguration` propiedad no está especificada y, por lo tanto, no está configurada en. `PRIVATE`
   + Un `AWS::ApiGateway::RestApi` recurso que cumple con la primera intención con la `EndpointConfiguration` propiedad establecida en`PRIVATE`, pero no cumple con la segunda porque no tiene ninguna declaración de política definida. Espere que esta prueba pase.

   El siguiente es el archivo de pruebas unitarias actualizado.

   ```
   ---
   - 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. Ejecute `test` con el archivo de pruebas unitarias actualizado.

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

   El tercer resultado es `FAIL` y el cuarto resultado es`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. Comenta las pruebas 1 a 3 en tu archivo de pruebas unitarias. Acceda al contexto detallado solo para la cuarta prueba. El siguiente es el archivo de pruebas unitarias actualizado.

   ```
   ---
   #- 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. Inspeccione los resultados de la evaluación ejecutando el `test` comando en su terminal, utilizando el `--verbose` indicador. El contexto detallado es útil para entender las evaluaciones. En este caso, proporciona información detallada sobre por qué la cuarta prueba tuvo éxito y obtuvo un `PASS` resultado.

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

   Este es el resultado de esa ejecución.

   ```
   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 observación clave del resultado es la línea`Clause(Location[file:api_gateway_private.guard, line:22, column:5], Check: Properties.EndpointConfiguration.Types[*] EQUALS String("PRIVATE")), PASS)`, que indica que la comprobación ha sido aprobada. El ejemplo también mostró el caso en el que se `Types` esperaba que fuera una matriz, pero se proporcionó un único valor. En ese caso, Guard continuó la evaluación y proporcionó un resultado correcto.

1. Agregue un caso de prueba como el cuarto caso de prueba a su archivo de pruebas unitarias para un `AWS::ApiGateway::RestApi` recurso con la `EndpointConfiguration` propiedad especificada. El caso de prueba fallará en lugar de aprobarse. El siguiente es el archivo de pruebas unitarias actualizado.

   ```
   ---
   #- 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. Ejecute el `test` comando con el archivo de pruebas unitarias actualizado utilizando el `--verbose` indicador.

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

   El resultado es `FAIL` el esperado porque `REGIONAL` se ha especificado para`EndpointConfiguration`, pero no se espera.

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

   El resultado detallado del `test` comando sigue la estructura del archivo de reglas. Cada bloque del archivo de reglas es un bloque de la salida detallada. El bloque más alto es cada regla. Si hay `when` condiciones que no cumplan con la regla, aparecen en un bloque de condiciones similar. En el siguiente ejemplo, la condición `%api_gws !empty` se prueba y se aprueba.

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

   Una vez que se cumple la condición, probamos las cláusulas de la regla.

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

   `%api_gws`es una regla de bloqueo que corresponde al `BlockClause` nivel de la salida (línea:21). La cláusula de regla es un conjunto de cláusulas de conjunción (AND), donde cada cláusula de conjunción es un conjunto de disyunciones. `OR` La conjunción tiene una sola cláusula,. `Properties.EndpointConfiguration.Types[*] == "PRIVATE"` Por lo tanto, el resultado detallado muestra una sola cláusula. La ruta `/Resources/apiGw/Properties/EndpointConfiguration/Types/1` muestra qué valores de la entrada se comparan, que en este caso es el elemento `Types` indexado en 1.

En[Validar los datos de entrada según las reglas de Guard](validating-rules.md), puede usar los ejemplos de esta sección para usar el `validate` comando para evaluar los datos de entrada según las reglas.