

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# AWS Identity and Access Management 인증을 사용하여 Amazon Neptune 데이터베이스에 연결
<a name="iam-auth-connecting"></a>

IAM DB 인증이 활성화된 Amazon Neptune 리소스는 AWS 서명 버전 4를 사용하여 모든 HTTP 요청에 서명해야 합니다. AWS 서명 버전 4로 요청에 서명하는 방법에 대한 일반적인 내용은 [AWS API 요청 서명을 참조하세요](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-signing.html).

AWS 서명 버전 4는 요청에 인증 정보를 AWS 추가하는 프로세스입니다. 보안을 위해에 대한 대부분의 요청은 액세스 키 ID와 보안 액세스 키로 구성된 액세스 키로 서명해야 AWS 합니다.

**참고**  
임시 자격 증명을 사용하는 경우 *세션 토큰을 포함하여* 지정된 간격 후에 만료됩니다.  
새 자격 증명을 요청할 경우 세션 토큰을 업데이트해야 합니다. 자세한 내용은 [임시 보안 자격 증명을 사용하여 AWS 리소스에 대한 액세스 요청을 참조하세요](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html).

**중요**  
IAM 기반 인증을 사용하여 Neptune에 액세스하려면 HTTP 요청을 만들어 요청에 직접 서명해야 합니다.

**서명 버전 4의 작동 방식**

1. 표준 요청을 생성합니다.

1. 표준 요청 및 일부 기타 정보를 사용하여 서명할 문자열을 생성합니다.

1.  AWS 보안 액세스 키를 사용하여 서명 키를 파생한 다음 해당 서명 키와 string-to-sign을 사용하여 서명을 생성합니다.

1. 헤더의 HTTP 요청에 결과 서명을 추가하거나 쿼리 문자열 파라미터로 결과 서명을 추가합니다.

Neptune에서는 요청을 수신하면 서명을 계산하는 데 사용한 것과 동일한 단계를 수행합니다. 그런 다음 Neptune은 계산된 서명을 요청과 함께 전송된 서명과 비교합니다. 서명이 일치하는 경우 요청이 처리됩니다. 서명이 일치하지 않는 경우 요청이 거부됩니다.

 AWS 서명 버전 4로 요청에 서명하는 방법에 대한 일반적인 내용은의 [서명 버전 4 서명 프로세스를](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html) 참조하세요*AWS 일반 참조*.

