使用 Amazon AppSync 私有 API - Amazon AppSync
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

使用 Amazon AppSync 私有 API

如果使用 Amazon Virtual Private Cloud (Amazon VPC),您可以创建 Amazon AppSync 私有 API,只能从 VPC 中访问这些 API。通过使用私有 API,您可以限制对内部应用程序的 API 访问并连接到 GraphQL 和实时终端节点,而不会公开暴露数据。

要在您的 VPC 和 Amazon AppSync 服务之间建立私有连接,您必须创建一个接口 VPC 终端节点。接口终端节点由 Amazon PrivateLink 提供支持,该技术支持您通过私有连接访问 Amazon AppSync API,而无需采用互联网网关、NAT 设备、VPN 连接或 Amazon Direct Connect 连接。VPC 中的实例即使没有公有 IP 地址也可与 Amazon AppSync API 进行通信。您的 VPC 和 Amazon AppSync 之间的流量不会离开 Amazon 网络。

在启用私有 API 功能之前,需要考虑一些其他因素:

  • 通过为启用了私有 DNS 功能的 Amazon AppSync 设置 VPC 接口终端节点,将禁止 VPC 中的资源使用 Amazon AppSync 生成的 API URL 调用其他 Amazon AppSync 公有 API。这是因为对公有 API 的请求是通过接口终端节点路由的,而公有 API 不允许这样做。要在该场景中调用公有 API,建议在公有 API 上配置自定义域名,VPC 中的资源可以使用这些域名调用公有 API。

  • 您的 Amazon AppSync 私有 API 只能从您的 VPC 中使用。只有在您的浏览器的网络配置可以将流量路由到您的 VPC(例如,通过 VPN 或 Amazon Direct Connect 连接)时,Amazon AppSync 控制台查询编辑器才能够访问您的 API。

  • 通过使用 Amazon AppSync 的 VPC 接口终端节点,您可以访问同一 Amazon 账户和区域中的任何私有 API。要进一步限制对私有 API 的访问,您可以考虑使用以下选项:

    • 确保仅所需的管理员可以为 Amazon AppSync 创建 VPC 终端节点接口。

    • 使用 VPC 终端节点自定义策略限制可以从 VPC 中的资源调用哪些 API。

    • 对于 VPC 中的资源,我们建议您使用 IAM 授权调用 Amazon AppSync API,以确保为资源分配 API 的范围缩小角色。

  • 在创建或使用限制 IAM 主体的策略时,您必须将方法的 authorizationType 设置为 AWS_IAMNONE

创建 Amazon AppSync 私有 API

以下步骤说明了如何在 Amazon AppSync 服务中创建私有 API。

警告

您只能在创建 API 期间启用私有 API 功能。在创建 Amazon AppSync API 或 Amazon AppSync 私有 API 后,无法在这些 API 上修改该设置。

  1. 登录到 Amazon Web Services Management Console,然后打开 AppSync 控制台

    1. 控制面板中,选择创建 API

  2. 选择从头开始设计 API,然后选择下一步

  3. 私有 API 部分中,选择使用私有 API 功能

  4. 配置其余选项,检查您的 API 的数据,然后选择创建

您必须先在 VPC 中为 Amazon AppSync 配置一个接口终端节点,然后才能使用 Amazon AppSync 私有 API。请注意,私有 API 和 VPC 必须位于同一 Amazon 账户和区域中。

为 Amazon AppSync 创建接口终端节点

您可以使用 Amazon VPC 控制台或 Amazon Command Line Interface (Amazon CLI) 为 Amazon AppSync 创建接口终端节点。有关更多信息,请参阅 Amazon VPC 用户指南中的创建接口端点

Console
  1. 登录到 Amazon Web Services Management Console,然后打开 Amazon VPC 控制台的终端节点页面。

  2. 选择 Create endpoint(创建端点)。

    1. 服务类别字段中,验证是否选择了 Amazon 服务

    2. 服务表中,选择 com.amazonaws.{region}.appsync-api。验证类型列值是否为 Interface

    3. VPC 字段中,选择一个 VPC 及其子网。

    4. 要为接口终端节点启用私有 DNS 功能,请选中启用 DNS 名称复选框。

    5. 安全组字段中,选择一个或多个安全组。

  3. 选择 Create endpoint(创建端点)。

CLI

使用 create-vpc-endpoint 命令并指定 VPC ID、VPC 端点类型(接口)、服务名称、将使用端点的子网以及要与端点的网络接口关联的安全组。例如:

$ aws ec2 create-vpc-endpoint —vpc-id vpc-ec43eb89 \ —vpc-endpoint-type Interface \ —service-name com.amazonaws.{region}.appsync-api \ —subnet-id subnet-abababab —security-group-id sg-1a2b3c4d

