在 亚马逊云科技 AppSync 上引入私有 API

亚马逊云科技 AppSync 是一项完全托管的服务,它使开发人员能够创建 GraphQL API,以便安全地访问、操作和合并来自一个或多个数据源的数据。当您在 AppSync 上创建 GraphQL API 时,将生成一个公共端点,该端点可用于向该 API 发送查询、变更和订阅请求。但是,私有网络(例如 亚马逊虚拟私有云 (VPC) 或本地网络)中的客户端将需要通过互联网的网络路由才能到达 AppSync 公共端点。对于需要更改安全策略和防火墙规则才能向 AppSync API 发送请求的客户来说,这可能是一个挑战。

今天,我们宣布 AppSync 私有 API 已正式上线。使用私有 API,您可以将对 GraphQL API 的访问权限限制为私有网络中的客户端,例如 VPC 或本地数据中心。对您的私有 API 的请求将通过 亚马逊云科技 的私有网络传输,无需通过互联网。首先,您可以在 AppSync 上创建 GraphQL API 时将您的 API 设置为私有,并在调用 API 的同一 亚马逊云科技 账户中的每个 VPC 中附加一个接口 VPC 终端节点。您还可以使用 亚马逊云科技 Direct Connect 亚马逊云科技 站点 到站点 VPN 来建立从您的本地网络到托管接口终端节点的 VPC 的私有连接。通过此连接,您的本地数据中心中的客户端可以调用私有 API。

下图显示了如何从 VPC 中运行的应用程序连接到 亚马逊云科技 AppSync 上的私有 API。在此示例中,我使用 亚马逊弹性计算云 (EC2) 作为调用 API 的计算平台;如果使用其他计算平台(如 亚马逊云科技 L ambda 或 亚马逊云科技 Fargat e)来调用 API,则架构将采用类似的配置。 来自您的应用程序的 GraphQL 请求将通过接口终端节点路由到 亚马逊云科技 AppSync。接口终端节点使用 亚马逊云科技 Pri v ateLink,这是一种高度可用、可扩展的技术,使您能够将您的 VPC 私下连接到 亚马逊云科技 AppSync(以及其他 亚马逊云科技 和第三方服务)等服务,就好像它们在您的 VPC 中一样。它可以部署在您的 VPC 中的任何子网中,建议在每个可用区 (AZ) 中至少部署一个终端节点以确保高可用性。

High level architecture for connecting to AppSync Private API from Amazon VPC

图 1:用于从亚马逊 VPC 连接到 AppSync 私有 API 的高级架构

创建并连接到您的 AppSync 私有 API

在本节中,我们将在 亚马逊云科技 AppSync 上创建一个私有 API,然后从在 VPC 中运行的 EC2 实例中调用该 API。我们将做以下事情:

  • 创建一个简单的 Todo API,将 API 设置为私有
  • 创建分布在两个可用区 (AZ) 的 VPC,每个可用区中都有公有子网和私有子网
  • 将 亚马逊云科技 AppSync 的接口终端节点连接到 VPC 私有子网
  • 从部署在私有子网中的 EC2 实例中调用 API

创建 AppSync 私有 API

  • 导航到 AppSync 控制台,然后单击 “ 创建 API”
  • 在 API 创建向导的步骤 1 中,选择 “从头开始 设计”, 然后单击 “ 下一步” 。 注意 :您还可以在从现有 DynamoDB 表创建新 API 或创建实时 API 时创建私有 API。

Step 1-Select API Type

  • 在步骤 2 中,提供 API 的名称并选中 “私有 API” 部分中的 “ 使用私有 API 功能 ” 复选框,然后单击 “下一步”。选中此复选框会将您的 API 设为私有。

