From 6a467ec50f50a14ad67845b3d46eadab919c8719 Mon Sep 17 00:00:00 2001 From: Ciaran Evans <9111975+ciaranevans@users.noreply.github.com> Date: Fri, 4 Sep 2020 10:22:21 +0100 Subject: [PATCH] Add validation on execution input --- moto/stepfunctions/exceptions.py | 5 +++ moto/stepfunctions/models.py | 11 +++++ .../test_stepfunctions/test_stepfunctions.py | 41 +++++++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/moto/stepfunctions/exceptions.py b/moto/stepfunctions/exceptions.py index 6000bab4e..4abb6a8af 100644 --- a/moto/stepfunctions/exceptions.py +++ b/moto/stepfunctions/exceptions.py @@ -38,6 +38,11 @@ class InvalidName(AWSError): STATUS = 400 +class InvalidExecutionInput(AWSError): + TYPE = "InvalidExecutionInput" + STATUS = 400 + + class StateMachineDoesNotExist(AWSError): TYPE = "StateMachineDoesNotExist" STATUS = 400 diff --git a/moto/stepfunctions/models.py b/moto/stepfunctions/models.py index 19fb4561d..3184d6456 100644 --- a/moto/stepfunctions/models.py +++ b/moto/stepfunctions/models.py @@ -1,3 +1,4 @@ +import json import re from datetime import datetime @@ -11,6 +12,7 @@ from .exceptions import ( ExecutionAlreadyExists, ExecutionDoesNotExist, InvalidArn, + InvalidExecutionInput, InvalidName, StateMachineDoesNotExist, ) @@ -209,6 +211,7 @@ class StepFunctionBackend(BaseBackend): def start_execution(self, state_machine_arn, name=None, execution_input=None): state_machine_name = self.describe_state_machine(state_machine_arn).name self._ensure_execution_name_doesnt_exist(name) + self._validate_execution_input(execution_input) execution = Execution( region_name=self.region_name, account_id=self._get_account_id(), @@ -290,6 +293,14 @@ class StepFunctionBackend(BaseBackend): "Execution Already Exists: '" + execution.execution_arn + "'" ) + def _validate_execution_input(self, execution_input): + try: + json.loads(execution_input) + except Exception as ex: + raise InvalidExecutionInput( + "Invalid State Machine Execution Input: '" + str(ex) + "'" + ) + def _get_account_id(self): return ACCOUNT_ID diff --git a/tests/test_stepfunctions/test_stepfunctions.py b/tests/test_stepfunctions/test_stepfunctions.py index d94867719..36b08487c 100644 --- a/tests/test_stepfunctions/test_stepfunctions.py +++ b/tests/test_stepfunctions/test_stepfunctions.py @@ -425,6 +425,47 @@ def test_state_machine_start_execution_fails_on_duplicate_execution_name(): ) +@mock_stepfunctions +@mock_sts +def test_state_machine_start_execution_with_custom_input(): + client = boto3.client("stepfunctions", region_name=region) + # + sm = client.create_state_machine( + name="name", definition=str(simple_definition), roleArn=_get_default_role() + ) + execution_input = json.dumps({"input_key": "input_value"}) + execution = client.start_execution( + stateMachineArn=sm["stateMachineArn"], input=execution_input + ) + # + execution["ResponseMetadata"]["HTTPStatusCode"].should.equal(200) + uuid_regex = "[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}" + expected_exec_name = ( + "arn:aws:states:" + + region + + ":" + + _get_account_id() + + ":execution:name:" + + uuid_regex + ) + execution["executionArn"].should.match(expected_exec_name) + execution["startDate"].should.be.a(datetime) + + +@mock_stepfunctions +@mock_sts +def test_state_machine_start_execution_with_invalid_input(): + client = boto3.client("stepfunctions", region_name=region) + # + sm = client.create_state_machine( + name="name", definition=str(simple_definition), roleArn=_get_default_role() + ) + with assert_raises(ClientError): + _ = client.start_execution(stateMachineArn=sm["stateMachineArn"], input="") + with assert_raises(ClientError): + _ = client.start_execution(stateMachineArn=sm["stateMachineArn"], input="{") + + @mock_stepfunctions @mock_sts def test_state_machine_list_executions():