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
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.
Rubriques
Prérequis
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.
Vue d'ensemble des fichiers de tests unitaires Guard
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 unitairesmy_rules_tests.yaml.
Syntaxe
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
Voici les propriétés d'un fichier de test Guard.
input-
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-
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: PASSObligatoire : oui
-
Procédure pas à pas de rédaction d'un fichier de test unitaire des règles Guard
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 allAWS::ApiGateway::RestApiresources # present in theResourcessection of the template. # let api_gws = Resources.*[ Type == 'AWS::ApiGateway::RestApi'] # # Rule intent: # 1) AllAWS::ApiGateway::RestApiresources deployed must be private. # 2) AllAWS::ApiGateway::RestApiresources 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 noAWS::ApiGateway::RestApiresources in the template. # 2) PASS when: # ALLAWS::ApiGateway::RestApiresources in the template have theEndpointConfigurationproperty set toType:PRIVATE. # ALLAWS::ApiGateway::RestApiresources in the template have one IAM condition key specified in thePolicyproperty withaws:sourceVpcor: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 { # # ALLAWS::ApiGateway::RestApiresources in the template have one IAM condition key specified in thePolicyproperty with #aws:sourceVpcor: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.
-
Créez un fichier de test unitaire appelé
api_gateway_private_tests.yamlqui contient le test initial suivant. Lors du test initial, ajoutez une entrée vide et attendez-vous à ce que la règlecheck_rest_api_is_privatesoit ignorée car il n'y a aucuneAWS::ApiGateway::RestApiressource en entrée.--- - name: MyTest1 input: {} expectations: rules: check_rest_api_is_private: SKIP -
Exécutez le premier test dans votre terminal à l'aide de la
testcommande. Pour le--rules-fileparamètre, spécifiez votre fichier de règles. Pour le--test-dataparamètre, spécifiez votre fichier de test unitaire.cfn-guard test --rules-file api_gateway_private.guard --test-data api_gateway_private_tests.yamlLe résultat du premier test est
PASS.Test Case #1 Name: "MyTest1" PASS Rules: check_rest_api_is_private: Expected = SKIP, Evaluated = SKIP -
Ajoutez un autre test à votre fichier de tests unitaires. Maintenant, étendez les tests pour inclure les ressources vides. Le
api_gateway_private_tests.yamlfichier 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 -
Exécutez
testavec le fichier de test unitaire mis à jour.cfn-guard test --rules-file api_gateway_private.guard --test-data api_gateway_private_tests.yamlLe 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 -
Ajoutez deux autres tests à votre fichier de tests unitaires. Étendez les tests pour inclure les éléments suivants :
-
AWS::ApiGateway::RestApiRessource 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
EndpointConfigurationpropriété n'est pas spécifiée et n'est donc pas définie surPRIVATE. -
AWS::ApiGateway::RestApiRessource qui répond à la première intention avec laEndpointConfigurationpropriété définie sur,PRIVATEmais 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 -
-
Exécutez
testavec 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'estPASS.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 -
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 -
Vérifiez les résultats de l'évaluation en exécutant la
testcommande dans votre terminal à l'aide de l'--verboseindicateur. 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é unPASSrésultat.cfn-guard test --rules-file api_gateway_private.guard --test-data api_gateway_private_tests.yaml \ --verboseVoici 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'Typesattendait à 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. -
Ajoutez un scénario de test tel que le quatrième scénario de test à votre fichier de test unitaire pour une
AWS::ApiGateway::RestApiressource dont laEndpointConfigurationproprié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 -
Exécutez la
testcommande avec le fichier de test unitaire mis à jour à l'aide de l'--verboseindicateur.cfn-guard test --rules-file api_gateway_private.guard --test-data api_gateway_private_tests.yaml \ --verboseLe résultat est
FAILconforme aux attentes carREGIONALil est spécifiéEndpointConfigurationmais 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
testcommande 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 existewhendes conditions contraires à la règle, elles apparaissent dans un bloc de conditions frère. Dans l'exemple suivant, la condition%api_gws !emptyest 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_gwsest une règle de blocage qui correspond auBlockClauseniveau 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.ORLa 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/1indique quelles valeurs de l'entrée sont comparées. Dans ce cas, il s'agit de l'élément àTypesindexer à 1.
DansValidation des données d'entrée par rapport aux règles Guard, 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.