示例#1
0
    def test_with_policy_templates(self):
        self.create_and_verify_stack("combination/state_machine_with_policy_templates")

        state_machine_role_name = self.get_stack_outputs()["MyStateMachineRole"]

        # There should be two policies created. Each policy has the name <resource-logicalid>Policy<index>

        # Verify the contents of first policy
        sqs_poller_policy = get_policy_statements(
            state_machine_role_name, "MyStateMachineRolePolicy0", self.client_provider.iam_client
        )
        self.assertEqual(len(sqs_poller_policy), 1, "Only one statement must be in SQS Poller policy")

        sqs_policy_statement = sqs_poller_policy[0]
        self.assertTrue(type(sqs_policy_statement["Resource"]) != list)

        queue_url = self.get_physical_id_by_type("AWS::SQS::Queue")
        parts = queue_url.split("/")
        expected_queue_name = parts[-1]
        actual_queue_arn = sqs_policy_statement["Resource"]
        self.assertTrue(
            actual_queue_arn.endswith(expected_queue_name),
            "Queue Arn " + actual_queue_arn + " must end with suffix " + expected_queue_name,
        )

        # Verify the contents of second policy
        lambda_invoke_policy = get_policy_statements(
            state_machine_role_name, "MyStateMachineRolePolicy1", self.client_provider.iam_client
        )
        self.assertEqual(len(lambda_invoke_policy), 1, "One policies statements should be present")

        lambda_policy_statement = lambda_invoke_policy[0]
        self.assertTrue(type(lambda_policy_statement["Resource"]) != list)

        function_name = self.get_physical_id_by_type("AWS::Lambda::Function")
        #  NOTE: The resource ARN has "*" suffix to allow for any Lambda function version as well
        expected_function_suffix = "function:" + function_name + "*"
        actual_function_arn = lambda_policy_statement["Resource"]
        self.assertTrue(
            actual_function_arn.endswith(expected_function_suffix),
            "Function ARN " + actual_function_arn + " must end with suffix " + expected_function_suffix,
        )
    def test_state_machine_with_schedule(self):
        self.create_and_verify_stack("combination/state_machine_with_schedule")
        outputs = self.get_stack_outputs()
        state_machine_arn = outputs["MyStateMachineArn"]
        schedule_name = outputs["MyScheduleName"]
        event_role_name = outputs["MyEventRole"]

        # get the cloudwatch schedule rule
        cloud_watch_event_client = self.client_provider.cloudwatch_event_client
        cw_rule_result = cloud_watch_event_client.describe_rule(
            Name=schedule_name)

        # checking if the name, description and state properties are correct
        self.assertEqual(cw_rule_result["Name"], schedule_name)
        self.assertEqual(cw_rule_result["Description"], "test schedule")
        self.assertEqual(cw_rule_result["State"], "DISABLED")
        self.assertEqual(cw_rule_result["ScheduleExpression"],
                         "rate(1 minute)")

        # checking if the role used by the event rule to trigger the state machine execution is correct
        start_execution_policy = get_policy_statements(
            event_role_name,
            "MyStateMachineCWScheduleRoleStartExecutionPolicy",
            self.client_provider.iam_client)
        self.assertEqual(
            len(start_execution_policy), 1,
            "Only one statement must be in Start Execution policy")

        start_execution_policy_statement = start_execution_policy[0]

        self.assertTrue(
            type(start_execution_policy_statement["Action"]) != list)
        policy_action = start_execution_policy_statement["Action"]
        self.assertEqual(
            policy_action,
            "states:StartExecution",
            "Action referenced in event role policy must be 'states:StartExecution'",
        )

        self.assertTrue(
            type(start_execution_policy_statement["Resource"]) != list)
        referenced_state_machine_arn = start_execution_policy_statement[
            "Resource"]
        self.assertEqual(
            referenced_state_machine_arn,
            state_machine_arn,
            "State machine referenced in event role policy is incorrect",
        )
    def _test_api_integration_with_state_machine(self, api_id, method, path,
                                                 role_name, role_arn,
                                                 policy_name,
                                                 state_machine_arn, partition,
                                                 region):
        apigw_client = self.client_provider.api_client

        resources = apigw_client.get_resources(restApiId=api_id)["items"]
        resource = get_resource_by_path(resources, path)

        post_method = apigw_client.get_method(restApiId=api_id,
                                              resourceId=resource["id"],
                                              httpMethod=method)
        method_integration = post_method["methodIntegration"]
        self.assertEqual(method_integration["credentials"], role_arn)

        # checking if the uri in the API integration is set for Step Functions State Machine execution
        expected_integration_uri = "arn:" + partition + ":apigateway:" + region + ":states:action/StartExecution"
        self.assertEqual(method_integration["uri"], expected_integration_uri)

        # checking if the role used by the event rule to trigger the state machine execution is correct
        start_execution_policy = get_policy_statements(
            role_name, policy_name, self.client_provider.iam_client)
        self.assertEqual(
            len(start_execution_policy), 1,
            "Only one statement must be in Start Execution policy")

        start_execution_policy_statement = start_execution_policy[0]

        self.assertTrue(
            type(start_execution_policy_statement["Action"]) != list)
        policy_action = start_execution_policy_statement["Action"]
        self.assertEqual(
            policy_action,
            "states:StartExecution",
            "Action referenced in event role policy must be 'states:StartExecution'",
        )

        self.assertTrue(
            type(start_execution_policy_statement["Resource"]) != list)
        referenced_state_machine_arn = start_execution_policy_statement[
            "Resource"]
        self.assertEqual(
            referenced_state_machine_arn,
            state_machine_arn,
            "State machine referenced in event role policy is incorrect",
        )
