

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

# 使用 AWS Identity and Access Management 身分驗證連線至 Amazon Neptune 資料庫
<a name="iam-auth-connecting"></a>

已啟用 IAM 資料庫身分驗證的 Amazon Neptune 資源需要使用 AWS Signature 第 4 版簽署所有 HTTP 請求。如需使用 AWS Signature 第 4 版簽署請求的一般資訊，請參閱[簽署 AWS API 請求](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-signing.html)。

AWS Signature 第 4 版是將身分驗證資訊新增至 AWS 請求的程序。為了安全起見，對 的大多數請求 AWS 都必須使用存取金鑰簽署，該金鑰包含存取金鑰 ID 和私密存取金鑰。

**注意**  
如果您使用臨時登入資料，登入資料會在指定的時間後過期，*包括工作階段字符*。  
當您請求新的登入資料時，必須更新工作階段字符。如需詳細資訊，請參閱[使用暫時安全登入資料來請求存取 AWS 資源](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html)。

**重要**  
透過 IAM 型身分驗證存取 Neptune 會要求您建立 HTTP 請求並自行簽署這些請求。

**Signature 第 4 版的運作方式**

1. 建立正式的請求。

1. 您可以使用正式請求及一些其他資訊來建立要簽署的字串。

1. 您可以使用 AWS 私密存取金鑰來衍生簽署金鑰，然後使用該簽署金鑰和string-to-sign來建立簽章。

1. 您可以對標頭中的 HTTP 請求新增所產生的簽章，或做為查詢字串參數。

當 Neptune 收到請求時，便會執行您計算簽章所做的相同步驟。接著 Neptune 就會比較計算簽章與跟請求一併傳送的簽章。如果簽章相符，就會受理請求。如果簽章不相符，則會拒絕請求。

如需使用 AWS Signature 第 4 版簽署請求的一般資訊，請參閱 中的 [Signature 第 4 版簽署程序](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html)*AWS 一般參考*。

下列章節會包含範例，示範如何在啟用 IAM 身分驗證的情況下，將已簽署的請求傳送至 Neptune 資料庫執行個體的 Gremlin 和 SPARQL 端點。

**Topics**
+ [使用 IAM 身分驗證連接 Amazon Neptune 資料庫的先決條件](iam-auth-connect-prerq.md)
+ [從命令列使用 IAM 身分驗證連線至 Amazon Neptune 資料庫](iam-auth-connect-command-line.md)
+ [使用 IAM 身分驗證搭配 Gremlin 主控台連線至 Amazon Neptune 資料庫](iam-auth-connecting-gremlin-console.md)
+ [使用 IAM 搭配 Gremlin Java 連線至 Amazon Neptune 資料庫](iam-auth-connecting-gremlin-java.md)
+ [使用 IAM 身分驗證搭配 Java 和 SPARQL 連線至 Amazon Neptune 資料庫](iam-auth-connecting-sparql-java.md)
+ [使用 IAM 身分驗證搭配 SPARQL 和 Node.js 連線至 Amazon Neptune 資料庫](iam-auth-connecting-sparql-node.md)
+ [使用 IAM 身分驗證搭配 Python 連線至 Amazon Neptune 資料庫](iam-auth-connecting-python.md)
+ [使用 IAM 身分驗證搭配 Gremlin Python 連線至 Amazon Neptune 資料庫](gremlin-python-iam-auth.md)
+ [使用 IAM 身分驗證搭配 Gremlin JavaScript 連線至 Amazon Neptune 資料庫](gremlin-javascript-iam-auth.md)
+ [使用 IAM 身分驗證搭配 Gremlin Go 連線至 Amazon Neptune 資料庫](gremlin-go-iam-auth.md)
+ [使用 IAM 身分驗證搭配 Gremlin .NET 連線至 Amazon Neptune 資料庫](gremlin-dotnet-iam-auth.md)

# 使用 IAM 身分驗證連接 Amazon Neptune 資料庫的先決條件
<a name="iam-auth-connect-prerq"></a>

以下說明如何在 Amazon EC2 執行個體上安裝 Apache Maven 和 Java 8。這些是 Amazon Neptune Signature 第 4 版身分驗證範例的必要項目。

**若要在 EC2 執行個體上安裝 Apache Maven 和 Java 8。**

1. 使用 SSH 用戶端連線至 Amazon EC2 執行個體。

