翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。
AWS CloudFormation Guard ルールのテスト
組み込みの AWS CloudFormation Guard ユニットテストフレームワークを使用して、Guard ルールが意図したとおりに動作することを確認できます。このセクションでは、ユニットテストファイルを作成する方法と、それを使用して test コマンドでルールファイルをテストする方法について説明します。
ユニットテストファイルには、、.json、.JSON、、.jsn.yaml.YAML、または のいずれかの拡張子が必要です.yml。
前提条件
入力データを評価するための Guard ルールを記述します。詳細については、「ガードルールの記述」を参照してください。
ガードユニットテストファイルの概要
ガードユニットテストファイルは、複数の入力と、ガードルールファイル内に書き込まれたルールの期待される結果を含む JSON または YAML 形式のファイルです。さまざまな期待を評価するためのサンプルが複数ある場合があります。まず空の入力をテストしてから、さまざまなルールと句を評価するための情報を段階的に追加することをお勧めします。
また、サフィックス_test.jsonまたは を使用してユニットテストファイルに名前を付けることをお勧めします_tests.yaml。たとえば、 という名前のルールファイルがある場合はmy_rules.guard、ユニットテストファイル に名前を付けますmy_rules_tests.yaml。
構文
以下は、YAML 形式のユニットテストファイルの構文を示しています。
--- - name: <TEST NAME> input: <SAMPLE INPUT> expectations: rules: <RULE NAME>: [PASS|FAIL|SKIP]
プロパティ
以下は、Guard テストファイルのプロパティです。
input-
ルールをテストするデータ。次の例に示すように、最初のテストでは空の入力を使用することをお勧めします。
--- - name: MyTest1 input {}後続のテストでは、テストする入力データを追加します。
必須: はい
expectations-
入力データに対して特定のルールが評価された場合に期待される結果。各ルールで期待される結果に加えて、テストする 1 つ以上のルールを指定します。期待される結果は、次のいずれかである必要があります。
-
PASS– 入力データに対して実行すると、ルールは に評価されますtrue。 -
FAIL– 入力データに対して実行すると、ルールは に評価されますfalse。 -
SKIP– 入力データに対して実行すると、ルールはトリガーされません。
expectations: rules: check_rest_api_is_private: PASS必須: はい
-
ガードルールユニットテストファイルの記述のチュートリアル
以下は、 という名前のルールファイルですapi_gateway_private.guard。このルールの目的は、CloudFormation テンプレートで定義されているすべての Amazon API Gateway リソースタイプがプライベートアクセス専用にデプロイされているかどうかを確認することです。また、少なくとも 1 つのポリシーステートメントが Virtual Private Cloud (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 } } } }
このチュートリアルでは、最初のルールインテントをテストします。デプロイされたすべてのAWS::ApiGateway::RestApiリソースはプライベートである必要があります。
-
次の初期テスト
api_gateway_private_tests.yamlを含む というユニットテストファイルを作成します。最初のテストでは、空の入力を追加し、入力としてAWS::ApiGateway::RestApiリソースがないためルールがスキップcheck_rest_api_is_privateされることを期待します。--- - name: MyTest1 input: {} expectations: rules: check_rest_api_is_private: SKIP -
testコマンドを使用して、ターミナルで最初のテストを実行します。--rules-fileパラメータで、ルールファイルを指定します。--test-dataパラメータには、ユニットテストファイルを指定します。cfn-guard test --rules-file api_gateway_private.guard --test-data api_gateway_private_tests.yaml最初のテストの結果は です
PASS。Test Case #1 Name: "MyTest1" PASS Rules: check_rest_api_is_private: Expected = SKIP, Evaluated = SKIP -
ユニットテストファイルに別のテストを追加します。次に、テストを拡張して空のリソースを含めます。更新された
api_gateway_private_tests.yamlファイルは次のとおりです。--- - name: MyTest1 input: {} expectations: rules: check_rest_api_is_private: SKIP - name: MyTest2 input: Resources: {} expectations: rules: check_rest_api_is_private: SKIP -
更新されたユニットテストファイル
testを使用して を実行します。cfn-guard test --rules-file api_gateway_private.guard --test-data api_gateway_private_tests.yaml2 番目のテストの結果は です
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 -
ユニットテストファイルにさらに 2 つのテストを追加します。テストを拡張して、以下を含めます。
-
プロパティが指定されていない
AWS::ApiGateway::RestApiリソース。注記
これは有効な CloudFormation テンプレートではありませんが、不正な形式の入力でもルールが正しく機能するかどうかをテストすると便利です。
EndpointConfigurationプロパティが指定されていないため、このテストは失敗することが想定されます。したがって、 は に設定されませんPRIVATE。 -
EndpointConfigurationプロパティを に設定して最初のインテントを満たすPRIVATEが、ポリシーステートメントが定義されていないため、2 番目のインテントを満たさないAWS::ApiGateway::RestApiリソース。このテストは合格するはずです。
更新されたユニットテストファイルを次に示します。
--- - 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 -
-
更新されたユニットテストファイル
testを使用して を実行します。cfn-guard test --rules-file api_gateway_private.guard --test-data api_gateway_private_tests.yaml \3 番目の結果は で
FAIL、4 番目の結果は です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~3 をコメントアウトします。4 番目のテストのみの詳細コンテキストにアクセスします。更新されたユニットテストファイルを次に示します。
--- #- 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 -
評価結果を確認するには、
--verboseフラグを使用してターミナルでtestコマンドを実行します。詳細なコンテキストは、評価を理解するのに役立ちます。この場合、4 番目のテストがPASS結果で成功した理由に関する詳細情報を提供します。cfn-guard test --rules-file api_gateway_private.guard --test-data api_gateway_private_tests.yaml \ --verbose以下は、その実行からの出力です。
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)出力からの主な観測値は
Clause(Location[file:api_gateway_private.guard, line:22, column:5], Check: Properties.EndpointConfiguration.Types[*] EQUALS String("PRIVATE")), PASS)、チェックに合格したことを示す行 です。この例では、Typesが配列であると予想されるが、単一の値が指定されたケースも示しました。この場合、Guard は引き続き評価を行い、正しい結果を提供しました。 -
4 番目のテストケースのようなテストケースを、
EndpointConfigurationプロパティが指定されたAWS::ApiGateway::RestApiリソースのユニットテストファイルに追加します。テストケースは合格ではなく失敗します。更新されたユニットテストファイルを次に示します。--- #- 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 -
--verboseフラグを使用して、更新されたユニットテストファイルでtestコマンドを実行します。cfn-guard test --rules-file api_gateway_private.guard --test-data api_gateway_private_tests.yaml \ --verboseは に指定されている
EndpointConfigurationが、 は想定されていないためREGIONAL、結果は想定FAILどおりです。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)testコマンドの詳細出力は、ルールファイルの構造に従います。ルールファイル内のすべてのブロックは、詳細出力のブロックです。一番上のブロックは各ルールです。ルールにwhen条件がある場合は、兄弟条件ブロックに表示されます。次の例では、 条件%api_gws !emptyがテストされ、合格します。rule check_rest_api_is_private when %api_gws !empty {条件が成功したら、ルール句をテストします。
%api_gws { Properties.EndpointConfiguration.Types[*] == "PRIVATE" }%api_gwsは、出力BlockClauseのレベル (line:21) に対応するブロックルールです。ルール句は、連結 (AND) 句のセットであり、各連結句は一連の差分 (ORs) です。連結には 1 つの句 がありますProperties.EndpointConfiguration.Types[*] == "PRIVATE"。したがって、詳細出力には 1 つの句が表示されます。パスは、入力内のどの値が比較されるか/Resources/apiGw/Properties/EndpointConfiguration/Types/1を示します。この場合、 は 1 でTypesインデックス付けされた の 要素です。
ではGuard ルールに対する入力データの検証、このセクションの例を使用して、 validate コマンドを使用して入力データをルールに対して評価できます。