示例#4
0
    def test_state_machine_with_cwe(self):
        self.create_and_verify_stack("combination/state_machine_with_cwe")
        outputs = self.get_stack_outputs()
        state_machine_arn = outputs["MyStateMachineArn"]
        rule_name = outputs["MyEventName"]
        event_role_name = outputs["MyEventRole"]

        cloud_watch_events_client = self.client_provider.cloudwatch_event_client

        # Check if the CWE rule is created with the state machine as the target
        rule_name_by_target_result = cloud_watch_events_client.list_rule_names_by_target(TargetArn=state_machine_arn)
        self.assertEqual(len(rule_name_by_target_result["RuleNames"]), 1)
        rule_name_with_state_machine_target = rule_name_by_target_result["RuleNames"][0]
        self.assertEqual(rule_name_with_state_machine_target, rule_name)

        # checking if the role used by the event rule to trigger the state machine execution is correct
        start_execution_policy = get_policy_statements(
            event_role_name, "MyStateMachineCWEventRoleStartExecutionPolicy", self.client_provider.iam_client
        )
        self.assertEqual(len(start_execution_policy), 1, "Only one statement must be in Start Execution policy")

        start_execution_policy_statement = start_execution_policy[0]

        self.assertTrue(type(start_execution_policy_statement["Action"]) != list)
        policy_action = start_execution_policy_statement["Action"]
        self.assertEqual(
            policy_action,
            "states:StartExecution",
            "Action referenced in event role policy must be 'states:StartExecution'",
        )

        self.assertTrue(type(start_execution_policy_statement["Resource"]) != list)
        referenced_state_machine_arn = start_execution_policy_statement["Resource"]
        self.assertEqual(
            referenced_state_machine_arn,
            state_machine_arn,
            "State machine referenced in event role policy is incorrect",
        )
    def test_state_machine_with_cwe(self):
        self.create_and_verify_stack(
            "combination/state_machine_with_cwe_dlq_generated")
        outputs = self.get_stack_outputs()
        state_machine_arn = outputs["MyStateMachineArn"]
        rule_name = outputs["MyEventName"]
        event_role_name = outputs["MyEventRole"]
        state_machine_target_dlq_arn = outputs["MyDLQArn"]
        state_machine_target_dlq_url = outputs["MyDLQUrl"]

        cloud_watch_events_client = self.client_provider.cloudwatch_event_client
        cw_rule_result = cloud_watch_events_client.describe_rule(
            Name=rule_name)

        # Check if the CWE rule is created with the state machine as the target
        rule_name_by_target_result = cloud_watch_events_client.list_rule_names_by_target(
            TargetArn=state_machine_arn)
        self.assertEqual(len(rule_name_by_target_result["RuleNames"]), 1)
        rule_name_with_state_machine_target = rule_name_by_target_result[
            "RuleNames"][0]
        self.assertEqual(rule_name_with_state_machine_target, rule_name)

        # checking if the role used by the event rule to trigger the state machine execution is correct
        start_execution_policy = get_policy_statements(
            event_role_name, "MyStateMachineCWEventRoleStartExecutionPolicy",
            self.client_provider.iam_client)
        self.assertEqual(
            len(start_execution_policy), 1,
            "Only one statement must be in Start Execution policy")

        start_execution_policy_statement = start_execution_policy[0]

        self.assertTrue(
            type(start_execution_policy_statement["Action"]) != list)
        policy_action = start_execution_policy_statement["Action"]
        self.assertEqual(
            policy_action,
            "states:StartExecution",
            "Action referenced in event role policy must be 'states:StartExecution'",
        )

        self.assertTrue(
            type(start_execution_policy_statement["Resource"]) != list)
        referenced_state_machine_arn = start_execution_policy_statement[
            "Resource"]
        self.assertEqual(
            referenced_state_machine_arn,
            state_machine_arn,
            "State machine referenced in event role policy is incorrect",
        )

        # checking if the target has a dead-letter queue attached to it
        targets = cloud_watch_events_client.list_targets_by_rule(
            Rule=rule_name)["Targets"]

        self.assertEqual(len(targets), 1,
                         "Rule should contain a single target")
        target = targets[0]
        self.assertEqual(target["Arn"], state_machine_arn)
        self.assertEqual(target["DeadLetterConfig"]["Arn"],
                         state_machine_target_dlq_arn)

        # checking target's retry policy properties
        self.assertEqual(target["RetryPolicy"]["MaximumEventAgeInSeconds"],
                         200)
        self.assertIsNone(target["RetryPolicy"].get("MaximumRetryAttempts"))

        # checking if the generated dead-letter queue has necessary resource based policy attached to it
        dlq_policy = get_queue_policy(state_machine_target_dlq_url,
                                      self.client_provider.sqs_client)
        self.assertEqual(
            len(dlq_policy), 1,
            "Only one statement must be in Dead-letter queue policy")
        dlq_policy_statement = dlq_policy[0]

        # checking policy action
        self.assertFalse(
            isinstance(dlq_policy_statement["Action"], list),
            "Only one action must be in dead-letter queue policy"
        )  # if it is an array, it means has more than one action
        self.assertEqual(
            dlq_policy_statement["Action"],
            "sqs:SendMessage",
            "Action referenced in dead-letter queue policy must be 'sqs:SendMessage'",
        )

        # checking service principal
        self.assertEqual(
            len(dlq_policy_statement["Principal"]),
            1,
        )
        self.assertEqual(
            dlq_policy_statement["Principal"]["Service"],
            "events.amazonaws.com",
            "Policy should grant EventBridge service principal to send messages to dead-letter queue",
        )

        # checking condition type
        key, value = get_first_key_value_pair_in_dict(
            dlq_policy_statement["Condition"])
        self.assertEqual(key, "ArnEquals")

        # checking condition key
        self.assertEqual(len(dlq_policy_statement["Condition"]), 1)
        condition_kay, condition_value = get_first_key_value_pair_in_dict(
            value)
        self.assertEqual(condition_kay, "aws:SourceArn")

        # checking condition value
        self.assertEqual(len(dlq_policy_statement["Condition"][key]), 1)
        self.assertEqual(
            condition_value,
            cw_rule_result["Arn"],
            "Policy should only allow requests coming from schedule rule resource",
        )
    def test_state_machine_with_schedule(self):
        self.create_and_verify_stack(
            "combination/state_machine_with_schedule_dlq_and_retry_policy")
        outputs = self.get_stack_outputs()
        state_machine_arn = outputs["MyStateMachineArn"]
        schedule_name = outputs["MyScheduleName"]
        state_machine_target_dlq_arn = outputs["MyDLQArn"]
        event_role_name = outputs["MyEventRole"]

        # get the cloudwatch schedule rule
        cloud_watch_event_client = self.client_provider.cloudwatch_event_client
        cw_rule_result = cloud_watch_event_client.describe_rule(
            Name=schedule_name)

        # checking if the name, description and state properties are correct
        self.assertEqual(cw_rule_result["Name"], schedule_name)
        self.assertEqual(cw_rule_result["Description"], "test schedule")
        self.assertEqual(cw_rule_result["State"], "DISABLED")
        self.assertEqual(cw_rule_result["ScheduleExpression"],
                         "rate(1 minute)")

        # checking if the target's DLQ and RetryPolicy properties are correct
        targets = cloud_watch_event_client.list_targets_by_rule(
            Rule=schedule_name)["Targets"]

        self.assertEqual(len(targets), 1,
                         "Rule should contain a single target")

        target = targets[0]
        self.assertEqual(target["Arn"], state_machine_arn)
        self.assertEqual(target["DeadLetterConfig"]["Arn"],
                         state_machine_target_dlq_arn)

        self.assertIsNone(
            target["RetryPolicy"].get("MaximumEventAgeInSeconds"))
        self.assertEqual(target["RetryPolicy"]["MaximumRetryAttempts"], 2)

        # checking if the role used by the event rule to trigger the state machine execution is correct
        start_execution_policy = get_policy_statements(
            event_role_name,
            "MyStateMachineCWScheduleRoleStartExecutionPolicy",
            self.client_provider.iam_client)
        self.assertEqual(
            len(start_execution_policy), 1,
            "Only one statement must be in Start Execution policy")

        start_execution_policy_statement = start_execution_policy[0]

        self.assertTrue(
            type(start_execution_policy_statement["Action"]) != list)
        policy_action = start_execution_policy_statement["Action"]
        self.assertEqual(
            policy_action,
            "states:StartExecution",
            "Action referenced in event role policy must be 'states:StartExecution'",
        )

        self.assertTrue(
            type(start_execution_policy_statement["Resource"]) != list)
        referenced_state_machine_arn = start_execution_policy_statement[
            "Resource"]
        self.assertEqual(
            referenced_state_machine_arn,
            state_machine_arn,
            "State machine referenced in event role policy is incorrect",
        )