

# AWS アカウント間での DAX へのアクセス
<a name="DAX.cross-account-access"></a>

ある AWS アカウント (アカウント A) で DynamoDB アクセラレーター (DAX) クラスターが実行されていて、別の AWS アカウント (アカウント B) の Amazon Elastic Compute Cloud (Amazon EC2) インスタンスから DAX クラスターにアクセスできる必要があるとします。このチュートリアルでは、アカウント B の IAM ロールを持つ EC2 インスタンスをアカウント B で起動することでこれを実現します。次に、EC2 インスタンスの一時的なセキュリティ認証情報を使用して、アカウント A から IAM ロールを引き受けます。最後に、IAM ロールを引き受けることで得られた一時的なセキュリティ認証情報を使用し、アカウント A の DAX クラスターに対して Amazon VPC ピアリング接続を介してアプリケーション呼び出しを行います。これらのタスクを実行するには、両方の AWS アカウントで管理アクセスが必要です。

**重要**  
 DAX クラスターに、別のアカウントから DynamoDB テーブルにアクセスさせることはできません。

**Topics**
+ [IAM のセットアップ](#DAX.cross-account-access.iam-setup)
+ [VPC をセットアップする](#DAX.cross-account-access.vpc-setup)
+ [クロスアカウントアクセスを許可するように DAX クライアントを変更します](#DAX.cross-account-access.modify-client)

## IAM のセットアップ
<a name="DAX.cross-account-access.iam-setup"></a>

1. 次のコンテンツを含む `AssumeDaxRoleTrust.json` という名前のテキストファイルを作成します。これにより、Amazon EC2 がお客様に代わって作業できるようになります。

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

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Principal": {
                   "Service": "ec2.amazonaws.com"
               },
               "Action": "sts:AssumeRole"
           }
       ]
   }
   ```

------

1. アカウント B で、インスタンスの起動時に Amazon EC2 が使用できるロールを作成します。

   ```
   aws iam create-role \
       --role-name AssumeDaxRole \
       --assume-role-policy-document file://AssumeDaxRoleTrust.json
   ```

1. 次のコンテンツを含む `AssumeDaxRolePolicy.json` という名前のテキストファイルを作成します。これにより、アカウント B の EC2 インスタンスで実行されているコードが、アカウント A の IAM ロールを引き受けることができるようになります。*accountA* は、アカウント A の実際の ID に置き換えます。

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

****  

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

------

1. 作成したロールにそのポリシーを追加します。

   ```
   aws iam put-role-policy \
       --role-name AssumeDaxRole \
       --policy-name AssumeDaxRolePolicy \
       --policy-document file://AssumeDaxRolePolicy.json
   ```

1. インスタンスプロファイルを作成して、インスタンスがロールを使用できるようにします。

   ```
   aws iam create-instance-profile \
       --instance-profile-name AssumeDaxInstanceProfile
   ```

1. ロールをインスタンスプロファイルに関連付けます。

   ```
   aws iam add-role-to-instance-profile \
       --instance-profile-name AssumeDaxInstanceProfile \
       --role-name AssumeDaxRole
   ```

1. 次の内容を含む `DaxCrossAccountRoleTrust.json` という名前のテキストファイルを作成します。これにより、アカウント B がアカウント A ロールを引き受けることができるようになります。*accountB* は、アカウント B の実際の ID に置き換えます。

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

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Principal": {
                   "AWS": "arn:aws:iam::111122223333:role/AssumeDaxRole"
               },
               "Action": "sts:AssumeRole"
           }
       ]
   }
   ```

------

1. アカウント A で、アカウント B が引き受けることができるロールを作成します。

   ```
   aws iam create-role \
       --role-name DaxCrossAccountRole \
       --assume-role-policy-document file://DaxCrossAccountRoleTrust.json
   ```