Step 2-Specify API metadata

  • 在步骤 3 中的 “ 创建 GraphQL 类型” 下 ,选择 “立即 创建由 DynamoDB 表支持的类型” , 然后在 “ 模型信息” 下提供 GraphQL 类型的名称(模型名称),并为每个字段指定字段和相应的数据类型。然后,提供 DynamoDB 表的名称、主键和排序键,完成后,单击 “ 下一步”。

Step 3-Specify GraphQL Resources

  • 在步骤 4 中,查看 API 详细信息,然后单击 “ 创建 API” 。它开始创建 API 和 DynamoDB 表,完成后,导航到 API 设置页面以查看新的 私有 API 开启状态 ,指示 AP I 为私有。您还将在该地区创建的 AppSync API 列表中看到附有私有 API 的挂锁标志。

AppSync Setting Page showing Private API On

创建具有公有和私有子网的 VPC

您可以在 VPC 控制台 上使用 VPC 向导 创建 VPC。您可以配置 VPC 设置以创建具有两个公有和私有子网、路由表、互联网网关和 NAT 网关的 VPC,如下所示。预览部分显示了将要创建的资源。确保选中 “ 启用 DNS 解析” 和 “ 启用 DNS 主机名 ” 选项(有关这两个值 的更多详细信息,请参阅 VPC 文档 )。

VPC layout

为 亚马逊云科技 AppSync 创建接口终端节点

  • 导航到 Amazon VPC 控制台 ,在左侧导航窗格中,选择 终端节点, 然后选择 创建终端节点。
  • 您可以为端点指定名称标签,例如 appsync-private-ap i-endpoint
  • 对于服务类别,将其设置为 亚马逊云科技 服务

