Repository: getmoto/moto (python)

Issue:
S3 `restore_object` erroneously throws `DaysMustProvidedExceptForSelectRequest` exception.
If `Days` isn't specified moto will throw a `DaysMustProvidedExceptForSelectRequest` exception when calling `restore_object`. However the S3 API documentation states: 

> Lifetime of the active copy in days. **_Do not use with restores that specify `OutputLocation`_**

Emphasis mine. `restore_object` should allow `Days` to be undefined the call is restoring to a different location rather than in-place. 

Pull request description:
S3: RestoreObject: Remove validation around Days-parameter
Originally introduced in #7468. The validation surrounding the Days-parameter is a lot more complicated then the docs suggest, so the current implementation throws the exception when it shouldn't.

I've tried testing this against AWS, but they keep returning a `MalformedXML`-exception without explaining what's wrong - so that makes it a lot more difficult to determine how this is supposed to work. Hence the current 'fix', that just removes the validation - better to have no validation, then wrong validation.

Fixes #8635 

Patch:
diff --git a/moto/iam/models.py b/moto/iam/models.py
index 868e30797..a2a3da00b 100644
--- a/moto/iam/models.py
+++ b/moto/iam/models.py
@@ -802,7 +802,7 @@ class Role(CloudFormationModel):
         account_id: str,
         region_name: str,
     ) -> None:
-        backend = iam_backends[account_id][get_partition(region_name)]
+        backend: IAMBackend = iam_backends[account_id][get_partition(region_name)]
         for profile in backend.instance_profiles.values():
             profile.delete_role(role_name=resource_name)
 
@@ -810,6 +810,13 @@ class Role(CloudFormationModel):
             if role.name == resource_name:
                 for arn in list(role.policies.keys()):
                     role.delete_policy(arn)
+
+        # We may have inline policies attached to this role - make sure that they don't reference a deleted role
+        # If the reference still exists, it's impossible to delete the policy, because on deletion
+        # it will try to detach itself from a role that no longer exists
+        for policy in backend.inline_policies.values():
+            policy.role_names = [n for n in policy.role_names if n != resource_name]
+
         backend.delete_role(resource_name)
 
     @property
diff --git a/moto/s3/exceptions.py b/moto/s3/exceptions.py
index 21a98e8d5..bfd600f7f 100644
--- a/moto/s3/exceptions.py
+++ b/moto/s3/exceptions.py
@@ -620,26 +620,6 @@ class HeadOnDeleteMarker(Exception):
         self.marker = marker
 
 
-class DaysMustNotProvidedForSelectRequest(S3ClientError):
-    code = 400
-
-    def __init__(self) -> None:
-        super().__init__(
-            "DaysMustNotProvidedForSelectRequest",
-            "`Days` must not be provided for select requests",
-        )
-
-
-class DaysMustProvidedExceptForSelectRequest(S3ClientError):
-    code = 400
-
-    def __init__(self) -> None:
-        super().__init__(
-            "DaysMustProvidedExceptForSelectRequest",
-            "`Days` must be provided except for select requests",
-        )
-
-
 class MethodNotAllowed(S3ClientError):
     code = 405
 
diff --git a/moto/s3/models.py b/moto/s3/models.py
index c34e30c57..6350801e7 100644
--- a/moto/s3/models.py
+++ b/moto/s3/models.py
@@ -40,8 +40,6 @@ from moto.s3.exceptions import (
     BucketNeedsToBeNew,
     CopyObjectMustChangeSomething,
     CrossLocationLoggingProhibitted,
-    DaysMustNotProvidedForSelectRequest,
-    DaysMustProvidedExceptForSelectRequest,
     EntityTooSmall,
     HeadOnDeleteMarker,
     InvalidBucketName,
@@ -3104,12 +3102,6 @@ class S3Backend(BaseBackend, CloudWatchMetricProvider):
         if not key:
             raise MissingKey
 
-        if days is None and type_ is None:
-            raise DaysMustProvidedExceptForSelectRequest()
-
-        if days and type_:
-            raise DaysMustNotProvidedForSelectRequest()
-
         if key.storage_class not in ARCHIVE_STORAGE_CLASSES:
             raise InvalidObjectState(storage_class=key.storage_class)
         had_expiry_date = key.expiry_date is not None
diff --git a/moto/ssm/resources/regions.json b/moto/ssm/resources/regions.json
index e4b931efb..cd86c9077 100644
--- a/moto/ssm/resources/regions.json
+++ b/moto/ssm/resources/regions.json
@@ -1582,6 +1582,15 @@
                   "Value": "HTTPS, HTTP"
                 }
               },
