Search code examples
amazon-web-servicesaws-api-gateway

API Gateway: Why would you need both ALLOW and DENY resource policies?


I was looking at the official AWS Documentation where they are describing how to create a policy that will ALLOW requests only when the SourceIP is within a particular CIDR.

The issue I'm trying to wrap my head around is, why would you need both ALLOW and DENY? Since resource policies are supposed to define permission boundaries, shouldn't the DENY suffice?

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:region:account-id:*"
        },
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:region:account-id:*",
            "Condition": {
                "NotIpAddress": {
                    "aws:SourceIp": "123.4.5.6/24"
                }
            }
        }
    ]
}

Wouldn't something like this suffice (Option 1)?

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:region:account-id:api-id:*",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": ["123.4.5.6/24" ]
                }
            }
        }
    ]
}

Or (Option 2) with just a Deny except:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:region:account-id:api-id:*",
            "Condition": {
                "NotIpAddress": {
                    "aws:SourceIp": ["123.4.5.6/24" ]
                }
            }
        }
    ]
}

Solution

  • When someone tries to access the API:

    1. If there is a DENY policy that applies, then access is denied; Otherwise
    2. If there is an ALLOW policy that applies, then access is allowed; Otherwise
    3. Access is denied.

    So your option 2 just doesn't work, because there is no applicable ALLOW policy.

    Your option 1 does allow the access you want, but other policies might also allow access to various principals under various conditions.

    The version from the documentation ensures that access is only provided to principals with a sourceIP in the given range, no matter what other policies apply, because DENY policies are checked first.