1. DAX クラスターへのアクセスを許可する `DaxCrossAccountPolicy.json` という名前のテキストファイルを作成します。*dax-cluster-arn* は、DAX クラスターの正しい Amazon リソースネーム (ARN) に置き換えます。

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

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": [
                   "dax:GetItem",
                   "dax:BatchGetItem",
                   "dax:Query",
                   "dax:Scan",
                   "dax:PutItem",
                   "dax:UpdateItem",
                   "dax:DeleteItem",
                   "dax:BatchWriteItem",
                   "dax:ConditionCheckItem"
               ],
               "Resource": "arn:aws:dax:us-east-1:111122223333:cache/dax-cluster-name"
           }
       ]
   }
   ```

------

1. アカウント A で、ロールにポリシーを追加します。

   ```
   aws iam put-role-policy \
       --role-name DaxCrossAccountRole \
       --policy-name DaxCrossAccountPolicy \
       --policy-document file://DaxCrossAccountPolicy.json
   ```

## VPC をセットアップする
<a name="DAX.cross-account-access.vpc-setup"></a>

1. アカウント A の DAX クラスターのサブネットグループを見つけます。*cluster-name* は、アカウント B がアクセスする必要のある DAX クラスターの名前に置き換えます。

   ```
   aws dax describe-clusters \
       --cluster-name cluster-name
       --query 'Clusters[0].SubnetGroup'
   ```

1. その *subnet-group* を使用して、クラスターの VPC を見つけます。

   ```
   aws dax describe-subnet-groups \
       --subnet-group-name subnet-group \
       --query 'SubnetGroups[0].VpcId'
   ```

1. その *vpc-id* を使用して、VPC の CIDR を見つけます。

   ```
   aws ec2 describe-vpcs \
       --vpc vpc-id \
       --query 'Vpcs[0].CidrBlock'
   ```

1. アカウント B から、前のステップで見つかったものとは異なる重複しない CIDR を使用して VPC を作成します。次に、少なくとも 1 つのサブネットを作成します。AWS マネジメントコンソール の [VPC 作成ウィザード](https://docs.aws.amazon.com/vpc/latest/userguide/getting-started-ipv4.html#getting-started-create-vpc)または [AWS CLI](https://docs.aws.amazon.com/cli/latest/reference/ec2/create-vpc.html) のいずれかを使用できます。

1. アカウント B から、「[VPC ピアリング接続の作成と使用](https://docs.aws.amazon.com/vpc/latest/peering/create-vpc-peering-connection.html)」の説明に従って、アカウント A VPC へのピアリング接続をリクエストします。アカウント A から接続を受け入れます。

1. アカウント B から、新しい VPC のルーティングテーブルを見つけます。*vpc-id* は、アカウント B で作成した VPC の ID に置き換えます。

   ```
   aws ec2 describe-route-tables \
       --filters 'Name=vpc-id,Values=vpc-id' \
       --query 'RouteTables[0].RouteTableId'
   ```

1. アカウント A の CIDR 宛てのトラフィックを VPC ピアリング接続に送信するルートを追加します。必ず、各*ユーザー入力プレースホルダ*は、アカウントの正しい値に置き換えます。

   ```
   aws ec2 create-route \
       --route-table-id accountB-route-table-id \
       --destination-cidr accountA-vpc-cidr \
       --vpc-peering-connection-id peering-connection-id
   ```

1. アカウント A から、以前に見つけた *vpc-id* を使用して DAX クラスターのルートテーブルを見つけます。

   ```
   aws ec2 describe-route-tables \
       --filters 'Name=vpc-id, Values=accountA-vpc-id' \
       --query 'RouteTables[0].RouteTableId'
   ```

1. アカウント A から、アカウント B の CIDR 宛てのトラフィックを VPC ピアリング接続に送信するルートを追加します。各*ユーザー入力プレースホルダ*は、アカウントの正しい値に置き換えます。

   ```
   aws ec2 create-route \
       --route-table-id accountA-route-table-id \
       --destination-cidr accountB-vpc-cidr \
       --vpc-peering-connection-id peering-connection-id
   ```

1. アカウント B から、前のステップで作成した VPC で EC2 インスタンスを起動します。それに `AssumeDaxInstanceProfile` を指定します。AWS マネジメントコンソール または [AWS CLI](https://docs.aws.amazon.com/cli/latest/reference/ec2/run-instances.html) いずれかの [Launch Wizard](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/launching-instance.html) を使用できます。インスタンスのセキュリティグループをメモしておきます。

1. アカウント A から、DAX クラスターが使用するセキュリティグループを見つけます。*cluster-name* を DAX クラスターの名前に置き換えることを記憶します。

   ```
   aws dax describe-clusters \
       --cluster-name cluster-name \
       --query 'Clusters[0].SecurityGroups[0].SecurityGroupIdentifier'
   ```

1. アカウント B で作成した EC2 インスタンスのセキュリティグループからのインバウンドトラフィックを許可するように、DAX クラスターのセキュリティグループを更新します。*ユーザー入力プレースホルダー*は、アカウントの正しい値に置き換えることを記憶します。

   ```
   aws ec2 authorize-security-group-ingress \
       --group-id accountA-security-group-id \
       --protocol tcp \
       --port 8111 \
       --source-group accountB-security-group-id \
       --group-owner accountB-id
   ```

この時点で、アカウント B の EC2 インスタンスのアプリケーションは、インスタンスプロファイルを使用して `arn:aws:iam::accountA-id:role/DaxCrossAccountRole` ロールを引き受け、DAX クラスターを使用できます。

## クロスアカウントアクセスを許可するように DAX クライアントを変更します
<a name="DAX.cross-account-access.modify-client"></a>

**注記**  
AWS Security Token Service (AWS STS) 認証情報は一時的な認証情報です。自動的に更新を処理するクライアントもあれば、認証情報を更新するための追加のロジックを必要とするクライアントもあります。該当するマニュアルの指示に従うことをお勧めします。

------
#### [ Java ]

このセクションでは、既存の DAX クライアントコードを変更して、クロスアカウント DAX アクセスを許可する方法について説明します。DAX クライアントコードがまだない場合は、「[Java および DAX](DAX.client.run-application-java.md)」チュートリアルで実際のコード例を見つけることができます。

1. 次のインポートを追加します。

   ```
   import com.amazonaws.auth.STSAssumeRoleSessionCredentialsProvider;
   import com.amazonaws.services.securitytoken.AWSSecurityTokenService;
   import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClientBuilder;
   ```

1. AWS STS から認証情報プロバイダを取得し、DAX クライアントオブジェクトを作成します。必ず、各*ユーザー入力プレースホルダ*は、アカウントの正しい値に置き換えます。

   ```
   AWSSecurityTokenService awsSecurityTokenService = AWSSecurityTokenServiceClientBuilder
        .standard()
        .withRegion(region)
        .build();
   
   STSAssumeRoleSessionCredentialsProvider credentials =  new STSAssumeRoleSessionCredentialsProvider.Builder("arn:aws:iam::accountA:role/RoleName", "TryDax")
        .withStsClient(awsSecurityTokenService)
        .build();
   
   DynamoDB client = AmazonDaxClientBuilder.standard()
       .withRegion(region)
       .withEndpointConfiguration(dax_endpoint)
       .withCredentials(credentials)
       .build();
   ```

------
#### [ .NET ]

このセクションでは、既存の DAX クライアントコードを変更して、クロスアカウント DAX アクセスを許可する方法について説明します。DAX クライアントコードがまだない場合は、「[.NET および DAX](DAX.client.run-application-dotnet.md)」チュートリアルで実際のコード例を見つけることができます。

1. [AWSSDK.SecurityToken](https://www.nuget.org/packages/AWSSDK.SecurityToken) NuGet パッケージをソリューションに追加します。

   ```
   <PackageReference Include="AWSSDK.SecurityToken" Version="latest version" />
   ```

1. `SecurityToken` および `SecurityToken.Model` パッケージを使用します。

   ```
   using Amazon.SecurityToken;
   using Amazon.SecurityToken.Model;
   ```

1. `AmazonSimpleTokenService` から一時的な認証情報を取得し、`ClusterDaxClient` オブジェクトを作成します。必ず、各*ユーザー入力プレースホルダ*は、アカウントの正しい値に置き換えます。

   ```
   IAmazonSecurityTokenService sts = new AmazonSecurityTokenServiceClient();
   
   var assumeRoleResponse = sts.AssumeRole(new AssumeRoleRequest
   {
       RoleArn = "arn:aws:iam::accountA:role/RoleName",
                   RoleSessionName = "TryDax"
   });
   
   Credentials credentials = assumeRoleResponse.Credentials;
   
   var clientConfig = new DaxClientConfig(dax_endpoint, port)
   {
       AwsCredentials = assumeRoleResponse.Credentials
                      
   };
   
   var client = new ClusterDaxClient(clientConfig);
   ```

------
#### [ Go ]

このセクションでは、既存の DAX クライアントコードを変更して、クロスアカウント DAX アクセスを許可する方法について説明します。DAX クライアントコードがまだない場合は、[GitHub で実際のコード例](https://github.com/aws-samples/aws-dax-go-sample/blob/master/try_dax.go)を見つけることができます。

1. AWS STS およびセッションパッケージをインポートします。

   ```
   import (
       "github.com/aws/aws-sdk-go/aws/session"
       "github.com/aws/aws-sdk-go/service/sts"
       "github.com/aws/aws-sdk-go/aws/credentials/stscreds"
   )
   ```

1. `AmazonSimpleTokenService` から一時的な認証情報を取得し、DAX クライアントオブジェクトを作成します。必ず、各*ユーザー入力プレースホルダ*は、アカウントの正しい値に置き換えます。

   ```
   sess, err := session.NewSession(&aws.Config{
       Region: aws.String(region)},
   )
   if err != nil {
       return nil, err
   }
   
   stsClient := sts.New(sess)
   arp := &stscreds.AssumeRoleProvider{
                   Duration:     900 * time.Second,
                   ExpiryWindow: 10 * time.Second,
                   RoleARN:      "arn:aws:iam::accountA:role/role_name",
                   Client:       stsClient,
                   RoleSessionName: "session_name",
           }cfg := dax.DefaultConfig()
   
   cfg.HostPorts = []string{dax_endpoint}
   cfg.Region = region
   cfg.Credentials = credentials.NewCredentials(arp)
   daxClient := dax.New(cfg)
   ```

------
#### [ Python ]

このセクションでは、既存の DAX クライアントコードを変更して、クロスアカウント DAX アクセスを許可する方法について説明します。DAX クライアントコードがまだない場合は、「[Python および DAX](DAX.client.run-application-python.md)」チュートリアルで実際のコード例を見つけることができます。

1. `boto3` をインポートします。

   ```
   import boto3
   ```

1. `sts` から一時的な認証情報を取得し、`AmazonDaxClient` オブジェクトを作成します。必ず、各*ユーザー入力プレースホルダ*は、アカウントの正しい値に置き換えます。

   ```
   sts = boto3.client('sts')
   stsresponse = sts.assume_role(RoleArn='arn:aws:iam::accountA:role/RoleName',RoleSessionName='tryDax')
   credentials = botocore.session.get_session()['Credentials']
   
   dax = amazondax.AmazonDaxClient(session, region_name=region, endpoints=[dax_endpoint], aws_access_key_id=credentials['AccessKeyId'], aws_secret_access_key=credentials['SecretAccessKey'], aws_session_token=credentials['SessionToken'])
   client = dax
   ```

------
#### [ Node.js ]

このセクションでは、既存の DAX クライアントコードを変更して、クロスアカウント DAX アクセスを許可する方法について説明します。DAX クライアントコードがまだない場合は、「[Node.js および DAX](DAX.client.run-application-nodejs.md)」チュートリアルで実際のコード例を見つけることができます。必ず、各*ユーザー入力プレースホルダ*は、アカウントの正しい値に置き換えます。

```
const AmazonDaxClient = require('amazon-dax-client');
const AWS = require('aws-sdk');
const region = 'region';
const endpoints = [daxEndpoint1, ...];

const getCredentials = async() => {
  return new Promise((resolve, reject) => {
    const sts = new AWS.STS();
    const roleParams = {
      RoleArn: 'arn:aws:iam::accountA:role/RoleName',
      RoleSessionName: 'tryDax',
    };
    sts.assumeRole(roleParams, (err, session) => {
      if(err) {
        reject(err);
      } else {
        resolve({
          accessKeyId: session.Credentials.AccessKeyId,
          secretAccessKey: session.Credentials.SecretAccessKey,
          sessionToken: session.Credentials.SessionToken,
        });
      }
    });
  });
};

const createDaxClient = async() => {
  const credentials = await getCredentials();
  const daxClient = new AmazonDaxClient({endpoints: endpoints, region: region, accessKeyId: credentials.accessKeyId, secretAccessKey: credentials.secretAccessKey, sessionToken: credentials.sessionToken});
  return new AWS.DynamoDB.DocumentClient({service: daxClient});
};

createDaxClient().then((client) => {
  client.get(...);
  ...
}).catch((error) => {
  console.log('Caught an error: ' + error);
});
```

------