跨 AWS 账户访问 DAX
假设一个 DynamoDB Accelerator (DAX) 集群在一个 AWS 账户(账户 A)中运行,需要能够从另一个 AWS 账户(账户 B)中的 Amazon Elastic Compute Cloud (Amazon EC2) 实例访问 DAX 集群。在本教程中,您可以通过使用账户 B 中的 IAM 角色启动账户 B 中的 EC2 实例来做到这一点。然后,您可以使用 EC2 实例中的临时安全凭证来代入账户 A 中的 IAM 角色。最后,您可以通过代入账户 A 中的 IAM 角色来使用临时安全凭证,以通过与账户 A 中的 DAX 集群的 Amazon VPC 对等连接来进行应用程序调用。要执行这些任务,您将需要两个 AWS 账户中的管理访问权限。
无法让 DAX 集群通过其它账户访问 DynamoDB 表。
设置 IAM
-
使用以下内容创建一个名为 AssumeDaxRoleTrust.json
的文本文件,允许 Amazon EC2 代表您工作。
- JSON
-
-
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
-
在账户 B 中,创建一个启动实例时 Amazon EC2 可以使用的角色。
aws iam create-role \
--role-name AssumeDaxRole \
--assume-role-policy-document file://AssumeDaxRoleTrust.json
-
使用以下内容创建一个名为 AssumeDaxRolePolicy.json
的文本文件,从而允许在账户 B 中的 EC2 实例上运行的代码代入账户 A 中的 IAM 角色。将 accountA
替换为账户 A 的实际 ID。
- JSON
-
-
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::accountA
:role/DaxCrossAccountRole"
}
]
}
-
将该策略添加到您刚刚创建的角色。
aws iam put-role-policy \
--role-name AssumeDaxRole \
--policy-name AssumeDaxRolePolicy \
--policy-document file://AssumeDaxRolePolicy.json
-
创建实例配置文件以允许实例使用该角色。
aws iam create-instance-profile \
--instance-profile-name AssumeDaxInstanceProfile
-
将该角色与实例配置文件关联。
aws iam add-role-to-instance-profile \
--instance-profile-name AssumeDaxInstanceProfile \
--role-name AssumeDaxRole
-
使用以下内容创建一个名为 DaxCrossAccountRoleTrust.json
的文本文件,这将允许账户 B 代入账户 A 角色。将 accountB
替换为账户 B 的实际 ID。
- JSON
-
-
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::accountB
:role/AssumeDaxRole"
},
"Action": "sts:AssumeRole"
}
]
}
-
在账户 A 中,创建账户 B 可代入的角色。
aws iam create-role \
--role-name DaxCrossAccountRole \
--assume-role-policy-document file://DaxCrossAccountRoleTrust.json
-
创建一个名为 DaxCrossAccountPolicy.json
的文本文件来允许访问 DAX 集群。将 dax-cluster-arn
替换为 DAX 集群的正确 Amazon Resource Name (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": "dax-cluster-arn
"
}
]
}
-
在账户 A 中,将策略添加到角色。
aws iam put-role-policy \
--role-name DaxCrossAccountRole \
--policy-name DaxCrossAccountPolicy \
--policy-document file://DaxCrossAccountPolicy.json
设置 VPC
-
查找账户 A 的 DAX 集群的子网组。将 cluster-name
替换为账户 B 必须访问的 DAX 集群的名称。
aws dax describe-clusters \
--cluster-name cluster-name
--query 'Clusters[0].SubnetGroup'
-
使用该 subnet-group
查找集群的 VPC。
aws dax describe-subnet-groups \
--subnet-group-name subnet-group
\
--query 'SubnetGroups[0].VpcId'
-
使用该 vpc-id
查找 VPC 的 CIDR。
aws ec2 describe-vpcs \
--vpc vpc-id
\
--query 'Vpcs[0].CidrBlock'
-
从账户 B 中,使用与上一步中找到的 CIDR 不重叠的其他 CIDR 创建 VPC。然后,创建至少一个子网。您可以使用 AWS Management Console 或 AWS CLI 的 VPC 创建向导。
-
从账户 B 中,请求与账户 A VPC 的对等连接,如创建并接受 VPC 对等连接中所述。从账户 A 中,接受连接。
-
从账户 B 中,查找新 VPC 的路由表。将 vpc-id
替换为您在账户 B 中创建的 VPC 的 ID。
aws ec2 describe-route-tables \
--filters 'Name=vpc-id,Values=vpc-id
' \
--query 'RouteTables[0].RouteTableId'
-
添加一条路由,以将发送到账户 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
-
在账户 A 中,使用之前找到的 vc-id
查找 DAX 集群路由表。
aws ec2 describe-route-tables \
--filters 'Name=vpc-id, Values=accountA-vpc-id
' \
--query 'RouteTables[0].RouteTableId'
-
在账户 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
-
从账户 B 中,在您之前创建的 VPC 中启动 EC2 实例。为它提供 AssumeDaxInstanceProfile
。可以使用 AWS Management Console 或 AWS CLI 的启动向导。记下实例的安全组。
-
在账户 A 中,查找 DAX 集群使用的安全组。请记住将 cluster-name
替换为您的 DAX 集群的名称。
aws dax describe-clusters \
--cluster-name cluster-name
\
--query 'Clusters[0].SecurityGroups[0].SecurityGroupIdentifier'
-
更新 DAX 集群的安全组,允许来自您在账户 B 中创建的 EC2 实例安全组的入站流量。请记住将用户输入占位符
替换为您账户的正确值。
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 客户端以允许跨账户存取
AWS Security Token Service (AWS STS) 凭证是临时凭证。一些客户端会自动处理刷新,而其他客户端则需要额外的逻辑才能刷新凭证。建议您遵循相应文档的指导信息。
- Java
-
此部分帮助您修改现有的 DAX 客户端代码以允许跨账户 DAX 访问。如果您没有 DAX 客户端代码,则可在 Java 和 DAX 教程中查找工作代码示例。
-
添加以下导入。
import com.amazonaws.auth.STSAssumeRoleSessionCredentialsProvider;
import com.amazonaws.services.securitytoken.AWSSecurityTokenService;
import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClientBuilder;
-
从 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 教程中查找工作代码示例。
-
将 AWSSDK.SecurityToken NuGet 程序包添加到解决方案。
<PackageReference Include="AWSSDK.SecurityToken" Version="latest version
" />
-
使用 SecurityToken
和 SecurityToken.Model
程序包。
using Amazon.SecurityToken;
using Amazon.SecurityToken.Model;
-
从 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 上的工作代码示例。
-
导入 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"
)
-
从 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 教程中查找工作代码示例。
-
导入 boto3
。
import boto3
-
从 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 教程中查找工作代码示例。请记住,将每个用户输入占位符
替换为您帐户的正确值。
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);
});