要使用私有 DNS 选项,您必须设置 VPC 的 enableDnsHostnamesenableDnsSupportattributes 值。有关更多信息,请参阅 Amazon VPC 用户指南中的查看和更新 VPC 的 DNS 支持。如果您为接口终端节点启用私有 DNS 功能,您可以使用其默认公有 DNS 终端节点向 Amazon AppSync API GraphQL 和实时终端节点发出请求(使用以下格式):

https://{api_url_identifier}.appsync-api.{region}.amazonaws.com/graphql

有关服务终端节点的更多信息,请参阅 Amazon General Reference 中的 Service endpoints and quotas

有关与服务接口终端节点的交互的更多信息,请参阅《Amazon VPC 用户指南》中的使用接口 VPC 端点访问服务

有关使用 Amazon CloudFormation 创建和配置终端节点的信息,请参阅 Amazon CloudFormation User Guide 中的 Amazon::EC2::VPCEndpoint

高级 示例

如果您为接口终端节点启用私有 DNS 功能,您可以使用其默认公有 DNS 终端节点向 Amazon AppSync API GraphQL 和实时终端节点发出请求(使用以下格式):

https://{api_url_identifier}.appsync-api.{region}.amazonaws.com/graphql

在使用接口 VPC 终端节点公有 DNS 主机名时,调用 API 的基本 URL 将采用以下格式:

https://{vpc_endpoint_id}-{endpoint_dns_identifier}.appsync-api.{region}.vpce.amazonaws.com/graphql

如果已在可用区中部署终端节点,您也可以使用可用区特定的 DNS 主机名:

https://{vpc_endpoint_id}-{endpoint_dns_identifier}-{az_id}.appsync-api.{region}.vpce.amazonaws.com/graphql.

使用 VPC 终端节点公有 DNS 名称需要将 Amazon AppSync API 终端节点主机名作为 Host x-appsync-domain 标头传递给请求。这些示例使用在启动示例架构指南中创建的 TodoAPI

curl https://{vpc_endpoint_id}-{endpoint_dns_identifier}.appsync-api.{region}.vpce.amazonaws.com/graphql \ -H "Content-Type:application/graphql" \ -H "x-api-key:da2-{xxxxxxxxxxxxxxxxxxxxxxxxxx}" \ -H "Host:{api_url_identifier}.appsync-api.{region}.amazonaws.com" \ -d '{"query":"mutation add($createtodoinput: CreateTodoInput!) {\n createTodo(input: $createtodoinput) {\n id\n name\n where\n when\n description\n }\n}","variables":{"createtodoinput":{"name":"My first GraphQL task","when":"Friday Night","where":"Day 1","description":"Learn more about GraphQL"}}}'

在以下示例中,我们使用在启动示例架构指南中生成的 Todo 应用程序。为了测试示例 Todo API,我们将使用私有 DNS 调用该 API。您可以使用所选的任何命令行工具;该示例使用 curl 发送查询和变更,并使用 wscat 设置订阅。要模拟我们的示例,请将下面命令中的花括号 ({ }) 中的值替换为您的 Amazon 账户中的相应值。

测试变更操作 - createTodo 请求

curl https://{api_url_identifier}.appsync-api.{region}.amazonaws.com/graphql \ -H "Content-Type:application/graphql" \ -H "x-api-key:da2-{xxxxxxxxxxxxxxxxxxxxxxxxxx}" \ -d '{"query":"mutation add($createtodoinput: CreateTodoInput!) {\n createTodo(input: $createtodoinput) {\n id\n name\n where\n when\n description\n }\n}","variables":{"createtodoinput":{"name":"My first GraphQL task","when":"Friday Night","where":"Day 1","description":"Learn more about GraphQL"}}}'

测试变更操作 - createTodo 响应

{ "data": { "createTodo": { "id": "<todo-id>", "name": "My first GraphQL task", "where": "Day 1", "when": "Friday Night", "description": "Learn more about GraphQL" } } }

测试查询操作 - listTodos 请求

curl https://{api_url_identifier}.appsync-api.{region}.amazonaws.com/graphql \ -H "Content-Type:application/graphql" \ -H "x-api-key:da2-{xxxxxxxxxxxxxxxxxxxxxxxxxx}" \ -d '{"query":"query ListTodos {\n listTodos {\n items {\n description\n id\n name\n when\n where\n }\n }\n}\n","variables":{"createtodoinput":{"name":"My first GraphQL task","when":"Friday Night","where":"Day 1","description":"Learn more about GraphQL"}}}'

测试查询操作 - listTodos 请求

{ "data": { "listTodos": { "items": [ { "description": "Learn more about GraphQL", "id": "<todo-id>", "name": "My first GraphQL task", "when": "Friday night", "where": "Day 1" } ] } } }

测试订阅操作 - 订阅 createTodo 变更

