

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 使用 AWS AppSync 私有 APIs
<a name="using-private-apis"></a>

如果您使用 Amazon Virtual Private Cloud (Amazon VPC)，您可以建立 AWS AppSync 私有 APIs，這是只能從 VPC 存取的 APIs。使用私有 API，您可以限制對內部應用程式的 API 存取，並連接到 GraphQL 和 Realtime 端點，而無需公開資料。

若要在 VPC 和服務之間建立私有連線 AWS AppSync ，您必須建立介面 VPC 端點。介面端點採用 技術[AWS PrivateLink](https://aws.amazon.com/privatelink)，可讓您在沒有網際網路閘道、NAT 裝置、VPN 連線或 Direct Connect 連線的情況下私下存取 AWS AppSync APIs。VPC 中的執行個體不需要公有 IP 地址，即能與 AWS AppSync API 通訊。​ VPC 與 之間的流量 AWS AppSync 不會離開 AWS 網路。

AWS AppSync AWS PrivateLink 支援資料平面和控制平面操作：
+ **資料平面端點 **(`com.amazonaws.{region}.appsync-api`)：提供 GraphQL 和即時 APIs私有存取權，用於查詢、變動和訂閱。
+ **控制平面端點 **(`com.amazonaws.{region}.appsync`)：提供 AWS AppSync 管理操作的私有存取權，例如建立 APIs、更新結構描述和設定資料來源。

![\[AWS 雲端 architecture showing VPC with public and private subnets connecting to AWS AppSync via PrivateLink.\]](http://docs.aws.amazon.com/zh_tw/appsync/latest/devguide/images/private-api-architecture.png)


啟用私有 API 功能之前，需要考慮一些其他因素：
+ 在啟用私有 DNS 功能 AWS AppSync 的情況下設定 的 VPC 介面端點，會使 VPC 中的資源無法使用 AWS AppSync 產生的 APIs URL 叫用其他 AWS AppSync 公有 API。這是因為透過界面端點路由至公有 API 的請求，公有 APIs 不允許此請求。若要在此案例中叫用公有 APIs，建議您在公有 APIs上設定自訂網域名稱，然後由 VPC 中的資源用來叫用公有 API。
+ 您的 AWS AppSync 私有 APIs只能從您的 VPC 取得。 AWS AppSync 主控台查詢編輯器只有在瀏覽器的網路組態可以將流量路由到 VPC （例如，透過 VPN 或 的連線 Direct Connect) 時，才能連線到您的 API。
+ 使用 的 VPC 介面端點 AWS AppSync，您可以存取相同 AWS 帳戶和區域中的任何私有 API。若要進一步限制對私有 APIs存取，您可以考慮下列選項：
  + 確保只有必要的管理員可以為其建立 VPC 端點介面 AWS AppSync。
  + 使用 VPC 端點自訂政策來限制可從 VPC 中的資源叫用哪些 APIs。
  + 對於 VPC 中的資源，我們建議您使用 IAM 授權來呼叫 AWS AppSync APIs方法是確保將資源授予 APIs 的縮小範圍角色。
+ 建立或使用限制 IAM 主體的政策時，您必須將 方法`authorizationType`的 設定為 `AWS_IAM`或 `NONE`。

## 建立 AWS AppSync 私有 APIs
<a name="creating-private-apis"></a>

下列步驟說明如何在 AWS AppSync 服務中建立私有 APIs。

**警告**  
您只能在建立 API 期間啟用私有 API 功能。建立 API 或 AWS AppSync 私有 AWS AppSync API 之後，就無法在 API 或私有 API 上修改此設定。

1. 登入 AWS 管理主控台 並開啟 [AppSync 主控台](https://console.aws.amazon.com/appsync/)。

   1. 在**儀表板**上，選擇 **Create API (建立 API)**。

1. 選擇**從頭開始設計 API**，然後選擇**下一步**。

1. 在**私有 API** 區段中，選擇**使用私有 API 功能**。

1. 設定其餘選項，檢閱 API 的資料，然後選擇**建立**。

您必須先在 VPC AWS AppSync 中設定 的介面端點，才能使用 AWS AppSync 私有 API。請注意，私有 API 和 VPC 必須位於相同的 AWS 帳戶和區域。

## 建立 的介面端點 AWS AppSync
<a name="creating-interface-endpoint"></a>

您可以使用 Amazon VPC AWS AppSync 主控台或 AWS Command Line Interface () 為 建立介面端點AWS CLI。根據您的使用案例，您可能需要建立一個或兩個端點類型：
+ **資料平面端點**：從 VPC 存取私有 APIs時需要
+ **控制平面端點**：使用 AWS CLI 或 SDKs 從 VPC 管理 AWS AppSync 資源時需要

如需詳細資訊，請參閱《Amazon VPC 使用者指南》**中的[建立介面端點](https://docs.aws.amazon.com/vpc/latest/privatelink/vpce-interface.html#create-interface-endpoint)。

**注意**  
請確定您選取正確的 VPC 端點服務；AppSync 有兩個： `com.amazonaws.{region}.appsync-api` 是私有 APIs所需的服務，而 `com.amazonaws.{region}.appsync` 用於 API 管理。

------
#### [ Console ]

1. 登入 AWS 管理主控台 並開啟 Amazon VPC 主控台的[端點](https://console.aws.amazon.com/vpc/home?#Endpoints)頁面。

1. 選擇**建立端點**。

   1. 在**服務類別**欄位中，確認已選取**AWS 服務**。

   1. 在**服務**表格中，選擇下列其中一項服務：
      + 對於資料平面存取： `com.amazonaws.{region}.appsync-api`
      + 對於控制平面存取： `com.amazonaws.{region}.appsync`

      確認**類型**資料欄值為 `Interface`。

   1. 在 **VPC** 欄位中，選擇 VPC 及其子網路。

   1. 若要啟用介面端點的私有 DNS 功能，請勾選**啟用 DNS 名稱**核取方塊。

   1. 在**安全群組**欄位中，選擇一或多個安全群組。

1. 選擇**建立端點**。

1. 視需要重複此程序以建立第二個端點類型。

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

使用 `[create-vpc-endpoint](https://docs.aws.amazon.com/cli/latest/reference/ec2/create-vpc-endpoint.html)` 命令，並指定 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
```

**建立控制平面端點：**

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

------

若要使用私有 DNS 選項，您必須設定 VPC 的 `enableDnsHostnames`和 `enableDnsSupportattributes`值。如需詳細資訊，請參閱 *Amazon VPC 使用者指南*中的[檢視並更新 VPC 的 DNS 支援](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-dns.html#vpc-dns-updating)。如果您為介面端點啟用私有 DNS 功能，您可以使用其預設公有 DNS 端點，使用以下格式向 AWS AppSync API GraphQL 和即時端點提出請求：

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

對於控制平面操作，您可以使用標準 AWS AppSync 服務端點：

```
https://appsync.{region}.amazonaws.com
```

如需服務端點的詳細資訊，請參閱《 *AWS 一般參考*》中的[服務端點和配額](https://docs.aws.amazon.com/general/latest/gr/aws-service-information.html)。

如需與介面端點進行服務互動的詳細資訊，請參閱《*Amazon VPC 使用者指南*》中的[透過介面端點存取服務](https://docs.aws.amazon.com/vpc/latest/privatelink/vpce-interface.html#access-service-though-endpoint)。

如需有關使用 AWS CloudFormation 建立和設定端點的資訊，請參閱 *AWS CloudFormation 使用者指南*中的 [AWS：：EC2：：VPCEndpoint](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpcendpoint.html) 資源。

## 進階 範例
<a name="advanced-example"></a>

如果您為介面端點啟用私有 DNS 功能，您可以使用其預設公有 DNS 端點，使用以下格式向 AWS 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
```

如果您已在 AZ 中部署端點，您也可以使用 AZ 特定的 DNS 主機名稱：

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

使用 VPC 端點公有 DNS 名稱需要將 AWS AppSync API 端點主機名稱做為 `Host` 或 ` x-appsync-domain` 標頭傳遞給請求。這些範例使用`TodoAPI`在[啟動範例結構描述指南中建立的 ](https://docs.aws.amazon.com/appsync/latest/devguide/quickstart-launch-a-sample-schema.html)：

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

在下列範例中，我們將使用[啟動範例結構描述](https://docs.aws.amazon.com/appsync/latest/devguide/quickstart-launch-a-sample-schema.html)指南中產生的 *Todo* 應用程式。為了測試範例 Todo API，我們將使用私有 DNS 來叫用 API。您可以使用您選擇的任何命令列工具；此範例使用 [curl](https://curl.se/) 傳送查詢和變動，並使用 [wscat](https://www.npmjs.com/package/wscat) 設定訂閱。若要模擬我們的範例，請將以下命令`{ }`中括號中的值取代為來自您 AWS 帳戶的對應值。

**測試變動操作 – `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`變動**

若要在 中設定 GraphQL 訂閱 AWS AppSync，請參閱[建置即時 WebSocket 用戶端。](https://docs.aws.amazon.com/appsync/latest/devguide/real-time-websocket-client.html)從 VPC 中的 Amazon EC2 執行個體，您可以使用 [wscat](https://github.com/websockets/wscat) 測試 AWS 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`命令中指定**主機**標頭以建立 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"}}}}
```

## 控制平面範例
<a name="control-plane-examples"></a>

設定控制平面 VPC 端點後，您可以使用 AWS CLI 或 SDKs 從 VPC 內管理 AWS AppSync 資源。以下是常見控制平面操作的範例：

**使用 建立 API AWS CLI**

```
aws appsync create-graphql-api \
  --name "MyPrivateAPI" \
  --authentication-type API_KEY \
  --visibility PRIVATE
```

**更新結構描述**

```
aws appsync start-schema-creation \
  --api-id {api-id} \
  --definition file://schema.graphql
```

**建立資料來源**

```
aws appsync create-data-source \
  --api-id {api-id} \
  --name "MyDataSource" \
  --type AWS_LAMBDA \
  --lambda-config lambdaFunctionArn=arn:aws:lambda:{region}:{account}:function:MyFunction
```

在啟用私有 DNS 的情況下使用控制平面端點時，這些命令會自動透過 VPC 端點路由。如果未啟用私有 DNS，您可以指定端點 URL：

```
aws appsync create-graphql-api \
  --endpoint-url https://{vpc_endpoint_id}-{endpoint_dns_identifier}.appsync.{region}.vpce.amazonaws.com \
  --name "MyPrivateAPI" \
  --authentication-type API_KEY \
  --visibility PRIVATE
```

## 使用 IAM 政策限制公有 API 建立
<a name="blocking-public-apis"></a>

AWS AppSync 支援搭配私有 APIs 使用的 IAM [`Condition`陳述](https://docs.aws.amazon.com/service-authorization/latest/reference/reference_policies_actions-resources-contextkeys.html)式。`visibility` 欄位可以包含在 `appsync:CreateGraphqlApi` 操作的 IAM 政策陳述式中，以控制哪些 IAM 角色和使用者可以建立私有和公有 APIs。這可讓 IAM 管理員定義 IAM 政策，僅允許使用者建立 Private GraphQL API。嘗試建立公有 API 的使用者會收到未經授權的訊息。

例如，IAM 管理員可以建立下列 IAM 政策陳述式，以允許建立私有 APIs：

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

IAM 管理員也可以新增下列[服務控制政策](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html)，以阻止 AWS 組織中的所有使用者建立私有 AWS AppSync APIs以外的 APIs：

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

## VPC PrivateLink 支援
<a name="privatelink-support"></a>

VPC Privatelink 支援可在 中使用 AWS AppSync。PrivateLink 可讓您使用 AWS 服務並與之互動，而不需要離開 AWS 網路的任何流量。

AWS AppSync AWS PrivateLink 支援資料平面和控制平面操作。
+ **VPCE 端點** (`appsync.<region>.vpce.amazonaws.com`)：提供資料平面的 VPC 存取權和控制平面操作，如下所示：
  + 控制平面操作的 **appync** 
  + 用於資料平面操作的 **appync-api** 