

# 创建私有 API
<a name="apigateway-private-api-create"></a>

在创建私有 API 之前，您首先为 API Gateway 创建一个 VPC 端点。接下来，您要创建私有 API 并向其附加资源策略。（可选）您可以将 VPC 端点与私有 API 关联，来简化调用 API 的过程。最后，您部署 API。

以下过程介绍了如何执行完成此操作。您可以使用 AWS 管理控制台、AWS CLI 或 AWS SDK 创建私有 REST API。

## 先决条件
<a name="apigateway-private-api-create-interface-vpc-prerequisites"></a>

要执行以下步骤，您必须拥有完全配置的 VPC。要了解如何创建 VPC，请参阅《Amazon VPC 用户指南》**中的[仅创建 VPC](https://docs.aws.amazon.com/vpc/latest/userguide/create-vpc.html#create-vpc-only)。要在创建 VPC 时遵循所有推荐的步骤，请启用私有 DNS。这样，您就可以在 VPC 内调用 API，而不必传递 Host 或 `x-apigw-api-id` 标头。

要启用私有 DNS，VPC 的 `enableDnsSupport` 和 `enableDnsHostnames` 属性必须设置为 `true`。有关更多信息，请参阅 [VPC 中的 DNS 支持](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-dns.html#vpc-dns-support)和[更新 VPC 的 DNS 支持](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-dns.html#vpc-dns-updating)。

## 步骤 1：在 VPC 中为 API Gateway 创建 VPC 端点
<a name="apigateway-private-api-create-interface-vpc-endpoint"></a>

以下过程展示如何为 API Gateway 创建 VPC 端点。要为 API Gateway 创建 VPC 端点，您需要为在其中创建私有 API 的 AWS 区域指定 `execute-api` 域。`execute-api` 域是用于 API 执行的 API Gateway 组件服务。

在为 API Gateway 创建 VPC 端点时，需要指定 DNS 设置。如果您关闭私有 DNS，则只能使用公有 DNS 访问您的 API。有关更多信息，请参阅 [问题：我无法从 API Gateway VPC 端点连接到我的公有 API](#apigateway-private-api-troubleshooting-public-access)。

------
#### [ AWS 管理控制台 ]

**为 API Gateway 创建接口 VPC 端点**

1. 登录到 AWS 管理控制台并打开 Amazon VPC 控制台，网址：[https://console.aws.amazon.com/vpc/](https://console.aws.amazon.com/vpc/)。

1. 在导航窗格中的**虚拟私有云**下，选择**端点**。

1. 选择**创建端点**。

1. （可选）对于**名称标签**，输入名称以协助标识您的 VPC 端点。

1. 对于**服务类别**，选择 **AWS 服务**。

1. 在**服务**下的搜索栏中，输入 **execute-api**。然后，在您将创建 API 的 AWS 区域中选择 API Gateway 服务端点。服务名称应类似于 `com.amazonaws.us-east-1.execute-api`，**类型**应为**接口**。

1. 对于 **VPC**，选择要在其中创建端点的 VPC。

1. （可选）要关闭**启用私有 DNS 名称**，请选择**其他设置**，然后清除**启用私有 DNS 名称**。

1. 对于**子网**，选择在其中创建了端点网络接口的可用区。要提高 API 的可用性，请选择多个子网。

1. 对于**安全组**，选择要与 VPC 端点网络接口关联的安全组。

   您选择的安全组必须设置为允许来自您的 VPC 中的 IP 范围或您的 VPC 中的其他安全组的 TCP 端口 443 入站 HTTPS 通信。

1. 对于**策略**，请执行以下操作之一：
   + 如果您尚未创建私有 API 或者不想配置自定义 VPC 端点策略，请选择**完全访问权限**。
   + 如果您已经创建了私有 API 并想要配置自定义 VPC 端点策略，则可以输入自定义 VPC 端点策略。有关更多信息，请参阅 [在 API Gateway 中为私有 API 使用 VPC 端点策略](apigateway-vpc-endpoint-policies.md)。

   创建 VPC 端点后，您可以更新 VPC 端点策略。有关更多信息，请参阅 [Update a VPC endpoint policy](https://docs.aws.amazon.com/vpc/latest/privatelink/vpc-endpoints-access.html#update-vpc-endpoint-policy)。

1. 选择 **Create endpoint**（创建端点）。

1. 复制生成的 VPC 端点 ID，以便在将来的步骤中使用。

------
#### [ AWS CLI ]

使用以下 [create-vpc-endpoint](https://docs.aws.amazon.com/cli/latest/reference/ec2/create-vpc-endpoint.html) 命令创建 VPC 端点：

```
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
```

复制生成的 VPC 端点 ID，以便在将来的步骤中使用。

------

## 步骤 2：创建私有密钥
<a name="apigateway-private-api-create-using-console"></a>

创建 VPC 端点后，您创建一个私有 REST API。以下过程说明了如何创建私有 API。

------
#### [ AWS 管理控制台 ]

**要创建私有 API**

1. 通过以下网址登录到 Amazon API Gateway 控制台：[https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway)。

1. 选择**创建 API**。

1. 在 **REST API** 下，选择 **Build (生成)**。

1. 对于**名称**，输入名称。

1.  （可选）对于**描述**，输入描述。

1. 对于 **API 端点类型**，选择**私有**。

1. （可选）对于 **VPC 端点 ID**，输入 VPC 端点 ID。

   如果您将 VPC 端点 ID 与私有 API 关联，则可以从 VPC 内调用 API，而无需覆盖 `Host` 标头或传递 `x-apigw-api-id header`。有关更多信息，请参阅[（可选）将 VPC 端点与私有 API 关联或取消关联](#associate-private-api-with-vpc-endpoint)。

1. 对于 **IP 地址类型**，选择**双堆栈**。

1. 选择**创建 API**。

 完成前面的步骤之后，您可以按照[开始使用 REST API 控制台](getting-started-rest-new-console.md)中的说明来为此 API 设置方法和集成，但您无法部署 API。要部署您的 API，请执行步骤 3 并将资源策略附加到 API。

------
#### [ AWS CLI ]

使用以下 [create-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-rest-api.html) 命令创建私有 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"], "ipAddressType": "dualstack" }'
```

成功调用返回类似于以下内容的输出：

```
{
    "createdDate": "2017-10-13T18:41:39Z",
    "description": "Simple private PetStore API",
    "endpointConfiguration": {
        "types": [
            "PRIVATE"
        ],
        "ipAddressType": "dualstack"
    },
    "id": "0qzs2sy7bh",
    "name": "Simple PetStore (AWS CLI, Private)"
}
```

 完成前面的步骤之后，您可以按照[教程：使用 AWS SDK 或 AWS CLI 创建 REST API](api-gateway-create-api-cli-sdk.md)中的说明来为此 API 设置方法和集成，但您无法部署 API。要部署您的 API，请执行步骤 3 并将资源策略附加到 API。

------
#### [ SDK JavaScript v3 ]

以下示例说明了如何使用适用于 JavaScript 的 AWS SDK v3 创建私有 API：

```
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)
 }
};
```

成功调用返回类似于以下内容的输出：

```
{
  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'
}
```

 完成前面的步骤之后，您可以按照[教程：使用 AWS SDK 或 AWS CLI 创建 REST API](api-gateway-create-api-cli-sdk.md)中的说明来为此 API 设置方法和集成，但您无法部署 API。要部署您的 API，请执行步骤 3 并将资源策略附加到 API。

------
#### [ Python SDK ]

以下示例说明了如何使用适用于 Python 的 AWS SDK 创建私有 API：

```
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
```

成功调用返回类似于以下内容的输出：

```
"{\"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\"}"
```

 完成前面的步骤之后，您可以按照[教程：使用 AWS SDK 或 AWS CLI 创建 REST API](api-gateway-create-api-cli-sdk.md)中的说明来为此 API 设置方法和集成，但您无法部署 API。要部署您的 API，请执行步骤 3 并将资源策略附加到 API。

------

## 步骤 3：为私有 API 设置资源策略
<a name="apigateway-private-api-set-up-resource-policy"></a>

所有 VPC 都无法访问您当前的私有 API。使用资源策略授予您的 VPC 和 VPC 端点访问私有 API 的权限。您可以向任何 AWS 账户中的 VPC 端点授予访问权限。

您的资源策略应包含 `aws:SourceVpc` 或 `aws:SourceVpce` 条件来限制访问权限。我们建议您标识特定的 VPC 和 VPC 端点，而不要创建允许所有 VPC 和 VPC 端点访问的资源策略。

以下过程展示如何向 API 附加资源策略。

------
#### [ AWS 管理控制台 ]

1. 通过以下网址登录到 Amazon API Gateway 控制台：[https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway)。

1. 选择一个 REST API。

1. 在主导航窗格中，选择**资源策略**。

1. 选择**创建策略**。

1. 选择**选择模板**，然后选择**源 VPC**。

1. 将 `{{vpcID}}`（包括大括号）替换为您的 VPC ID。

1. 选择**保存更改**。

------
#### [ AWS CLI ]

使用以下 [update-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-rest-api.html) 命令将资源策略附加到现有 API：

```
aws apigateway update-rest-api \
    --rest-api-id a1b2c3 \
    --patch-operations op=replace,path=/policy,value='"{\"jsonEscapedPolicyDocument\"}"'
```

------

您可能还要控制哪些资源可以访问您的 VPC 端点。要控制哪些资源可以访问 VPC 端点，请向 VPC 端点附加端点策略。有关更多信息，请参阅 [在 API Gateway 中为私有 API 使用 VPC 端点策略](apigateway-vpc-endpoint-policies.md)。

## （可选）将 VPC 端点与私有 API 关联或取消关联
<a name="associate-private-api-with-vpc-endpoint"></a>

当您将 VPC 端点与私有 API 关联时，API Gateway 将生成新的 Route 53 别名 DNS 记录。您可以使用此记录调用私有 API，就像使用公有 API 一样，而无需覆盖 `Host` 标头或传递 `x-apigw-api-id` 标头。

生成的基本 URL 采用以下格式：

```
https://{rest-api-id}-{vpce-id}.execute-api.{region}.amazonaws.com/{stage}
```

------
#### [ Associate a VPC endpoint (AWS 管理控制台) ]

您可以在创建私有 API 时或创建后，将 VPC 端点与私有 API 关联起来。以下过程展示如何将 VPC 端点与先前创建的 API 相关联。

**将 VPC 端点与私有 API 关联**

1. 通过以下网址登录到 Amazon API Gateway 控制台：[https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway)。

1. 选择您的私有 API。

1. 在主导航窗格中，选择**资源策略**。

1. 编辑您的资源策略以允许来自其他 VPC 端点的调用。

1. 在主导航窗格中，选择 **API 设置**。

1. 在 **API 详细信息**部分中，选择**编辑**。

1. 对于 **VPC 端点 ID**，请选择其他 VPC 端点 ID。

1. 选择**保存**。

1. 重新部署 API 以使更改生效。

------
#### [ Dissociate a VPC endpoint (AWS 管理控制台) ]

**将 VPC 端点与私有 REST API 取消关联**

1. 通过以下网址登录到 Amazon API Gateway 控制台：[https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway)。

1. 选择您的私有 API。

1. 在主导航窗格中，选择**资源策略**。

1. 编辑您的资源策略，对于您要与私有 API 取消关联的 VPC 端点，删除提及该端点的内容。

1. 在主导航窗格中，选择 **API 设置**。

1. 在 **API 详细信息**部分中，选择**编辑**。

1. 对于 **VPC 端点 ID**，选择 **X** 以与 VPC 端点取消关联。

1. 选择**保存**。

1. 重新部署 API 以使更改生效。

------
#### [ Associate a VPC endpoint (AWS CLI) ]

使用以下 [create-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-rest-api.html) 命令在创建 API 时关联 VPC 端点。

```
aws apigateway create-rest-api \
    --name Petstore \
    --endpoint-configuration '{ "types": ["PRIVATE"], "vpcEndpointIds" : ["vpce-0212a4ababd5b8c3e", "vpce-0393a628149c867ee"] }' \
    --region us-west-2
```

输出将与以下内容类似：

```
{
    "apiKeySource": "HEADER",
    "endpointConfiguration": {
        "types": [
            "PRIVATE"
        ],
        "vpcEndpointIds": [
            "vpce-0212a4ababd5b8c3e",
            "vpce-0393a628149c867ee"
        ]
    },
    "id": "u67n3ov968",
    "createdDate": 1565718256,
    "name": "Petstore"
}
```

使用以下 [update-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-rest-api.html) 命令将 VPC 端点与已经创建的 API 关联：

```
aws apigateway update-rest-api \
    --rest-api-id u67n3ov968 \
    --patch-operations "op='add',path='/endpointConfiguration/vpcEndpointIds',value='vpce-01d622316a7df47f9'" \
    --region us-west-2
```

输出将与以下内容类似：

```
{
    "name": "Petstore",
    "apiKeySource": "1565718256",
    "tags": {},
    "createdDate": 1565718256,
    "endpointConfiguration": {
        "vpcEndpointIds": [
            "vpce-0212a4ababd5b8c3e",
            "vpce-0393a628149c867ee",
            "vpce-01d622316a7df47f9"
        ],
        "types": [
            "PRIVATE"
        ]
    },
    "id": "u67n3ov968"
}
```

重新部署 API 以使更改生效。

------
#### [ Disassociate a VPC endpoint (AWS CLI) ]

使用以下 [update-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-rest-api.html) 命令将 VPC 端点与私有 API 取消关联：

```
aws apigateway update-rest-api \
    --rest-api-id u67n3ov968 \
    --patch-operations "op='remove',path='/endpointConfiguration/vpcEndpointIds',value='vpce-0393a628149c867ee'" \
    --region us-west-2
```

输出将与以下内容类似：

```
{
    "name": "Petstore",
    "apiKeySource": "1565718256",
    "tags": {},
    "createdDate": 1565718256,
    "endpointConfiguration": {
        "vpcEndpointIds": [
            "vpce-0212a4ababd5b8c3e",
            "vpce-01d622316a7df47f9"
        ],
        "types": [
            "PRIVATE"
        ]
    },
    "id": "u67n3ov968"
}
```

重新部署 API 以使更改生效。

------

## 步骤 4：部署私有 API
<a name="apigateway-private-api-deploy-using-console"></a>

要部署 API，您可以创建 API 部署并将其与阶段关联。以下过程显示如何部署私有 API。

------
#### [ AWS 管理控制台 ]

**部署私有 API**

1. 选择 API。

1. 选择**部署 API**。

1. 对于**阶段**，选择**新建阶段**。

1. 对于**阶段名称**，输入阶段名称。

1. （可选）对于**描述**，输入描述。

1. 选择**部署**。

------
#### [ AWS CLI ]

使用以下 [create-deployment](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-deployment.html) 命令部署私有 API：

```
aws apigateway create-deployment --rest-api-id a1b2c3 \ 
  --stage-name test \
  --stage-description 'Private API test stage' \
  --description 'First deployment'
```

------

## 对私有 API 进行故障排除
<a name="apigateway-private-api-troubleshooting"></a>

以下内容为您在创建私有 API 时可能遇到的错误和问题提供故障排除建议。

### 问题：我无法从 API Gateway VPC 端点连接到我的公有 API
<a name="apigateway-private-api-troubleshooting-public-access"></a>

创建 VPC 时，您可以配置 DNS 设置。我们建议您为 VPC 开启私有 DNS。如果您选择关闭私有 DNS，您只能通过公有 DNS 访问您的 API。

如果您启用私有 DNS，则无法从 VPC 端点访问公有 API Gateway API 的默认端点。您可以使用自定义域名访问 API。

如果您创建区域自定义域名，请使用 A 类型别名记录；如果您创建边缘优化的自定义域名，则不限制记录类型。您可以在启用私有 DNS 的情况下访问这些公有 API。有关更多信息，请参阅[问题：我无法从 API Gateway VPC 端点连接到我的公有 API](https://repost.aws/knowledge-center/api-gateway-vpc-connections)。

### 问题：我的 API 返回 `{"Message":"User: anonymous is not authorized to perform: execute-api:Invoke on resource: arn:aws:execute-api:us-east-1:********/****/****/"}`
<a name="apigateway-private-api-troubleshooting-principal"></a>

在资源策略中，如果您将主体设置为 AWS 主体，如下所示：

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::111122223333:role/developer",
                    "arn:aws:iam::111122223333:role/Admin"
                ]
            },
            "Action": "execute-api:Invoke",
            "Resource": [
                "execute-api:/stage/GET/pets"
            ]
        }
    ]
}
```

------

您必须对 API 中的每个方法使用 `AWS_IAM` 授权，否则 API 会返回之前的错误消息。有关如何为方法开启 `AWS_IAM` 授权的更多说明，请参阅 [API Gateway 中用于 REST API 的方法](how-to-method-settings.md)。

### 问题：我无法分辨我的 VPC 端点是否与我的 API 关联
<a name="apigateway-private-api-troubleshooting-associate-wait-time"></a>

如果您将 VPC 端点与私有 API 关联或取消关联，则需要重新部署 API。由于 DNS 传播，更新操作可能需要几分钟才能完成。在这段时间内，您的 API 将可用，但新生成的 DNS URL 的 DNS 传播可能仍在进行中。如果几分钟后，您的新 URL 仍无法在 DNS 中解析，我们建议您重新部署 API。