Acessando o DAX em contas da AWS - Amazon DynamoDB

Acessando o DAX em contas da AWS

Suponha que você tenha um cluster do DynamoDB Accelerator (DAX) em execução em uma conta da AWS (conta A) e que o cluster do DAX precise ser acessível de uma instância do Amazon Elastic Compute Cloud (Amazon EC2) em outra conta da AWS (conta B). Neste tutorial, isso é feito iniciando uma instância do EC2 na conta B com uma função do IAM da conta B. Então, você usa credenciais de segurança temporárias da instância do EC2 para assumir uma função do IAM da conta A. Por fim, você usa as credenciais de segurança temporárias da função do IAM da conta A para fazer chamadas de aplicação em uma conexão de emparelhamento da Amazon VPC para o cluster do DAX na conta A. Para realizar essas tarefas, é preciso ter acesso administrativo em ambas as contas da AWS.

Importante

Não é possível que um cluster do DAX acesse uma tabela do DynamoDB de uma conta diferente.

Configurar o IAM

  1. Crie um arquivo de texto chamado AssumeDaxRoleTrust.json com o conteúdo a seguir, que permite que o Amazon EC2 trabalhe em seu nome.

    { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "ec2.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }
  2. Na conta B, crie uma função que o Amazon EC2 possa usar ao executar instâncias.

    aws iam create-role \ --role-name AssumeDaxRole \ --assume-role-policy-document file://AssumeDaxRoleTrust.json
  3. Crie um arquivo de texto chamado AssumeDaxRolePolicy.json com o seguinte conteúdo, que permite que o código executado na instância do EC2 na conta B assuma uma função do IAM na conta A. Substitua accountA pelo ID real da conta A.

    { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "sts:AssumeRole", "Resource": "arn:aws:iam::accountA:role/DaxCrossAccountRole" } ] }
  4. Adicione essa política à função que acabou de criar.

    aws iam put-role-policy \ --role-name AssumeDaxRole \ --policy-name AssumeDaxRolePolicy \ --policy-document file://AssumeDaxRolePolicy.json
  5. Crie um perfil de instância para permitir que as instâncias usem a função.

    aws iam create-instance-profile \ --instance-profile-name AssumeDaxInstanceProfile
  6. Associe a função ao perfil de instância.

    aws iam add-role-to-instance-profile \ --instance-profile-name AssumeDaxInstanceProfile \ --role-name AssumeDaxRole
  7. Crie um arquivo de texto chamado DaxCrossAccountRoleTrust.json com o seguinte conteúdo, que permite que a conta B assuma uma função da conta A. Substitua accountB pelo ID real da conta B.

    { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::accountB:role/AssumeDaxRole" }, "Action": "sts:AssumeRole" } ] }
  8. Na conta A, crie a função que a conta B poderá assumir.

    aws iam create-role \ --role-name DaxCrossAccountRole \ --assume-role-policy-document file://DaxCrossAccountRoleTrust.json
  9. Crie um arquivo de texto chamado DaxCrossAccountPolicy.json que permite acesso ao cluster do DAX. Substitua dax-cluster-arn pelo nome do recurso da Amazon (ARN) correto do cluster do DAX.

    { "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": "dax-cluster-arn" } ] }
  10. Na conta A, adicione a política à função.

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

Configure uma VPC

  1. Localize o grupo de sub-redes do cluster do DAX da conta A. Substitua cluster-name pelo nome do cluster do DAX que a conta B deve acessar.

    aws dax describe-clusters \ --cluster-name cluster-name --query 'Clusters[0].SubnetGroup'
  2. Usando o subnet-group, encontre a VPC do cluster.

    aws dax describe-subnet-groups \ --subnet-group-name subnet-group \ --query 'SubnetGroups[0].VpcId'
  3. Usando o vpc-id, encontre o CIDR da VPC.

    aws ec2 describe-vpcs \ --vpc vpc-id \ --query 'Vpcs[0].CidrBlock'
  4. Na conta B, crie uma VPC usando um CIDR não sobreposto diferente daquele encontrado na etapa anterior. Em seguida, crie pelo menos uma sub-rede. Você pode usar o assistente de criação da VPC no AWS Management Console ou a AWS CLI.

  5. Na conta B, solicite uma conexão de emparelhamento com a VPC da conta A conforme descrito em Criar e aceitar uma conexão de emparelhamento da VPC. Na conta A, aceite a conexão.

  6. Na conta B, localize a nova tabela de roteamento da VPC. Substitua vpc-id pelo ID da VPC que você criou na conta B.

    aws ec2 describe-route-tables \ --filters 'Name=vpc-id,Values=vpc-id' \ --query 'RouteTables[0].RouteTableId'
  7. Adicione uma rota para enviar o tráfego destinado ao CIDR da conta A para a conexão de emparelhamento da VPC. Lembre-se de substituir cada espaço reservado de entrada de usuário pelos valores corretos para suas contas.

    aws ec2 create-route \ --route-table-id accountB-route-table-id \ --destination-cidr accountA-vpc-cidr \ --vpc-peering-connection-id peering-connection-id
  8. Na conta A, localize a tabela de rotas do cluster do DAX usando o vpc-id encontrado anteriormente.

    aws ec2 describe-route-tables \ --filters 'Name=vpc-id, Values=accountA-vpc-id' \ --query 'RouteTables[0].RouteTableId'
  9. Na conta A, adicione uma rota para enviar o tráfego destinado ao CIDR da conta B para a conexão de emparelhamento da VPC. Substitua cada espaço reservado de entrada de usuário pelos valores corretos para suas contas.

    aws ec2 create-route \ --route-table-id accountA-route-table-id \ --destination-cidr accountB-vpc-cidr \ --vpc-peering-connection-id peering-connection-id
  10. Na conta B, execute uma instância do EC2 na VPC que você criou anteriormente. Forneça o AssumeDaxInstanceProfile. Você pode usar o assistente de inicialização no AWS Management Console ou a AWS CLI. Anote o grupo de segurança da instância.

  11. Na conta A, localize o grupo de segurança usado pelo cluster do DAX. Lembre-se de substituir cluster-name pelo nome do cluster do DAX.

    aws dax describe-clusters \ --cluster-name cluster-name \ --query 'Clusters[0].SecurityGroups[0].SecurityGroupIdentifier'
  12. Atualize o grupo de segurança do cluster do DAX para permitir o tráfego de entrada do grupo de segurança da instância do EC2 que você criou na conta B. Lembre-se de substituir os espaços reservados de entrada do usuário pelos valores corretos para suas contas.

    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