Create VPC endpoint

  • 对于服务名称,将其设置为 com.amazonaws。{region} .appsync-api, 同时使用您正在开发的当前区域替换区域。
  • 对于 VPC,请选择您在上一步中创建的 VPC。
  • 展开 “ 其他设置” 部分,确保选中 “ 启用 DNS 名称 ” 复选框。这会将私有托管区域与包含记录集的 VPC 关联起来,使您能够利用亚马逊与 AppSync 服务的私有网络连接,同时使用 AppSync API 网址(例如 https://{api_url_identifier}.appsync-api)发出请求。{区域} .amazonaws.com/graphql )。 注意 :启用私有 DNS 将阻止 VPC 中的资源使用 AppSync 生成的 API 网址调用其他 AppSync 公共 API。这是因为对公共 API 的请求将通过公共 API 不允许的接口端点进行路由。要在这种情况下调用公共 API,建议在公共 API 上配置自定义域名,然后 VPC 中的资源可以使用这些域名来调用公共 API。

Create VPC Endpoint-select service name

  • 在每个可用区中选择两个可用区和一个子网来部署终端节点。我选择在私有子网中创建端点
  • 对于安全组,我创建了一个新的安全组 appsync-private-api-endpoint-sg, 它仅允许通过端口 443 (HTTPS) 进行内部 VPC 流量。您可以配置安全组以将其范围缩小到子网 IP 地址范围或将调用 API 的资源的 IP 地址。
  • 对于 VPC 终端节点策略,我选择了 完全访问权限 以允许任何 亚马逊云科技 原则调用私有 API。如果您的 AppSync API 使用身份和访问管理 (IAM) 授权模式,建议您缩小自定义策略的范围,仅向所需的 IAM 用户和角色授予必要的权限。
  • 将其他选项保留为默认值,然后选择 创建端点。

select subnets, security group and endpoint policy

从 EC2 实例调用私有 API

我们将使用部署在我的私有子网中的 EC2 实例来调用 API。连接到 EC2 实例和 VPC 终端节点的安全组需要允许双向入站和出站流量。您可以使用 亚马逊云科技 系统管理器会话管理器 连接 到 EC2 实例,使用 VPC 可访问性分析器 来解决连接问题。

现在要调用私有 API,你可以使用两个不同的域名系统 (DNS) 名称:

  • 私有 DNS(如果您在创建 VPC 终端节点时启用了私有 DNS 命名)
  • 接口 VPC 端点公有 DNS 主机名

VPC 终端节点的详细信息页面显示了这两个 DNS 名称,如下所示。

VPC details page

使用私有 DNS,调用 API 的基本 URL 将采用以下格式

https://{api_url_identifier}.appsync-api。{区域}. amazonaws.com/graphql

这与创建私有 API 时由 AppSync 生成的 API 网址相同(请参阅 AppSync 控制台上的 AppSync API 设置页面)。使用私有 DNS 意味着,如果应用程序已经在使用 AppSync 生成的 API 网址,则无需对其进行任何更改。

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

https://{vpc_endpoint_id}-{endpoint_dns_identifier}.appsync-api。{区域} .vpce. amazonaws.com/graphql

或者,如果您已在 AZ 中部署了终端节点,也可以使用特定于 AZ 的 DNS 主机名,

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

使用 VPC 端点公共主机名将要求将 AppSync API 端点主机名作为主机或 x-appsync 域标头传递给请求(参见下方示例)。

$ curl -v 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 createTodo($createtodoinput: CreateTodoInput!) {createTodo(input: $createtodoinput) {id title description priority}}","variables":"{\"createtodoinput\": {\"title\": \"Hello, world!\",\"description\": \"Hello, world!\",\"priority\": 4}}"}'

为了测试示例 Todo API,我们将使用私有 DNS 来调用 API。你可以使用你选择的任何命令行工具,这里我将使用 c url 发送查询和突变,使用 wscat 来设置订阅。在亚马逊 EC2 linux 上,你需要安装 npm ,这是安装 wscat 所必需的。使用您的 亚马逊云科技 账户中的相应值替换大括号中的所有值。

测试突变操作 — create ToDo 请求

$ curl -v https://{api_url_identifier}.appsync-api.{region}.amazonaws.com/graphql \
-H "Content-Type:application/graphql" \
-H "x-api-key:da2-{xxxxxxxxxxxxxxxxxxxxxxxxxx}" \
-d '{"query": "mutation createTodo($createtodoinput: CreateTodoInput!) {createTodo(input: $createtodoinput) {id title description priority}}","variables":"{\"createtodoinput\": {\"title\": \"Read emails\",\"description\": \"Read emails\",\"priority\": 4}}"}'

测试突变操作 — create ToDo 响应

{
  "data": {
    "createTodo": {
      "id": "fec31cdd-9a45-414f-85eb-fec711ba0a79",
      "title": "Read emails",
      "description": "Read emails",
      "priority": 4
    }
  }
}

测试查询操作 — ListToDos 请求

$ curl -v 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 {listTodos {items {id title description priority}}}","variables":"{}"}'

测试查询操作 — L istToDos 响应

{
  "data": {
    "listTodos": {
      "items": [
        {
          "description": "Read emails",
          "priority": 4,
          "id": "fec31cdd-9a45-414f-85eb-fec711ba0a79",
          "title": "Read emails"
        }
      ]
    }
  }
}

测试订阅操作 — 订阅 createToDo 突变

有关在 AppSync 上设置 GraphQL 订阅的详细信息,请参阅 构建实时 WebSocket 客户端。 我将使用 AZ1 私有子网中的 EC2 实例作为启动 OnCreateTodo 订阅订阅请求的客户端,使用 AZ2 私有子网中的 EC2 实例作为调用 createTo Do 突变的客户端。

我将在 AZ1 私有子网中的 EC2 实例上运行以下命令

$ header=`echo '{"host":"{api_url_identifier}.appsync-api.{region}.amazonaws.com","x-api-key":"da2-{xxxxxxxxxxxxxxxxxxxxxxxxxx}"}' | base64 -w0`
$ wscat -p 13 -s graphql-ws -c  "wss://{api_url_identifier}.appsync-realtime-api.{region}.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 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"}

