Repository: getmoto/moto

Issue:
API Gateway missing support for resource policies on REST APIs
API Gateway supports adding a resource policy to REST APIs in order to control access to the API, but moto is missing support for the `policy` parameter in the API Gateway models/responses:
https://docs.aws.amazon.com/apigateway/api-reference/resource/rest-api/#policy

Would also be nice if the syntax of the resource policy was validated using the existing IAM policy validation logic in moto (although it doesn't fully support resource-based policies currently).


Discussion:

Resolving patch:
diff --git a/moto/apigateway/models.py b/moto/apigateway/models.py
--- a/moto/apigateway/models.py
+++ b/moto/apigateway/models.py
@@ -461,6 +461,7 @@ def __init__(self, id, region_name, name, description, **kwargs):
         self.description = description
         self.create_date = int(time.time())
         self.api_key_source = kwargs.get("api_key_source") or "HEADER"
+        self.policy = kwargs.get("policy") or None
         self.endpoint_configuration = kwargs.get("endpoint_configuration") or {
             "types": ["EDGE"]
         }
@@ -485,6 +486,7 @@ def to_dict(self):
             "apiKeySource": self.api_key_source,
             "endpointConfiguration": self.endpoint_configuration,
             "tags": self.tags,
+            "policy": self.policy,
         }
 
     def add_child(self, path, parent_id=None):
@@ -713,6 +715,7 @@ def create_rest_api(
         api_key_source=None,
         endpoint_configuration=None,
         tags=None,
+        policy=None,
     ):
         api_id = create_id()
         rest_api = RestAPI(
@@ -723,6 +726,7 @@ def create_rest_api(
             api_key_source=api_key_source,
             endpoint_configuration=endpoint_configuration,
             tags=tags,
+            policy=policy,
         )
         self.apis[api_id] = rest_api
         return rest_api
diff --git a/moto/apigateway/responses.py b/moto/apigateway/responses.py
--- a/moto/apigateway/responses.py
+++ b/moto/apigateway/responses.py
@@ -59,6 +59,7 @@ def restapis(self, request, full_url, headers):
             api_key_source = self._get_param("apiKeySource")
             endpoint_configuration = self._get_param("endpointConfiguration")
             tags = self._get_param("tags")
+            policy = self._get_param("policy")
 
             # Param validation
             if api_key_source and api_key_source not in API_KEY_SOURCES:
@@ -94,6 +95,7 @@ def restapis(self, request, full_url, headers):
                 api_key_source=api_key_source,
                 endpoint_configuration=endpoint_configuration,
                 tags=tags,
+                policy=policy,
             )
             return 200, {}, json.dumps(rest_api.to_dict())
 


Test patch:
diff --git a/tests/test_apigateway/test_apigateway.py b/tests/test_apigateway/test_apigateway.py
--- a/tests/test_apigateway/test_apigateway.py
+++ b/tests/test_apigateway/test_apigateway.py
@@ -69,6 +69,22 @@ def test_create_rest_api_with_tags():
     response["tags"].should.equal({"MY_TAG1": "MY_VALUE1"})
 
 
+@mock_apigateway
+def test_create_rest_api_with_policy():
+    client = boto3.client("apigateway", region_name="us-west-2")
+
+    policy = '{"Version": "2012-10-17","Statement": []}'
+    response = client.create_rest_api(
+        name="my_api", description="this is my api", policy=policy
+    )
+    api_id = response["id"]
+
+    response = client.get_rest_api(restApiId=api_id)
+
+    assert "policy" in response
+    response["policy"].should.equal(policy)
+
+
 @mock_apigateway
 def test_create_rest_api_invalid_apikeysource():
     client = boto3.client("apigateway", region_name="us-west-2")