翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。
テスト 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 all
AWS::ApiGateway::RestApi
resources # present in theResources
section of the template. # let api_gws = Resources.*[ Type == 'AWS::ApiGateway::RestApi'] # # Rule intent: # 1) AllAWS::ApiGateway::RestApi
resources deployed must be private. # 2) AllAWS::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 noAWS::ApiGateway::RestApi
resources in the template. # 2) PASS when: # ALLAWS::ApiGateway::RestApi
resources in the template have theEndpointConfiguration
property set toType
:PRIVATE
. # ALLAWS::ApiGateway::RestApi
resources in the template have one IAM condition key specified in thePolicy
property withaws: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 { # # ALLAWS::ApiGateway::RestApi
resources in the template have one IAM condition key specified in thePolicy
property with #aws:sourceVpc
or: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.yaml \
2 番目のテストの結果は です
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) 句のセットであり、各組み合わせ句は一連の分離 (OR
) です。組み合わせには 1 つの句 がありますProperties.EndpointConfiguration.Types[*] == "PRIVATE"
。したがって、詳細な出力には 1 つの句が表示されます。パスは、入力内のどの値が比較されるか/Resources/apiGw/Properties/EndpointConfiguration/Types/1
を示します。この場合、 は 1 でTypes
インデックス付けされた 要素です。
ではGuard ルールに対する入力データの検証、このセクションの例を使用して、 validate
コマンドを使用して入力データをルールと照合できます。