要在 Amazon AppSync 中设置 GraphQL 订阅,请参阅构建实时 WebSocket 客户端。从 VPC 上的 Amazon EC2 实例中,您可以使用 wscat 测试您的 Amazon AppSync 私有 API 订阅终端节点。以下示例使用 API KEY 进行授权。

$ header=`echo '{"host":"{api_url_identifier}.appsync-api.{region}.amazonaws.com","x-api-key":"da2-{xxxxxxxxxxxxxxxxxxxxxxxxxx}"}' | base64 | tr -d '\n'` $ wscat -p 13 -s graphql-ws -c "wss://{api_url_identifier}.appsync-realtime-api.us-west-2.amazonaws.com/graphql?header=$header&payload=e30=" Connected (press CTRL+C to quit) > {"type": "connection_init"} < {"type":"connection_ack","payload":{"connectionTimeoutMs":300000}} < {"type":"ka"} > {"id":"f7a49717","payload":{"data":"{\"query\":\"subscription onCreateTodo {onCreateTodo {description id name where when}}\",\"variables\":{}}","extensions":{"authorization":{"x-api-key":"da2-{xxxxxxxxxxxxxxxxxxxxxxxxxx}","host":"{api_url_identifier}.appsync-api.{region}.amazonaws.com"}}},"type":"start"} < {"id":"f7a49717","type":"start_ack"}

或者,使用 VPC 终端节点域名,同时确保在 wscat 命令中指定 Host 标头以建立 WebSocket 连接:

$ header=`echo '{"host":"{api_url_identifier}.appsync-api.{region}.amazonaws.com","x-api-key":"da2-{xxxxxxxxxxxxxxxxxxxxxxxxxx}"}' | base64 | tr -d '\n'` $ wscat -p 13 -s graphql-ws -c "wss://{vpc_endpoint_id}-{endpoint_dns_identifier}.appsync-api.{region}.vpce.amazonaws.com/graphql?header=$header&payload=e30=" --header Host:{api_url_identifier}.appsync-realtime-api.us-west-2.amazonaws.com Connected (press CTRL+C to quit) > {"type": "connection_init"} < {"type":"connection_ack","payload":{"connectionTimeoutMs":300000}} < {"type":"ka"} > {"id":"f7a49717","payload":{"data":"{\"query\":\"subscription onCreateTodo {onCreateTodo {description id priority title}}\",\"variables\":{}}","extensions":{"authorization":{"x-api-key":"da2-{xxxxxxxxxxxxxxxxxxxxxxxxxx}","host":"{api_url_identifier}.appsync-api.{region}.amazonaws.com"}}},"type":"start"} < {"id":"f7a49717","type":"start_ack"}

运行下面的变更代码:

curl https://{api_url_identifier}.appsync-api.{region}.amazonaws.com/graphql \ -H "Content-Type:application/graphql" \ -H "x-api-key:da2-{xxxxxxxxxxxxxxxxxxxxxxxxxx}" \ -d '{"query":"mutation add($createtodoinput: CreateTodoInput!) {\n createTodo(input: $createtodoinput) {\n id\n name\n where\n when\n description\n }\n}","variables":{"createtodoinput":{"name":"My first GraphQL task","when":"Friday Night","where":"Day 1","description":"Learn more about GraphQL"}}}'

然后,将触发订阅并显示消息通知,如下所示:

< {"id":"f7a49717","type":"data","payload":{"data":{"onCreateTodo":{"description":"Go to the shops","id":"169ce516-b7e8-4a6a-88c1-ab840184359f","priority":5,"title":"Go to the shops"}}}}

使用 IAM 策略限制创建公有 API

Amazon AppSync支持将 IAM Condition 语句与私有 API 一起使用。可以在 appsync:CreateGraphqlApi 操作的 IAM 策略语句中包含 visibility 字段,以控制哪些 IAM 角色和用户可以创建私有和公有 API。这样,IAM 管理员就能够定义仅允许用户创建私有 GraphQL API 的 IAM 策略。尝试创建公有 API 的用户将收到“未经授权”消息。

例如,IAM 管理员可以创建以下 IAM 策略语句以允许创建私有 API:

{ "Sid": "AllowPrivateAppSyncApis", "Effect": "Allow", "Action": "appsync:CreateGraphqlApi", "Resource": "*", "Condition": { "ForAnyValue:StringEquals": { "appsync:Visibility": "PRIVATE" } } }

IAM 管理员还可以添加以下服务控制策略,以阻止 Amazon 组织中的所有用户创建私有 API 以外的 Amazon AppSync API:

{ "Sid": "BlockNonPrivateAppSyncApis", "Effect": "Deny", "Action": "appsync:CreateGraphqlApi", "Resource": "*", "Condition": { "ForAnyValue:StringNotEquals": { "appsync:Visibility": "PRIVATE" } } }