

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

# 使用身份验证连接到您的亚马逊 Neptune 数据库 AWS Identity and Access Management
<a name="iam-auth-connecting"></a>

启用了 IAM 数据库身份验证的 Amazon Neptune 资源要求使用签 AWS 名版本 4 对所有 HTTP 请求进行签名。有关使用签 AWS 名版本 4 对请求进行签名的一般信息，请参阅[签署 AWS API 请求](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-signing.html)。

AWS 签名版本 4 是向 AWS 请求添加身份验证信息的过程。为了安全起见，对的大多数请求都 AWS 必须使用访问密钥进行签名，访问密钥由访问密钥 ID 和私有访问密钥组成。

**注意**  
如果您使用的是临时凭证，这些凭证（*包括会话令牌*）将在指定时间间隔后到期。  
在请求新凭证时，您必须更新您的会话令牌。有关更多信息，请参阅[使用临时安全证书请求对 AWS 资源的访问权限](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html)。

**重要**  
使用基于 IAM 的身份验证访问 Neptune 需要创建 HTTP 请求并自己对这些请求签名。

**签名版本 4 的工作原理**

1. 您创建一个规范请求。

1. 您可以使用规范请求和其他一些信息来创建. string-to-sign 

1. 您可以使用您的 AWS 私有访问密钥派生签名密钥，然后使用该签名密钥和 string-to-sign来创建签名。

1. 您将生成的签名添加到 HTTP 请求的标头中或者作为查询字符串参数添加。

Neptune 收到请求后，将执行完成的相同步骤来计算签名。之后，Neptune 会将计算得到的签名与在请求中发送的签名进行比较。如果签名匹配，则处理请求。如果签名不匹配，则拒绝请求。

有关使用签 AWS 名版本 4 对请求进行签名的一般信息，请参阅中的[签名版本 4 签名流程*AWS 一般参考*](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html)。

以下部分包含示例，演示如何将签名请求发送到启用了 IAM 身份验证的 Neptune 数据库实例的 Gremlin 和 SPARQL 端点。