1. 在 EC2 執行個體上安裝 Apache Maven。如果使用 Amazon Linux 2023 （偏好），請使用：

   ```
   sudo dnf update -y
   sudo dnf install maven -y
   ```

   如果使用 Amazon Linux 2，請從 [https://maven.apache.org/download.cgi：// 下載最新的二進位檔： ](https://maven.apache.org/download.cgi:)

   ```
   sudo yum remove maven -y
   wget https://dlcdn.apache.org/maven/maven-3/ <version>/binaries/apache-maven-<version>-bin.tar.gz
   sudo tar -xzf apache-maven-<version>-bin.tar.gz -C /opt/
   sudo ln -sf /opt/apache-maven-<version> /opt/maven
   echo 'export MAVEN_HOME=/opt/maven' >> ~/.bashrc
   echo 'export PATH=$MAVEN_HOME/bin:$PATH' >> ~/.bashrc
   source ~/.bashrc
   ```

1. Gremlin 二進位碼需要 Java 8。輸入以下內容將 Java 8 安裝在您的 EC2 執行個體上。

   ```
   sudo yum install java-1.8.0-devel
   ```

1. 輸入以下內容將 Java 8 設定為 EC2 執行個體上預設的執行時間。

   ```
   sudo /usr/sbin/alternatives --config java
   ```

   出現提示時，輸入 Java 8 的數字。

1. 輸入以下內容，將 Java 8 設為 EC2 執行個體上的預設編譯器。

   ```
   sudo /usr/sbin/alternatives --config javac
   ```

   出現提示時，輸入 Java 8 的數字。

# 從命令列使用 IAM 身分驗證連線至 Amazon Neptune 資料庫
<a name="iam-auth-connect-command-line"></a>

如本文件中的許多範例所示，具有將查詢提交至 Neptune 資料庫叢集的命令列工具非常方便。如果未啟用 IAM 身分驗證，[curl](https://curl.haxx.se/) 工具是與 Neptune 端點通訊的絕佳選擇。

**不過，若要保護您的資料，最好啟用 IAM 身分驗證。**

當 IAM 身分驗證啟用時，每個請求都必須使用 [Signature 第 4 版 (Sig4) 進行簽署](https://docs.aws.amazon.com/general/latest/gr/signing-aws-api-requests.html)。第三方 [awscurl](https://github.com/okigan/awscurl) 命令列工具會使用與 `curl` 相同的語法，並且可以使用 Sig4 簽署來簽署查詢。以下 [使用 `awscurl`](#iam-auth-connect-awscurl) 一節說明如何安全地使用 `awscurl` 搭配臨時憑證。

## 設定命令列工具來使用 HTTPS
<a name="iam-auth-connect-command-line-https"></a>

Neptune 要求所有連線都使用 HTTPS。任何命令行工具 (例如 `curl` 或 `awscurl`) 需要存取適當的憑證，才能使用 HTTPS。只要 `curl` 或 `awscurl` 可以找到適當的憑證，它們處理 HTTPS 連線的方式就跟 HTTP 連線一樣，無需額外參數。此文件的範例是以該案例為基礎。

若要了解如何取得這類憑證，以及如何將它們正確格式化為 `curl` 可以使用的憑證授權機構 (CA) 憑證存放區，請參閱 `curl` 文件中的 [SSL 憑證驗證](https://curl.haxx.se/docs/sslcerts.html)。

然後，您可以使用 `CURL_CA_BUNDLE` 環境變數來指定此 CA 憑證存放區的位置。在 Windows 上，`curl` 會自動在名為 `curl-ca-bundle.crt` 的檔案中尋找它。它會先在和 `curl.exe` 相同的目錄中尋找，然後再尋找路徑的其他位置。如需詳細資訊，請參閱 [SSL Certificate Verification](https://curl.haxx.se/docs/sslcerts.html)。

## 使用 `awscurl` 搭配臨時憑證，安全地連線至啟用 IAM 身分驗證的資料庫叢集
<a name="iam-auth-connect-awscurl"></a>

[awscurl](https://github.com/okigan/awscurl) 工具會使用與 `curl` 相同的語法，但也需要額外的資訊：
+ **`--access_key`** – 有效的存取金鑰。如果未使用此參數提供，則必須在 `AWS_ACCESS_KEY_ID` 環境變數或在組態檔案中提供它。
+ **`--secret_key`** – 對應至存取金鑰的有效私密存鑰。如果未使用此參數提供，則必須在 `AWS_SECRET_ACCESS_KEY` 環境變數或在組態檔案中提供它。
+ **`--security_token`** – 有效的工作階段權杖。如果未使用此參數提供，則必須在 `AWS_SECURITY_TOKEN` 環境變數或在組態檔案中提供它。

在過去，常見的做法是使用永久憑證搭配 `awscurl` (例如 IAM 使用者憑證，甚至是根憑證)，但不建議這麼做。相反地，使用其中一個 [AWS Security Token Service (STS) API](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html) 或其中一個 [AWS CLI 包裝函式](https://docs.aws.amazon.com/cli/latest/reference/sts/index.html)來產生臨時憑證。

最好將 STS 呼叫所傳回的 `AccessKeyId`、`SecretAccessKey` 和 `SessionToken` 值放入 Shell 工作階段中的適當環境變數中，而不是放入組態檔案中。然後，當 Shell 終止時，憑證會自動捨棄，而組態檔案不是這種情況。同樣地，請不要為臨時憑證請求長於您可能需要的持續時間。

下列範例展示您可能在 Linux Shell 中採取的步驟，以使用 [sts assume-role](https://docs.aws.amazon.com/cli/latest/reference/sts/assume-role) 取得有效半小時的臨時憑證，然後將它們放在 `awscurl` 可以找到它們的環境變數中：

```
aws sts assume-role \
    --duration-seconds 1800 \
    --role-arn "arn:aws:iam::(account-id):role/(rolename)" \
    --role-session-name AWSCLI-Session > $output
AccessKeyId=$(echo $output | jq '.Credentials''.AccessKeyId')
SecretAccessKey=$(echo $output | jq '.Credentials''.SecretAccessKey')
SessionToken=$(echo $output | jq '.Credentials''.SessionToken')

export AWS_ACCESS_KEY_ID=$AccessKeyId
export AWS_SECRET_ACCESS_KEY=$SecretAccessKey
export AWS_SESSION_TOKEN=$SessionToken
```

然後，您可以使用 `awscurl` 對資料庫叢集提出簽署的請求，如下所示：

```
awscurl (your cluster endpoint):8182/status \
    --region us-east-1 \
    --service neptune-db
```

# 使用 IAM 身分驗證搭配 Gremlin 主控台連線至 Amazon Neptune 資料庫
<a name="iam-auth-connecting-gremlin-console"></a>

若要使用具有 Signature 第 4 版身分驗證的 Gremlin 主控台連線至 Amazon Neptune，您可以使用 `requestInterceptor()`將 SigV4 簽署者插入 `:remote`命令建立的連線。這需要您手動設定`Cluster`物件，然後將其傳遞至 `:remote`命令。

請注意，這與 `:remote` 命令需要組態檔案形成連線的典型情況完全不同。組態檔案方法將無法運作，因為 `requestInterceptor()` 必須以程式設計方式設定，並且無法從檔案中載入其組態。

**注意**  
下列範例使用在 TinkerPop 3.6.6 中引入`requestInterceptor()`的 。如果您使用的 TinkerPop 版本早於 3.6.6 （但為 3.5.5 或更新版本），請使用 `handshakeInterceptor()`，而不是下列程式碼範例中`requestInterceptor()`的 。

下列先決條件為必要條件：
+ 您必須具有簽署請求所需的 IAM 憑證。請參閱《 適用於 Java 的 AWS SDK 開發人員指南》中的[使用預設憑證提供者鏈結](https://docs.aws.amazon.com//sdk-for-java/latest/developer-guide/credentials-chain.html)。
+ 您必須已安裝與資料庫叢集所使用的 Neptune 引擎版本相容的 Gemlin 主控台版本。

如果您使用的是臨時憑證，它們會在指定的間隔後過期，而工作階段權杖也一樣，因此在您請求新憑證時必須更新您的工作階段權杖。請參閱《IAM 使用者指南》中的[使用臨時安全登入資料來請求存取 AWS 資源](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html)。

如需使用 SSL/TLS 進行連線的說明，請參閱 [SSL/TLS 組態](access-graph-gremlin-java.md#access-graph-gremlin-java-ssl)。

**使用 Sig4 簽署來連接 Gremlin 主控台**

1. 啟動 Gremlin 主控台：

   ```
   $ bin/gremlin.sh
   ```

1. 在 `gremlin>` 提示中，安裝 `amazon-neptune-sigv4-signer` 程式庫 (只需要為主控台完成一次此操作)：

   ```
   :install com.amazonaws amazon-neptune-sigv4-signer 2.4.0
   ```

   如果您在此步驟中遇到問題，則參閱有關 [Grape](http://docs.groovy-lang.org/latest/html/documentation/grape.html) 組態的 [TinkerPop 文件](https://tinkerpop.apache.org/docs/current/reference/#gremlin-applications)可能會有所幫助 。
**注意**  
如果您使用的是 HTTP Proxy，在此步驟中可能會遇到 `:install` 命令未完成的錯誤。若要解決此問題，請執行下列命令，以告知主控台有關 Proxy 的相關資訊：  

   ```
   System.setProperty("https.proxyHost", "(the proxy IP address)")
   System.setProperty("https.proxyPort", "(the proxy port)")
   ```

1. 將處理簽署所需的類別匯入至 `requestInterceptor()`：

   ```
   :import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider
   :import com.amazonaws.neptune.auth.NeptuneNettyHttpSigV4Signer
   ```

1. 如果您使用的是臨時憑證，則還需要提供工作階段權杖，如下所示：

   ```
   System.setProperty("aws.sessionToken","(your session token)")
   ```

1. 如果您尚未以其他方式建立帳戶憑證，則可以指派它們，如下所示：

   ```
   System.setProperty("aws.accessKeyId","(your access key)")
   System.setProperty("aws.secretKey","(your secret key)")
   ```

1. 手動建構要連線至 Neptune 的 `Cluster` 物件：

   ```
   cluster = Cluster.build("(host name)")  \
                    .enableSsl(true) \
                    .requestInterceptor { r ->  \
                      def sigV4Signer = new NeptuneNettyHttpSigV4Signer("(Amazon region)", \
                                        DefaultCredentialsProvider.create()); \
                      sigV4Signer.signRequest(r); \
                      return r; } \
                    .create()
   ```

   如需尋找 Neptune 資料庫執行個體主機名稱的說明，請參閱 [連線至 Amazon Neptune 端點](feature-overview-endpoints.md)。

1. 使用上一個步驟中 `Cluster` 物件的變數名稱來建立 `:remote` 連線：

   ```
   :remote connect tinkerpop.server cluster
   ```

1. 輸入以下命令以切換至遠端模式。這會將所有 Gremlin 查詢傳送至遠端連線：

   ```
   :remote console
   ```

# 使用 IAM 搭配 Gremlin Java 連線至 Amazon Neptune 資料庫
<a name="iam-auth-connecting-gremlin-java"></a>

以下是如何使用 Gremlin Java API 搭配 Sig4 簽署來連線至 Neptune 的範例 （它假設具有使用 Maven 的一般知識）。此範例使用 [Amazon Neptune SigV4 Signer](https://github.com/aws/amazon-neptune-sigv4-signer) 程式庫協助簽署請求。首先，將相依性定義為 `pom.xml` 檔案的一部分：

**注意**  
下列範例使用在 TinkerPop 3.6.6 中引入`requestInterceptor()`的 。如果您使用的 TinkerPop 版本早於 3.6.6 （但為 3.5.5 或更新版本），請使用 `handshakeInterceptor()`，而不是下列程式碼範例中`requestInterceptor()`的 。

```
<dependency>
  <groupId>com.amazonaws</groupId>
  <artifactId>amazon-neptune-sigv4-signer</artifactId>
  <version>3.1.0</version>
</dependency>
```

 Amazon Neptune SigV4 Signer 同時支援 AWS Java 開發套件的 1.x 和 2.x 版本。下列範例使用 2.x，其中 `DefaultCredentialsProvider` 是`software.amazon.awssdk.auth.credentials.AwsCredentialsProvider`執行個體。如果您要從 1.x 升級到 2.x，請參閱適用於 Java 的 AWS SDK 2.x 文件中的[登入資料提供者變更](https://docs.aws.amazon.com//sdk-for-java/latest/developer-guide/migration-client-credentials.html)。

```
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
import com.amazonaws.neptune.auth.NeptuneNettyHttpSigV4Signer;
import com.amazonaws.neptune.auth.NeptuneSigV4SignerException;

 ...

System.setProperty("aws.accessKeyId","your-access-key");
System.setProperty("aws.secretKey","your-secret-key");

 ...

Cluster cluster = Cluster.build((your cluster))
                 .enableSsl(true)
                 .requestInterceptor( r ->
                  {
                    try {
                      NeptuneNettyHttpSigV4Signer sigV4Signer =
                        new NeptuneNettyHttpSigV4Signer("(your region)", DefaultCredentialsProvider.create());
                      sigV4Signer.signRequest(r);
                    } catch (NeptuneSigV4SignerException e) {
                      throw new RuntimeException("Exception occurred while signing the request", e);
                    }
                    return r;
                  }
                 ).create();
try {
  Client client = cluster.connect();
  client.submit("g.V().has('code','IAD')").all().get();
} catch (Exception e) {
  throw new RuntimeException("Exception occurred while connecting to cluster", e);
}
```

## 跨帳戶 IAM 身分驗證
<a name="iam-auth-connecting-gremlin-java-cross-account"></a>

 Amazon Neptune 透過使用角色假設支援跨帳戶 IAM 身分驗證，有時也稱為[角色鏈結](https://docs.aws.amazon.com//neptune/latest/userguide/bulk-load-tutorial-chain-roles.html#bulk-load-tutorial-chain-cross-account)。若要從託管在不同 AWS 帳戶中的應用程式提供 Neptune 叢集的存取權：
+  在應用程式 AWS 帳戶中建立新的 IAM 使用者或角色，其信任政策允許使用者或角色擔任另一個 IAM 角色。將此角色指派給託管應用程式的運算 (EC2 執行個體、Lambda 函數、ECS 任務等）。

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

****  

  ```
  {
    "Version":"2012-10-17",		 	 	 
    "Statement": [
      {
        "Sid": "assumeRolePolicy",
        "Effect": "Allow",
        "Action": "sts:AssumeRole",
        "Resource": "arn:aws:iam::111122223333:role/role-name"
      }
    ]
  }
  ```

------
+  在 Neptune 資料庫 AWS 帳戶中建立新的 IAM 角色，允許存取 Neptune 資料庫，並允許應用程式帳戶 IAM 使用者/角色擔任角色。使用信任政策：

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

****  

  ```
  {
      "Version":"2012-10-17",		 	 	 
      "Statement": [
          {
              "Effect": "Allow",
              "Principal": {
                  "AWS": [
                      "(ARN of application account IAM user or role)"
                  ]
              },
              "Action": "sts:AssumeRole",
              "Condition": {}
          }
      ]
  }
  ```

------
+  使用以下程式碼範例做為如何使用這兩個角色以允許應用程式存取 Neptune 的指引。在此範例中，應用程式帳戶角色會在建立 時透過 [DefaultCredentialProviderChain](https://docs.aws.amazon.com//sdk-for-java/v1/developer-guide/credentials.html) 擔任`STSclient`。`STSclient` 然後，透過 使用 `STSAssumeRoleSessionCredentialsProvider`來擔任 Neptune 資料庫 AWS 帳戶中託管的角色。

  ```
  public static void main( String[] args )
    {
  
      /* 
       * Establish an STS client from the application account.
       */
      AWSSecurityTokenService client = AWSSecurityTokenServiceClientBuilder
          .standard()
          .build();
  
      /*
       * Define the role ARN that you will be assuming in the database account where the Neptune cluster resides.
       */
      String roleArnToAssume = "arn:aws:iam::012345678901:role/CrossAccountNeptuneRole";
      String crossAccountSessionName = "cross-account-session-" + UUID.randomUUID();
  
      /*
       * Change the Credentials Provider in the SigV4 Signer to use the STSAssumeRole Provider and provide it
       * with both the role to be assumed, the original STS client, and a session name (which can be
       * arbitrary.)
       */
      Cluster cluster = Cluster.build()
                   .addContactPoint("neptune-cluster.us-west-2.neptune.amazonaws.com")
                   .enableSsl(true)
                   .port(8182)
                   .requestInterceptor( r ->
                    {
                      try {
                        NeptuneNettyHttpSigV4Signer sigV4Signer =
                          // new NeptuneNettyHttpSigV4Signer("us-west-2", DefaultCredentialsProvider.create());
                          new NeptuneNettyHttpSigV4Signer(
                                  "us-west-2",  
                                   new STSAssumeRoleSessionCredentialsProvider
                                      .Builder(roleArnToAssume, crossAccountSessionName)
                                          .withStsClient(client)
                                          .build());
                        sigV4Signer.signRequest(r);
                      } catch (NeptuneSigV4SignerException e) {
                        throw new RuntimeException("Exception occurred while signing the request", e);
                      }
                      return r;
                    }
                   ).create();
  
      GraphTraversalSource g = traversal().withRemote(DriverRemoteConnection.using(cluster));
  
      /* whatever application code is necessary */
  
      cluster.close();
    }
  ```

# 使用 IAM 身分驗證搭配 Java 和 SPARQL 連線至 Amazon Neptune 資料庫
<a name="iam-auth-connecting-sparql-java"></a>

本節說明如何搭配 Signature 第 4 版身分驗證，使用 RDF4J 或 Apache Jena 連線到 Neptune。

**先決條件**
+ Java 8 或更高版本。
+ Apache Maven 3.3 或更高版本。

  如需在執行 Amazon Linux 的 EC2 執行個體上安裝這些先決條件的詳細資訊，請參閱[使用 IAM 身分驗證連接 Amazon Neptune 資料庫的先決條件](iam-auth-connect-prerq.md)。
+ 用於簽署請求的 IAM 登入資料。如需詳細資訊，請參閱《*適用於 Java 的 AWS SDK 開發人員指南*》中的[使用預設憑證提供者鏈結](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/credentials.html#credentials-default)。
**注意**  
如果您使用臨時登入資料，登入資料會在指定的時間後過期，*包括工作階段字符*。  
當您請求新的登入資料時，必須更新工作階段字符。如需詳細資訊，請參閱《*IAM 使用者指南*》中的[使用暫時安全登入資料來請求存取 AWS 資源](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html)。
+ 將 `SERVICE_REGION` 變數設為下列其中一項，指出 Neptune 資料庫執行個體的區域：
  + 美國東部 (維吉尼亞北部)：`us-east-1`
  + 美國東部 (俄亥俄)：`us-east-2`
  + 美國西部 (加利佛尼亞北部)：`us-west-1`
  + 美國西部 (奧勒岡)：`us-west-2`
  + 加拿大 (中部)：`ca-central-1`
  + 加拿大西部 （卡加利）：   `ca-west-1`
  + 南美洲 (聖保羅)：`sa-east-1`
  + 歐洲 (斯德哥爾摩)：`eu-north-1`
  + 歐洲 （西班牙）：   `eu-south-2`
  + 歐洲 (愛爾蘭)：`eu-west-1`
  + 歐洲 (倫敦)：`eu-west-2`
  + 歐洲 (巴黎)：`eu-west-3`
  + 歐洲 (法蘭克福)：`eu-central-1`
  + 中東 (巴林)：`me-south-1`
  + 中東 (阿拉伯聯合大公國)：`me-central-1`
  + 以色列 (特拉維夫)：`il-central-1`
  + 非洲 (開普敦)：`af-south-1`
  + 亞太區域 (香港)：`ap-east-1`
  + 亞太區域 (東京)：`ap-northeast-1`
  + 亞太區域 (首爾)：`ap-northeast-2`
  + 亞太區域 （大阪）：   `ap-northeast-3`
  + 亞太區域 (新加坡)：`ap-southeast-1`
  + 亞太區域 (雪梨)：`ap-southeast-2`
  + 亞太區域 (雅加達)：`ap-southeast-3`
  + 亞太區域 （墨爾本）：   `ap-southeast-4`
  + 亞太區域 （馬來西亞）：   `ap-southeast-5`
  + 亞太區域 (孟買)：`ap-south-1`
  + 亞太區域 （海德拉巴）：   `ap-south-2`
  + 中國 (北京)：`cn-north-1`
  + 中國 (寧夏)：`cn-northwest-1`
  + AWS GovCloud （美國西部）：   `us-gov-west-1`
  + AWS GovCloud （美國東部）：   `us-gov-east-1`

**搭配 Signature 第 4 版簽署，使用 RDF4J 或 Apache Jena 連線到 Neptune**

1. 從 GitHub 複製範本儲存庫。

   ```
   git clone https://github.com/aws/amazon-neptune-sparql-java-sigv4.git
   ```

1. 變更到複製的目錄。

   ```
   cd amazon-neptune-sparql-java-sigv4
   ```

1. 透過簽出具有 latest (最新) 標籤的分支，取得專案的最新版本。

   ```
   git checkout $(git describe --tags `git rev-list --tags --max-count=1`)
   ```

1. 輸入以下其中一個命令來編譯及執行範例程式碼。

   將 *your-neptune-endpoint* 取代為 Neptune 資料庫執行個體的主機名稱或 IP 地址。預設連接埠為 8182。
**注意**  
如需尋找 Neptune 資料庫執行個體主機名稱的相關資訊，請參閱 [連線至 Amazon Neptune 端點](feature-overview-endpoints.md) 一節。

**Eclipse RDF4J**  
輸入以下內容來執行 RDF4J 範例。

   ```
   mvn compile exec:java \
       -Dexec.mainClass="com.amazonaws.neptune.client.rdf4j.NeptuneRdf4JSigV4Example" \
       -Dexec.args="https://your-neptune-endpoint:portsparql region-name"
   ```

**Apache Jena**  
輸入以下內容來執行 Apache Jena 範例。

   ```
   mvn compile exec:java \
       -Dexec.mainClass="com.amazonaws.neptune.client.jena.NeptuneJenaSigV4Example" \
       -Dexec.args="https://your-neptune-endpoint:port"
   ```

1. 若要查看範例的原始程式碼，請參閱 `src/main/java/com/amazonaws/neptune/client/` 目錄中的範例。

若要在您自己 Java 應用程式中使用 SigV4 簽署驅動程式，請將 `amazon-neptune-sigv4-signer` Maven 套件新增到您 `pom.xml` 的 `<dependencies>` 區段。我們建議您使用範例做為起點。

# 使用 IAM 身分驗證搭配 SPARQL 和 Node.js 連線至 Amazon Neptune 資料庫
<a name="iam-auth-connecting-sparql-node"></a>

## 使用簽章 V4 簽署和適用於 Javascript V3 的 AWS SDK 進行查詢
<a name="iam-auth-querying-sparql-js-sdk-v3"></a>

以下是如何使用具有簽章第 4 版身分驗證的 Node.js 和適用於 Javascript V3 的 AWS SDK 連線至 Neptune SPARQL 的範例：

```
const { HttpRequest }  = require('@smithy/protocol-http');
const { fromNodeProviderChain } = require('@aws-sdk/credential-providers');
const { SignatureV4 } = require('@smithy/signature-v4');
const { Sha256 } = require('@aws-crypto/sha256-universal');
const https = require('https');

var region = 'us-west-2'; // e.g. us-west-1
var neptune_endpoint = 'your-Neptune-cluster-endpoint';  // like: 'cluster-id.region.neptune.amazonaws.com'
var query = `query=PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX class: <http://aws.amazon.com/neptune/csv2rdf/class/>
PREFIX resource: <http://aws.amazon.com/neptune/csv2rdf/resource/>
PREFIX prop: <http://aws.amazon.com/neptune/csv2rdf/datatypeProperty/>
PREFIX objprop: <http://aws.amazon.com/neptune/csv2rdf/objectProperty/>

SELECT ?movies ?title WHERE {
  ?jel prop:name "James Earl Jones" .
  ?movies ?p2 ?jel .
  ?movies prop:title ?title
} LIMIT 10`;

runQuery(query);

function runQuery(q) {
  var request = new HttpRequest({
    hostname: neptune_endpoint,
    port: 8182,
    path: 'sparql',
    body: encodeURI(query),
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
      'host': neptune_endpoint + ':8182',
    },
    method: 'POST',
  });

  const credentialProvider = fromNodeProviderChain();
  let credentials = credentialProvider();
  credentials.then(
    (cred)=>{
      var signer = new SignatureV4({credentials: cred, region: region, sha256: Sha256, service: 'neptune-db'});
      signer.sign(request).then(
        (req)=>{
          var responseBody = '';
          var sendreq = https.request(
            {
              host: req.hostname,
              port: req.port,
              path: req.path,
              method: req.method,
              headers: req.headers,
            },
          (res) => {
            res.on('data', (chunk) => { responseBody += chunk; });
            res.on('end', () => {
                console.log(JSON.parse(responseBody));
            });
          });
          sendreq.write(req.body);
          sendreq.end();
        }
      );
    },
    (err)=>{
      console.error(err);
    }
  );
}
```

## 使用簽章 V4 簽署和適用於 Javascript V2 的 AWS SDK 進行查詢
<a name="iam-auth-querying-sparql-js-sdk-v2"></a>

以下是如何使用具有簽章第 4 版身分驗證的 Node.js 和適用於 Javascript V2 的 AWS SDK 連接到 Neptune SPARQL 的範例：

```
var AWS = require('aws-sdk');

var region = 'us-west-2'; // e.g. us-west-1
var neptune_endpoint = 'your-Neptune-cluster-endpoint';  // like: 'cluster-id.region.neptune.amazonaws.com'
var query = `query=PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX class: <http://aws.amazon.com/neptune/csv2rdf/class/>
PREFIX resource: <http://aws.amazon.com/neptune/csv2rdf/resource/>
PREFIX prop: <http://aws.amazon.com/neptune/csv2rdf/datatypeProperty/>
PREFIX objprop: <http://aws.amazon.com/neptune/csv2rdf/objectProperty/>

SELECT ?movies ?title WHERE {
    ?jel prop:name "James Earl Jones" .
    ?movies ?p2 ?jel .
    ?movies prop:title ?title
} LIMIT 10`;

runQuery(query);

function runQuery(q) {

    var endpoint = new AWS.Endpoint(neptune_endpoint);
    endpoint.port = 8182;
    var request = new AWS.HttpRequest(endpoint, region);
    request.path += 'sparql';
    request.body = encodeURI(query);
    request.headers['Content-Type'] = 'application/x-www-form-urlencoded';
    request.headers['host'] = neptune_endpoint;
    request.method = 'POST';

    var credentials = new AWS.CredentialProviderChain();
    credentials.resolve((err, cred)=>{
        var signer = new AWS.Signers.V4(request, 'neptune-db');
        signer.addAuthorization(cred, new Date());
    });

    var client = new AWS.HttpClient();
    client.handleRequest(request, null, function(response) {
        console.log(response.statusCode + ' ' + response.statusMessage);
        var responseBody = '';
        response.on('data', function (chunk) {
            responseBody += chunk;
        });
        response.on('end', function (chunk) {
            console.log('Response body: ' + responseBody);
        });
    }, function(error) {
        console.log('Error: ' + error);
    });
}
```

# 使用 IAM 身分驗證搭配 Python 連線至 Amazon Neptune 資料庫
<a name="iam-auth-connecting-python"></a>

本節顯示以 Python 撰寫的程式範例，說明如何針對 Amazon Neptune 使用 Signature 第 4 版。此範例是根據 [https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html](https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html)* 中的Amazon Web Services 一般參考 Signature 第 4 版簽署程序*部分。

若要使用此範例程式，您需要以下項目：
+ 將 Python 3.x 安裝在電腦上，這個程式可從 [Python 網站](https://www.python.org/downloads/)取得。這些程式已使用 Python 3.6 來測試。
+ [Python requests library](https://pypi.python.org/pypi/requests)，在範例指令碼中用來進行 web 請求。Python 套件安裝方便，只要使用 `pip` 即可從 Python 套件索引網站取得套件。然後，您可以在命令列執行 `pip install requests`，即可安裝 `requests`。
+ 環境變數中的存取金鑰 (存取金鑰 ID 和私密存取金鑰) 名為 `AWS_ACCESS_KEY_ID` `AWS_SECRET_ACCESS_KEY`。根據最佳實務，建議您*請勿* 在程式碼中內嵌登入資料。如需詳細資訊，請參閱「AWS 帳戶管理 參考指南」**中的 [AWS 帳戶的最佳實務](https://docs.aws.amazon.com//accounts/latest/reference/best-practices.html)。

  名為 `SERVICE_REGION` 的環境變數中 Neptune 資料庫叢集的區域。

  如果您使用臨時的登入資料，除了指定 `AWS_ACCESS_KEY_ID`、`AWS_SECRET_ACCESS_KEY`、`SERVICE_REGION`，還必須指定 `AWS_SESSION_TOKEN`。
**注意**  
如果您使用臨時登入資料，登入資料會在指定的時間後過期，*包括工作階段字符*。  
當您請求新的登入資料時，必須更新工作階段字符。如需詳細資訊，請參閱[使用臨時安全憑證來請求對 AWS 資源的存取](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html)。

以下範例說明如何使用 Python 對 Neptune 提出已簽署的請求。此請求提出 GET 或 POST 請求。身分驗證資訊會使用 `Authorization` 請求標頭來傳遞。

此範例也可做為 AWS Lambda 函數。如需詳細資訊，請參閱[為 Neptune IAM 身分驗證設定 AWS Lambda](iam-auth-temporary-credentials.md#iam-auth-temporary-credentials-lambda)。

**對 Gremlin 和 SPARQL Neptune 端點提出已簽署的請求**

1. 建立名為 `neptunesigv4.py` 的新檔案，並在文字編輯器中開啟。

1. 複製以下程式碼，並在 `neptunesigv4.py` 檔案中貼上。

   ```
   # Amazon Neptune version 4 signing example (version v3)
   
   # The following script requires python 3.6+
   #    (sudo yum install python36 python36-virtualenv python36-pip)
   # => the reason is that we're using urllib.parse() to manually encode URL
   #    parameters: the problem here is that SIGV4 encoding requires whitespaces
   #    to be encoded as %20 rather than not or using '+', as done by previous/
   #    default versions of the library.
   
   
   # See: https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html
   import sys, datetime, hashlib, hmac
   import requests  # pip3 install requests
   import urllib
   import os
   import json
   from botocore.auth import SigV4Auth
   from botocore.awsrequest import AWSRequest
   from botocore.credentials import ReadOnlyCredentials
   from types import SimpleNamespace
   from argparse import RawTextHelpFormatter
   from argparse import ArgumentParser
   
   # Configuration. https is required.
   protocol = 'https'
   
   # The following lines enable debugging at httplib level (requests->urllib3->http.client)
   # You will see the REQUEST, including HEADERS and DATA, and RESPONSE with HEADERS but without DATA.
   #
   # The only thing missing will be the response.body which is not logged.
   #
   # import logging
   # from http.client import HTTPConnection
   # HTTPConnection.debuglevel = 1
   # logging.basicConfig()
   # logging.getLogger().setLevel(logging.DEBUG)
   # requests_log = logging.getLogger("requests.packages.urllib3")
   # requests_log.setLevel(logging.DEBUG)
   # requests_log.propagate = True
   
   
   # Read AWS access key from env. variables. Best practice is NOT
   # to embed credentials in code.
   access_key = os.getenv('AWS_ACCESS_KEY_ID', '')
   secret_key = os.getenv('AWS_SECRET_ACCESS_KEY', '')
   region = os.getenv('SERVICE_REGION', '')
   
   # AWS_SESSION_TOKEN is optional environment variable. Specify a session token only if you are using temporary
   # security credentials.
   session_token = os.getenv('AWS_SESSION_TOKEN', '')
   
   ### Note same script can be used for AWS Lambda (runtime = python3.6).
   ## Steps to use this python script for AWS Lambda
   # 1. AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN and AWS_REGION variables are already part of Lambda's Execution environment
   #    No need to set them up explicitly.
   # 3. Create Lambda deployment package https://docs.aws.amazon.com/lambda/latest/dg/lambda-python-how-to-create-deployment-package.html
   # 4. Create a Lambda function in the same VPC and assign an IAM role with neptune access
   
   def lambda_handler(event, context):
       # sample_test_input = {
       #     "host": "END_POINT:8182",
       #     "method": "GET",
       #     "query_type": "gremlin",
       #     "query": "g.V().count()"
       # }
   
       # Lambda uses AWS_REGION instead of SERVICE_REGION
       global region
       region = os.getenv('AWS_REGION', '')
   
       host = event['host']
       method = event['method']
       query_type = event['query_type']
       query =  event['query']
   
       return make_signed_request(host, method, query_type, query)
   
   def validate_input(method, query_type):
       # Supporting GET and POST for now:
       if (method != 'GET' and method != 'POST'):
           print('First parameter must be "GET" or "POST", but is "' + method + '".')
           sys.exit()
   
       # SPARQL UPDATE requires POST
       if (method == 'GET' and query_type == 'sparqlupdate'):
           print('SPARQL UPDATE is not supported in GET mode. Please choose POST.')
           sys.exit()
   
   def get_canonical_uri_and_payload(query_type, query, method):
       # Set the stack and payload depending on query_type.
       if (query_type == 'sparql'):
           canonical_uri = '/sparql/'
           payload = {'query': query}
   
       elif (query_type == 'sparqlupdate'):
           canonical_uri = '/sparql/'
           payload = {'update': query}
   
       elif (query_type == 'gremlin'):
           canonical_uri = '/gremlin/'
           payload = {'gremlin': query}
           if (method == 'POST'):
               payload = json.dumps(payload)
   
       elif (query_type == 'openCypher'):
           canonical_uri = '/openCypher/'
           payload = {'query': query}
   
       elif (query_type == "loader"):
           canonical_uri = "/loader/"
           payload = query
   
       elif (query_type == "status"):
           canonical_uri = "/status/"
           payload = {}
   
       elif (query_type == "gremlin/status"):
           canonical_uri = "/gremlin/status/"
           payload = {}
   
       elif (query_type == "openCypher/status"):
           canonical_uri = "/openCypher/status/"
           payload = {}
   
       elif (query_type == "sparql/status"):
           canonical_uri = "/sparql/status/"
           payload = {}
   
       else:
           print(
               'Third parameter should be from ["gremlin", "sparql", "sparqlupdate", "loader", "status] but is "' + query_type + '".')
           sys.exit()
       ## return output as tuple
       return canonical_uri, payload
   
   def make_signed_request(host, method, query_type, query):
       service = 'neptune-db'
       endpoint = protocol + '://' + host
   
       print()
       print('+++++ USER INPUT +++++')
       print('host = ' + host)
       print('method = ' + method)
       print('query_type = ' + query_type)
       print('query = ' + query)
   
       # validate input
       validate_input(method, query_type)
   
       # get canonical_uri and payload
       canonical_uri, payload = get_canonical_uri_and_payload(query_type, query, method)
   
       # assign payload to data or params
       data = payload if method == 'POST' else None
       params = payload if method == 'GET' else None
   
       # create request URL
       request_url = endpoint + canonical_uri
   
       # create and sign request
       creds = SimpleNamespace(
           access_key=access_key, secret_key=secret_key, token=session_token, region=region,
       )
   
       request = AWSRequest(method=method, url=request_url, data=data, params=params)
       SigV4Auth(creds, service, region).add_auth(request)
   
       r = None
   
       # ************* SEND THE REQUEST *************
       if (method == 'GET'):
   
           print('++++ BEGIN GET REQUEST +++++')
           print('Request URL = ' + request_url)
           r = requests.get(request_url, headers=request.headers, verify=False, params=params)
   
       elif (method == 'POST'):
   
           print('\n+++++ BEGIN POST REQUEST +++++')
           print('Request URL = ' + request_url)
           if (query_type == "loader"):
               request.headers['Content-type'] = 'application/json'
           r = requests.post(request_url, headers=request.headers, verify=False, data=data)
   
       else:
           print('Request method is neither "GET" nor "POST", something is wrong here.')
   
       if r is not None:
           print()
           print('+++++ RESPONSE +++++')
           print('Response code: %d\n' % r.status_code)
           response = r.text
           r.close()
           print(response)
   
           return response
   
   help_msg = '''
       export AWS_ACCESS_KEY_ID=[MY_ACCESS_KEY_ID]
       export AWS_SECRET_ACCESS_KEY=[MY_SECRET_ACCESS_KEY]
       export AWS_SESSION_TOKEN=[MY_AWS_SESSION_TOKEN]
       export SERVICE_REGION=[us-east-1|us-east-2|us-west-2|eu-west-1]
   
       python version >=3.6 is required.
   
       Examples: For help
       python3 program_name.py -h
   
       Examples: Queries
       python3 program_name.py -ho your-neptune-endpoint -p 8182 -a GET -q status
       python3 program_name.py -ho your-neptune-endpoint -p 8182 -a GET -q sparql/status
       python3 program_name.py -ho your-neptune-endpoint -p 8182 -a GET -q sparql -d "SELECT ?s WHERE { ?s ?p ?o }"
       python3 program_name.py -ho your-neptune-endpoint -p 8182 -a POST -q sparql -d "SELECT ?s WHERE { ?s ?p ?o }"
       python3 program_name.py -ho your-neptune-endpoint -p 8182 -a POST -q sparqlupdate -d "INSERT DATA { <https://s> <https://p> <https://o> }"
       python3 program_name.py -ho your-neptune-endpoint -p 8182 -a GET -q gremlin/status
       python3 program_name.py -ho your-neptune-endpoint -p 8182 -a GET -q gremlin -d "g.V().count()"
       python3 program_name.py -ho your-neptune-endpoint -p 8182 -a POST -q gremlin -d "g.V().count()"
       python3 program_name.py -ho your-neptune-endpoint -p 8182 -a GET -q openCypher/status
       python3 program_name.py -ho your-neptune-endpoint -p 8182 -a GET -q openCypher -d "MATCH (n1) RETURN n1 LIMIT 1;"
       python3 program_name.py -ho your-neptune-endpoint -p 8182 -a POST -q openCypher -d "MATCH (n1) RETURN n1 LIMIT 1;"
       python3 program_name.py -ho your-neptune-endpoint -p 8182 -a GET -q loader -d '{"loadId": "68b28dcc-8e15-02b1-133d-9bd0557607e6"}'
       python3 program_name.py -ho your-neptune-endpoint -p 8182 -a GET -q loader -d '{}'
       python3 program_name.py -ho your-neptune-endpoint -p 8182 -a POST -q loader -d '{"source": "source", "format" : "csv", "failOnError": "fail_on_error", "iamRoleArn": "iam_role_arn", "region": "region"}'
   
       Environment variables must be defined as AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and SERVICE_REGION.
       You should also set AWS_SESSION_TOKEN environment variable if you are using temporary credentials (ex. IAM Role or EC2 Instance profile).
   
       Current Limitations:
       - Query mode "sparqlupdate" requires POST (as per the SPARQL 1.1 protocol)
               '''
   
   def exit_and_print_help():
       print(help_msg)
       exit()
   
   def parse_input_and_query_neptune():
   
   
       parser = ArgumentParser(description=help_msg, formatter_class=RawTextHelpFormatter)
       group_host = parser.add_mutually_exclusive_group()
       group_host.add_argument("-ho", "--host", type=str)
       group_port = parser.add_mutually_exclusive_group()
       group_port.add_argument("-p", "--port", type=int, help="port ex. 8182, default=8182", default=8182)
       group_action = parser.add_mutually_exclusive_group()
       group_action.add_argument("-a", "--action", type=str, help="http action, default = GET", default="GET")
       group_endpoint = parser.add_mutually_exclusive_group()
       group_endpoint.add_argument("-q", "--query_type", type=str, help="query_type, default = status ", default="status")
       group_data = parser.add_mutually_exclusive_group()
       group_data.add_argument("-d", "--data", type=str, help="data required for the http action", default="")
   
       args = parser.parse_args()
       print(args)
   
       # Read command line parameters
       host = args.host
       port = args.port
       method = args.action
       query_type = args.query_type
       query = args.data
   
       if (access_key == ''):
           print('!!! ERROR: Your AWS_ACCESS_KEY_ID environment variable is undefined.')
           exit_and_print_help()
   
       if (secret_key == ''):
           print('!!! ERROR: Your AWS_SECRET_ACCESS_KEY environment variable is undefined.')
           exit_and_print_help()
   
       if (region == ''):
           print('!!! ERROR: Your SERVICE_REGION environment variable is undefined.')
           exit_and_print_help()
   
       if host is None:
           print('!!! ERROR: Neptune DNS is missing')
           exit_and_print_help()
   
       host = host + ":" + str(port)
       make_signed_request(host, method, query_type, query)
   
   
   if __name__ == "__main__":
       parse_input_and_query_neptune()
   ```

1. 在終端機瀏覽到 `neptunesigv4.py` 檔案的位置。

1. 輸入以下命令，將存取金鑰、私有金鑰和區域取代成正確值。

   ```
   export AWS_ACCESS_KEY_ID=MY_ACCESS_KEY_ID
   export AWS_SECRET_ACCESS_KEY=MY_SECRET_ACCESS_KEY
   export SERVICE_REGION=us-east-1 or us-east-2 or us-west-1 or us-west-2 or ca-central-1 or
                         ca-west-1 or sa-east-1 or eu-north-1 or eu-south-2 or eu-west-1 or eu-west-2 or eu-west-3 or
                         eu-central-1 or me-south-1 or me-central-1 or il-central-1 or af-south-1 or ap-east-1 or
                         ap-northeast-1 or ap-northeast-2 or ap-northeast-3 or ap-southeast-1 or ap-southeast-2 or
                         ap-southeast-3 or ap-southeast-4 or ap-southeast-5 or ap-south-1 or ap-south-2 or
                         cn-north-1 or cn-northwest-1 or
                         us-gov-east-1 or us-gov-west-1
   ```

   如果您使用臨時的登入資料，除了指定 `AWS_ACCESS_KEY_ID`、`AWS_SECRET_ACCESS_KEY`、`SERVICE_REGION`，還必須指定 `AWS_SESSION_TOKEN`。

   ```
   export AWS_SESSION_TOKEN=MY_AWS_SESSION_TOKEN
   ```
**注意**  
如果您使用臨時登入資料，登入資料會在指定的時間後過期，*包括工作階段字符*。  
當您請求新的登入資料時，必須更新工作階段字符。如需詳細資訊，請參閱[使用臨時安全憑證來請求對 AWS 資源的存取](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html)。

1. 輸入以下其中一個命令，將已簽署的請求傳送到 Neptune 資料庫執行個體。這些範例使用 Python 3.6 版。

   **端點狀態**

   ```
   python3.6 neptunesigv4.py -ho your-neptune-endpoint -p 8182 -a GET -q status
   ```

   **Gremlin**

   ```
   python3.6 neptunesigv4.py -ho your-neptune-endpoint -p 8182 -a GET -q gremlin -d "g.V().count()"
   
   python3.6 neptunesigv4.py -ho your-neptune-endpoint -p 8182 -a POST -q gremlin -d "g.V().count()"
   ```

   **Gremlin 狀態**

   ```
   python3.6 neptunesigv4.py -ho your-neptune-endpoint -p 8182 -a GET -q gremlin/status
   ```

   **SPARQL**

   ```
   python3.6 neptunesigv4.py -ho your-neptune-endpoint -p 8182 -a GET -q sparql -d "SELECT ?s WHERE { ?s ?p ?o }"
   ```

   **SPARQL UPDATE**

   ```
   python3.6 neptunesigv4.py -ho your-neptune-endpoint -p 8182 -a POST -q sparqlupdate -d "INSERT DATA { <https://s> <https://p> <https://o> }"
   ```

   **SPARQL 狀態**

   ```
   python3.6 neptunesigv4.py -ho your-neptune-endpoint -p 8182 -a GET -q sparql/status
   ```

   **openCypher**

   ```
   python3.6 neptunesigv4.py -ho your-neptune-endpoint -p 8182 -a GET -q openCypher -d "MATCH (n1) RETURN n1 LIMIT 1;"
   
   python3.6 neptunesigv4.py -ho your-neptune-endpoint -p 8182 -a POST -q openCypher -d "MATCH (n1) RETURN n1 LIMIT 1;"
   ```

   **openCypher 狀態**

   ```
   python3.6 neptunesigv4.py -ho your-neptune-endpoint -p 8182 -a GET -q openCypher/status
   ```

   **載入器**

   ```
   python3.6 neptunesigv4.py -ho your-neptune-endpoint -p 8182 -a GET -q loader -d '{"loadId": "68b28dcc-8e15-02b1-133d-9bd0557607e6"}'
   
   python3.6 neptunesigv4.py -ho your-neptune-endpoint -p 8182 -a GET -q loader -d '{}'
   
   python3.6 neptunesigv4.py -ho your-neptune-endpoint -p 8182 -a POST -q loader -d '{"source": "source", "format" : "csv", "failOnError": "fail_on_error", "iamRoleArn": "iam_role_arn", "region": "region"}'
   ```

1. 執行 Python 指令碼的語法如下：

   ```
   python3.6 neptunesigv4.py -ho your-neptune-endpoint -p port -a GET|POST -q gremlin|sparql|sparqlupdate|loader|status -d "string0data"
   ```

   SPARQL UPDATE 要求 `POST`。

# 使用 IAM 身分驗證搭配 Gremlin Python 連線至 Amazon Neptune 資料庫
<a name="gremlin-python-iam-auth"></a>

## 概觀
<a name="gremlin-python-iam-auth-overview"></a>

 本指南示範如何使用 Gremlin Python 驅動程式、Signature Version 4 身分驗證和 AWS SDK for Python (Boto3) 來連線至已啟用 IAM 身分驗證的 Amazon Neptune 資料庫。

## 建立基本連線
<a name="gremlin-python-iam-auth-basic-connection"></a>

 使用以下程式碼範例作為如何使用 Gremlin Python 驅動程式與 IAM 身分驗證建立基本連線的指引。

```
from boto3 import Session
from botocore.auth import SigV4Auth
from botocore.awsrequest import AWSRequest

from gremlin_python.process.anonymous_traversal import traversal
from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection

def main():
    endpoint = 'your.cluster.endpoint.neptune.amazonaws.com'
    conn_string = 'wss://' + endpoint + ':8182/gremlin'
    default_region = 'us-east-1'
    service = 'neptune-db'

    credentials = Session().get_credentials()
    if credentials is None:
        raise Exception("No AWS credentials found")
    creds = credentials.get_frozen_credentials()
    # region set inside config profile or via AWS_DEFAULT_REGION environment variable will be loaded
    region = Session().region_name if Session().region_name else default_region

    request = AWSRequest(method='GET', url=conn_string, data=None)
    SigV4Auth(creds, service, region).add_auth(request)

    rc = DriverRemoteConnection(conn_string, 'g', headers=request.headers.items())
    g = traversal().with_remote(rc)

    # simple query to verify connection
    count = g.V().count().next()
    print('Vertex count: ' + str(count))

    # cleanup
    rc.close()

if __name__ == "__main__":
    main()
```

# 使用 IAM 身分驗證搭配 Gremlin JavaScript 連線至 Amazon Neptune 資料庫
<a name="gremlin-javascript-iam-auth"></a>

## 概觀
<a name="gremlin-javascript-iam-auth-overview"></a>

 本指南示範如何使用 Gremlin JavaScript 驅動程式、Signature 第 4 版身分驗證和適用於 Javascript v3 的 AWS SDK 來連線至已啟用 IAM 身分驗證的 Amazon Neptune 資料庫。

## 先決條件
<a name="gremlin-javascript-iam-auth-prereqs"></a>
+  啟用 IAM 身分驗證的 Amazon Neptune 叢集。
+  節點 13 或更新版本 （請參閱 Gremlin JavaScript 的最低版本和適用於 [AWS Javascript v3 的 SDK](https://docs.aws.amazon.com//AWSJavaScriptSDK/v3/latest/introduction/#release-cadence))。
+  AWS 設定的登入資料 （透過環境變數、共用登入資料檔案或 IAM 角色）。

## 建立基本連線
<a name="gremlin-javascript-iam-auth-basic-connection"></a>

 使用下列程式碼範例做為如何使用 Gremlin JavaScript 驅動程式與 IAM 身分驗證建立基本連線的指引。

```
const { fromNodeProviderChain } = require('@aws-sdk/credential-providers');
const { getUrlAndHeaders } = require('gremlin-aws-sigv4/lib/utils');
const { loadConfig } = require("@smithy/node-config-provider");
const { NODE_REGION_CONFIG_FILE_OPTIONS, NODE_REGION_CONFIG_OPTIONS } = require("@smithy/config-resolver");

const gremlin = require('gremlin');
const DriverRemoteConnection = gremlin.driver.DriverRemoteConnection;
const traversal = gremlin.process.AnonymousTraversalSource.traversal;

const DEFAULT_REGION = 'us-east-1';

const getCredentials = async () => {
    try {
        // Loads the default credential provider chain
        return await fromNodeProviderChain();
    } catch (e) {
        console.error("No credentials found", e);
        throw e;
    }
};

(main = async () => {
    console.log('Starting');

    const credentials = await getCredentials();
    try {
        // region set inside config profile or via AWS_REGION environment variable will be loaded
        credentials['region'] = await loadConfig(NODE_REGION_CONFIG_OPTIONS, NODE_REGION_CONFIG_FILE_OPTIONS)();
    } catch (e) {
        credentials['region'] = DEFAULT_REGION
    }

    const connInfo = getUrlAndHeaders(
        'you.cluster.endpoint.neptune.amazonaws.com',
        '8182',
        credentials,
        '/gremlin',
        'wss');

    const dc = new DriverRemoteConnection(connInfo['url'], {headers: connInfo['headers']});
    const g = traversal().withRemote(dc);

    const query = g.V().limit(5).count();
    const count = await query.next();
    console.log("Vertex count: " + count.value);

    await dc.close();
})

main();
```

# 使用 IAM 身分驗證搭配 Gremlin Go 連線至 Amazon Neptune 資料庫
<a name="gremlin-go-iam-auth"></a>

## 概觀
<a name="gremlin-go-iam-auth-overview"></a>

 本指南示範如何使用 Gremlin Go 驅動程式、Signature Version 4 身分驗證和 AWS SDK for GO v2，以啟用 IAM 身分驗證連線至 Amazon Neptune 資料庫。

## 先決條件
<a name="gremlin-go-iam-auth-prereqs"></a>
+  啟用 IAM 身分驗證的 Amazon Neptune 叢集。
+  Go 1.22 或更新版本 （請參閱 [ Gremlin Go](https://pkg.go.dev/github.com/apache/tinkerpop/gremlin-go/v3/driver) 和 [AWS SDK for Go v2](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2) 的最低支援版本）。
+  AWS 設定的登入資料 （透過環境變數、共用登入資料檔案或 IAM 角色） 

## 建立基本連線
<a name="gremlin-go-iam-auth-basic-connection"></a>

 使用下列程式碼範例做為如何使用 Gremlin Go 驅動程式與 IAM 身分驗證建立基本連線的指引。

```
package main

import (
	"context"
	"fmt"
	"github.com/aws/aws-sdk-go-v2/config"
	"net/http"
	"strings"
	"time"

	gremlingo "github.com/apache/tinkerpop/gremlin-go/v3/driver"
	v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4"
)

const emptyStringSHA256 = `e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855`

func main() {
	neptuneEndpoint := "you.cluster.endpoint.neptune.amazonaws.com"
	connString := "wss://" + neptuneEndpoint + ":8182/gremlin"
	service := "neptune-db"
	defaultRegion := "us-east-1"

	// Create request to sign
	req, err := http.NewRequest(http.MethodGet, connString, strings.NewReader(""))
	if err != nil {
		fmt.Println(err)
		return
	}

	// Loads the default config with default credentials provider
	// See https://github.com/aws/aws-sdk-go-v2 for additional docs on API usage
	cfg, err := config.LoadDefaultConfig(context.TODO())
	if err != nil {
		fmt.Println(err)
		return
	}
	// Retrieve loaded credentials 
	cr, err := cfg.Credentials.Retrieve(context.TODO())
	if err != nil {
		fmt.Println(err)
		return
	}

	region := defaultRegion
	if cfg.Region != "" {
		// region set inside config profile, or via AWS_REGION or AWS_DEFAULT_REGION environment variable will be loaded
		region = cfg.Region
	}

	signer := v4.NewSigner()
	// Sign request
	err = signer.SignHTTP(context.TODO(), cr, req, emptyStringSHA256, service, "us-east-2", time.Now())
	if err != nil {
		fmt.Println(err)
		return
	}

	// Pass the signed request header into gremlingo.HeaderAuthInfo()
	driverRemoteConnection, err := gremlingo.NewDriverRemoteConnection(connString,
		func(settings *gremlingo.DriverRemoteConnectionSettings) {
			settings.TraversalSource = "g"
			settings.AuthInfo = gremlingo.HeaderAuthInfo(req.Header)
			// settings.TlsConfig = &tls.Config{InsecureSkipVerify: true} // Use this only if you're on a Mac running Go 1.18+ doing local dev. See https://github.com/golang/go/issues/51991
		})
	if err != nil {
		fmt.Println(err)
		return
	}

	// Cleanup
	defer driverRemoteConnection.Close()

	// Creating graph traversal
	g := gremlingo.Traversal_().WithRemote(driverRemoteConnection)

	// Query execution
	count, err := g.V().Limit(5).Count().Next()
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("Vertex count:", *count)
}
```

## Gremlin Go 動態登入資料重新整理
<a name="gremlin-go-iam-auth-go-credential-refresh"></a>

 Gremlin Go 具有 DynamicAuth，允許注入函數指標擷取登入資料並產生 標頭，以防止標頭因長時間執行的連線而過期。

```
package main

import (
	"context"
	"crypto/tls"
	"fmt"
	"github.com/aws/aws-sdk-go-v2/config"
	"net/http"
	"strings"
	"time"

	gremlingo "github.com/apache/tinkerpop/gremlin-go/v3/driver"
	v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4"
)

const emptyStringSHA256 = `e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855`

func main() {
	neptuneEndpoint := "you.cluster.endpoint.neptune.amazonaws.com"
	connString := "wss://" + neptuneEndpoint + ":8182/gremlin"
	service := "neptune-db"
	defaultRegion := "us-east-1"

	//Create the request to sign
	req, err := http.NewRequest(http.MethodGet, connString, strings.NewReader(""))
	if err != nil {
		fmt.Println(err)
		return
	}

	// Loads the default config with default credentials provider
	// See https://github.com/aws/aws-sdk-go-v2 for additional docs on API usage
	cfg, err := config.LoadDefaultConfig(context.TODO())
	if err != nil {
		fmt.Println(err)
		return
	}

	region := defaultRegion
	if cfg.Region != "" {
		// region set inside config profile, or via AWS_REGION or AWS_DEFAULT_REGION environment variable will be loaded
		region = cfg.Region
	}
	
	signer := v4.NewSigner()

	// This is the function that will be used for dynamic refreseh of credentials and signed headers
	gen := func() gremlingo.AuthInfoProvider {
		// Retrieve loaded credentials 
		cr, err := cfg.Credentials.Retrieve(context.TODO())
		fmt.Println("AWS Credentials: ", cr)
		if err != nil {
			fmt.Println(err)
			return
		}
		// Sign request
		err = signer.SignHTTP(context.TODO(), cr, req, emptyStringSHA256, service, region, time.Now())
		if err != nil {
			fmt.Println(err)
			return
		}
		fmt.Println(req.Header)
		return gremlingo.HeaderAuthInfo(req.Header)
	}

	// Pass the function into gremlingo.NewDynamicAuth(), which will generate the AuthInfoProvider to pass into gremlingo.DriverRemoteConnectionSettings below
	auth := gremlingo.NewDynamicAuth(gen)

	driverRemoteConnection, err := gremlingo.NewDriverRemoteConnection(connString,
		func(settings *gremlingo.DriverRemoteConnectionSettings) {
			settings.TraversalSource = "g"
			settings.AuthInfo = auth
			// settings.TlsConfig = &tls.Config{InsecureSkipVerify: true} // Use this only if you're on a Mac running Go 1.18+ doing local dev. See https://github.com/golang/go/issues/51991

		})
	if err != nil {
		fmt.Println(err)
		return
	}

	// Cleanup
	defer driverRemoteConnection.Close()

	// Creating graph traversal
	g := gremlingo.Traversal_().WithRemote(driverRemoteConnection)

	// Query execution
	count, err := g.V().Limit(5).Count().Next()
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("Vertex count:", *count)
}
```

# 使用 IAM 身分驗證搭配 Gremlin .NET 連線至 Amazon Neptune 資料庫
<a name="gremlin-dotnet-iam-auth"></a>

## 概觀
<a name="gremlin-dotnet-iam-auth-overview"></a>

 本指南示範如何使用 Gremlin .NET 驅動程式、Signature Version 4 身分驗證和適用於 .NET v3 的 AWS SDK，以啟用 IAM 身分驗證連線至 Amazon Neptune 資料庫。

## 建立基本連線
<a name="gremlin-dotnet-iam-auth-basic-connection"></a>

 若要與 Gremlin .NET 連線，請使用自訂程式庫 [https://github.com/aws/amazon-neptune-gremlin-dotnet-sigv4 ](https://github.com/aws/amazon-neptune-gremlin-dotnet-sigv4)中的`SigV4RequestSigner`來源檔案。範例專案設定位於 https：//[https://github.com/aws/amazon-neptune-gremlin-dotnet-sigv4/tree/main/example](https://github.com/aws/amazon-neptune-gremlin-dotnet-sigv4/tree/main/example)。

專案檔案：

```
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp8.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <Compile Include="../src/SigV4RequestSigner.cs" Link="SigV4RequestSigner.cs" />
    <PackageReference Include="AWSSDK.Core" Version="3.7.402.24" />
    <PackageReference Include="gremlin.net" Version="3.7.3" />
  </ItemGroup>

</Project>
```

範例程式：

```
using System;
using System.Collections.Generic;
using System.Net.WebSockets;
using System.Linq;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using Gremlin.Net;
using Gremlin.Net.Driver;
using Gremlin.Net.Driver.Remote;
using Gremlin.Net.Process;
using Gremlin.Net.Process.Traversal;
using Gremlin.Net.Structure;
using static Gremlin.Net.Process.Traversal.AnonymousTraversalSource;
using static Gremlin.Net.Process.Traversal.__;
using static Gremlin.Net.Process.Traversal.P;
using static Gremlin.Net.Process.Traversal.Order;
using static Gremlin.Net.Process.Traversal.Operator;
using static Gremlin.Net.Process.Traversal.Pop;
using static Gremlin.Net.Process.Traversal.Scope;
using static Gremlin.Net.Process.Traversal.TextP;
using static Gremlin.Net.Process.Traversal.Column;
using static Gremlin.Net.Process.Traversal.Direction;
using static Gremlin.Net.Process.Traversal.T;
using Amazon.Runtime.CredentialManagement;
using Amazon.Runtime;
using Amazon;
using Amazon.Util;
using Amazon.Neptune.Gremlin.Driver;

namespace NeptuneExample
{
    class Program
    {
        static void Main(string[] args)
        {
            /*
                Include your Neptune endpoint and port below.
            */
            var neptune_host = "neptune-endpoint"; // ex: mycluster.cluster.us-east-1.neptune.amazonaws.com
            var neptune_port = 8182;

            var gremlinServer = new GremlinServer(neptune_host, neptune_port);
            var gremlinClient = new GremlinClient(gremlinServer, webSocketConfiguration: new SigV4RequestSigner().signRequest(neptune_host, neptune_port));
            var remoteConnection = new DriverRemoteConnection(gremlinClient);
            var g = Traversal().WithRemote(remoteConnection);

            /* Example code to pull the first 5 vertices in a graph. */
            Console.WriteLine("Get List of Node Labels:");
            Int32 limitValue = 5;
            var output = g.V().Limit<Vertex>(limitValue).ToList();
            foreach(var item in output) {
                Console.WriteLine(item);
            }
        }
    }
}
```