diff --git a/sceptre/diffing/stack_differ.py b/sceptre/diffing/stack_differ.py index a575c6afc..a8d269996 100644 --- a/sceptre/diffing/stack_differ.py +++ b/sceptre/diffing/stack_differ.py @@ -197,10 +197,20 @@ def _create_deployed_stack_config( try: description = stack_actions.describe() except ClientError as err: + # Check for AWS access exceptions + if err.response["Error"]["Code"] == "ForbiddenException": + raise SceptreException( + "ForbiddenException: Confirm your current AWS profile is authenticated", + "and has the necessary access.", + ) + # This means the stack has not been deployed yet if err.response["Error"]["Message"].endswith("does not exist"): return None + # Unknown error, raise it as-is + raise err + stacks = description["Stacks"] for stack in stacks: if stack["StackStatus"] in self.STACK_STATUSES_INDICATING_NOT_DEPLOYED: diff --git a/tests/test_diffing/test_stack_differ.py b/tests/test_diffing/test_stack_differ.py index b05a2f045..f2e9887f4 100644 --- a/tests/test_diffing/test_stack_differ.py +++ b/tests/test_diffing/test_stack_differ.py @@ -63,6 +63,7 @@ def setup_method(self, method): self._stack = None self._actions = None self._parameters = None + self._describe_fn = self.describe_stack_success @property def parameters_on_stack(self): @@ -103,6 +104,9 @@ def actions(self) -> Union[StackActions, Mock]: return self._actions def describe_stack(self): + return self._describe_fn() + + def describe_stack_success(self): return { "Stacks": [ { @@ -177,6 +181,17 @@ def expected_deployed_config(self): cloudformation_service_role=self.deployed_cloudformation_service_role, ) + def test__create_deployed_stack_config__wraps_aws_ForbiddenException(self): + def fail_with_ForbiddenException(): + raise ClientError( + {"Error": {"Code": "ForbiddenException", "Message": "No access"}}, + "describe", + ) + + self._describe_fn = fail_with_ForbiddenException + with pytest.raises(SceptreException): + self.differ._create_deployed_stack_config(self.actions) + def test_diff__compares_deployed_template_to_generated_template(self): self.differ.diff(self.actions)