Nesse ponto, uma aplicação na instância do EC2 da conta B pode usar o perfil de instância para assumir a função arn:aws:iam::accountA-id:role/DaxCrossAccountRole e usar o cluster do DAX.

Modificar o cliente do DAX para permitir acesso entre contas

nota

As credenciais do AWS Security Token Service (AWS STS) são temporárias. Alguns clientes lidam com a atualização automaticamente, enquanto outros exigem lógica adicional para atualizar as credenciais. Recomendamos seguir as orientações da documentação apropriada.

Java

Esta seção ajuda você a modificar seu código de cliente do DAX existente para permitir o acesso ao DAX entre contas. Caso ainda não tenha um código de cliente do DAX, você pode encontrar exemplos de código que funcionam no tutorial do Java e DAX.

  1. Adicione as seguintes importações.

    import com.amazonaws.auth.STSAssumeRoleSessionCredentialsProvider; import com.amazonaws.services.securitytoken.AWSSecurityTokenService; import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClientBuilder;
  2. Obtenha um provedor de credenciais do AWS STS e crie um objeto de cliente do DAX. Lembre-se de substituir cada espaço reservado de entrada de usuário pelos valores corretos para suas contas.

    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 seção ajuda você a modificar seu código de cliente do DAX existente para permitir o acesso ao DAX entre contas. Caso ainda não tenha um código de cliente do DAX, você pode encontrar exemplos de código que funcionam no tutorial do .NET e DAX.

  1. Adicione o pacote AWSSDK.SecurityToken NuGet à solução.

    <PackageReference Include="AWSSDK.SecurityToken" Version="latest version" />
  2. Use os pacotes SecurityToken e SecurityToken.Model.

    using Amazon.SecurityToken; using Amazon.SecurityToken.Model;
  3. Obtenha credenciais temporárias do AmazonSimpleTokenService e crie um objeto ClusterDaxClient. Lembre-se de substituir cada espaço reservado de entrada de usuário pelos valores corretos para suas contas.

    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 seção ajuda você a modificar seu código de cliente do DAX existente para permitir o acesso ao DAX entre contas. Caso ainda não tenha um código de cliente do DAX, você poderá encontrar exemplos de código funcionais no GitHub.

  1. Importe os pacotes de AWS STS e sessão.

    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" )
  2. Obtenha credenciais temporárias do AmazonSimpleTokenService e crie um objeto de cliente do DAX. Lembre-se de substituir cada espaço reservado de entrada de usuário pelos valores corretos para suas contas.

    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 seção ajuda você a modificar seu código de cliente do DAX existente para permitir o acesso ao DAX entre contas. Caso ainda não tenha um código de cliente do DAX, você pode encontrar exemplos de código que funcionam no tutorial do Python e DAX.

  1. Importe o boto3.

    import boto3
  2. Obtenha credenciais temporárias do sts e crie um objeto do AmazonDaxClient. Lembre-se de substituir cada espaço reservado de entrada de usuário pelos valores corretos para suas contas.

    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 seção ajuda você a modificar seu código de cliente do DAX existente para permitir o acesso ao DAX entre contas. Caso ainda não tenha um código de cliente do DAX, você pode encontrar exemplos de código que funcionam no tutorial do Node.js e DAX. Lembre-se de substituir cada espaço reservado de entrada de usuário pelos valores corretos para suas contas.

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