**Topics**
+ [使用 IAM 身份验证连接 Amazon Neptune 数据库的先决条件](iam-auth-connect-prerq.md)
+ [通过命令行使用 IAM 身份验证连接到 Amazon Neptune 数据库](iam-auth-connect-command-line.md)
+ [通过 Gremlin 控制台使用 IAM 身份验证连接到 Amazon Neptune 数据库](iam-auth-connecting-gremlin-console.md)
+ [通过 Gremlin Java 使用 IAM 连接到 Amazon Neptune 数据库](iam-auth-connecting-gremlin-java.md)
+ [通过 Java 和 SPARQL 使用 IAM 身份验证连接到 Amazon Neptune 数据库](iam-auth-connecting-sparql-java.md)
+ [通过 SPARQL 和 Node.js 使用 IAM 身份验证连接到 Amazon Neptune 数据库](iam-auth-connecting-sparql-node.md)
+ [通过 Python 使用 IAM 身份验证连接到 Amazon Neptune 数据库](iam-auth-connecting-python.md)
+ [通过 Gremlin Python 使用 IAM 身份验证连接到 Amazon Neptune 数据库](gremlin-python-iam-auth.md)
+ [使用 Gremlin 的 IAM 身份验证连接到亚马逊 Neptune 数据库 JavaScript](gremlin-javascript-iam-auth.md)
+ [通过 Gremlin Go 使用 IAM 身份验证连接到 Amazon Neptune 数据库](gremlin-go-iam-auth.md)
+ [通过 Gremlin .NET 使用 IAM 身份验证连接到 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 签名版本 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。输入以下命令以在 EC2 实例上安装 Java 8。

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

1. 输入以下命令以在 EC2 实例上将 Java 8 设置为默认运行时系统。

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

   在系统提示时，输入 Java 8 的版本号。

1. 输入以下命令以在 EC2 实例上将 Java 8 设置为默认编译器。

   ```
   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 身份验证后，必须使用[签名版本 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` 可以找到相应的证书，它们即可像处理 HTTP 连接一样处理 HTTPS 连接，而无需额外的参数。本文档中的示例基于该场景。

要了解如何获取此类证书以及如何将其正确格式化为 `curl` 可以使用的证书颁发机构 (CA) 证书存储，请参阅 `curl` 文档中的 [SSL 证书验证](https://curl.haxx.se/docs/sslcerts.html)。

然后，您使用 `CURL_CA_BUNDLE` 环境变量指定此 CA 证书存储的位置。在 Windows 上，`curl` 自动在名为 `curl-ca-bundle.crt` 的文件中查找它。首先在与 `curl.exe` 相同的目录中查找，然后在路径的其他位置查找。有关更多信息，请参阅 [SSL 证书验证](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 安全令牌服务 (STS) APIs](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
```

# 通过 Gremlin 控制台使用 IAM 身份验证连接到 Amazon Neptune 数据库
<a name="iam-auth-connecting-gremlin-console"></a>

要使用带有签名版本 4 身份验证的 Gremlin 控制台连接到 Amazon Neptune，您需要在命令建立的连接中插入 Sigv4 签名器。`requestInterceptor()` `:remote`这需要您手动配置`Cluster`对象，然后将其传递给`:remote`命令。

请注意，这与 `:remote` 命令使用配置文件来形成连接的典型情况大不相同。配置文件方法不起作用，因为必须以编程方式设置 `requestInterceptor()`，并且无法从文件加载其配置。

**注意**  
以下示例使用`requestInterceptor()`了 TinkerPop 3.6.6 中引入的。如果您使用的是早于 3.6.6 的 TinkerPop 版本（但是 3.5.5 或更高版本），请在下面的代码示例`requestInterceptor()`中使用`handshakeInterceptor()`代替。

以下先决条件是必要的：
+ 您必须具有对请求进行签名所需的 IAM 凭证。请参阅[《 适用于 Java 的 AWS SDK 开发者指南》中的使用默认凭证提供商链](https://docs.aws.amazon.com//sdk-for-java/latest/developer-guide/credentials-chain.html)。
+ 您已安装的 Gremlin 控制台版本必须与数据库集群正在使用的 Neptune 引擎版本兼容。

如果您使用的是临时凭证，则它们将在指定的间隔后过期，会话令牌也是如此，因此在请求新凭证时必须更新会话令牌。请参阅 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
   ```

   如果您在此步骤中遇到问题，请参考有关 Gr [ap](http://docs.groovy-lang.org/latest/html/documentation/grape.html) e 配置的[TinkerPop 文档](https://tinkerpop.apache.org/docs/current/reference/#gremlin-applications)可能会有所帮助。
**注意**  
如果您使用的是 HTTP 代理，则在此步骤中可能会遇到 `:install` 命令未完成的错误。要解决此问题，请运行以下命令来告知控制台有关代理的信息：  

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

# 通过 Gremlin Java 使用 IAM 连接到 Amazon Neptune 数据库
<a name="iam-auth-connecting-gremlin-java"></a>

以下是如何使用带有 Sig4 签名的 Gremlin Java API 连接到 Neptune 的示例（它假设对使用 Maven 有常识）。此示例使用 [Amazon Neptune SigV4 Signer](https://github.com/aws/amazon-neptune-sigv4-signer) 库来协助请求签名。首先，将依赖关系定义为 `pom.xml` 文件的一部分：

**注意**  
以下示例使用`requestInterceptor()`了 TinkerPop 3.6.6 中引入的。如果您使用的是早于 3.6.6 的 TinkerPop 版本（但是 3.5.5 或更高版本），请在下面的代码示例`requestInterceptor()`中使用`handshakeInterceptor()`代替。

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

 亚马逊 Neptune Sigv4 Signer 支持 Java SDK 的 1.x 和 2.x 版本。 AWS 以下示例使用 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 支持通过使用角色代入（有时也称为[角色链](https://docs.aws.amazon.com//neptune/latest/userguide/bulk-load-tutorial-chain-roles.html#bulk-load-tutorial-chain-cross-account)）来进行跨账户 IAM 身份验证。要提供从托管在不同 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`。然后通过使用`STSAssumeRoleSessionCredentialsProvider`来代替 Neptune 数据库 AWS 账户中托管的角色。`STSclient`

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

# 通过 Java 和 SPARQL 使用 IAM 身份验证连接到 Amazon Neptune 数据库
<a name="iam-auth-connecting-sparql-java"></a>

本节介绍如何使用带有签名版本 4 身份验证的 RDF4 J 或 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`

**使用签名版本 4 签名的 RDF4 J 或 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. 通过检出具有最新标签的分支获取项目的最新版本。

   ```
   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 J RDF4**  
输入以下内容以运行 RDF4 J 示例。

   ```
   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>` 部分。我们建议您从示例开始着手。

# 通过 SPARQL 和 Node.js 使用 IAM 身份验证连接到 Amazon Neptune 数据库
<a name="iam-auth-connecting-sparql-node"></a>

## 使用签名 V4 签名和 Javascript V3 AWS 开发工具包进行查询
<a name="iam-auth-querying-sparql-js-sdk-v3"></a>

以下是如何使用带有签名版本 4 身份验证的 Node.js 和适用于 Javascript V3 的 S AWS DK 连接到 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 的 S AWS DK 连接到 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);
    });
}
```

# 通过 Python 使用 IAM 身份验证连接到 Amazon Neptune 数据库
<a name="iam-auth-connecting-python"></a>

本部分演示使用 Python 编写的程序示例，此示例阐释如何对 Amazon Neptune 使用签名版本 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 一般参考签名版本 4 签名过程*部分中的示例。

要使用此示例程序，您需要：
+ 计算机上安装有 Python 3.x，您可以从 [Python 站点](https://www.python.org/downloads/)获取。这些程序已使用 Python 3.6 测试过。
+ [Python 请求库](https://pypi.python.org/pypi/requests)，示例脚本使用此库发出 Web 请求。一种方便的 Python 程序包安装方法是使用 `pip`，它可从 Python 程序包索引站点获取程序包。然后，您可以在命令行上运行 `requests` 来安装 `pip install requests`。
+ 环境变量中名为 `AWS_ACCESS_KEY_ID` 和 `AWS_SECRET_ACCESS_KEY` 的访问密钥（访问密钥 ID 和私有访问密钥）。作为最佳实践，我们建议您*不要*在代码中嵌入凭证。有关更多信息，请参阅《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`。

# 通过 Gremlin Python 使用 IAM 身份验证连接到 Amazon Neptune 数据库
<a name="gremlin-python-iam-auth"></a>

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

 本指南演示了如何使用 Gremlin Python 驱动程序、签名版本 4 身份验证和 AWS 适用于 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()
```

# 使用 Gremlin 的 IAM 身份验证连接到亚马逊 Neptune 数据库 JavaScript
<a name="gremlin-javascript-iam-auth"></a>

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

 本指南演示如何使用 Gremlin JavaScript 驱动程序、签名版本 4 身份验证和适用于 Javascript v3 的 AWS 软件开发工具包连接到启用 IAM 身份验证的 Amazon Neptune 数据库。

## 先决条件
<a name="gremlin-javascript-iam-auth-prereqs"></a>
+  启用 IAM 身份验证的 Amazon Neptune 集群。
+  节点 13 或更高版本（请参阅 Gremlin 的最低版本 JavaScript 和 [Javascript v3 的AWS 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();
```

# 通过 Gremlin Go 使用 IAM 身份验证连接到 Amazon Neptune 数据库
<a name="gremlin-go-iam-auth"></a>

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

 本指南演示如何使用 Gremlin Go 驱动程序、签名版本 4 身份验证和适用于 GO v2 的 AWS 软件开发工具包连接到启用 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) 和[适用于 Go v2 的AWS SDK](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)
}
```

# 通过 Gremlin .NET 使用 IAM 身份验证连接到 Amazon Neptune 数据库
<a name="gremlin-dotnet-iam-auth"></a>

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

 本指南演示如何使用 Gremlin .NET 驱动程序、签名版本 4 身份验证和适用于.NET 的 AWS SDK v3 连接到启用 IAM 身份验证的 Amazon Neptune 数据库。

## 创建基本连接
<a name="gremlin-dotnet-iam-auth-basic-connection"></a>

 [要连接 Gremlin .NET，请使用自定义库 https://github.com/aws/amazon-neptune-gremlin-dotnet中的`SigV4RequestSigner`源文件-sigv4。](https://github.com/aws/amazon-neptune-gremlin-dotnet-sigv4)示例项目设置位于 [ https://github.com/aws/amazon-neptune-gremlin-dotnet-sigv4/](https://github.com/aws/amazon-neptune-gremlin-dotnet-sigv4/tree/main/example) 中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);
            }
        }
    }
}
```