- Knowledge Base
- Amazon Web Services
- Amazon API Gateway
- Limit REST API Access by IP Address
Ensure that Amazon API Gateway API access is limited only to specific (trusted) IP addresses or range of IP addresses in order to protect your REST APIs against unapproved access.
Allowing untrustworthy access to your Amazon API Gateway APIs can lead to unauthorized API invocation. To prevent API exposure, you can use the API resource policies to allow your REST APIs to be securely invoked by trusted IP addresses and/or IP address ranges.
Audit
To determine if the access to your Amazon API Gateway REST APIs is restricted to specific IP addresses/ranges, perform the following operations:
Using AWS Console
01 Sign in to the AWS Management Console.
02 Navigate to Amazon API Gateway console at https://console.aws.amazon.com/apigateway/.
03 In the left navigation panel, select APIs to access the Amazon API Gateway APIs listing page.
04 Click on the name of the REST API that you want to examine to access the API configuration. To identify a REST API check the value available in the Protocol column for each listed API.
05 In the navigation panel, within the API submenu, choose Resource Policy to access the resource policy attached to the selected API. An API resource policy is a JSON policy document that you can attach to your API in order to control whether a specified AWS principal (typically an IAM user or role) can invoke your API.
06 Inside the Resource Policy document box, search for the "Condition" policy element that contains the "aws:SourceIp" condition key, e.g. "Condition" : { "IpAddress": { "aws:SourceIp": [ "192.0.2.0/32" ] } }, where "192.0.2.0/32" is the trusted IP address that can access your REST API. The "Condition" element lets you specify conditions for when an access policy is in effect. Within the "Condition" element block you build expressions in which you use operators to match the condition in the policy against the values in the request. The "Condition" values can include the IP address of the requester, date, time, the ARN of the request source, the user name, the user ID or the user agent of the requester. For this conformity rule, the "Condition" element values must include one or more IP addresses in combination with the "Effect" element set to "Allow", which allows access based on trusted IP addresses only. If the "Condition" element does not include "aws:SourceIp" key or the "Condition" element block is not defined within the policy document, the access to the selected Amazon API Gateway REST API is not limited to trusted IP addresses/ranges only.
07 Repeat steps no. 4 – 6 for each REST API available within the current AWS cloud region.
08 Change the AWS region from the navigation bar and repeat the audit process for other regions.
Using AWS CLI
01 Run get-rest-apis command (OSX/Linux/UNIX) with custom query filters to list the IDs of the REST APIs created in the selected AWS cloud region:
aws apigateway get-rest-apis --region us-east-1 --output table --query 'items[*].id'
02 The command output should return a table with the requested API identifiers (IDs):
---------------- | GetRestApis | +--------------+ | aaabbbbccc | | aabbccddee | | abcdabcdab | +--------------+
03 Run get-rest-api command (OSX/Linux/UNIX) using the ID of the REST API that you want to examine as the identifier parameter and custom query filters to describe the resource policy attached to the selected API:
aws apigateway get-rest-api --region us-east-1 --rest-api-id aaabbbbccc --query 'policy'
04 The command output should return the attached resource policy in JSON format:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Deny", "Principal": "*", "Action": "execute-api:Invoke", "Resource": "arn:aws:execute-api:us-east-1:123456789012:aaabbbbccc///", "Condition": { "StringNotEquals": { "aws:sourceVpc": "vpc-abcdabcd" } } }, { "Effect": "Allow", "Principal": "*", "Action": "execute-api:Invoke", "Resource": "arn:aws:execute-api:us-east-1:123456789012:aaabbbbccc///" } ] }
Search the policy document returned by the get-rest-api command output for the "Condition" element that contains the "aws:SourceIp" condition key, e.g. "Condition" : { "IpAddress": { "aws:SourceIp": [ "192.0.5.0/32" ] } }, where "192.0.5.0/32" is the trusted IP address that can access your REST API. For compliance, the "Condition" element values must include one or more IP addresses in combination with the "Effect" element set to "Allow", which allows access based on trusted IP addresses only. If the "Condition" element does not include "aws:SourceIp" key or the "Condition" element block is not defined within the policy document, the access to the selected Amazon API Gateway REST API is not limited to trusted IP addresses/ranges only.
05 Repeat steps no. 3 and 4 for each REST API available in the selected AWS cloud region.
06 Change the AWS region by updating the --region command parameter value and repeat steps no. 1 – 5 to perform the audit process for other regions.
Remediation / Resolution
To enforce access to Amazon API Gateway REST APIs from specific (trusted) IP addresses/ranges only using API resource policies, perform the following operations:
Using AWS CloudFormation
01 CloudFormation template (JSON):
{ "AWSTemplateFormatVersion": "2010-09-09", "Description": "Allows Access from Specific IP Addresses", "Resources": { "RestAPI": { "Type": "AWS::ApiGateway::RestApi", "Properties": { "Name": "WebServiceRestAPI", "Description": "A simple API Gateway REST API", "Policy": { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": "*", "Action": "execute-api:Invoke", "Resource": "arn:aws:execute-api:us-east-1:123456789012:aaabbbbccc/Production/*", "Condition": { "IpAddress": { "aws:SourceIp": [ "192.0.5.0/32", "198.40.100.0/32" ] } } } ] } } }, "StageDeployment": { "Type": "AWS::ApiGateway::Deployment", "Properties": { "RestApiId": { "Ref": "RestAPI" } } }, "APIStage": { "Type": "AWS::ApiGateway::Stage", "Properties": { "DeploymentId": { "Ref": "StageDeployment" }, "RestApiId": { "Ref": "RestAPI" }, "StageName": "Production" } } } }
02 CloudFormation template (YAML):
AWSTemplateFormatVersion: '2010-09-09' Description: Allows Access from Specific IP Addresses Resources: RestAPI: Type: AWS::ApiGateway::RestApi Properties: Name: WebServiceRestAPI Description: A simple API Gateway REST API Policy: Version: '2012-10-17' Statement: - Effect: Allow Principal: '*' Action: execute-api:Invoke Resource: arn:aws:execute-api:us-east-1:123456789012:aaabbbbccc/Production/* Condition: IpAddress: aws:SourceIp: - 192.0.5.0/32 - 198.40.100.0/32 StageDeployment: Type: AWS::ApiGateway::Deployment Properties: RestApiId: !Ref 'RestAPI' APIStage: Type: AWS::ApiGateway::Stage Properties: DeploymentId: !Ref 'StageDeployment' RestApiId: !Ref 'RestAPI' StageName: Production
Using Terraform (AWS Provider)
01 Terraform configuration file (.tf):
terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 4.0" } } required_version = ">= 0.14.9" } provider "aws" { profile = "default" region = "us-east-1" } resource "aws_api_gateway_rest_api" "rest-api" { name = "web-service-rest-api" description = "A simple API Gateway REST API" } # Allows Access from Specific IP Addresses data "aws_iam_policy_document" "iam-policy-document" { statement { effect = "Allow" principals { type = "AWS" identifiers = ["*"] } actions = ["execute-api:Invoke"] resources = [aws_api_gateway_rest_api.rest-api.execution_arn] condition { test = "IpAddress" variable = "aws:SourceIp" values = ["192.0.5.0/32","198.40.100.0/32"] } } } resource "aws_api_gateway_rest_api_policy" "rest-api-policy" { rest_api_id = aws_api_gateway_rest_api.rest-api.id policy = data.aws_iam_policy_document.iam-policy-document.json } resource "aws_api_gateway_deployment" "rest-api-deployment" { rest_api_id = aws_api_gateway_rest_api.rest-api.id } resource "aws_api_gateway_stage" "api-stage" { deployment_id = aws_api_gateway_deployment.rest-api-deployment.id rest_api_id = aws_api_gateway_rest_api.rest-api.id stage_name = "Production" }
Using AWS Console
01 Sign in to the AWS Management Console.
02 Navigate to Amazon API Gateway console at https://console.aws.amazon.com/apigateway/.
03 In the left navigation panel, select APIs to access the Amazon API Gateway APIs listing page.
04 Click on the name of the REST API that you want to reconfigure (see Audit section part I to identify the right API) to access the API configuration.
05 In the navigation panel, within the API submenu, choose Resource Policy to access the resource policy attached to the selected API.
06 Within the Resource Policy editor box, find the policy statement with the "Effect" set to "Allow" and the "Action" set to "execute-api:Invoke", and append the following "Condition" element: "Condition" : { "IpAddress": { "aws:SourceIp": ["192.0.5.0/32", "198.40.100.0/32" ] }, where 192.0.5.0 and 198.40.100.0 are examples of trusted IP addresses that can invoke the selected Amazon API Gateway API (replace the described IP(s) with your own trusted IP(s)). Choose Save to apply the changes. Once the API policy has been successfully updated, only requests that originate from the IP addresses specified in the "Condition" element value can reach the selected API.
07 Repeat steps no. 4 – 6 to reconfigure other Amazon API Gateway APIs available within the current AWS region.
08 Change the AWS cloud region from the navigation bar and repeat the remediation process for other regions.
Using AWS CLI
01 Modify the existing resource policy attached to the Amazon API Gateway API that you want to reconfigure (see Audit section part II to identify the attached resource policy), to append the following "Condition" element: "Condition" : { "IpAddress": { "aws:SourceIp": ["192.0.5.0/32", "198.40.100.0/32" ] }, where 192.0.5.0 and 198.40.100.0 are examples of trusted IP addresses that can invoke the selected API (replace the described IP(s) with your own trusted IP(s)). Make sure that the "Effect" is set to "Allow" and the "Action" is set to "execute-api:Invoke", e.g.:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Deny", "Principal": "*", "Action": "execute-api:Invoke", "Resource": "arn:aws:execute-api:us-east-1:123456789012:aaabbbbccc///", "Condition": { "StringNotEquals": { "aws:sourceVpc": "vpc-abcdabcd" } } }, { "Effect": "Allow", "Principal": "*", "Action": "execute-api:Invoke", "Resource": "arn:aws:execute-api:us-east-1:123456789012:aaabbbbccc///", "Condition" : { "IpAddress": { "aws:SourceIp": ["192.0.5.0/32", "198.40.100.0/32" ] } } } ] }
02 Run update-rest-api command (OSX/Linux/UNIX) using the ID of the REST API that you want to reconfigure as the identifier parameter, to replace the existing resource policy attached to the selected API with the one modified at the previous step. Replace jsonEscapedPolicyDocument placeholder with your properly-escaped JSON policy document:
aws apigateway update-rest-api --region us-east-1 --rest-api-id aaabbbbccc --patch-operations op=replace,path=/policy,value='{\"jsonEscapedPolicyDocument\"}'
03 The command output should return the metadata available for the reconfigured API:
{ "id": "aaabbbbccc", "name": "cc-project5-api", "description": "Project5 Web API", "createdDate": "2021-02-04T10:00:00+00:00", "apiKeySource": "HEADER", "endpointConfiguration": { "types": [ "REGIONAL" ] }, "policy": "{\\\"Version\\\":\\\"2012-10-17\\\",\\\"Statement\\\":[{\\\"Effect\\\":\\\"Deny\\\",\\\"Principal\\\":\\\"*\\\",\\\"Action\\\":\\\"execute-api:Invoke\\\",\\\"Resource\\\":\\\"arn:aws:execute-api:us-east-1:123456789012:aaabbbbccc\\/\\/\\/\\\",\\\"Condition\\\":{\\\"StringNotEquals\\\":{\\\"aws:sourceVpc\\\":\\\"vpc-abcdabcd\\\"}}},{\\\"Effect\\\":\\\"Allow\\\",\\\"Principal\\\":\\\"*\\\",\\\"Action\\\":\\\"execute-api:Invoke\\\",\\\"Resource\\\":\\\"arn:aws:execute-api:us-east-1:123456789012:aaabbbbccc\\/\\/\\/\\\",\\\"Condition\\\":{\\\"IpAddress\\\":{\\\"aws:SourceIp\\\":[\\\"192.0.5.0\\/32\\\",\\\"198.40.100.0\\/32\\\"]}}}]}", "tags": {}, "disableExecuteApiEndpoint": false }
04 Repeat steps no. 1 – 3 to reconfigure other Amazon API Gateway APIs available in the selected AWS region.
05 Change the AWS cloud region by updating the --region command parameter value and repeat the remediation process for other regions.
References
- AWS Documentation
- Controlling and managing access to a REST API in API Gateway
- Controlling access to an API with API Gateway resource policies
- API Gateway resource policy examples
- Create and attach an API Gateway resource policy to an API
- AWS Command Line Interface (CLI) Documentation
- apigateway
- get-rest-apis
- get-rest-api
- update-rest-api