

# Acceso a DAX a través de las cuentas de AWS
<a name="DAX.cross-account-access"></a>

Imagine que tiene un clúster de DynamoDB Accelerator (DAX) ejecutándose en una cuenta de AWS (cuenta A) y que el clúster de DAX debe ser accesible desde una instancia de Amazon Elastic Compute Cloud (Amazon EC2) en otra cuenta de AWS (cuenta B). En este tutorial, lo logrará lanzando una instancia EC2 en la cuenta B con un rol de IAM de la cuenta B. A continuación, utiliza las credenciales de seguridad temporales de la instancia EC2 para asumir un rol de IAM de la cuenta A. Por último, utiliza las credenciales de seguridad temporales de asumir el rol de IAM en la cuenta A para realizar llamadas a la aplicación a través de una interconexión de Amazon VPC al clúster de DAX en la cuenta A. Para realizar estas tareas necesitará acceso administrativo en ambas cuentas de AWS.

**importante**  
 No es posible hacer que un clúster DAX acceda a una tabla de DynamoDB desde una cuenta diferente. 

**Topics**
+ [Configurar IAM](#DAX.cross-account-access.iam-setup)
+ [Configurar una VPC](#DAX.cross-account-access.vpc-setup)
+ [Modificar el cliente de DAX para permitir el acceso entre cuentas](#DAX.cross-account-access.modify-client)

## Configurar IAM
<a name="DAX.cross-account-access.iam-setup"></a>

1. Cree un archivo de texto denominado `AssumeDaxRoleTrust.json` con el siguiente contenido, que permite a Amazon EC2 trabajar en su nombre.

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

****  

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

------

1. En la cuenta B, cree un rol que Amazon EC2 pueda utilizar al lanzar instancias.

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

1. Cree un archivo de texto denominado `AssumeDaxRolePolicy.json` con el siguiente contenido, que permite que el código que se ejecuta en la instancia EC2 en la cuenta B asuma un rol de IAM en la cuenta A. Reemplace *accountA* por el ID real de la cuenta A.

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

****  

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

------

1. Agregue esa política al rol que acaba de crear.

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

1. Cree un perfil de instancia para permitir que las instancias utilicen el rol.

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

1. Asocie el rol con el perfil de instancia.

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

1. Cree un archivo de texto denominado `DaxCrossAccountRoleTrust.json` con el siguiente contenido, lo que permite a la cuenta B asumir un rol de cuenta A. Reemplace *cuentaB* por el ID real de la cuenta B.

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

****  

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

------

1. En la cuenta A, cree el rol que la cuenta B puede asumir.

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

1. Cree un archivo de texto denominado `DaxCrossAccountPolicy.json` que permita el acceso al clúster de DAX. Reemplace *dax-cluster-arn* por el nombre de recurso de Amazon (ARN) correcto de su clúster de DAX.

------
#### [ 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. En la cuenta A, agregue la política al rol.

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

## Configurar una VPC
<a name="DAX.cross-account-access.vpc-setup"></a>

1. Busque el grupo de subred del clúster de DAX de la cuenta A. Reemplace *cluster-name* por el nombre del clúster de DAX al que debe tener acceso la cuenta B.

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

1. Utilizando ese *grupo de subred*, busque la VPC del clúster.

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

1. Usando ese *vpc-id*, busque el CIDR de la VPC.

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

1. Desde la cuenta B, cree una VPC utilizando un CIDR diferente y no superpuesto que el encontrado en el paso anterior. A continuación, cree al menos una subred. Puede utilizar el [asistente de creación de VPC](https://docs.aws.amazon.com/vpc/latest/userguide/getting-started-ipv4.html#getting-started-create-vpc) en la Consola de administración de AWS o en la [AWS CLI](https://docs.aws.amazon.com/cli/latest/reference/ec2/create-vpc.html).

1. Desde la cuenta B, solicite una interconexión a la VPC de la cuenta A como se describe en [Creación y aceptación de una conexión de emparejamiento de VPC](https://docs.aws.amazon.com/vpc/latest/peering/create-vpc-peering-connection.html). Desde la cuenta A, acepte la conexión.

1. En la cuenta B, busque la nueva tabla de ruteo de la VPC. Reemplace *vpc-id* por el ID de la VPC que creó en la cuenta B.

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

1. Agregue una ruta para enviar tráfico destinado al CIDR de la cuenta A a la interconexión de VPC. Recuerde reemplazar cada *marcador de posición de entrada de usuario* por los valores correctos para sus cuentas.

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

1. En la cuenta A, busque la tabla de enrutamiento del clúster de DAX utilizando el *vpc-id* que encontró anteriormente.

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

1. Desde la cuenta A, agregue una ruta para enviar tráfico destinado al CIDR de la cuenta B a la interconexión de VPC. Reemplace cada *marcador de posición de entrada de usuario* por los valores correctos para sus cuentas.

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

1. Desde la cuenta B, lance una instancia EC2 en la VPC que creó anteriormente. Dele el `AssumeDaxInstanceProfile`. Puede utilizar el [asistente de inicio](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/launching-instance.html) en la Consola de administración de AWS o en la [AWS CLI](https://docs.aws.amazon.com/cli/latest/reference/ec2/run-instances.html). Tome nota del grupo de seguridad de la instancia.

1. En la cuenta A, busque el grupo de seguridad utilizado por el clúster de DAX. Recuerde sustituir *cluster-name* por el nombre de su clúster de DAX.

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

1. Actualice el grupo de seguridad del clúster de DAX para permitir el tráfico entrante desde el grupo de seguridad de la instancia EC2 que creó en la cuenta B. Recuerde sustituir los *marcadores de posición de entrada del usuario* por los valores correctos para sus cuentas.

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

En este punto, una aplicación en la instancia EC2 de la cuenta B puede utilizar el perfil de instancias para asumir el rol `arn:aws:iam::accountA-id:role/DaxCrossAccountRole` y utilizar el clúster de DAX.

## Modificar el cliente de DAX para permitir el acceso entre cuentas
<a name="DAX.cross-account-access.modify-client"></a>

**nota**  
Las credenciales de AWS Security Token Service (AWS STS) son credenciales temporales. Algunos clientes manejan la actualización automáticamente, mientras que otros requieren lógica adicional para actualizar las credenciales. Le recomendamos que siga las instrucciones de la documentación correspondiente.

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

Esta sección le ayuda a modificar el código de cliente de DAX existente para permitir el acceso de DAX entre cuentas. Si aún no tiene código de cliente de DAX, puede encontrar ejemplos de código de trabajo en el tutorial [Java y DAX](DAX.client.run-application-java.md).

1. Agregue las siguientes importaciones:

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

1. Obtenga un proveedor de credenciales de AWS STS y cree un objeto cliente de DAX. Recuerde reemplazar cada *marcador de posición de entrada de usuario* por los valores correctos para sus cuentas.

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

Esta sección le ayuda a modificar el código de cliente de DAX existente para permitir el acceso de DAX entre cuentas. Si aún no tiene código de cliente de DAX, puede encontrar ejemplos de código de trabajo en el tutorial [.NET y DAX](DAX.client.run-application-dotnet.md).

1. Agregue el paquete NuGet [AWSSDK.SecurityToken](https://www.nuget.org/packages/AWSSDK.SecurityToken) a la solución.

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

1. Utilice los paquetes `SecurityToken` y `SecurityToken.Model`.

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

1. Obtenga credenciales temporales de `AmazonSimpleTokenService` y cree un objeto de `ClusterDaxClient`. Recuerde reemplazar cada *marcador de posición de entrada de usuario* por los valores correctos para sus cuentas.

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

Esta sección le ayuda a modificar el código de cliente de DAX existente para permitir el acceso de DAX entre cuentas. Si aún no tiene código de cliente de DAX, puede encontrar [ejemplos de código en funcionamiento en GitHub](https://github.com/aws-samples/aws-dax-go-sample/blob/master/try_dax.go).

1. Importe los paquetes de AWS STS y de sesión.

   ```
   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. Obtener credenciales temporales de `AmazonSimpleTokenService` y crear un objeto cliente de DAX. Recuerde reemplazar cada *marcador de posición de entrada de usuario* por los valores correctos para sus cuentas.

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

Esta sección le ayuda a modificar el código de cliente de DAX existente para permitir el acceso de DAX entre cuentas. Si aún no tiene código de cliente de DAX, puede encontrar ejemplos de código de trabajo en el tutorial [Python y DAX](DAX.client.run-application-python.md).

1. Importe `boto3`.

   ```
   import boto3
   ```

1. Obtenga credenciales temporales de `sts` y cree un objeto `AmazonDaxClient`. Recuerde reemplazar cada *marcador de posición de entrada de usuario* por los valores correctos para sus cuentas.

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

Esta sección le ayuda a modificar el código de cliente de DAX existente para permitir el acceso de DAX entre cuentas. Si aún no tiene código de cliente de DAX, puede encontrar ejemplos de código de trabajo en el tutorial [Node.js y DAX](DAX.client.run-application-nodejs.md). Recuerde reemplazar cada *marcador de posición de entrada de usuario* por los valores correctos para sus cuentas.

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

------