Create a private API
Before you create a private API, you first create a VPC endpoint for API Gateway. Next you create your private API and attach
a resource policy to it. Optionally, you can associate your VPC endpoint with your private API to simplify how you
invoke your API. Finally, you deploy your API.
The following procedures describe how to accomplish this. You can
create a private REST API using the AWS Management Console, AWS CLI or an AWS SDK.
Prerequisites
To follow these steps, you must have a fully configured VPC. To learn how to create a VPC, see Create a VPC only in
the Amazon VPC User Guide. To follow all recommend steps when you create your VPC, enable
private DNS. This way you can invoke your API within a VPC without having to pass the Host or x-apigw-api-id
header.
To enable private DNS, the enableDnsSupport
and
enableDnsHostnames
attributes of your VPC must be set
to true
. For more information, see DNS Support in Your
VPC and Updating DNS Support for Your VPC.
Step 1: Create a VPC endpoint for API Gateway in your VPC
The following procedure shows how to create a VPC endpoint for API Gateway. To create a VPC endpoint for API Gateway,
you specify the execute-api
domain for the AWS Region where you create your private API. The
execute-api
domain is the API Gateway component service for API execution.
When you create your VPC endpoint for API Gateway, you specify the DNS settings. If you turn off private DNS, you
can only access your API using public DNS. For more information, see Issue: I can't
connect to my public API from an API Gateway VPC endpoint.
- AWS Management Console
To create an interface VPC endpoint for API Gateway
-
Sign in to the AWS Management Console and open the Amazon VPC console at
https://console.aws.amazon.com/vpc/.
-
In the navigation pane, under Virtual private cloud, choose
Endpoints.
-
Choose Create endpoint.
-
(Optional) For Name tag, enter a name to help identify your VPC endpoint.
-
For Service category, choose AWS
services.
-
Under Services, in the search bar, enter execute-api
.
Then, choose the API Gateway service endpoint in the AWS Region where you will create your API. The service name
should look like com.amazonaws.us-east-1.execute-api
and the Type
should be Interface.
-
For VPC, choose the VPC that you want to create
the endpoint in.
-
(Optional) To turn off Enable Private DNS
Name, choose Additional settings and then clear Enable Private DNS
Name.
-
For Subnets, choose the Availability Zones where you created the
endpoint network interfaces. To improve the availability of your API, choose multiple subnets.
-
For Security group, select the security group to
associate with the VPC endpoint network interfaces.
The security group you choose must be set to allow TCP Port 443
inbound HTTPS traffic from either an IP range in your VPC or another
security group in your VPC.
-
For Policy, do one of the following:
If you have not created your private API or you don't want to configure a custom VPC endpoint policy, choose Full access.
-
If you have already created a private API and want to configure a custom VPC endpoint policy,
you can enter a custom VPC endpoint policy. For more information, see Use VPC endpoint policies for private
APIs in API Gateway.
You can update the VPC endpoint policy after you create your VPC endpoint. For more information,
see Update a VPC
endpoint policy.
-
Choose Create endpoint.
Copy the resulting VPC endpoint ID, as you might use it in future steps.
- AWS CLI
The following create-vpc-endpoint command creates a VPC endpoint:
aws ec2 create-vpc-endpoint \
--vpc-id vpc-1a2b3c4d \
--vpc-endpoint-type Interface \
--service-name com.amazonaws.us-east-1.execute-api \
--subnet-ids subnet-7b16de0c \
--security-group-id sg-1a2b3c4d
Copy the resulting VPC endpoint ID, as you might use it in future steps.
Step 2: Create a private API
After you create your VPC endpoint, you create a private REST API. The following procedure shows how to
create a private API.
- AWS Management Console
To create a private API
-
Sign in to the API Gateway console at https://console.aws.amazon.com/apigateway.
-
Choose Create API.
-
Under REST API, choose Build.
-
For Name, enter a name.
(Optional) For Description, enter a description.
-
For API endpoint type, select Private.
-
(Optional) For VPC endpoint IDs, enter a VPC endpoint ID.
If you associate a VPC endpoint ID with your private API, you can invoke your API from within your VPC without overriding a Host
header or passing an
x-apigw-api-id header
For more information, see (Optional) Associate or disassociate a VPC endpoint
with a private API.
-
Choose Create API.
After completing the preceding steps, you can follow the instructions in Get started with the REST API console to set up methods and integrations for this API, but you
can't deploy your API. To deploy your API, follow step 3 and attach a resource policy to your API.
- AWS CLI
The following create-rest-api command creates a private API:
aws apigateway create-rest-api \
--name 'Simple PetStore (AWS CLI, Private)' \
--description 'Simple private PetStore API' \
--region us-west-2 \
--endpoint-configuration '{ "types": ["PRIVATE"] }'
A successful call returns output similar to the following:
{
"createdDate": "2017-10-13T18:41:39Z",
"description": "Simple private PetStore API",
"endpointConfiguration": {
"types": "PRIVATE"
},
"id": "0qzs2sy7bh",
"name": "Simple PetStore (AWS CLI, Private)"
}
After completing the preceding steps, you can follow the instructions in Tutorial: Create a REST API using
AWS SDKs or the AWS CLI to set up methods and integrations for this API, but you
can't deploy your API. To deploy your API, follow step 3 and attach a resource policy to your API.
- SDK JavaScript v3
The following example shows how to create a private API by using the AWS SDK for JavaScript v3:
import {APIGatewayClient, CreateRestApiCommand} from "@aws-sdk/client-api-gateway";
const apig = new APIGatewayClient({region:"us-east-1"});
const input = { // CreateRestApiRequest
name: "Simple PetStore (JavaScript v3 SDK, private)", // required
description: "Demo private API created using the AWS SDK for JavaScript v3",
version: "0.00.001",
endpointConfiguration: { // EndpointConfiguration
types: [ "PRIVATE"],
},
};
export const handler = async (event) => {
const command = new CreateRestApiCommand(input);
try {
const result = await apig.send(command);
console.log(result);
} catch (err){
console.error(err)
}
};
A successful call returns output similar to the following:
{
apiKeySource: 'HEADER',
createdDate: 2024-04-03T17:56:36.000Z,
description: 'Demo private API created using the AWS SDK for JavaScript v3',
disableExecuteApiEndpoint: false,
endpointConfiguration: { types: [ 'PRIVATE' ] },
id: 'abcd1234',
name: 'Simple PetStore (JavaScript v3 SDK, private)',
rootResourceId: 'efg567',
version: '0.00.001'
}
After completing the preceding steps, you can follow the instructions in Tutorial: Create a REST API using
AWS SDKs or the AWS CLI to set up methods and integrations for this API, but you
can't deploy your API. To deploy your API, follow step 3 and attach a resource policy to your API.
- Python SDK
-
The following example shows how to create a private API by using the AWS SDK for Python:
import json
import boto3
import logging
logger = logging.getLogger()
apig = boto3.client('apigateway')
def lambda_handler(event, context):
try:
result = apig.create_rest_api(
name='Simple PetStore (Python SDK, private)',
description='Demo private API created using the AWS SDK for Python',
version='0.00.001',
endpointConfiguration={
'types': [
'PRIVATE',
],
},
)
except botocore.exceptions.ClientError as error:
logger.exception("Couldn't create private API %s.", error)
raise
attribute=["id", "name", "description", "createdDate", "version", "apiKeySource", "endpointConfiguration"]
filtered_data ={key:result[key] for key in attribute}
result = json.dumps(filtered_data, default=str, sort_keys='true')
return result
A successful call returns output similar to the following:
"{\"apiKeySource\": \"HEADER\", \"createdDate\": \"2024-04-03 17:27:05+00:00\", \"description\": \"Demo private API created using the AWS SDK for \", \"endpointConfiguration\": {\"types\": [\"PRIVATE\"]}, \"id\": \"abcd1234\", \"name\": \"Simple PetStore (Python SDK, private)\", \"version\": \"0.00.001\"}"
After completing the preceding steps, you can follow the instructions in Tutorial: Create a REST API using
AWS SDKs or the AWS CLI to set up methods and integrations for this API, but you
can't deploy your API. To deploy your API, follow step 3 and attach a resource policy to your API.
Step 3: Set up a resource policy
for a private API
Your current private API is inaccessible to all VPCs. Use a resource policy to grant your VPCs and VPC endpoints access
to your private APIs. You can grant access to a VPC endpoint in any AWS account.
Your resource policy should contain aws:SourceVpc
or aws:SourceVpce
conditions to
restrict access. We recommend that you identify specific VPCs and VPC endpoints and don't create a resource
policy that allows access for all VPCs and VPC endpoints.
The following procedure shows how to attach a resource policy to your API.
- AWS Management Console
-
Sign in to the API Gateway console at https://console.aws.amazon.com/apigateway.
Choose a REST API.
-
In the main navigation pane, choose Resource policy.
-
Choose Create policy.
-
Choose Select a template and then choose Source VPC.
-
Replace {{vpcID}}
(including the curly braces) with your VPC ID.
-
Choose Save changes.
- AWS CLI
The following update-rest-api command attaches a resource policy to an existing API:
aws apigateway update-rest-api \
--rest-api-id a1b2c3 \
--patch-operations op=replace,path=/policy,value='"{\"jsonEscapedPolicyDocument
\"}"'
You might also want to control which resources have access to your VPC endpoint. To control which resources
have access to your VPC endpoint, attach an endpoint policy to your VPC endpoint. For more information, see
Use VPC endpoint policies for private
APIs in API Gateway.
(Optional) Associate or disassociate a VPC endpoint
with a private API
When you associate a VPC endpoint with your private API, API Gateway generates a new RouteĀ 53 alias DNS record. You
can use this record to invoke your private APIs just as you do your public APIs without overriding a
Host
header or passing an x-apigw-api-id
header.
The generated base URL is in the following format:
https://{rest-api-id}
-{vpce-id}
.execute-api.{region}
.amazonaws.com/{stage}
- Associate a VPC endpoint (AWS Management Console)
-
You can associate a VPC endpoint with your private API when you create it, or after it's created. The
following procedure shows how to associate a VPC endpoint with a previously created API.
To associate a VPC endpoint with a private API
Sign in to the API Gateway console at https://console.aws.amazon.com/apigateway.
-
Choose your private API.
-
In the main navigation pane, choose Resource policy.
-
Edit your resource policy to allow calls from your additional VPC endpoint.
-
In the main navigation pane, choose API settings.
-
In the API details section, choose Edit.
-
For VPC endpoint IDs, select additional VPC endpoint IDs.
-
Choose Save.
-
Redeploy your API for the changes to take effect.
- Dissociate a VPC endpoint (AWS Management Console)
-
To disassociate a VPC endpoint from a private REST API
Sign in to the API Gateway console at https://console.aws.amazon.com/apigateway.
-
Choose your private API.
-
In the main navigation pane, choose Resource policy.
-
Edit your resource policy to remove mentions of the VPC endpoint you want to dissociate from your
private API.
-
In the main navigation pane, choose API settings.
-
In the API details section, choose Edit.
-
For VPC endpoint IDs, choose the X to dissociate the VPC
endpoint.
-
Choose Save.
-
Redeploy your API for the changes to take effect.
- Associate a VPC endpoint (AWS CLI)
-
The following create-rest-api
command associates VPC endpoints at the time of API creation:
aws apigateway create-rest-api \
--name Petstore \
--endpoint-configuration '{ "types": ["PRIVATE"], "vpcEndpointIds" : ["vpce-0212a4ababd5b8c3e", "vpce-0393a628149c867ee"] }' \
--region us-west-2
The output will look like the following:
{
"apiKeySource": "HEADER",
"endpointConfiguration": {
"types": [
"PRIVATE"
],
"vpcEndpointIds": [
"vpce-0212a4ababd5b8c3e",
"vpce-0393a628149c867ee"
]
},
"id": "u67n3ov968",
"createdDate": 1565718256,
"name": "Petstore"
}
The following update-rest-api
command associates VPC endpoints to an API that you already created:
aws apigateway update-rest-api \
--rest-api-id u67n3ov968 \
--patch-operations "op='add',path='/endpointConfiguration/vpcEndpointIds',value='vpce-01d622316a7df47f9'" \
--region us-west-2
The output will look like the following:
{
"name": "Petstore",
"apiKeySource": "1565718256",
"tags": {},
"createdDate": 1565718256,
"endpointConfiguration": {
"vpcEndpointIds": [
"vpce-0212a4ababd5b8c3e",
"vpce-0393a628149c867ee",
"vpce-01d622316a7df47f9"
],
"types": [
"PRIVATE"
]
},
"id": "u67n3ov968"
}
Redeploy your API for the changes to take effect.
- Disassociate a VPC endpoint (AWS CLI)
-
The following update-rest-api
command dissociates a VPC endpoint from a private API:
aws apigateway update-rest-api \
--rest-api-id u67n3ov968 \
--patch-operations "op='remove',path='/endpointConfiguration/vpcEndpointIds',value='vpce-0393a628149c867ee'" \
--region us-west-2
The output will look like the following:
{
"name": "Petstore",
"apiKeySource": "1565718256",
"tags": {},
"createdDate": 1565718256,
"endpointConfiguration": {
"vpcEndpointIds": [
"vpce-0212a4ababd5b8c3e",
"vpce-01d622316a7df47f9"
],
"types": [
"PRIVATE"
]
},
"id": "u67n3ov968"
}
Redeploy your API for the changes to take effect.
Step 4: Deploy a private API
To deploy your API, you create an API deployment and associate it with a stage. The following procedure
shows how to deploy your private API.
- AWS Management Console
To deploy a private API
Choose your API.
Choose Deploy API.
For Stage, select New stage.
For Stage name, enter a stage name.
(Optional) For Description, enter a description.
Choose Deploy.
- AWS CLI
The following create-deployment command deploys a private API:
aws apigateway create-deployment --rest-api-id a1b2c3 \
--stage-name test \
--stage-description 'Private API test stage' \
--description 'First deployment'
Troubleshoot your private API
The following provides troubleshooting advice for errors and issues that you might encounter when
creating a private API.
Issue: I can't
connect to my public API from an API Gateway VPC endpoint
When you create your VPC, you can configure the DNS settings. We recommend that you turn on private DNS
for your VPC. If you choose turn off private DNS, you're only able to access your API via public
DNS.
If you enable private DNS, you can't access the default endpoint of a public API Gateway API from your VPC
endpoint. You can access an API with a custom domain name.
If you create a Regional custom domain name, use an A type alias record, if you create an
edge-optimized custom domain name, there are no restrictions for your record type. You can access
these public APIs with private DNS enabled. For more information, see Issue: I
connect to my public API from an API Gateway VPC endpoint.
Issue: My API returns {"Message":"User:
anonymous is not authorized to perform: execute-api:Invoke on resource:
arn:aws:execute-api:us-east-1:********/****/****/"}
In your resource policy, if you set the Principal to an AWS principal, such as the following:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
""Principal": {
"AWS": [
"arn:aws:iam::account-id:role/developer",
"arn:aws:iam::account-id:role/Admin"
]
},
"Action": "execute-api:Invoke",
"Resource": [
"execute-api:/*"
]
},
...
}
You must use AWS_IAM
authorization for every method in your API, or else your API returns
the previous error message. For more instructions on how to turn on AWS_IAM
authorization for a
method, see Methods for REST APIs in API Gateway.
Issue: I can't tell if my VPC endpoint is associated with my API
If you associate or dissociate a VPC endpoint with your private API, you need to redeploy your API. The
update operation might take few minutes to complete due to DNS propagation. During this time, your API is
available, but DNS propagation for the newly generated DNS URLs may still be in progress. If after several
minutes, your new URLs are not resolving in DNS, we recommend that you redeploy your API.