在 AZ2 私有子网中的 EC2 实例上,我将执行 createToDo 突变。

$ curl -v https://{api_url_identifier}.appsync-api.{region}.amazonaws.com/graphql \
-H "Content-Type:application/graphql" \
-H "x-api-key:da2-{xxxxxxxxxxxxxxxxxxxxxxxxxx}" \
-d '{"query": "mutation createTodo($createtodoinput: CreateTodoInput!) {createTodo(input: $createtodoinput) {id title description priority}}","variables":"{\"createtodoinput\": {\"title\": \"Go to the shops\",\"description\": \"Go to the shops\",\"priority\": 5}}"}'

在 AZ1 私有子网中的 EC2 实例上,我可以看到订阅通知已触发,消息通知如下所示

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

如果您打算使用 VPC 终端节点公有主机名 来设置订阅,以下是在 EC2 上启动连接的示例查询

$ header=`echo '{"host":"{api_url_identifier}.appsync-api.{region}.amazonaws.com","x-api-key":"da2-{xxxxxxxxxxxxxxxxxxxxxxxxxx}"}' | base64 -w0`
$ wscat -H "x-appsync-domain:{api_url_identifier}.appsync-realtime-api.{region}.amazonaws.com" -p 13 -s graphql-ws -c "wss://vpce-0dc6000550d45e160-m78pnq69.appsync-api.{region}.vpce.amazonaws.com/graphql?header=$header&payload=e30="

那么初始化连接后启动订阅的示例查询如下所示:

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

需要知道的重要事项

  • API 只能在创建时设置为私有。创建 API 后无法将其设为私有,私有 API 在创建后也无法更改。
  • 为启用私有 DNS 的 Aws AppSync 设置 VPC 接口终端节点将阻止 VPC 中的资源使用 AppSync 生成的 API 网址调用其他 AppSync 公共 API。这是因为对公共 API 的请求将通过公共 API 不允许的接口端点进行路由。要在这种情况下调用公共 API,建议在公共 API 上配置自定义域名,然后 VPC 中的资源可以使用这些域名来调用公共 API。
  • 使用适用于 亚马逊云科技 AppSync 的 VPC 接口终端节点,您可以访问同一 亚马逊云科技 账户和区域中的任何私有 API。要进一步限制对私有 API 的访问,您可以考虑以下几点:
    • 确保只有必需的管理员才能为 亚马逊云科技 A ppSync 创建 VPC 终端节点接口
    • 使用 VPC 终端节点自定义策略来限制可以从 V PC 中的资源调用哪些 API
    • 来获取 VPC 中的资源,建议使用 IAM 授权来调用 AppSync API;切记确保为资源分配的角色范围仅限于 API。
  • 要测试您的私有 API,测试客户端或查询编辑器需要通过 亚马逊云科技 AppSync 的 VPC 接口终端节点向 API 发送请求。您可以使用通往接口终端节点的网络路由在 VPC 或本地数据中心设置测试客户端。

今天就开始吧!

AppSync 私有 API 通常可在当今推出 Aws AppSync 的所有 亚马逊云科技 地区使用。您可以参阅 亚马逊云科技 区域服务列表 ,了解可用 AppSync 的区域。要了解有关私有 API 的更多信息,请参阅 AppSync 文档

作者简介

Ozioma Uzoegwu

Ozioma 是亚马逊网络服务的高级解决方案架构师。在他的职位上,他通过提供架构指导和最佳实践,帮助各种规模的客户在 亚马逊云科技 云平台上实现转型和现代化。Ozioma 在网络开发、架构、云和 IT 管理方面拥有多年的经验。在加入 亚马逊云科技 之前,Ozioma 曾与 亚马逊云科技 高级咨询合作伙伴合作,担任 亚马逊云科技 业务的首席架构师。他热衷于软件开发,对使用无服务器技术构建现代应用程序有着浓厚的兴趣。