Skip to content

Incorrect API-Gateway resource policy for API Event function with '+' path parameters  #1549

@lintal

Description

@lintal

Description:

I have created a stack with an AWS::Serverless::Function and an AWS::Serverless::Api resource with the intention of restricting access to an IP address range. An example stack looks as follows:

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Transform": "AWS::Serverless-2016-10-31",
  "Globals": {
    "Function": {
      "Timeout": 10,
      "MemorySize": 128
    }
  },
"Resources": {
    "AppwRepublishFunction": {
      "Type": "AWS::Serverless::Function",
      "Properties": {
        "FunctionName": "MyRepublisherLambda",
        "Handler": "index.handler",
        "Runtime": "nodejs12.x",
        "CodeUri": "...",
        "Events": {
          "Post": {
            "Type": "Api",
            "Properties": {
              "Path": "/republish/{parameters+}",
              "Method": "post",
              "RestApiId": { "Ref": "ApiGateway" }
            }
          }
        },
        "Policies": [ "..." ]
      }
    },
    "ApiGateway": {
      "Type": "AWS::Serverless::Api",
      "Properties": {
        "Auth": {
          "ResourcePolicy": {
            "IpRangeWhitelist": ["111.222.0.0/16"]
          }
        },
        "CacheClusterEnabled": false,
        "EndpointConfiguration": "REGIONAL",
        "Name": "MyRepublisherApi",
        "StageName": "MyStage"
      }
    }
  }
}

When the API-Gateway resource policy, the resultant document looks as follows:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
                "arn:aws:execute-api:my-region-1:123456789012:my-api-id/MyStage/POST/republish/{parameters+}"
            ]
        },
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
                "arn:aws:execute-api:my-region-1:123456789012:my-api-id/MyStage/POST/republish/{parameters+}"
            ],
            "Condition": {
                "NotIpAddress": {
                    "aws:SourceIp": "111.222.0.0/16"
                }
            }
        }
    ]
}

The above however doesn't work even when connecting to the specified IP address range. I have to manually update the resource identifier to arn:aws:execute-api:my-region-1:123456789012:my-api-id/MyStage/POST/republish/* instead.

--

It is also worth noting that a precursor to my above example, I had setup the path to be /republish/{entityType}/{parameters+} and this gave a resource-policy with a resource-identifier
arn:aws:execute-api:my-region-1:123456789012:my-api-id/MyStage/POST/republish/*/{parameters+}.
My point is that standard parameters (without +) seem to get translated to a *, so the behaviour should likely be the same with parameters suffixed with a +.

Steps to reproduce the issue:

  1. Import a stack structured like the one provided above, setting the IP address to a suitable value for yourself.
  2. Attempt to access the API through the endpoint created.
  3. An error will be observed.
  4. Modify the Resource Policy in the AWS Api-Gateway console to use a simple * wildcard symbol, then republish the API.
  5. Attempt to access the API again and you will gain access.

Observed result:

The automatically generated Resource-Policy does not describe parameters suffixed with + and therefore in the above example, access is denied.

Expected result:

Access in the above example should be granted.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions