As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.
AWS CloudFormation Guard Regras de teste
Você pode usar a estrutura de teste de unidade AWS CloudFormation Guard integrada para verificar se as regras do Guard funcionam conforme o esperado. Esta seção fornece uma explicação passo a passo sobre como escrever um arquivo de teste unitário e como usá-lo para testar seu arquivo de regras com o test comando.
Seu arquivo de teste de unidade deve ter uma das seguintes extensões:.json,.JSON,.jsn,.yaml,.YAML, ou.yml.
Tópicos
Pré-requisitos
Escreva as regras do Guard para avaliar seus dados de entrada. Para obter mais informações, consulte Regras do Writing Guard.
Visão geral dos arquivos de teste unitário do Guard
Os arquivos de teste de unidade do Guard são arquivos no formato JSON ou YAML que contêm várias entradas e os resultados esperados para regras escritas dentro de um arquivo de regras do Guard. Pode haver várias amostras para avaliar diferentes expectativas. Recomendamos que você comece testando entradas vazias e, em seguida, adicione progressivamente informações para avaliar várias regras e cláusulas.
Além disso, recomendamos que você nomeie os arquivos de teste de unidade usando o sufixo _test.json ou_tests.yaml. Por exemplo, se você tiver um arquivo de regras chamadomy_rules.guard, nomeie seu arquivo de teste de unidademy_rules_tests.yaml.
Sintaxe
Veja a seguir a sintaxe de um arquivo de teste de unidade no formato YAML.
--- - name: <TEST NAME> input: <SAMPLE INPUT> expectations: rules: <RULE NAME>: [PASS|FAIL|SKIP]
Propriedades
A seguir estão as propriedades de um arquivo de teste do Guard.
input-
Dados para testar suas regras. Recomendamos que seu primeiro teste use uma entrada vazia, conforme mostrado no exemplo a seguir.
--- - name: MyTest1 input {}Para testes subsequentes, adicione dados de entrada para testar.
Obrigatório: Sim
expectations-
O resultado esperado quando regras específicas são avaliadas em relação aos dados de entrada. Especifique uma ou várias regras que você deseja testar além do resultado esperado para cada regra. O resultado esperado deve ser um dos seguintes:
-
PASS— Quando executadas com base em seus dados de entrada, as regras são avaliadas comotrue. -
FAIL— Quando executadas com base em seus dados de entrada, as regras são avaliadas comofalse. -
SKIP— Quando executada com base nos dados de entrada, a regra não é acionada.
expectations: rules: check_rest_api_is_private: PASSObrigatório: Sim
-
Passo a passo da criação de um arquivo de teste unitário de regras do Guard
A seguir está um arquivo de regras chamadoapi_gateway_private.guard. A intenção dessa regra é verificar se todos os tipos de recursos do Amazon API Gateway definidos em um CloudFormation modelo são implantados somente para acesso privado. Também verifica se pelo menos uma declaração de política permite acesso a partir de uma nuvem privada virtual (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 } } } }
Este passo a passo testa a intenção da primeira regra: todos os AWS::ApiGateway::RestApi recursos implantados devem ser privados.
-
Crie um arquivo de teste unitário chamado
api_gateway_private_tests.yamlque contenha o seguinte teste inicial. Com o teste inicial, adicione uma entrada vazia e espere que a regracheck_rest_api_is_privateseja ignorada porque não háAWS::ApiGateway::RestApirecursos como entradas.--- - name: MyTest1 input: {} expectations: rules: check_rest_api_is_private: SKIP -
Execute o primeiro teste em seu terminal usando o
testcomando. Para o--rules-fileparâmetro, especifique seu arquivo de regras. Para o--test-dataparâmetro, especifique seu arquivo de teste de unidade.cfn-guard test --rules-file api_gateway_private.guard --test-data api_gateway_private_tests.yamlO resultado do primeiro teste é
PASS.Test Case #1 Name: "MyTest1" PASS Rules: check_rest_api_is_private: Expected = SKIP, Evaluated = SKIP -
Adicione outro teste ao seu arquivo de teste unitário. Agora, estenda o teste para incluir recursos vazios. A seguir está o
api_gateway_private_tests.yamlarquivo atualizado.--- - name: MyTest1 input: {} expectations: rules: check_rest_api_is_private: SKIP - name: MyTest2 input: Resources: {} expectations: rules: check_rest_api_is_private: SKIP -
Execute
testcom o arquivo de teste de unidade atualizado.cfn-guard test --rules-file api_gateway_private.guard --test-data api_gateway_private_tests.yamlO resultado do segundo teste é
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 -
Adicione mais dois testes ao seu arquivo de teste unitário. Estenda o teste para incluir o seguinte:
-
Um
AWS::ApiGateway::RestApirecurso sem propriedades especificadas.nota
Esse não é um CloudFormation modelo válido, mas é útil testar se a regra funciona corretamente mesmo para entradas malformadas.
Espere que esse teste falhe porque a
EndpointConfigurationpropriedade não foi especificada e, portanto, não está definida comoPRIVATE. -
Um
AWS::ApiGateway::RestApirecurso que satisfaz a primeira intenção com aEndpointConfigurationpropriedade definida comoPRIVATE, mas não satisfaz a segunda intenção porque não tem declarações de política definidas. Espere que esse teste passe.
A seguir está o arquivo de teste unitário atualizado.
--- - 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 -
-
Execute
testcom o arquivo de teste de unidade atualizado.cfn-guard test --rules-file api_gateway_private.guard --test-data api_gateway_private_tests.yaml \O terceiro resultado é
FAIL, e o quarto resultado é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 -
Comente os testes 1—3 em seu arquivo de teste unitário. Acesse o contexto detalhado somente para o quarto teste. A seguir está o arquivo de teste unitário atualizado.
--- #- 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 -
Inspecione os resultados da avaliação executando o
testcomando em seu terminal, usando o--verbosesinalizador. O contexto detalhado é útil para entender as avaliações. Nesse caso, ele fornece informações detalhadas sobre por que o quarto teste teve sucesso com umPASSresultado.cfn-guard test --rules-file api_gateway_private.guard --test-data api_gateway_private_tests.yaml \ --verboseAqui está a saída dessa execução.
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)A principal observação da saída é a linha
Clause(Location[file:api_gateway_private.guard, line:22, column:5], Check: Properties.EndpointConfiguration.Types[*] EQUALS String("PRIVATE")), PASS), que indica que a verificação foi aprovada. O exemplo também mostrou o caso em que se esperava queTypesfosse uma matriz, mas um único valor foi fornecido. Nesse caso, a Guard continuou avaliando e fornecendo um resultado correto. -
Adicione um caso de teste como o quarto caso de teste ao seu arquivo de teste de unidade para um
AWS::ApiGateway::RestApirecurso com aEndpointConfigurationpropriedade especificada. O caso de teste falhará em vez de ser aprovado. A seguir está o arquivo de teste unitário atualizado.--- #- 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 -
Execute o
testcomando com o arquivo de teste de unidade atualizado usando o--verbosesinalizador.cfn-guard test --rules-file api_gateway_private.guard --test-data api_gateway_private_tests.yaml \ --verboseO
FAILresultado é o esperado porqueREGIONALestá especificadoEndpointConfiguration, mas não é esperado.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)A saída detalhada do
testcomando segue a estrutura do arquivo de regras. Cada bloco no arquivo de regras é um bloco na saída detalhada. O bloco mais alto é cada regra. Se houverwhencondições contrárias à regra, elas aparecerão em um bloco de condições de irmãos. No exemplo a seguir, a condição%api_gws !emptyé testada e aprovada.rule check_rest_api_is_private when %api_gws !empty {Depois que a condição for aprovada, testamos as cláusulas da regra.
%api_gws { Properties.EndpointConfiguration.Types[*] == "PRIVATE" }%api_gwsé uma regra de bloqueio que corresponde aoBlockClausenível na saída (linha: 21). A cláusula de regra é um conjunto de cláusulas de conjunção (AND), em que cada cláusula de conjunção é um conjunto de disjunções.ORA conjunção tem uma única cláusula,.Properties.EndpointConfiguration.Types[*] == "PRIVATE"Portanto, a saída detalhada mostra uma única cláusula. O caminho/Resources/apiGw/Properties/EndpointConfiguration/Types/1mostra quais valores na entrada são comparados, que nesse caso é o elementoTypesindexado em 1.
EmValidando os dados de entrada de acordo com as regras do Guard, você pode usar os exemplos desta seção para usar o validate comando para avaliar os dados de entrada em relação às regras.