+              "socialmessaging": {
+                "Value": "socialmessaging",
+                "endpoint": {
+                  "Value": "social-messaging.af-south-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "sqs": {
                 "Value": "sqs",
                 "endpoint": {
@@ -3137,6 +3146,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "rum": {
+                "Value": "rum",
+                "endpoint": {
+                  "Value": "rum.ap-east-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "s3": {
                 "Value": "s3",
                 "endpoint": {
@@ -6032,6 +6050,15 @@
                   "Value": "HTTPS, HTTP"
                 }
               },
+              "socialmessaging": {
+                "Value": "socialmessaging",
+                "endpoint": {
+                  "Value": "social-messaging.ap-northeast-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "sqs": {
                 "Value": "sqs",
                 "endpoint": {
@@ -8576,6 +8603,15 @@
                   "Value": "HTTPS, HTTP"
                 }
               },
+              "socialmessaging": {
+                "Value": "socialmessaging",
+                "endpoint": {
+                  "Value": "social-messaging.ap-northeast-2.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "sqs": {
                 "Value": "sqs",
                 "endpoint": {
@@ -14193,6 +14229,15 @@
                   "Value": "HTTPS, HTTP"
                 }
               },
+              "socialmessaging": {
+                "Value": "socialmessaging",
+                "endpoint": {
+                  "Value": "social-messaging.ap-south-2.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "sqs": {
                 "Value": "sqs",
                 "endpoint": {
@@ -19038,15 +19083,6 @@
                   "Value": "HTTPS"
                 }
               },
-              "opsworkscm": {
-                "Value": "opsworkscm",
-                "endpoint": {
-                  "Value": "opsworks-cm.ap-southeast-2.amazonaws.com"
-                },
-                "protocols": {
-                  "Value": "HTTPS"
-                }
-              },
               "opsworkspuppetenterprise": {
                 "Value": "opsworkspuppetenterprise",
                 "endpoint": {
@@ -19659,6 +19695,15 @@
                   "Value": "HTTPS, HTTP"
                 }
               },
+              "socialmessaging": {
+                "Value": "socialmessaging",
+                "endpoint": {
+                  "Value": "social-messaging.ap-southeast-2.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "sqs": {
                 "Value": "sqs",
                 "endpoint": {
@@ -23553,6 +23598,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "pca-connector-scep": {
+                "Value": "pca-connector-scep",
+                "endpoint": {
+                  "Value": "pca-connector-scep.ap-southeast-5.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "pi": {
                 "Value": "pi",
                 "endpoint": {
@@ -24013,6 +24067,15 @@
               "artifact": {
                 "Value": "artifact"
               },
+              "athena": {
+                "Value": "athena",
+                "endpoint": {
+                  "Value": "athena.ap-southeast-7.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "aurora": {
                 "Value": "aurora",
                 "endpoint": {
@@ -26954,6 +27017,15 @@
                   "Value": "HTTPS, HTTP"
                 }
               },
+              "socialmessaging": {
+                "Value": "socialmessaging",
+                "endpoint": {
+                  "Value": "social-messaging.ca-central-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "sqs": {
                 "Value": "sqs",
                 "endpoint": {
@@ -40744,6 +40816,15 @@
                   "Value": "HTTPS, HTTP"
                 }
               },
+              "socialmessaging": {
+                "Value": "socialmessaging",
+                "endpoint": {
+                  "Value": "social-messaging.eu-south-2.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "sqs": {
                 "Value": "sqs",
                 "endpoint": {
@@ -42902,15 +42983,6 @@
                   "Value": "HTTPS"
                 }
               },
-              "opsworkscm": {
-                "Value": "opsworkscm",
-                "endpoint": {
-                  "Value": "opsworks-cm.eu-west-1.amazonaws.com"
-                },
-                "protocols": {
-                  "Value": "HTTPS"
-                }
-              },
               "opsworkspuppetenterprise": {
                 "Value": "opsworkspuppetenterprise",
                 "endpoint": {
@@ -48589,6 +48661,9 @@
             "wavelength-zones": {
               "euw3-cmn1-wlz1": {
                 "Value": "euw3-cmn1-wlz1"
+              },
+              "euw3-dss1-wlz1": {
+                "Value": "euw3-dss1-wlz1"
               }
             }
           },
@@ -49677,6 +49752,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "rum": {
+                "Value": "rum",
+                "endpoint": {
+                  "Value": "rum.il-central-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "s3": {
                 "Value": "s3",
                 "endpoint": {
@@ -53322,6 +53406,15 @@
               "artifact": {
                 "Value": "artifact"
               },
+              "athena": {
+                "Value": "athena",
+                "endpoint": {
+                  "Value": "athena.mx-central-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "aurora": {
                 "Value": "aurora",
                 "endpoint": {
@@ -54036,6 +54129,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "transfer": {
+                "Value": "transfer",
+                "endpoint": {
+                  "Value": "transfer.mx-central-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "transitgateway": {
                 "Value": "transitgateway",
                 "endpoint": {
@@ -55951,6 +56053,15 @@
                   "Value": "HTTPS, HTTP"
                 }
               },
+              "socialmessaging": {
+                "Value": "socialmessaging",
+                "endpoint": {
+                  "Value": "social-messaging.sa-east-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "sqs": {
                 "Value": "sqs",
                 "endpoint": {
@@ -58510,15 +58621,6 @@
                   "Value": "HTTPS"
                 }
               },
-              "opsworkscm": {
-                "Value": "opsworkscm",
-                "endpoint": {
-                  "Value": "opsworks-cm.us-east-1.amazonaws.com"
-                },
-                "protocols": {
-                  "Value": "HTTPS"
-                }
-              },
               "opsworkspuppetenterprise": {
                 "Value": "opsworkspuppetenterprise",
                 "endpoint": {
diff --git a/moto/ssm/resources/services.json b/moto/ssm/resources/services.json
index 6222d56b2..048b59de4 100644
--- a/moto/ssm/resources/services.json
+++ b/moto/ssm/resources/services.json
@@ -5806,6 +5806,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "ap-southeast-7": {
+                "Value": "ap-southeast-7",
+                "endpoint": {
+                  "Value": "athena.ap-southeast-7.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "ca-central-1": {
                 "Value": "ca-central-1",
                 "endpoint": {
@@ -5941,6 +5950,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "mx-central-1": {
+                "Value": "mx-central-1",
+                "endpoint": {
+                  "Value": "athena.mx-central-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "sa-east-1": {
                 "Value": "sa-east-1",
                 "endpoint": {
@@ -48322,41 +48340,6 @@
               }
             }
           },
-          "opsworkscm": {
-            "Value": "opsworkscm",
-            "longName": {
-              "Value": "AWS OpsWorks for Chef Automate"
-            },
-            "regions": {
-              "ap-southeast-2": {
-                "Value": "ap-southeast-2",
-                "endpoint": {
-                  "Value": "opsworks-cm.ap-southeast-2.amazonaws.com"
-                },
-                "protocols": {
-                  "Value": "HTTPS"
-                }
-              },
-              "eu-west-1": {
-                "Value": "eu-west-1",
-                "endpoint": {
-                  "Value": "opsworks-cm.eu-west-1.amazonaws.com"
-                },
-                "protocols": {
-                  "Value": "HTTPS"
-                }
-              },
-              "us-east-1": {
-                "Value": "us-east-1",
-                "endpoint": {
-                  "Value": "opsworks-cm.us-east-1.amazonaws.com"
-                },
-                "protocols": {
-                  "Value": "HTTPS"
-                }
-              }
-            }
-          },
           "opsworkspuppetenterprise": {
             "Value": "opsworkspuppetenterprise",
             "longName": {
@@ -49580,6 +49563,10 @@
             }
           },
           "pca-connector-scep": {
+            "Value": "pca-connector-scep",
+            "longName": {
+              "Value": "Private CA Connector for SCEP"
+            },
             "regions": {
               "af-south-1": {
                 "Value": "af-south-1",
@@ -49680,6 +49667,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "ap-southeast-5": {
+                "Value": "ap-southeast-5",
+                "endpoint": {
+                  "Value": "pca-connector-scep.ap-southeast-5.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "ca-central-1": {
                 "Value": "ca-central-1",
                 "endpoint": {
@@ -57502,6 +57498,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "ap-east-1": {
+                "Value": "ap-east-1",
+                "endpoint": {
+                  "Value": "rum.ap-east-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "ap-northeast-1": {
                 "Value": "ap-northeast-1",
                 "endpoint": {
@@ -57664,6 +57669,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "il-central-1": {
+                "Value": "il-central-1",
+                "endpoint": {
+                  "Value": "rum.il-central-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "me-central-1": {
                 "Value": "me-central-1",
                 "endpoint": {
@@ -64667,6 +64681,33 @@
               "Value": "social-messaging"
             },
             "regions": {
+              "af-south-1": {
+                "Value": "af-south-1",
+                "endpoint": {
+                  "Value": "social-messaging.af-south-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
+              "ap-northeast-1": {
+                "Value": "ap-northeast-1",
+                "endpoint": {
+                  "Value": "social-messaging.ap-northeast-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
+              "ap-northeast-2": {
+                "Value": "ap-northeast-2",
+                "endpoint": {
+                  "Value": "social-messaging.ap-northeast-2.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "ap-south-1": {
                 "Value": "ap-south-1",
                 "endpoint": {
@@ -64676,6 +64717,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "ap-south-2": {
+                "Value": "ap-south-2",
+                "endpoint": {
+                  "Value": "social-messaging.ap-south-2.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "ap-southeast-1": {
                 "Value": "ap-southeast-1",
                 "endpoint": {
@@ -64685,6 +64735,24 @@
                   "Value": "HTTPS"
                 }
               },
+              "ap-southeast-2": {
+                "Value": "ap-southeast-2",
+                "endpoint": {
+                  "Value": "social-messaging.ap-southeast-2.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
+              "ca-central-1": {
+                "Value": "ca-central-1",
+                "endpoint": {
+                  "Value": "social-messaging.ca-central-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "eu-central-1": {
                 "Value": "eu-central-1",
                 "endpoint": {
@@ -64694,6 +64762,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "eu-south-2": {
+                "Value": "eu-south-2",
+                "endpoint": {
+                  "Value": "social-messaging.eu-south-2.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "eu-west-1": {
                 "Value": "eu-west-1",
                 "endpoint": {
@@ -64712,6 +64789,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "sa-east-1": {
+                "Value": "sa-east-1",
+                "endpoint": {
+                  "Value": "social-messaging.sa-east-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "us-east-1": {
                 "Value": "us-east-1",
                 "endpoint": {
@@ -69576,6 +69662,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "mx-central-1": {
+                "Value": "mx-central-1",
+                "endpoint": {
+                  "Value": "transfer.mx-central-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "sa-east-1": {
                 "Value": "sa-east-1",
                 "endpoint": {


Test patch:
diff --git a/tests/test_iam/test_iam_cloudformation.py b/tests/test_iam/test_iam_cloudformation.py
index 5650d81ca..d69c3388f 100644
--- a/tests/test_iam/test_iam_cloudformation.py
+++ b/tests/test_iam/test_iam_cloudformation.py
@@ -71,6 +71,50 @@ Resources:
         - !Ref RootRole
 """
 
+TEMPLATE_ROLE_AND_PROFILE = """
+---
+AWSTemplateFormatVersion: '2010-09-09'
+
+Resources:
+  Role:
+    Type: AWS::IAM::Role
+    Properties:
+      AssumeRolePolicyDocument:
+        Version: "2012-10-17"
+        Statement:
+          - Effect: Allow
+            Principal:
+              Service: ecs-tasks.amazonaws.com
+            Action: sts:AssumeRole
+      Policies:
+        - PolicyName: StandardTaskPolicy
+          PolicyDocument:
+            Version: "2012-10-17"
+            Statement:
+              - Sid: AllowCloudwatchLogging
+                Effect: Allow
+                Action:
+                  - logs:CreateLogStream
+                  - logs:DescribeLogGroups
+                  - logs:DescribeLogStreams
+                Resource: '*'
+
+  Pol10:
+    Type: AWS::IAM::Policy
+    Properties:
+      PolicyName: AdditionalInlinePolicy
+      PolicyDocument:
+        Version: "2012-10-17"
+        Statement:
+          - Sid: AllowCloudwatchLogging
+            Effect: Allow
+            Action:
+              - logs:PutLogEvents
+            Resource: '*'
+      Roles:
+        - !Ref Role
+"""
+
 
 # AWS::IAM::User Tests
 @mock_aws
@@ -1091,6 +1135,28 @@ Resources:
     assert exc.value.response["Error"]["Code"] == "NoSuchEntity"
 
 
+@mock_aws
+def test_delete_cfn_stack_with_policy_attached_to_role():
+    # The Stack has two resources, a Role and an InlinePolicy attached to this role.
+    # On deletion, there are two scenarios:
+    #
+    #    1. Policy is deleted first
+    #       a) removes policy from the roles it's attached to
+    #       b) removes the policy itself
+    #       c) removes the role last
+    #    2. Role is deleted first
+    #       a) removes the role
+    #       b) removes inline policy from the roles it's attached to
+    #       c) removes policy itself
+    #
+    # This test verifies that, at step 2b, we don't try to remove a policy from a role that no longer exist
+    cfn = boto3.client("cloudformation", region_name="us-east-1")
+
+    cfn.create_stack(StackName="stack1", TemplateBody=TEMPLATE_ROLE_AND_PROFILE)
+
+    cfn.delete_stack(StackName="stack1")
+
+
 # AWS::IAM::User AccessKeys
 @mock_aws
 def test_iam_cloudformation_create_user_with_access_key():
diff --git a/tests/test_s3/test_s3.py b/tests/test_s3/test_s3.py
index 952496327..4815aa317 100644
--- a/tests/test_s3/test_s3.py
+++ b/tests/test_s3/test_s3.py
@@ -711,32 +711,6 @@ def test_cannot_restore_standard_class_object():
     )
 
 
-@mock_aws
-def test_restore_object_invalid_request_params():
-    if not settings.TEST_DECORATOR_MODE:
-        raise SkipTest("Can't set transition directly in ServerMode")
-
-    s3_resource = boto3.resource("s3", region_name=DEFAULT_REGION_NAME)
-    bucket = s3_resource.Bucket("foobar")
-    bucket.create()
-
-    key = bucket.put_object(Key="the-key", Body=b"somedata", StorageClass="GLACIER")
-
-    # `Days` must be provided except for select requests
-    with pytest.raises(ClientError) as exc:
-        key.restore_object(RestoreRequest={})
-    err = exc.value.response["Error"]
-    assert err["Code"] == "DaysMustProvidedExceptForSelectRequest"
-    assert err["Message"] == "`Days` must be provided except for select requests"
-
-    # `Days` must not be provided for select requests
-    with pytest.raises(ClientError) as exc:
-        key.restore_object(RestoreRequest={"Days": 1, "Type": "SELECT"})
-    err = exc.value.response["Error"]
-    assert err["Code"] == "DaysMustNotProvidedForSelectRequest"
-    assert err["Message"] == "`Days` must not be provided for select requests"
-
-
 @mock_aws
 def test_get_versioning_status():
     s3_resource = boto3.resource("s3", region_name=DEFAULT_REGION_NAME)