다음 섹션에서는 IAM 인증이 활성화된 Neptune DB 인스턴스의 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 and 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 JavaScript에서 IAM 인증을 사용하여 Amazon Neptune 데이터베이스에 연결](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 Signature Version 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 DB 클러스터에 쿼리를 제출하는 명령줄 도구를 사용하면 매우 편리합니다. [curl](https://curl.haxx.se/) 도구는 IAM 인증이 활성화되지 않은 경우 Neptune 엔드포인트와 통신하기 위한 훌륭한 옵션입니다.

**하지만 데이터를 안전하게 보호하려면 IAM 인증을 활성화하는 것이 가장 좋습니다.**

IAM 인증이 활성화되면 모든 요청은 [Signature Version 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` 설명서의 [SSL 인증서 확인](https://curl.haxx.se/docs/sslcerts.html)에는 이러한 인증서를 가져오는 방법과 `curl`에서 사용할 수 있는 인증 기관(CA) 인증서 스토어로 적절하게 형식을 지정하는 방법이 나와 있습니다.

이렇게 하면 `CURL_CA_BUNDLE` 환경 변수를 사용하여 이 CA 인증서 스토어의 위치를 지정할 수 있습니다. Windows에서 `curl`은 `curl-ca-bundle.crt`라는 파일에서 자동으로 이 인증서를 찾습니다. 먼저 `curl.exe`와 동일한 디렉터리에서 찾은 다음 경로의 다른 곳을 찾습니다. 자세한 내용은 [SSL Certificate Verification](https://curl.haxx.se/docs/sslcerts.html)을 참조하십시오.

## 임시 보안 인증 정보와 `awscurl`을 사용하여 IAM 인증이 활성화된 상태에서 DB 클러스터에 안전하게 연결
<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` 환경 변수 또는 구성 파일에 입력해야 합니다.

과거에는 IAM 사용자 보안 인증 정보나 루트 보안 인증 정보와 같은 영구 보안 인증 정보를 `awscurl`과 사용하는 것이 일반적이었지만, 이는 권장되지 않습니다. 대신 [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` 값을 구성 파일이 아닌 쉘 세션의 적절한 환경 변수에 배치하는 것이 가장 좋습니다. 이 경우 쉘이 종료되면 보안 인증 정보가 자동으로 삭제되지만, 구성 파일의 경우에는 그렇지 않습니다. 마찬가지로, 필요한 기간보다 긴 기간 동안 임시 보안 인증 정보를 요청하지 마세요.

다음 예제는 [sts assume-role](https://docs.aws.amazon.com/cli/latest/reference/sts/assume-role)을 사용하여 Linux 쉘에서 30분 동안 사용할 수 있는 임시 보안 인증 정보를 얻은 후 `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`을 사용하여 DB 클러스터에 서명된 요청을 보낼 수 있습니다.

```
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에 연결하려면 `requestInterceptor()`를 사용하여 SigV4 서명자를 `:remote` 명령에 의해 설정된 연결에 연결합니다. 이렇게 하려면 `Cluster` 객체를 수동으로 구성한 다음 `:remote` 명령에 전달해야 합니다.

참고로 이는 `:remote` 명령이 구성 파일을 사용하여 연결을 형성하는 일반적인 상황과는 상당히 다릅니다. `requestInterceptor()`를 프로그래밍 방식으로 설정해야 하고 파일에서 구성을 로드할 수 없기 때문에 구성 파일 접근 방식이 효과가 없습니다.

**참고**  
다음 예제에서는 TinkerPop 3.6.6에 도입`requestInterceptor()`된를 사용합니다. 3.6.6 이전(3.5.5 이상)의 TinkerPop 버전을 사용하는 경우 아래 코드 예제`requestInterceptor()`에서 `handshakeInterceptor()` 대신를 사용합니다.

다음과 같은 사전 조건이 필요합니다.
+ 요청에 서명하는 데 필요한 IAM 보안 인증 정보가 있어야 합니다. AWS SDK for Java 개발자 안내서[의 기본 자격 증명 공급자 체인 사용을](https://docs.aws.amazon.com//sdk-for-java/latest/developer-guide/credentials-chain.html) 참조하세요.
+ DB 클러스터에서 사용 중인 Neptune 엔진 버전과 호환되는 Gremlin 콘솔 버전을 설치해야 합니다.

임시 보안 인증 정보를 사용하는 경우 세션 토큰과 마찬가지로 지정된 간격이 지나면 만료되므로, 새 보안 인증 정보를 요청할 때 세션 토큰을 업데이트해야 합니다. 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 프록시를 사용하는 경우 이 단계에서 `: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 DB 인스턴스의 호스트 이름을 찾는 데 도움이 필요하면 [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` 파일의 일부로 정의합니다.

**참고**  
다음 예제에서는 TinkerPop 3.6.6에 도입`requestInterceptor()`된를 사용합니다. 3.6.6 이전(3.5.5 이상)의 TinkerPop 버전을 사용하는 경우 아래 코드 예제`requestInterceptor()`에서 `handshakeInterceptor()` 대신를 사용합니다.

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

 Amazon Neptune SigV4 서명자는 AWS Java SDK 버전 1.x 및 2.x를 모두 지원합니다. 다음 예제에서는 2.x를 사용합니다. 여기서 `DefaultCredentialsProvider`는 `software.amazon.awssdk.auth.credentials.AwsCredentialsProvider` 인스턴스입니다. 1.x에서 2.x로 업그레이드하는 경우 Java 2.x용 AWS SDK 설명서의 [자격 증명 공급자 변경](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 클러스터에 대한 액세스를 제공하려면: 
+  사용자 또는 역할이 다른 IAM 역할을 수임하도록 허용하는 신뢰 정책을 사용하여 애플리케이션 AWS 계정에서 새 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 계정에서 Neptune 데이터베이스에 대한 액세스를 허용하고 애플리케이션 계정 IAM 사용자/역할의 역할 가정을 허용하는 새 IAM 역할을 생성합니다. 다음과 같은 신뢰 정책을 사용합니다.

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

****  

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

------
+  다음 코드 예제를 이 두 역할을 사용하여 애플리케이션이 Neptune에 액세스하도록 허용하는 방법에 대한 지침으로 사용합니다. 이 예제에서는 `STSclient`를 생성할 때 [DefaultCredentialProviderChain](https://docs.aws.amazon.com//sdk-for-java/v1/developer-guide/credentials.html)을 통해 애플리케이션 계정 역할이 인수됩니다. 그런 다음 `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();
    }
  ```

# Java and SPARQL에서 IAM 인증을 사용하여 Amazon Neptune 데이터베이스에 연결
<a name="iam-auth-connecting-sparql-java"></a>

이 섹션에서는 Signature Version 4 인증으로 RDF4J 또는 Apache Jena를 사용하여 Neptune에 연결하는 법을 보여줍니다.

**사전 조건**
+ Java 8 이상.
+ Apache Maven 3.3 이상.

  Amazon Linux를 실행하는 EC2 인스턴스에 이러한 사전 조건을 설치하는 방법은 [IAM 인증을 사용하여 Amazon Neptune 데이터베이스를 연결하기 위한 사전 조건](iam-auth-connect-prerq.md) 단원을 참조하십시오.
+ 요청에 서명할 IAM 자격 증명입니다. 자세한 내용은 *AWS SDK for Java 개발자 안내서*의 [기본 보안 인증 정보 공급자 체인 사용](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 DB 인스턴스의 리전을 표시할 수 있습니다.
  + 미국 동부(버지니아 북부):   `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`
  + 중동(UAE):   `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 Version 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. 최신 태그와 함께 브랜치를 확인하여 최신 버전의 프로젝트를 가져옵니다.

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

1. 다음 명령 중 하나를 입력하여 예제 코드를 컴파일하고 실행합니다.

   *your-neptune-endpoint*를 Neptune DB 인스턴스의 호스트 이름 또는 IP 주소로 바꿉니다. 기본 포트는 8182입니다.
**참고**  
사용자의 Neptune DB 인스턴스 호스트 이름을 찾는 방법은 [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 서명 드라이버를 사용하려면 `pom.xml`의 `<dependencies>` 섹션에 `amazon-neptune-sigv4-signer` Maven 패키지를 추가하십시오. 이 예제를 시작점으로 사용하는 것이 좋습니다.

# SPARQL 및 Node.js에서 IAM 인증을 사용하여 Amazon Neptune 데이터베이스에 연결
<a name="iam-auth-connecting-sparql-node"></a>

## Signature V4 서명 및 AWS SDK for Javascript V3를 사용하여 쿼리
<a name="iam-auth-querying-sparql-js-sdk-v3"></a>

다음은 서명 버전 4 인증 및 AWS SDK for Javascript V3와 함께 Node.js를 사용하여 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);
    }
  );
}
```

## Signature V4 서명 및 AWS SDK for Javascript V2를 사용하여 쿼리
<a name="iam-auth-querying-sparql-js-sdk-v2"></a>

다음은 서명 버전 4 인증 및 AWS SDK for Javascript V2와 함께 Node.js를 사용하여 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>

이 섹션에서는 Amazon Neptune에서 Signature Version 4로 작업하는 방법을 설명하는 Python으로 작성된 예제 프로그램을 보여줍니다. 이 예제는 *Amazon Web Services 일반 참조*의 [Signature Version 4 서명 프로세스](https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html) 섹션에 있는 예제를 기반으로 합니다.

이 예제 프로그램을 사용하려면 다음이 필요합니다.
+ Python 3.x가 컴퓨터에 설치되어 있어야 합니다. 이 버전은 [Python 사이트](https://www.python.org/downloads/)에서 얻을 수 있습니다. 이러한 프로그램은 Python 3.6을 사용하여 테스트했습니다.
+ 예제 스크립트에서 웹 요청을 생성하는 데 사용되는 [Python 요청 라이브러리](https://pypi.python.org/pypi/requests)가 필요합니다. Python 패키지를 설치하는 간편한 방법은 Python 패키지 인덱스 사이트에서 패키지를 가져오는 `pip`를 사용하는 것입니다. 그런 다음 명령줄에서 `pip install requests`를 실행하여 `requests`를 설치할 수 있습니다.
+ `AWS_ACCESS_KEY_ID` 및 `AWS_SECRET_ACCESS_KEY` 환경 변수에 액세스 키(액세스 키 ID 및 보안 액세스 키)가 필요합니다. 자격 증명을 코드에 포함하지 *않는 것이* 가장 좋은 방법입니다. 자세한 내용을 알아보려면 *AWS Account Management 참조 안내서*의 [AWS 계정의 모범 사례](https://docs.aws.amazon.com//accounts/latest/reference/best-practices.html)를 참조하세요.

  `SERVICE_REGION` 환경 변수에 있는 Neptune DB 클러스터의 리전이 필요합니다.

  임시 자격 증명을 사용하는 경우 `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 DB 인스턴스에 서명된 요청을 전송합니다. 이러한 예제에서는 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 status**

   ```
   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 업데이트**

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

   **SPARQL status**

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

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

 이 가이드는 서명 버전 4 인증 및 AWS SDK for Python(Boto3)과 함께 Gremlin Python 드라이버를 사용하여 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 JavaScript에서 IAM 인증을 사용하여 Amazon Neptune 데이터베이스에 연결
<a name="gremlin-javascript-iam-auth"></a>

## 개요
<a name="gremlin-javascript-iam-auth-overview"></a>

 이 설명서에서는 Gremlin JavaScript 드라이버를 사용하여 IAM 인증을 활성화하고 Signature Version 4 인증 및 AWS SDK for Javascript v3를 사용하여 Amazon Neptune 데이터베이스에 연결하는 방법을 보여줍니다.

## 사전 조건
<a name="gremlin-javascript-iam-auth-prereqs"></a>
+  IAM 인증이 활성화된 Amazon Neptune 클러스터입니다.
+  노드 13 이상(Gremlin JavaScript 및 [AWS SDK for Javascript v3](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 드라이버를 사용하여 IAM 인증을 활성화하고 서명 버전 4 인증 및 AWS SDK for GO v2를 사용하여 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)
}
```

# Gremlin .NET에서 IAM 인증을 사용하여 Amazon Neptune 데이터베이스에 연결
<a name="gremlin-dotnet-iam-auth"></a>

## 개요
<a name="gremlin-dotnet-iam-auth-overview"></a>

 이 가이드는 Gremlin .NET 드라이버를 사용하여 IAM 인증을 활성화하고 서명 버전 4 인증 및 AWS SDK for .NET v3를 사용하여 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://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);
            }
        }
    }
}
```