Repository: getmoto/moto
Pull request #7184 (2024-01-03 23:06:35)

Implements sso-admin AWS Managed Policies 
Added AWS Managed policy operations for sso-admin permissionsets.

The following API calls are implemented:

- [detach_managed_policy_from_permission_set](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/sso-admin/client/detach_managed_policy_from_permission_set.html)
- [attach_managed_policy_to_permission_set](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/sso-admin/client/attach_managed_policy_to_permission_set.html)
- [list_managed_policies_in_permission_set](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/sso-admin/client/list_managed_policies_in_permission_set.html)

Added additional exception handling.

Also references the managed policies [here](https://github.com/getmoto/moto/blob/master/moto/iam/aws_managed_policies.py) for validation of a proper AWS Managed Policy existing.


codecov[bot]: ## [Codecov](https://app.codecov.io/gh/getmoto/moto/pull/7184?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) Report
Attention: `1 lines` in your changes are missing coverage. Please review.
> Comparison is base [(`5fadeb8`)](https://app.codecov.io/gh/getmoto/moto/commit/5fadeb869e17ec3e9a66bcf82ff198409a84118b?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) 95.90% compared to head [(`bdaf596`)](https://app.codecov.io/gh/getmoto/moto/pull/7184?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) 95.91%.

| [Files](https://app.codecov.io/gh/getmoto/moto/pull/7184?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) | Patch % | Lines |
|---|---|---|
| [moto/ssoadmin/models.py](https://app.codecov.io/gh/getmoto/moto/pull/7184?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto#diff-bW90by9zc29hZG1pbi9tb2RlbHMucHk=) | 97.95% | [1 Missing :warning: ](https://app.codecov.io/gh/getmoto/moto/pull/7184?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) |

<details><summary>Additional details and impacted files</summary>


```diff
@@           Coverage Diff           @@
##           master    #7184   +/-   ##
=======================================
  Coverage   95.90%   95.91%           
=======================================
  Files         840      840           
  Lines       82542    82619   +77     
=======================================
+ Hits        79164    79240   +76     
- Misses       3378     3379    +1     
```

| [Flag](https://app.codecov.io/gh/getmoto/moto/pull/7184/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) | Coverage Δ | |
|---|---|---|
| [servertests](https://app.codecov.io/gh/getmoto/moto/pull/7184/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) | `35.47% <31.64%> (-0.01%)` | :arrow_down: |
| [unittests](https://app.codecov.io/gh/getmoto/moto/pull/7184/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) | `95.85% <98.73%> (+<0.01%)` | :arrow_up: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto#carryforward-flags-in-the-pull-request-comment) to find out more.


</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/getmoto/moto/pull/7184?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto).


Patch:
diff --git a/moto/cloudformation/models.py b/moto/cloudformation/models.py
index 296919853..1d6e18053 100644
--- a/moto/cloudformation/models.py
+++ b/moto/cloudformation/models.py
@@ -384,11 +384,12 @@ class FakeStack(CloudFormationModel):
         self.name = name
         self.account_id = account_id
         self.template = template
+        self.template_dict: Dict[str, Any]
         if template != {}:
             self._parse_template()
             self.description = self.template_dict.get("Description")
         else:
-            self.template_dict: Dict[str, Any] = {}
+            self.template_dict = {}
             self.description = None
         self.parameters = parameters
         self.region_name = region_name
@@ -412,12 +413,8 @@ class FakeStack(CloudFormationModel):
         self.status = "CREATE_PENDING"
 
     def has_template(self, other_template: str) -> bool:
-        our_template = (
-            self.template
-            if isinstance(self.template, dict)
-            else json.loads(self.template)
-        )
-        return our_template == json.loads(other_template)
+        self._parse_template()
+        return self.template_dict == self.parse_template(other_template)
 
     def has_parameters(self, other_parameters: Dict[str, Any]) -> bool:
         return self.parameters == other_parameters
@@ -465,11 +462,15 @@ class FakeStack(CloudFormationModel):
         self.events.append(event)
 
     def _parse_template(self) -> None:
+        self.template_dict = self.parse_template(self.template)  # type: ignore[arg-type]
+
+    @staticmethod
+    def parse_template(template: str) -> Dict[str, Any]:  # type: ignore[misc]
         yaml.add_multi_constructor("", yaml_tag_constructor)
         try:
-            self.template_dict = yaml.load(self.template, Loader=yaml.Loader)  # type: ignore[arg-type]
+            return yaml.load(template, Loader=yaml.Loader)
         except (ParserError, ScannerError):
-            self.template_dict = json.loads(self.template)  # type: ignore[arg-type]
+            return json.loads(template)
 
     @property
     def stack_parameters(self) -> Dict[str, Any]:  # type: ignore[misc]
diff --git a/moto/s3control/config.py b/moto/s3control/config.py
index 0f17b4a88..203b5e845 100644
--- a/moto/s3control/config.py
+++ b/moto/s3control/config.py
@@ -131,7 +131,7 @@ class S3AccountPublicAccessBlockConfigQuery(ConfigQueryModel[S3ControlBackend]):
 
         # Format the PAB to the AWS Config format:
         creation_time = utcnow()
-        config_data = {
+        config_data: Dict[str, Any] = {
             "version": "1.3",
             "accountId": account_id,
             "configurationItemCaptureTime": str(creation_time),
diff --git a/moto/ssoadmin/exceptions.py b/moto/ssoadmin/exceptions.py
index a5f5df6e2..32cc025ef 100644
--- a/moto/ssoadmin/exceptions.py
+++ b/moto/ssoadmin/exceptions.py
@@ -3,9 +3,30 @@ from moto.core.exceptions import JsonRESTError
 
 
 class ResourceNotFoundException(JsonRESTError):
-    def __init__(self, message: str = "Account not found") -> None:
+    code = 400
+
+    def __init__(self, message: str = "") -> None:
         super().__init__(
             error_type="ResourceNotFoundException",
             message=message,
-            code="ResourceNotFoundException",
+        )
+
+
+class ConflictException(JsonRESTError):
+    code = 400
+
+    def __init__(self, message: str = "") -> None:
+        super().__init__(
+            error_type="ConflictException",
+            message=message,
+        )
+
+
+class ServiceQuotaExceededException(JsonRESTError):
+    code = 400
+
+    def __init__(self, message: str = "") -> None:
+        super().__init__(
+            error_type="ServiceQuotaExceededException",
+            message=message,
         )
diff --git a/moto/ssoadmin/models.py b/moto/ssoadmin/models.py
index 5cb410868..7d7433f80 100644
--- a/moto/ssoadmin/models.py
+++ b/moto/ssoadmin/models.py
@@ -1,13 +1,22 @@
-from typing import Any, Dict, List
+import json
+from typing import Any, Dict, List, Optional
 
 from moto.core import BackendDict, BaseBackend, BaseModel
 from moto.core.utils import unix_time
+from moto.iam.aws_managed_policies import aws_managed_policies_data
 from moto.moto_api._internal import mock_random as random
 from moto.utilities.paginator import paginate
 
-from .exceptions import ResourceNotFoundException
+from .exceptions import (
+    ConflictException,
+    ResourceNotFoundException,
+    ServiceQuotaExceededException,
+)
 from .utils import PAGINATION_MODEL
 
+# https://docs.aws.amazon.com/singlesignon/latest/userguide/limits.html
+MAX_MANAGED_POLICIES_PER_PERMISSION_SET = 20
+
 
 class AccountAssignment(BaseModel):
     def __init__(
@@ -60,6 +69,10 @@ class PermissionSet(BaseModel):
         self.tags = tags
         self.created_date = unix_time()
         self.inline_policy = ""
+        self.managed_policies: List[ManagedPolicy] = list()
+        self.total_managed_policies_attached = (
+            0  # this will also include customer managed policies
+        )
 
     def to_json(self, include_creation_date: bool = False) -> Dict[str, Any]:
         summary: Dict[str, Any] = {
@@ -83,6 +96,17 @@ class PermissionSet(BaseModel):
         )
 
 
+class ManagedPolicy(BaseModel):
+    def __init__(self, arn: str, name: str):
+        self.arn = arn
+        self.name = name
+
+    def __eq__(self, other: Any) -> bool:
+        if not isinstance(other, ManagedPolicy):
+            return False
+        return self.arn == other.arn
+
+
 class SSOAdminBackend(BaseBackend):
     """Implementation of SSOAdmin APIs."""
 
@@ -90,6 +114,7 @@ class SSOAdminBackend(BaseBackend):
         super().__init__(region_name, account_id)
         self.account_assignments: List[AccountAssignment] = list()
         self.permission_sets: List[PermissionSet] = list()
+        self.aws_managed_policies: Optional[Dict[str, Any]] = None
 
     def create_account_assignment(
         self,
@@ -158,6 +183,26 @@ class SSOAdminBackend(BaseBackend):
                 return account
         raise ResourceNotFoundException
 
+    def _find_managed_policy(self, managed_policy_arn: str) -> ManagedPolicy:
+        """
+        Checks to make sure the managed policy exists.
+        This pulls from moto/iam/aws_managed_policies.py
+        """
+        # Lazy loading of aws managed policies file
+        if self.aws_managed_policies is None:
+            self.aws_managed_policies = json.loads(aws_managed_policies_data)
+
+        policy_name = managed_policy_arn.split("/")[-1]
+        managed_policy = self.aws_managed_policies.get(policy_name, None)
+        if managed_policy is not None:
+            path = managed_policy.get("path", "/")
+            expected_arn = f"arn:aws:iam::aws:policy{path}{policy_name}"
+            if managed_policy_arn == expected_arn:
+                return ManagedPolicy(managed_policy_arn, policy_name)
+        raise ResourceNotFoundException(
+            f"Policy does not exist with ARN: {managed_policy_arn}"
+        )
+
     @paginate(PAGINATION_MODEL)  # type: ignore[misc]
     def list_account_assignments(
         self, instance_arn: str, account_id: str, permission_set_arn: str
@@ -314,5 +359,70 @@ class SSOAdminBackend(BaseBackend):
         )
         permission_set.inline_policy = ""
 
+    def attach_managed_policy_to_permission_set(
+        self, instance_arn: str, permission_set_arn: str, managed_policy_arn: str
+    ) -> None:
+        permissionset = self._find_permission_set(
+            instance_arn,
+            permission_set_arn,
+        )
+        managed_policy = self._find_managed_policy(managed_policy_arn)
+
+        permissionset_id = permission_set_arn.split("/")[-1]
+        if managed_policy in permissionset.managed_policies:
+            raise ConflictException(
+                f"Permission set with id {permissionset_id} already has a typed link attachment to a manged policy with {managed_policy_arn}"
+            )
+
+        if (
+            permissionset.total_managed_policies_attached
+            >= MAX_MANAGED_POLICIES_PER_PERMISSION_SET
+        ):
+            permissionset_id = permission_set_arn.split("/")[-1]
+            raise ServiceQuotaExceededException(
+                f"You have exceeded AWS SSO limits. Cannot create ManagedPolicy more than {MAX_MANAGED_POLICIES_PER_PERMISSION_SET} for id {permissionset_id}. Please refer to https://docs.aws.amazon.com/singlesignon/latest/userguide/limits.html"
+            )
+
+        permissionset.managed_policies.append(managed_policy)
+        permissionset.total_managed_policies_attached += 1
+
+    @paginate(pagination_model=PAGINATION_MODEL)  # type: ignore[misc]
+    def list_managed_policies_in_permission_set(
+        self,
+        instance_arn: str,
+        permission_set_arn: str,
+    ) -> List[ManagedPolicy]:
+        permissionset = self._find_permission_set(
+            instance_arn,
+            permission_set_arn,
+        )
+        return permissionset.managed_policies
+
+    def _detach_managed_policy(
+        self, instance_arn: str, permission_set_arn: str, managed_policy_arn: str
+    ) -> None:
+        # ensure permission_set exists
+        permissionset = self._find_permission_set(
+            instance_arn,
+            permission_set_arn,
+        )
+
+        for managed_policy in permissionset.managed_policies:
+            if managed_policy.arn == managed_policy_arn:
+                permissionset.managed_policies.remove(managed_policy)
+                permissionset.total_managed_policies_attached -= 1
+                return
+
+        raise ResourceNotFoundException(
+            f"Could not find ManagedPolicy with arn {managed_policy_arn}"
+        )
+
+    def detach_managed_policy_from_permission_set(
+        self, instance_arn: str, permission_set_arn: str, managed_policy_arn: str
+    ) -> None:
+        self._detach_managed_policy(
+            instance_arn, permission_set_arn, managed_policy_arn
+        )
+
 
 ssoadmin_backends = BackendDict(SSOAdminBackend, "sso")
diff --git a/moto/ssoadmin/responses.py b/moto/ssoadmin/responses.py
index dec1cb94c..3187f803a 100644
--- a/moto/ssoadmin/responses.py
+++ b/moto/ssoadmin/responses.py
@@ -195,3 +195,52 @@ class SSOAdminResponse(BaseResponse):
             permission_set_arn=permission_set_arn,
         )
         return json.dumps({})
+
+    def attach_managed_policy_to_permission_set(self) -> str:
+        instance_arn = self._get_param("InstanceArn")
+        permission_set_arn = self._get_param("PermissionSetArn")
+        managed_policy_arn = self._get_param("ManagedPolicyArn")
+        self.ssoadmin_backend.attach_managed_policy_to_permission_set(
+            instance_arn=instance_arn,
+            permission_set_arn=permission_set_arn,
+            managed_policy_arn=managed_policy_arn,
+        )
+        return json.dumps({})
+
+    def list_managed_policies_in_permission_set(self) -> str:
+        instance_arn = self._get_param("InstanceArn")
+        permission_set_arn = self._get_param("PermissionSetArn")
+        max_results = self._get_int_param("MaxResults")
+        next_token = self._get_param("NextToken")
+
+        (
+            managed_policies,
+            next_token,
+        ) = self.ssoadmin_backend.list_managed_policies_in_permission_set(
+            instance_arn=instance_arn,
+            permission_set_arn=permission_set_arn,
+            max_results=max_results,
+            next_token=next_token,
+        )
+
+        managed_policies_response = [
+            {"Arn": managed_policy.arn, "Name": managed_policy.name}
+            for managed_policy in managed_policies
+        ]
+        return json.dumps(
+            {
+                "AttachedManagedPolicies": managed_policies_response,
+                "NextToken": next_token,
+            }
+        )
+
+    def detach_managed_policy_from_permission_set(self) -> str:
+        instance_arn = self._get_param("InstanceArn")
+        permission_set_arn = self._get_param("PermissionSetArn")
+        managed_policy_arn = self._get_param("ManagedPolicyArn")
+        self.ssoadmin_backend.detach_managed_policy_from_permission_set(
+            instance_arn=instance_arn,
+            permission_set_arn=permission_set_arn,
+            managed_policy_arn=managed_policy_arn,
+        )
+        return json.dumps({})
diff --git a/moto/ssoadmin/utils.py b/moto/ssoadmin/utils.py
index e7c3230ed..48d2a2952 100644
--- a/moto/ssoadmin/utils.py
+++ b/moto/ssoadmin/utils.py
@@ -30,4 +30,11 @@ PAGINATION_MODEL = {
             "PrincipalType",
         ],
     },
+    "list_managed_policies_in_permission_set": {
+        "input_token": "next_token",
+        "limit_key": "max_results",
+        "limit_default": 100,
+        "result_key": "AttachedManagedPolicies",
+        "unique_attribute": ["arn"],
+    },
 }


Test patch:
diff --git a/tests/test_cloudformation/test_cloudformation_stack_crud_boto3.py b/tests/test_cloudformation/test_cloudformation_stack_crud_boto3.py
index fcbfac2c0..9e3002b5d 100644
--- a/tests/test_cloudformation/test_cloudformation_stack_crud_boto3.py
+++ b/tests/test_cloudformation/test_cloudformation_stack_crud_boto3.py
@@ -24,6 +24,9 @@ from moto.cloudformation import cloudformation_backends
 from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID
 from tests import EXAMPLE_AMI_ID
 
+TEST_STACK_NAME = "test_stack"
+REGION_NAME = "us-east-1"
+
 dummy_template = {
     "AWSTemplateFormatVersion": "2010-09-09",
     "Description": "Stack 1",
@@ -120,6 +123,21 @@ Resources:
     Parameters:
 """
 
+dummy_update_template_yaml = """---
+AWSTemplateFormatVersion: '2010-09-09'
+Parameters:
+  KeyName:
+    Description: Name of an existing EC2 KeyPair
+    Type: AWS::EC2::KeyPair::KeyName
+    ConstraintDescription: must be the name of an existing EC2 KeyPair.
+Resources:
+  Instance:
+    Type: AWS::EC2::Instance
+    Properties:
+      ImageId: ami-12c6146b
+
+"""
+
 dummy_template_yaml_with_short_form_func = """---
 AWSTemplateFormatVersion: 2010-09-09
 Description: Stack1 with yaml template
@@ -310,27 +328,27 @@ dummy_unknown_template_json = json.dumps(dummy_unknown_template)
 @mock_cloudformation
 @mock_ec2
 def test_create_stack():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
-    cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json)
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
+    cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json)
     stack = cf.describe_stacks()["Stacks"][0]
-    assert stack["StackName"] == "test_stack"
+    assert stack["StackName"] == TEST_STACK_NAME
     assert stack["EnableTerminationProtection"] is False
 
-    template = cf.get_template(StackName="test_stack")["TemplateBody"]
+    template = cf.get_template(StackName=TEST_STACK_NAME)["TemplateBody"]
     assert template == dummy_template
 
 
 @mock_cloudformation
 def test_create_stack_with_additional_properties():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     cf.create_stack(
-        StackName="test_stack",
+        StackName=TEST_STACK_NAME,
         TemplateBody=dummy_template_json,
         EnableTerminationProtection=True,
         TimeoutInMinutes=25,
     )
     stack = cf.describe_stacks()["Stacks"][0]
-    assert stack["StackName"] == "test_stack"
+    assert stack["StackName"] == TEST_STACK_NAME
     assert stack["EnableTerminationProtection"] is True
     assert stack["TimeoutInMinutes"] == 25
 
@@ -338,7 +356,7 @@ def test_create_stack_with_additional_properties():
 @mock_cloudformation
 @mock_ec2
 def test_describe_stack_instances():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     cf.create_stack_set(StackSetName="teststackset", TemplateBody=dummy_template_json)
     cf.create_stack_instances(
         StackSetName="teststackset",
@@ -366,7 +384,7 @@ def test_describe_stack_instances():
 
 @mock_cloudformation
 def test_list_stacksets_length():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     cf.create_stack_set(StackSetName="teststackset", TemplateBody=dummy_template_json)
     cf.create_stack_set(StackSetName="teststackset2", TemplateBody=dummy_template_yaml)
     stacksets = cf.list_stack_sets()
@@ -375,10 +393,10 @@ def test_list_stacksets_length():
 
 @mock_cloudformation
 def test_filter_stacks():
-    conn = boto3.client("cloudformation", region_name="us-east-1")
-    conn.create_stack(StackName="test_stack", TemplateBody=dummy_template_json)
+    conn = boto3.client("cloudformation", region_name=REGION_NAME)
+    conn.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json)
     conn.create_stack(StackName="test_stack2", TemplateBody=dummy_template_json)
-    conn.update_stack(StackName="test_stack", TemplateBody=dummy_template_json2)
+    conn.update_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json2)
 
     stacks = conn.list_stacks(StackStatusFilter=["CREATE_COMPLETE"])
     assert len(stacks.get("StackSummaries")) == 1
@@ -388,7 +406,7 @@ def test_filter_stacks():
 
 @mock_cloudformation
 def test_list_stacksets_contents():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     cf.create_stack_set(StackSetName="teststackset", TemplateBody=dummy_template_json)
     stacksets = cf.list_stack_sets()
     assert stacksets["Summaries"][0]["StackSetName"] == "teststackset"
@@ -397,7 +415,7 @@ def test_list_stacksets_contents():
 
 @mock_cloudformation
 def test_stop_stack_set_operation():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     cf.create_stack_set(StackSetName="teststackset", TemplateBody=dummy_template_json)
     cf.create_stack_instances(
         StackSetName="teststackset",
@@ -414,7 +432,7 @@ def test_stop_stack_set_operation():
 
 @mock_cloudformation
 def test_describe_stack_set_operation():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     cf.create_stack_set(StackSetName="name", TemplateBody=dummy_template_json)
     operation_id = cf.create_stack_instances(
         StackSetName="name",
@@ -443,7 +461,7 @@ def test_describe_stack_set_operation():
 
 @mock_cloudformation
 def test_list_stack_set_operation_results():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     cf.create_stack_set(StackSetName="teststackset", TemplateBody=dummy_template_json)
     cf.create_stack_instances(
         StackSetName="teststackset",
@@ -466,7 +484,7 @@ def test_list_stack_set_operation_results():
 
 @mock_cloudformation
 def test_update_stack_instances():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     param = [
         {"ParameterKey": "TagDescription", "ParameterValue": "StackSetValue"},
         {"ParameterKey": "TagName", "ParameterValue": "StackSetValue2"},
@@ -524,7 +542,7 @@ def test_update_stack_instances():
 
 @mock_cloudformation
 def test_delete_stack_instances():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     tss = "teststackset"
     cf.create_stack_set(StackSetName=tss, TemplateBody=dummy_template_json)
     cf.create_stack_instances(
@@ -565,7 +583,7 @@ def test_delete_stack_instances():
 
 @mock_cloudformation
 def test_create_stack_instances():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     cf.create_stack_set(StackSetName="teststackset", TemplateBody=dummy_template_json)
     cf.create_stack_instances(
         StackSetName="teststackset",
@@ -580,7 +598,7 @@ def test_create_stack_instances():
 
 @mock_cloudformation
 def test_create_stack_instances_with_param_overrides():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     param = [
         {"ParameterKey": "TagDescription", "ParameterValue": "StackSetValue"},
         {"ParameterKey": "TagName", "ParameterValue": "StackSetValue2"},
@@ -615,7 +633,7 @@ def test_create_stack_instances_with_param_overrides():
 
 @mock_cloudformation
 def test_update_stack_set():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     param = [
         {"ParameterKey": "TagDescription", "ParameterValue": "StackSetValue"},
         {"ParameterKey": "TagName", "ParameterValue": "StackSetValue2"},
@@ -645,7 +663,7 @@ def test_update_stack_set():
 
 @mock_cloudformation
 def test_update_stack_set_with_previous_value():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     param = [
         {"ParameterKey": "TagDescription", "ParameterValue": "StackSetValue"},
         {"ParameterKey": "TagName", "ParameterValue": "StackSetValue2"},
@@ -675,7 +693,7 @@ def test_update_stack_set_with_previous_value():
 
 @mock_cloudformation
 def test_list_stack_set_operations():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     cf.create_stack_set(StackSetName="teststackset", TemplateBody=dummy_template_json)
     cf.create_stack_instances(
         StackSetName="teststackset",
@@ -695,7 +713,7 @@ def test_list_stack_set_operations():
 
 @mock_cloudformation
 def test_bad_list_stack_resources():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
 
     with pytest.raises(ClientError):
         cf.list_stack_resources(StackName="teststackset")
@@ -703,7 +721,7 @@ def test_bad_list_stack_resources():
 
 @mock_cloudformation
 def test_delete_stack_set_by_name():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     cf.create_stack_set(StackSetName="teststackset", TemplateBody=dummy_template_json)
     cf.delete_stack_set(StackSetName="teststackset")
 
@@ -721,7 +739,7 @@ def test_delete_stack_set_by_name():
 
 @mock_cloudformation
 def test_delete_stack_set_by_id():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     response = cf.create_stack_set(
         StackSetName="teststackset", TemplateBody=dummy_template_json
     )
@@ -736,7 +754,7 @@ def test_delete_stack_set_by_id():
 
 @mock_cloudformation
 def test_delete_stack_set__while_instances_are_running():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     cf.create_stack_set(StackSetName="a", TemplateBody=json.dumps(dummy_template3))
     cf.create_stack_instances(
         StackSetName="a",
@@ -762,7 +780,7 @@ def test_delete_stack_set__while_instances_are_running():
 
 @mock_cloudformation
 def test_create_stack_set():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     response = cf.create_stack_set(
         StackSetName="teststackset",
         TemplateBody=dummy_template_json,
@@ -780,7 +798,7 @@ def test_create_stack_set():
 @mock_cloudformation
 @pytest.mark.parametrize("name", ["1234", "stack_set", "-set"])
 def test_create_stack_set__invalid_name(name):
-    client = boto3.client("cloudformation", region_name="us-east-1")
+    client = boto3.client("cloudformation", region_name=REGION_NAME)
     with pytest.raises(ClientError) as exc:
         client.create_stack_set(StackSetName=name)
     err = exc.value.response["Error"]
@@ -793,7 +811,7 @@ def test_create_stack_set__invalid_name(name):
 
 @mock_cloudformation
 def test_create_stack_set_with_yaml():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     cf.create_stack_set(StackSetName="tss", TemplateBody=dummy_template_yaml)
 
     tmplt = cf.describe_stack_set(StackSetName="tss")["StackSet"]["TemplateBody"]
@@ -803,8 +821,8 @@ def test_create_stack_set_with_yaml():
 @mock_cloudformation
 @mock_s3
 def test_create_stack_set_from_s3_url():
-    s3 = boto3.client("s3", region_name="us-east-1")
-    s3_conn = boto3.resource("s3", region_name="us-east-1")
+    s3 = boto3.client("s3", region_name=REGION_NAME)
+    s3_conn = boto3.resource("s3", region_name=REGION_NAME)
     s3_conn.create_bucket(Bucket="foobar")
 
     s3_conn.Object("foobar", "template-key").put(Body=dummy_template_json)
@@ -820,7 +838,7 @@ def test_create_stack_set_from_s3_url():
 
 @mock_cloudformation
 def test_create_stack_set_with_ref_yaml():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     params = [
         {"ParameterKey": "TagDescription", "ParameterValue": "desc_ref"},
         {"ParameterKey": "TagName", "ParameterValue": "name_ref"},
@@ -837,7 +855,7 @@ def test_create_stack_set_with_ref_yaml():
 
 @mock_cloudformation
 def test_describe_stack_set_params():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     params = [
         {"ParameterKey": "TagDescription", "ParameterValue": "desc_ref"},
         {"ParameterKey": "TagName", "ParameterValue": "name_ref"},
@@ -854,7 +872,7 @@ def test_describe_stack_set_params():
 
 @mock_cloudformation
 def test_describe_stack_set_by_id():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     ss_id = cf.create_stack_set(StackSetName="s", TemplateBody=dummy_template_json)[
         "StackSetId"
     ]
@@ -865,7 +883,7 @@ def test_describe_stack_set_by_id():
 
 @mock_cloudformation
 def test_create_stack_fail_missing_parameter():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
 
     with pytest.raises(ClientError, match="Missing parameter KeyName"):
         cf.create_stack(StackName="ts", TemplateBody=dummy_parametrized_template_json)
@@ -873,7 +891,7 @@ def test_create_stack_fail_missing_parameter():
 
 @mock_cloudformation
 def test_create_stack_s3_long_name():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
 
     stack_name = "MyLongStackName01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012"
 
@@ -897,7 +915,7 @@ def test_create_stack_s3_long_name():
 
 @mock_cloudformation
 def test_create_stack_with_yaml():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     cf.create_stack(StackName="ts", TemplateBody=dummy_template_yaml)
 
     assert cf.get_template(StackName="ts")["TemplateBody"] == dummy_template_yaml
@@ -905,7 +923,7 @@ def test_create_stack_with_yaml():
 
 @mock_cloudformation
 def test_create_stack_with_short_form_func_yaml():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     cf.create_stack(
         StackName="ts", TemplateBody=dummy_template_yaml_with_short_form_func
     )
@@ -917,11 +935,11 @@ def test_create_stack_with_short_form_func_yaml():
 @mock_s3
 @mock_cloudformation
 def test_get_template_summary():
-    s3 = boto3.client("s3", region_name="us-east-1")
-    s3_conn = boto3.resource("s3", region_name="us-east-1")
+    s3 = boto3.client("s3", region_name=REGION_NAME)
+    s3_conn = boto3.resource("s3", region_name=REGION_NAME)
 
     # json template
-    conn = boto3.client("cloudformation", region_name="us-east-1")
+    conn = boto3.client("cloudformation", region_name=REGION_NAME)
     result = conn.get_template_summary(TemplateBody=json.dumps(dummy_template3))
     assert result["ResourceTypes"] == ["AWS::EC2::VPC"]
     assert result["Version"] == "2010-09-09"
@@ -929,8 +947,10 @@ def test_get_template_summary():
     assert result["Parameters"] == []
 
     # existing stack
-    conn.create_stack(StackName="test_stack", TemplateBody=json.dumps(dummy_template3))
-    result = conn.get_template_summary(StackName="test_stack")
+    conn.create_stack(
+        StackName=TEST_STACK_NAME, TemplateBody=json.dumps(dummy_template3)
+    )
+    result = conn.get_template_summary(StackName=TEST_STACK_NAME)
     assert result["ResourceTypes"] == ["AWS::EC2::VPC"]
     assert result["Version"] == "2010-09-09"
     assert result["Description"] == "Stack 3"
@@ -949,7 +969,7 @@ def test_get_template_summary():
     assert result["Description"] == "Stack 3"
 
     # yaml template
-    conn = boto3.client("cloudformation", region_name="us-east-1")
+    conn = boto3.client("cloudformation", region_name=REGION_NAME)
     result = conn.get_template_summary(TemplateBody=dummy_template_yaml)
     assert result["ResourceTypes"] == ["AWS::EC2::Instance"]
     assert result["Version"] == "2010-09-09"
@@ -958,7 +978,7 @@ def test_get_template_summary():
 
 @mock_cloudformation
 def test_get_template_summary_for_stack_created_by_changeset_execution():
-    conn = boto3.client("cloudformation", region_name="us-east-1")
+    conn = boto3.client("cloudformation", region_name=REGION_NAME)
     conn.create_change_set(
         StackName="stack_from_changeset",
         TemplateBody=json.dumps(dummy_template3),
@@ -980,11 +1000,12 @@ def test_get_template_summary_for_stack_created_by_changeset_execution():
 @mock_s3
 @mock_cloudformation
 def test_get_template_summary_for_template_containing_parameters():
-    conn = boto3.client("cloudformation", region_name="us-east-1")
+    conn = boto3.client("cloudformation", region_name=REGION_NAME)
     conn.create_stack(
-        StackName="test_stack", TemplateBody=json.dumps(dummy_template_with_parameters)
+        StackName=TEST_STACK_NAME,
+        TemplateBody=json.dumps(dummy_template_with_parameters),
     )
-    result = conn.get_template_summary(StackName="test_stack")
+    result = conn.get_template_summary(StackName=TEST_STACK_NAME)
     del result["ResponseMetadata"]
     assert result == {
         "Parameters": [
@@ -1021,18 +1042,18 @@ def test_get_template_summary_for_template_containing_parameters():
 
 @mock_cloudformation
 def test_create_stack_with_ref_yaml():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     params = [
         {"ParameterKey": "TagDescription", "ParameterValue": "desc_ref"},
         {"ParameterKey": "TagName", "ParameterValue": "name_ref"},
     ]
     cf.create_stack(
-        StackName="test_stack",
+        StackName=TEST_STACK_NAME,
         TemplateBody=dummy_template_yaml_with_ref,
         Parameters=params,
     )
 
-    template_body = cf.get_template(StackName="test_stack")["TemplateBody"]
+    template_body = cf.get_template(StackName=TEST_STACK_NAME)["TemplateBody"]
     assert template_body == dummy_template_yaml_with_ref
 
 
@@ -1040,8 +1061,8 @@ def test_create_stack_with_ref_yaml():
 def test_creating_stacks_across_regions():
     west1_cf = boto3.resource("cloudformation", region_name="us-west-1")
     west2_cf = boto3.resource("cloudformation", region_name="us-west-2")
-    west1_cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json)
-    west2_cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json)
+    west1_cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json)
+    west2_cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json)
 
     west1_stacks = list(west1_cf.stacks.all())
     west2_stacks = list(west2_cf.stacks.all())
@@ -1060,17 +1081,17 @@ def test_creating_stacks_across_regions():
 @mock_sns
 @mock_sqs
 def test_create_stack_with_notification_arn():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION_NAME)
     queue = sqs.create_queue(QueueName="fake-queue")
     queue_arn = queue.attributes["QueueArn"]
 
-    sns = boto3.client("sns", region_name="us-east-1")
+    sns = boto3.client("sns", region_name=REGION_NAME)
     topic = sns.create_topic(Name="fake-topic")
     topic_arn = topic["TopicArn"]
 
     sns.subscribe(TopicArn=topic_arn, Protocol="sqs", Endpoint=queue_arn)
 
-    cf = boto3.resource("cloudformation", region_name="us-east-1")
+    cf = boto3.resource("cloudformation", region_name=REGION_NAME)
     cf.create_stack(
         StackName="test_stack_with_notifications",
         TemplateBody=dummy_template_json,
@@ -1120,7 +1141,7 @@ def test_create_stack_with_notification_arn():
 
 @mock_cloudformation
 def test_create_stack_with_role_arn():
-    cf = boto3.resource("cloudformation", region_name="us-east-1")
+    cf = boto3.resource("cloudformation", region_name=REGION_NAME)
     cf.create_stack(
         StackName="test_stack_with_notifications",
         TemplateBody=dummy_template_json,
@@ -1133,8 +1154,8 @@ def test_create_stack_with_role_arn():
 @mock_cloudformation
 @mock_s3
 def test_create_stack_from_s3_url():
-    s3 = boto3.client("s3", region_name="us-east-1")
-    s3_conn = boto3.resource("s3", region_name="us-east-1")
+    s3 = boto3.client("s3", region_name=REGION_NAME)
+    s3_conn = boto3.resource("s3", region_name=REGION_NAME)
     s3_conn.create_bucket(Bucket="foobar")
 
     s3_conn.Object("foobar", "template-key").put(Body=dummy_template_json)
@@ -1152,7 +1173,7 @@ def test_create_stack_from_s3_url():
 def test_update_stack_fail_missing_new_parameter():
     name = "update_stack_fail_missing_new_parameter"
 
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
 
     cf.create_stack(StackName=name, TemplateBody=dummy_empty_template_json)
 
@@ -1163,7 +1184,7 @@ def test_update_stack_fail_missing_new_parameter():
 @mock_cloudformation
 def test_update_stack_fail_update_same_template_body():
     name = "update_stack_with_previous_value"
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     params = [
         {"ParameterKey": "TagName", "ParameterValue": "foo"},
         {"ParameterKey": "TagDescription", "ParameterValue": "bar"},
@@ -1198,7 +1219,7 @@ def test_update_stack_fail_update_same_template_body():
 def test_update_stack_deleted_resources_can_reference_deleted_parameters():
     name = "update_stack_deleted_resources_can_reference_deleted_parameters"
 
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
 
     template_json = json.dumps(
         {
@@ -1228,7 +1249,7 @@ def test_update_stack_deleted_resources_can_reference_deleted_parameters():
 def test_update_stack_deleted_resources_can_reference_deleted_resources():
     name = "update_stack_deleted_resources_can_reference_deleted_resources"
 
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
 
     template_json = json.dumps(
         {
@@ -1261,7 +1282,7 @@ def test_update_stack_deleted_resources_can_reference_deleted_resources():
 @mock_cloudformation
 def test_update_stack_with_previous_value():
     name = "update_stack_with_previous_value"
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     cf.create_stack(
         StackName=name,
         TemplateBody=dummy_template_yaml_with_ref,
@@ -1297,10 +1318,10 @@ def test_update_stack_with_previous_value():
 @mock_s3
 @mock_ec2
 def test_update_stack_from_s3_url():
-    s3 = boto3.client("s3", region_name="us-east-1")
-    s3_conn = boto3.resource("s3", region_name="us-east-1")
+    s3 = boto3.client("s3", region_name=REGION_NAME)
+    s3_conn = boto3.resource("s3", region_name=REGION_NAME)
 
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     cf.create_stack(
         StackName="update_stack_from_url",
         TemplateBody=dummy_template_json,
@@ -1329,8 +1350,8 @@ def test_update_stack_from_s3_url():
 @mock_cloudformation
 @mock_s3
 def test_create_change_set_from_s3_url():
-    s3 = boto3.client("s3", region_name="us-east-1")
-    s3_conn = boto3.resource("s3", region_name="us-east-1")
+    s3 = boto3.client("s3", region_name=REGION_NAME)
+    s3_conn = boto3.resource("s3", region_name=REGION_NAME)
     s3_conn.create_bucket(Bucket="foobar")
 
     s3_conn.Object("foobar", "template-key").put(Body=dummy_template_json)
@@ -1355,13 +1376,21 @@ def test_create_change_set_from_s3_url():
     )
 
 
+@pytest.mark.parametrize(
+    "stack_template,change_template",
+    [
+        pytest.param(dummy_template_yaml, dummy_update_template_json),
+        pytest.param(dummy_template_json, dummy_update_template_json),
+        pytest.param(dummy_template_yaml, dummy_update_template_yaml),
+    ],
+)
 @mock_cloudformation
 @mock_ec2
-def test_describe_change_set():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+def test_describe_change_set(stack_template, change_template):
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     cf.create_change_set(
         StackName="NewStack",
-        TemplateBody=dummy_template_json,
+        TemplateBody=stack_template,
         ChangeSetName="NewChangeSet",
         ChangeSetType="CREATE",
     )
@@ -1390,7 +1419,7 @@ def test_describe_change_set():
     cf.execute_change_set(ChangeSetName="NewChangeSet")
 
     # Verify that the changes have been applied
-    ec2 = boto3.client("ec2", region_name="us-east-1")
+    ec2 = boto3.client("ec2", region_name=REGION_NAME)
     assert len(ec2.describe_instances()["Reservations"]) == 1
 
     change_set = cf.describe_change_set(ChangeSetName="NewChangeSet")
@@ -1403,7 +1432,7 @@ def test_describe_change_set():
     # create another change set to update the stack
     cf.create_change_set(
         StackName="NewStack",
-        TemplateBody=dummy_update_template_json,
+        TemplateBody=change_template,
         ChangeSetName="NewChangeSet2",
         ChangeSetType="UPDATE",
         Parameters=[{"ParameterKey": "KeyName", "ParameterValue": "value"}],
@@ -1425,8 +1454,8 @@ def test_describe_change_set():
 @mock_cloudformation
 @mock_ec2
 def test_execute_change_set_w_arn():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
-    ec2 = boto3.client("ec2", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
+    ec2 = boto3.client("ec2", region_name=REGION_NAME)
     # Verify no instances exist at the moment
     assert len(ec2.describe_instances()["Reservations"]) == 0
     # Create a Change set, and verify no resources have been created yet
@@ -1447,7 +1476,7 @@ def test_execute_change_set_w_arn():
 
 @mock_cloudformation
 def test_execute_change_set_w_name():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     cf.create_change_set(
         StackName="NewStack",
         TemplateBody=dummy_template_json,
@@ -1459,7 +1488,7 @@ def test_execute_change_set_w_name():
 
 @mock_cloudformation
 def test_describe_stack_pagination():
-    conn = boto3.client("cloudformation", region_name="us-east-1")
+    conn = boto3.client("cloudformation", region_name=REGION_NAME)
     for i in range(100):
         conn.create_stack(StackName=f"test_stack_{i}", TemplateBody=dummy_template_json)
 
@@ -1476,10 +1505,10 @@ def test_describe_stack_pagination():
 
 @mock_cloudformation
 def test_describe_stack_resource():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
-    cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json)
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
+    cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json)
 
-    stack = cf.describe_stacks(StackName="test_stack")["Stacks"][0]
+    stack = cf.describe_stacks(StackName=TEST_STACK_NAME)["Stacks"][0]
 
     response = cf.describe_stack_resource(
         StackName=stack["StackName"], LogicalResourceId="EC2Instance1"
@@ -1494,10 +1523,10 @@ def test_describe_stack_resource():
 
 @mock_cloudformation
 def test_describe_stack_resource_when_resource_does_not_exist():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
-    cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json)
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
+    cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json)
 
-    stack = cf.describe_stacks(StackName="test_stack")["Stacks"][0]
+    stack = cf.describe_stacks(StackName=TEST_STACK_NAME)["Stacks"][0]
 
     with pytest.raises(ClientError, match="does not exist for stack"):
         cf.describe_stack_resource(
@@ -1507,10 +1536,10 @@ def test_describe_stack_resource_when_resource_does_not_exist():
 
 @mock_cloudformation
 def test_describe_stack_resources():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
-    cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json)
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
+    cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json)
 
-    stack = cf.describe_stacks(StackName="test_stack")["Stacks"][0]
+    stack = cf.describe_stacks(StackName=TEST_STACK_NAME)["Stacks"][0]
 
     response = cf.describe_stack_resources(StackName=stack["StackName"])
     resource = response["StackResources"][0]
@@ -1522,11 +1551,11 @@ def test_describe_stack_resources():
 
 @mock_cloudformation
 def test_describe_stack_by_name():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
-    cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json)
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
+    cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json)
 
-    stack = cf.describe_stacks(StackName="test_stack")["Stacks"][0]
-    assert stack["StackName"] == "test_stack"
+    stack = cf.describe_stacks(StackName=TEST_STACK_NAME)["Stacks"][0]
+    assert stack["StackName"] == TEST_STACK_NAME
     two_secs_ago = datetime.now(tz=timezone.utc) - timedelta(seconds=2)
     assert (
         two_secs_ago < stack["CreationTime"] < datetime.now(tz=timezone.utc)
@@ -1535,19 +1564,19 @@ def test_describe_stack_by_name():
 
 @mock_cloudformation
 def test_describe_stack_by_stack_id():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
-    cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json)
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
+    cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json)
 
-    stack = cf.describe_stacks(StackName="test_stack")["Stacks"][0]
+    stack = cf.describe_stacks(StackName=TEST_STACK_NAME)["Stacks"][0]
     stack_by_id = cf.describe_stacks(StackName=stack["StackId"])["Stacks"][0]
 
     assert stack_by_id["StackId"] == stack["StackId"]
-    assert stack_by_id["StackName"] == "test_stack"
+    assert stack_by_id["StackName"] == TEST_STACK_NAME
 
 
 @mock_cloudformation
 def test_list_change_sets():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     cf.create_change_set(
         StackName="NewStack2",
         TemplateBody=dummy_template_json,
@@ -1561,21 +1590,21 @@ def test_list_change_sets():
 
 @mock_cloudformation
 def test_list_stacks():
-    cf = boto3.resource("cloudformation", region_name="us-east-1")
-    cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json)
+    cf = boto3.resource("cloudformation", region_name=REGION_NAME)
+    cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json)
     cf.create_stack(StackName="test_stack2", TemplateBody=dummy_template_json)
 
     stacks = list(cf.stacks.all())
     assert len(stacks) == 2
     stack_names = [stack.stack_name for stack in stacks]
-    assert "test_stack" in stack_names
+    assert TEST_STACK_NAME in stack_names
     assert "test_stack2" in stack_names
 
 
 @mock_cloudformation
 def test_delete_stack_from_resource():
-    cf = boto3.resource("cloudformation", region_name="us-east-1")
-    stack = cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json)
+    cf = boto3.resource("cloudformation", region_name=REGION_NAME)
+    stack = cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json)
 
     assert len(list(cf.stacks.all())) == 1
     stack.delete()
@@ -1585,7 +1614,7 @@ def test_delete_stack_from_resource():
 @mock_cloudformation
 @mock_ec2
 def test_delete_change_set():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     cf.create_change_set(
         StackName="NewStack",
         TemplateBody=dummy_template_json,
@@ -1611,7 +1640,7 @@ def test_delete_change_set():
 @mock_cloudformation
 @mock_ec2
 def test_create_change_set_twice__no_changes():
-    cf_client = boto3.client("cloudformation", region_name="us-east-1")
+    cf_client = boto3.client("cloudformation", region_name=REGION_NAME)
 
     # Execute once
     change_set_id = cf_client.create_change_set(
@@ -1644,9 +1673,9 @@ def test_create_change_set_twice__no_changes():
 @mock_ec2
 @mock_s3
 def test_create_change_set_twice__using_s3__no_changes():
-    cf_client = boto3.client("cloudformation", region_name="us-east-1")
-    s3 = boto3.client("s3", region_name="us-east-1")
-    s3_conn = boto3.resource("s3", region_name="us-east-1")
+    cf_client = boto3.client("cloudformation", region_name=REGION_NAME)
+    s3 = boto3.client("s3", region_name=REGION_NAME)
+    s3_conn = boto3.resource("s3", region_name=REGION_NAME)
     s3_conn.create_bucket(Bucket="foobar")
 
     s3_conn.Object("foobar", "template-key").put(Body=dummy_template_json)
@@ -1690,24 +1719,24 @@ def test_create_change_set_twice__using_s3__no_changes():
 @mock_cloudformation
 @mock_ec2
 def test_delete_stack_by_name():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
-    cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json)
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
+    cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json)
 
     assert len(cf.describe_stacks()["Stacks"]) == 1
-    cf.delete_stack(StackName="test_stack")
+    cf.delete_stack(StackName=TEST_STACK_NAME)
     assert len(cf.describe_stacks()["Stacks"]) == 0
 
 
 @mock_cloudformation
 @mock_ec2
 def test_delete_stack():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
-    ec2 = boto3.client("ec2", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
+    ec2 = boto3.client("ec2", region_name=REGION_NAME)
 
-    cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json)
+    cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json)
     state = ec2.describe_instances()["Reservations"][0]["Instances"][0]["State"]
 
-    cf.delete_stack(StackName="test_stack")
+    cf.delete_stack(StackName=TEST_STACK_NAME)
     stacks = cf.list_stacks()
     assert stacks["StackSummaries"][0]["StackStatus"] == "DELETE_COMPLETE"
     assert ec2.describe_instances()["Reservations"][0]["Instances"][0]["State"] != state
@@ -1725,14 +1754,14 @@ def test_delete_stack_delete_not_implemented(monkeypatch):
     )
     monkeypatch.delattr("moto.ec2.models.instances.Instance.delete")
 
-    cf = boto3.client("cloudformation", region_name="us-east-1")
-    ec2 = boto3.client("ec2", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
+    ec2 = boto3.client("ec2", region_name=REGION_NAME)
 
-    cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json)
+    cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json)
     state = ec2.describe_instances()["Reservations"][0]["Instances"][0]["State"]
 
     # Mock stack deletion succeeds
-    cf.delete_stack(StackName="test_stack")
+    cf.delete_stack(StackName=TEST_STACK_NAME)
     stacks = cf.list_stacks()
     assert stacks["StackSummaries"][0]["StackStatus"] == "DELETE_COMPLETE"
     # But the underlying resource is untouched
@@ -1741,21 +1770,21 @@ def test_delete_stack_delete_not_implemented(monkeypatch):
 
 @mock_cloudformation
 def test_describe_deleted_stack():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
-    cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json)
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
+    cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json)
 
-    stack = cf.describe_stacks(StackName="test_stack")["Stacks"][0]
+    stack = cf.describe_stacks(StackName=TEST_STACK_NAME)["Stacks"][0]
     stack_id = stack["StackId"]
     cf.delete_stack(StackName=stack["StackId"])
     stack_by_id = cf.describe_stacks(StackName=stack_id)["Stacks"][0]
     assert stack_by_id["StackId"] == stack["StackId"]
-    assert stack_by_id["StackName"] == "test_stack"
+    assert stack_by_id["StackName"] == TEST_STACK_NAME
     assert stack_by_id["StackStatus"] == "DELETE_COMPLETE"
 
 
 @mock_cloudformation
 def test_describe_stack_with_special_chars():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     cf.create_stack(
         StackName="test_stack_spl",
         TemplateBody=dummy_template_special_chars_in_description_json,
@@ -1769,53 +1798,53 @@ def test_describe_stack_with_special_chars():
 @mock_cloudformation
 @mock_ec2
 def test_describe_updated_stack():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     cf.create_stack(
-        StackName="test_stack",
+        StackName=TEST_STACK_NAME,
         TemplateBody=dummy_template_json,
         Tags=[{"Key": "foo", "Value": "bar"}],
     )
 
     cf.update_stack(
-        StackName="test_stack",
+        StackName=TEST_STACK_NAME,
         RoleARN=f"arn:aws:iam::{ACCOUNT_ID}:role/moto",
         TemplateBody=dummy_update_template_json,
         Tags=[{"Key": "foo", "Value": "baz"}],
         Parameters=[{"ParameterKey": "KeyName", "ParameterValue": "value"}],
     )
 
-    stack = cf.describe_stacks(StackName="test_stack")["Stacks"][0]
+    stack = cf.describe_stacks(StackName=TEST_STACK_NAME)["Stacks"][0]
     stack_id = stack["StackId"]
     stack_by_id = cf.describe_stacks(StackName=stack_id)["Stacks"][0]
     assert stack_by_id["StackId"] == stack["StackId"]
-    assert stack_by_id["StackName"] == "test_stack"
+    assert stack_by_id["StackName"] == TEST_STACK_NAME
     assert stack_by_id["StackStatus"] == "UPDATE_COMPLETE"
     assert stack_by_id["RoleARN"] == f"arn:aws:iam::{ACCOUNT_ID}:role/moto"
     assert stack_by_id["Tags"] == [{"Key": "foo", "Value": "baz"}]
 
     # Verify the updated template is persisted
-    template = cf.get_template(StackName="test_stack")["TemplateBody"]
+    template = cf.get_template(StackName=TEST_STACK_NAME)["TemplateBody"]
     assert template == dummy_update_template
 
 
 @mock_cloudformation
 def test_update_stack_with_previous_template():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
-    cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json)
-    cf.update_stack(StackName="test_stack", UsePreviousTemplate=True)
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
+    cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json)
+    cf.update_stack(StackName=TEST_STACK_NAME, UsePreviousTemplate=True)
 
-    stack = cf.describe_stacks(StackName="test_stack")["Stacks"][0]
-    assert stack["StackName"] == "test_stack"
+    stack = cf.describe_stacks(StackName=TEST_STACK_NAME)["Stacks"][0]
+    assert stack["StackName"] == TEST_STACK_NAME
     assert stack["StackStatus"] == "UPDATE_COMPLETE"
 
     # Verify the original template is persisted
-    template = cf.get_template(StackName="test_stack")["TemplateBody"]
+    template = cf.get_template(StackName=TEST_STACK_NAME)["TemplateBody"]
     assert template == dummy_template
 
 
 @mock_cloudformation
 def test_bad_describe_stack():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     with pytest.raises(ClientError) as exc:
         cf.describe_stacks(StackName="non_existent_stack")
     err = exc.value.response["Error"]
@@ -1839,9 +1868,9 @@ def test_cloudformation_params():
     }
     dummy_template_with_params_json = json.dumps(dummy_template_with_params)
 
-    cf = boto3.resource("cloudformation", region_name="us-east-1")
+    cf = boto3.resource("cloudformation", region_name=REGION_NAME)
     stack = cf.create_stack(
-        StackName="test_stack",
+        StackName=TEST_STACK_NAME,
         TemplateBody=dummy_template_with_params_json,
         Parameters=[{"ParameterKey": "APPNAME", "ParameterValue": "testing123"}],
     )
@@ -1867,19 +1896,19 @@ def test_update_stack_with_parameters():
         "Parameters": {"Bar": {"Type": "String"}},
     }
     template_json = json.dumps(template)
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     cf.create_stack(
-        StackName="test_stack",
+        StackName=TEST_STACK_NAME,
         TemplateBody=template_json,
         Parameters=[{"ParameterKey": "Bar", "ParameterValue": "192.168.0.0/16"}],
     )
     cf.update_stack(
-        StackName="test_stack",
+        StackName=TEST_STACK_NAME,
         TemplateBody=template_json,
         Parameters=[{"ParameterKey": "Bar", "ParameterValue": "192.168.0.1/16"}],
     )
 
-    stack = cf.describe_stacks(StackName="test_stack")["Stacks"][0]
+    stack = cf.describe_stacks(StackName=TEST_STACK_NAME)["Stacks"][0]
     assert len(stack["Parameters"]) == 1
     assert stack["Parameters"][0] == {
         "ParameterKey": "Bar",
@@ -1890,19 +1919,19 @@ def test_update_stack_with_parameters():
 @mock_cloudformation
 @mock_ec2
 def test_update_stack_replace_tags():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     cf.create_stack(
-        StackName="test_stack",
+        StackName=TEST_STACK_NAME,
         TemplateBody=dummy_template_json,
         Tags=[{"Key": "foo", "Value": "bar"}],
     )
     cf.update_stack(
-        StackName="test_stack",
+        StackName=TEST_STACK_NAME,
         TemplateBody=dummy_template_json,
         Tags=[{"Key": "foo", "Value": "baz"}],
     )
 
-    stack = cf.describe_stacks(StackName="test_stack")["Stacks"][0]
+    stack = cf.describe_stacks(StackName=TEST_STACK_NAME)["Stacks"][0]
     assert stack["StackStatus"] == "UPDATE_COMPLETE"
     assert stack["Tags"] == [{"Key": "foo", "Value": "baz"}]
 
@@ -1911,8 +1940,8 @@ def test_update_stack_replace_tags():
 def test_update_stack_when_rolled_back():
     if settings.TEST_SERVER_MODE:
         raise SkipTest("Cant manipulate backend in server mode")
-    cf = boto3.client("cloudformation", region_name="us-east-1")
-    stack = cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json)
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
+    stack = cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json)
     stack_id = stack["StackId"]
 
     cloudformation_backends[ACCOUNT_ID]["us-east-1"].stacks[
@@ -1920,7 +1949,7 @@ def test_update_stack_when_rolled_back():
     ].status = "ROLLBACK_COMPLETE"
 
     with pytest.raises(ClientError) as ex:
-        cf.update_stack(StackName="test_stack", TemplateBody=dummy_template_json)
+        cf.update_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json)
 
     err = ex.value.response["Error"]
     assert err["Code"] == "ValidationError"
@@ -1951,7 +1980,7 @@ def test_cloudformation_params_conditions_and_resources_are_distinct():
         },
     }
     template_with_conditions = json.dumps(template_with_conditions)
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     cf.create_stack(
         StackName="test_stack1",
         TemplateBody=template_with_conditions,
@@ -1968,7 +1997,7 @@ def test_cloudformation_params_conditions_and_resources_are_distinct():
 @mock_cloudformation
 @mock_ec2
 def test_cloudformation_conditions_yaml_equals():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     cf.create_stack(
         StackName="teststack2",
         TemplateBody=dummy_yaml_template_with_equals,
@@ -1987,7 +2016,7 @@ def test_cloudformation_conditions_yaml_equals():
 def test_cloudformation_conditions_yaml_equals_shortform():
     _template = dummy_yaml_template_with_equals
     _template = _template.replace("Fn::Equals:", "!Equals")
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     cf.create_stack(
         StackName="teststack2",
         TemplateBody=_template,
@@ -2004,9 +2033,9 @@ def test_cloudformation_conditions_yaml_equals_shortform():
 @mock_cloudformation
 def test_stack_tags():
     tags = [{"Key": "foo", "Value": "bar"}, {"Key": "baz", "Value": "bleh"}]
-    cf = boto3.resource("cloudformation", region_name="us-east-1")
+    cf = boto3.resource("cloudformation", region_name=REGION_NAME)
     stack = cf.create_stack(
-        StackName="test_stack", TemplateBody=dummy_template_json, Tags=tags
+        StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json, Tags=tags
     )
     observed_tag_items = set(
         item for items in [tag.items() for tag in stack.tags] for item in items
@@ -2020,8 +2049,8 @@ def test_stack_tags():
 @mock_cloudformation
 @mock_ec2
 def test_stack_events():
-    cf = boto3.resource("cloudformation", region_name="us-east-1")
-    stack = cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json)
+    cf = boto3.resource("cloudformation", region_name=REGION_NAME)
+    stack = cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json)
     stack.update(
         TemplateBody=dummy_update_template_json,
         Parameters=[{"ParameterKey": "KeyName", "ParameterValue": "value"}],
@@ -2049,10 +2078,10 @@ def test_stack_events():
     try:
         for event in events:
             assert event.stack_id == stack.stack_id
-            assert event.stack_name == "test_stack"
+            assert event.stack_name == TEST_STACK_NAME
 
             if event.resource_type == "AWS::CloudFormation::Stack":
-                assert event.logical_resource_id == "test_stack"
+                assert event.logical_resource_id == TEST_STACK_NAME
                 assert event.physical_resource_id == stack.stack_id
 
                 status_to_look_for, reason_to_look_for = next(stack_events_to_look_for)
@@ -2078,10 +2107,10 @@ def test_stack_events():
 
 @mock_cloudformation
 def test_list_exports():
-    cf_client = boto3.client("cloudformation", region_name="us-east-1")
-    cf_resource = boto3.resource("cloudformation", region_name="us-east-1")
+    cf_client = boto3.client("cloudformation", region_name=REGION_NAME)
+    cf_resource = boto3.resource("cloudformation", region_name=REGION_NAME)
     stack = cf_resource.create_stack(
-        StackName="test_stack", TemplateBody=dummy_output_template_json
+        StackName=TEST_STACK_NAME, TemplateBody=dummy_output_template_json
     )
     output_value = "VPCID"
     exports = cf_client.list_exports()["Exports"]
@@ -2097,7 +2126,7 @@ def test_list_exports():
 
 @mock_cloudformation
 def test_list_exports_with_token():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     for i in range(101):
         # Add index to ensure name is unique
         dummy_output_template["Outputs"]["StackVPC"]["Export"]["Name"] += str(i)
@@ -2116,9 +2145,9 @@ def test_list_exports_with_token():
 
 @mock_cloudformation
 def test_delete_stack_with_export():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     stack = cf.create_stack(
-        StackName="test_stack", TemplateBody=dummy_output_template_json
+        StackName=TEST_STACK_NAME, TemplateBody=dummy_output_template_json
     )
 
     stack_id = stack["StackId"]
@@ -2131,17 +2160,19 @@ def test_delete_stack_with_export():
 
 @mock_cloudformation
 def test_export_names_must_be_unique():
-    cf = boto3.resource("cloudformation", region_name="us-east-1")
-    cf.create_stack(StackName="test_stack", TemplateBody=dummy_output_template_json)
+    cf = boto3.resource("cloudformation", region_name=REGION_NAME)
+    cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_output_template_json)
     with pytest.raises(ClientError):
-        cf.create_stack(StackName="test_stack", TemplateBody=dummy_output_template_json)
+        cf.create_stack(
+            StackName=TEST_STACK_NAME, TemplateBody=dummy_output_template_json
+        )
 
 
 @mock_sqs
 @mock_cloudformation
 def test_stack_with_imports():
-    cf = boto3.resource("cloudformation", region_name="us-east-1")
-    ec2_resource = boto3.resource("sqs", region_name="us-east-1")
+    cf = boto3.resource("cloudformation", region_name=REGION_NAME)
+    ec2_resource = boto3.resource("sqs", region_name=REGION_NAME)
 
     output_stack = cf.create_stack(
         StackName="test_stack1", TemplateBody=dummy_output_template_json
@@ -2156,7 +2187,7 @@ def test_stack_with_imports():
 @mock_sqs
 @mock_cloudformation
 def test_non_json_redrive_policy():
-    cf = boto3.resource("cloudformation", region_name="us-east-1")
+    cf = boto3.resource("cloudformation", region_name=REGION_NAME)
 
     stack = cf.create_stack(
         StackName="test_stack1", TemplateBody=dummy_redrive_template_json
@@ -2168,25 +2199,25 @@ def test_non_json_redrive_policy():
 
 @mock_cloudformation
 def test_create_duplicate_stack():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
-    cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json)
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
+    cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json)
 
     with pytest.raises(ClientError):
-        cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json)
+        cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json)
 
 
 @mock_dynamodb
 @mock_cloudformation
 def test_delete_stack_dynamo_template():
-    conn = boto3.client("cloudformation", region_name="us-east-1")
-    dynamodb_client = boto3.client("dynamodb", region_name="us-east-1")
-    conn.create_stack(StackName="test_stack", TemplateBody=dummy_template_json4)
+    conn = boto3.client("cloudformation", region_name=REGION_NAME)
+    dynamodb_client = boto3.client("dynamodb", region_name=REGION_NAME)
+    conn.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json4)
     table_desc = dynamodb_client.list_tables()
     assert len(table_desc.get("TableNames")) == 1
-    conn.delete_stack(StackName="test_stack")
+    conn.delete_stack(StackName=TEST_STACK_NAME)
     table_desc = dynamodb_client.list_tables()
     assert len(table_desc.get("TableNames")) == 0
-    conn.create_stack(StackName="test_stack", TemplateBody=dummy_template_json4)
+    conn.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json4)
 
 
 @mock_dynamodb
@@ -2195,7 +2226,7 @@ def test_delete_stack_dynamo_template():
 def test_create_stack_lambda_and_dynamodb():
     if settings.TEST_SERVER_MODE:
         raise SkipTest("Cant set environment variables in server mode")
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     template = {
         "AWSTemplateFormatVersion": "2010-09-09",
         "Description": "Stack Lambda Test 1",
@@ -2267,40 +2298,42 @@ def test_create_stack_lambda_and_dynamodb():
 @mock_cloudformation
 @mock_ec2
 def test_create_and_update_stack_with_unknown_resource():
-    cf = boto3.client("cloudformation", region_name="us-east-1")
+    cf = boto3.client("cloudformation", region_name=REGION_NAME)
     # Creating a stack with an unknown resource should throw a warning
     expected_err = "Tried to parse AWS::Cloud9::EnvironmentEC2 but it's not supported by moto's CloudFormation implementation"
     if settings.TEST_SERVER_MODE:
         # Can't verify warnings in ServerMode though
         cf.create_stack(
-            StackName="test_stack", TemplateBody=dummy_unknown_template_json
+            StackName=TEST_STACK_NAME, TemplateBody=dummy_unknown_template_json
         )
     else:
         with pytest.warns(UserWarning, match=expected_err):
             cf.create_stack(
-                StackName="test_stack", TemplateBody=dummy_unknown_template_json
+                StackName=TEST_STACK_NAME, TemplateBody=dummy_unknown_template_json
             )
 
     # The stack should exist though
     stacks = cf.describe_stacks()["Stacks"]
     assert len(stacks) == 1
-    assert stacks[0]["StackName"] == "test_stack"
+    assert stacks[0]["StackName"] == TEST_STACK_NAME
 
     # Updating an unknown resource should throw a warning, but not fail
     new_template = copy.deepcopy(dummy_unknown_template)
     new_template["Resources"]["UnknownResource"]["Properties"]["Sth"] = "other"
     if settings.TEST_SERVER_MODE:
-        cf.update_stack(StackName="test_stack", TemplateBody=json.dumps(new_template))
+        cf.update_stack(
+            StackName=TEST_STACK_NAME, TemplateBody=json.dumps(new_template)
+        )
     else:
         with pytest.warns(UserWarning, match=expected_err):
             cf.update_stack(
-                StackName="test_stack", TemplateBody=json.dumps(new_template)
+                StackName=TEST_STACK_NAME, TemplateBody=json.dumps(new_template)
             )
 
 
 def get_role_name():
     with mock_iam():
-        iam = boto3.client("iam", region_name="us-east-1")
+        iam = boto3.client("iam", region_name=REGION_NAME)
         try:
             return iam.get_role(RoleName="my-role")["Role"]["Arn"]
         except ClientError:
diff --git a/tests/test_ssoadmin/test_ssoadmin_policies.py b/tests/test_ssoadmin/test_ssoadmin_policies.py
index 7eee8260c..f9f2add04 100644
--- a/tests/test_ssoadmin/test_ssoadmin_policies.py
+++ b/tests/test_ssoadmin/test_ssoadmin_policies.py
@@ -5,6 +5,7 @@ import pytest
 from botocore.exceptions import ClientError
 
 from moto import mock_ssoadmin
+from moto.iam.aws_managed_policies import aws_managed_policies_data
 
 # See our Development Tips on writing tests for hints on how to write good tests:
 # http://docs.getmoto.org/en/latest/docs/contributing/development_tips/tests.html
@@ -15,6 +16,11 @@ DUMMY_PERMISSIONSET_ID = (
 DUMMY_INSTANCE_ARN = "arn:aws:sso:::instance/ins-aaaabbbbccccdddd"
 
 
+@pytest.fixture(name="managed_policies")
+def get_managed_policies():
+    return json.loads(aws_managed_policies_data)
+
+
 def create_permissionset(client) -> str:
     """Helper function to create a dummy permission set and returns the arn."""
 
@@ -130,3 +136,195 @@ def test_delete_inline_policy_to_permissionset():
     )
 
     assert response["InlinePolicy"] == ""
+
+
+@mock_ssoadmin
+def test_attach_managed_policy_to_permission_set():
+    client = boto3.client("sso-admin", region_name="us-east-1")
+
+    permission_set_arn = create_permissionset(client)
+    permissionset_id = permission_set_arn.split("/")[-1]
+    managed_policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
+
+    client.attach_managed_policy_to_permission_set(
+        InstanceArn=DUMMY_INSTANCE_ARN,
+        PermissionSetArn=permission_set_arn,
+        ManagedPolicyArn=managed_policy_arn,
+    )
+
+    response = client.list_managed_policies_in_permission_set(
+        InstanceArn=DUMMY_INSTANCE_ARN,
+        PermissionSetArn=permission_set_arn,
+    )
+
+    assert response["AttachedManagedPolicies"][0]["Name"] == "AdministratorAccess"
+    assert (
+        response["AttachedManagedPolicies"][0]["Arn"]
+        == "arn:aws:iam::aws:policy/AdministratorAccess"
+    )
+
+    # test for managed policy that is already attached
+    with pytest.raises(ClientError) as e:
+        client.attach_managed_policy_to_permission_set(
+            InstanceArn=DUMMY_INSTANCE_ARN,
+            PermissionSetArn=permission_set_arn,
+            ManagedPolicyArn=managed_policy_arn,
+        )
+    err = e.value.response["Error"]
+    assert err["Code"] == "ConflictException"
+    assert (
+        err["Message"]
+        == f"Permission set with id {permissionset_id} already has a typed link attachment to a manged policy with {managed_policy_arn}"
+    )
+
+    # test for managed policy that does not exist
+    not_exist_managed_policy_arn = "arn:aws:iam::aws:policy/DoesNotExist"
+    with pytest.raises(ClientError) as e:
+        client.attach_managed_policy_to_permission_set(
+            InstanceArn=DUMMY_INSTANCE_ARN,
+            PermissionSetArn=permission_set_arn,
+            ManagedPolicyArn=not_exist_managed_policy_arn,
+        )
+    err = e.value.response["Error"]
+    assert err["Code"] == "ResourceNotFoundException"
+    assert (
+        err["Message"]
+        == "Policy does not exist with ARN: arn:aws:iam::aws:policy/DoesNotExist"
+    )
+
+
+@mock_ssoadmin
+def test_list_managed_policies_quota_limit(managed_policies):
+    """
+    Tests exceeding the managed policy quota limit.
+    """
+    managed_policies_to_attach = []
+    policy_count = 0
+    for policy_name in managed_policies:
+        path = managed_policies[policy_name]["Path"]
+        # only attach policies with path "/"
+        if path != "/":
+            continue
+        managed_policies_to_attach.append(policy_name)
+        policy_count += 1
+        if policy_count >= 21:  # 20 is the quota limit
+            break
+
+    client = boto3.client("sso-admin", region_name="us-east-1")
+    permission_set_arn = create_permissionset(client)
+    permission_set_id = permission_set_arn.split("/")[-1]
+
+    arn_string = "arn:aws:iam::aws:policy/"
+    with pytest.raises(ClientError) as e:
+        # the 21st policy should exceed the quota limit
+        for managed_policy in managed_policies_to_attach:
+            client.attach_managed_policy_to_permission_set(
+                InstanceArn=DUMMY_INSTANCE_ARN,
+                PermissionSetArn=permission_set_arn,
+                ManagedPolicyArn=arn_string + managed_policy,
+            )
+    err = e.value.response["Error"]
+    assert err["Code"] == "ServiceQuotaExceededException"
+    assert (
+        err["Message"]
+        == f"You have exceeded AWS SSO limits. Cannot create ManagedPolicy more than 20 for id {permission_set_id}. Please refer to https://docs.aws.amazon.com/singlesignon/latest/userguide/limits.html"
+    )
+
+
+@mock_ssoadmin
+def test_list_managed_policies_in_permission_set(managed_policies):
+    """
+    Tests functionality of listing aws managed policies attached to a permission set.
+    This also tests the pagination functionality.
+    """
+    client = boto3.client("sso-admin", region_name="us-east-1")
+
+    arn_string = "arn:aws:iam::aws:policy/"
+
+    # create a dummy permission set
+    permission_set_arn = create_permissionset(client)
+
+    managed_policies_names = list(managed_policies.keys())
+
+    # attach 3 good managed policies
+    for idx in range(3):
+        managed_policy_name = managed_policies_names[idx]
+
+        client.attach_managed_policy_to_permission_set(
+            InstanceArn=DUMMY_INSTANCE_ARN,
+            PermissionSetArn=permission_set_arn,
+            ManagedPolicyArn=arn_string + managed_policy_name,
+        )
+
+    response = client.list_managed_policies_in_permission_set(
+        InstanceArn=DUMMY_INSTANCE_ARN,
+        PermissionSetArn=permission_set_arn,
+        MaxResults=2,
+    )
+
+    managed_policies = []
+
+    assert len(response["AttachedManagedPolicies"]) == 2
+    managed_policies.extend(response["AttachedManagedPolicies"])
+    next_token = response["NextToken"]
+
+    response = client.list_managed_policies_in_permission_set(
+        InstanceArn=DUMMY_INSTANCE_ARN,
+        PermissionSetArn=permission_set_arn,
+        MaxResults=2,
+        NextToken=next_token,
+    )
+
+    assert len(response["AttachedManagedPolicies"]) == 1
+    managed_policies.extend(response["AttachedManagedPolicies"])
+
+    # ensure the 3 unique managed policies were returned
+    actual_managed_policy_names = [
+        managed_policy["Name"] for managed_policy in managed_policies
+    ]
+    expected_managed_policy_names = managed_policies_names[:3]
+    assert all(
+        name in actual_managed_policy_names for name in expected_managed_policy_names
+    )
+
+
+@mock_ssoadmin
+def test_detach_managed_policy_from_permission_set():
+    client = boto3.client("sso-admin", region_name="us-east-1")
+    permission_set_arn = create_permissionset(client)
+    managed_policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
+
+    # test for managed policy that is not attached
+    with pytest.raises(ClientError) as e:
+        client.detach_managed_policy_from_permission_set(
+            InstanceArn=DUMMY_INSTANCE_ARN,
+            PermissionSetArn=permission_set_arn,
+            ManagedPolicyArn=managed_policy_arn,
+        )
+    err = e.value.response["Error"]
+    assert err["Code"] == "ResourceNotFoundException"
+    assert (
+        err["Message"] == f"Could not find ManagedPolicy with arn {managed_policy_arn}"
+    )
+
+    # attach managed policy
+    client.attach_managed_policy_to_permission_set(
+        InstanceArn=DUMMY_INSTANCE_ARN,
+        PermissionSetArn=permission_set_arn,
+        ManagedPolicyArn=managed_policy_arn,
+    )
+
+    # detach managed policy
+    client.detach_managed_policy_from_permission_set(
+        InstanceArn=DUMMY_INSTANCE_ARN,
+        PermissionSetArn=permission_set_arn,
+        ManagedPolicyArn=managed_policy_arn,
+    )
+
+    # ensure managed policy is detached
+    response = client.list_managed_policies_in_permission_set(
+        InstanceArn=DUMMY_INSTANCE_ARN,
+        PermissionSetArn=permission_set_arn,
+    )
+
+    assert len(response["AttachedManagedPolicies"]) == 0