How do I allow only specific IP addresses to access my API Gateway REST API?

5 minute read
1

I want to allow only specific IP addresses access to my Amazon API Gateway REST API. How do I restrict access to my API Gateway REST API?

Short description

Create a resource policy for your REST API that denies access to any IP address that isn't specifically allowed.

After the resource policy is attached to your REST API, users who call the API from specified IP addresses (allowed users) can access the API. Calls from any other IP addresses are denied access and receive an HTTP 403 Forbidden error.

To block specific IP addresses and allow access for all others, see Example: Deny API traffic based on source IP address or range.

Note: API Gateway HTTP APIs currently don't support resource policies.

Resolution

Note: For the following procedure, you can use either your existing API Gateway REST API or create an example REST API for testing. If you use the example API (PetStore), skip to the second section: Create and attach a resource policy that allows only specific IP address access to your API Gateway REST API.

Set up an API method

1.    Open the API Gateway console.

2.    Choose your REST API.

3.    In the Resources pane, choose Actions. Then, choose Create Method.

4.    In the dropdown list under the / resource node, choose ANY. Then, choose the check mark icon.

5.    On the / - ANY - Setup pane, for Integration type, choose Mock.

6.    Choose Save.

Note: A mock integration responds to any request that reaches it, which helps later with testing.

Create and attach a resource policy that allows only specific IP addresses access to your API Gateway REST API

1.    Open the API Gateway console.

2.    In the left navigation pane, choose Resource Policy.

3.    In the Resource Policy text box, paste the following example resource policy:

Example resource policy

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

3.    For aws:SourceIp, replace the sourceIpOrCIDRBlock value with the specific IP addresses that you want to grant access to. You can also specify a range of IP addresses using CIDR notation.

Example public IP address string that's listed in CIDR notation

["52.95.36.0/22", "15.230.39.196/31", "52.93.178.219/32"]

Important: The aws:SourceIp condition value works only for public IP address ranges. To allow access to private IP address ranges, use the condition value aws:VpcSourceIp instead. Then, for the aws:VpcSourceIp value, enter the private IP address of your HTTP client that's invoking your private API endpoint through the interface VPC endpoint. Note that you can invoke private API endpoints in API Gateway only through an interface VPC endpoint. For more information, see aws:VpcSourceIp.

4.    Choose Save.

Note: The $context.identity.sourceIp variable in your Amazon CloudWatch Logs lists any private IP addresses that call your REST API. For more information, see $context variables for data models, authorizers, mapping templates, and CloudWatch access logging.

Deploy your API

1.    In the Resources pane of your REST API, choose Actions.

2.    Choose Deploy API.

3.    For Deployment stage, choose [New Stage].

4.    For Stage name, enter a name. For example: v1 or demo.

5.    Choose Deploy.

Important: You must redeploy your REST API each time you make changes its resource policy.

Test the resource policy

Confirm that your REST API returns an HTTP 200 OK response to allowed IP addresses by testing your API's invoke URL using curl or the Postman app. Then, run another test from an environment without an allowed IP address to confirm that your REST API returns an HTTP 403 Forbidden error.

Note: If you don't have access to multiple environments for testing, then you can set up an Amazon Elastic Compute Cloud (Amazon EC2) instance. If you use an Amazon EC2 instance for testing, make sure that you add the instance's IP address to your API's resource policy first. Then, redeploy your API.

To test your REST API for an HTTP 200 OK response or HTTP 403 error using curl

Based on your operating system, run one of the following commands.

Important: Replace https://yourInvokeUrl/ with your REST API's invoke URL.

For Linux, Unix, and macOS environments, run the following command:

curl -IX GET https://yourInvokeUrl/

For Windows PowerShell, run the following command:

curl https://yourInvokeUrl/

If the resource policy is configured correctly, the allowed environment receives an HTTP 200 OK response. The denied environment receives an HTTP 403 Forbidden error.


Related information

Create and attach an API Gateway resource policy to an API

API Gateway resource policy examples

Access policy language overview for Amazon API Gateway

Controlling and managing access to a REST API in API Gateway

2 Comments

I was able to restrict the API Gateway access to VPN using the customer resource policy -

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": "*",
      "Action": "execute-api:Invoke",
      "Resource": "execute-api:/*/*/*"
    },
    {
      "Effect": "Deny",
      "Principal": "*",
      "Action": "execute-api:Invoke",
      "Resource": "execute-api:/*/*/*"
      "Condition": {
        "NotIpAddress": {
          "aws:SourceIp": "52.0.0.0/8"
        }
      }
    },
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:{REGION}:{AWS_ACCOUNT}:{YOUR_API_ID}/{YOUR_API_STAGE}/OPTIONS/*"
    }
  ]
}
replied 3 months ago

Thank you for your comment. We'll review and update the Knowledge Center article as needed.

profile pictureAWS
MODERATOR
replied 3 months ago