我正在尝试从另一个 AWS 账户上的 lambda 函数访问一个 AWS 账户上的 Kinesis 流。 lambda 函数尝试使用 Amazon.Kinesis.AmazonKinesisClient 类从 AWS 账户中提取数据。我已经在具有 Kinesis 流的帐户上设置了一个角色(我将其称为源帐户)以允许访问 Kinesis 流并信任包含 lambda 函数的 AWS 帐户上的一个角色(我将其称为 汇账户)。汇账户上的角色允许承担源账户上的角色。我目前收到以下异常:
Amazon.Kinesis.Model.AccessDeniedException: 'User: arn:aws:sts::<account ID>:assumed-role/cross-account-stream-access-role/AWS_SDK_User is not authorized to access this resource'
角色和策略设置
source和sink account上角色的权限和信任关系策略如下:
Kinesis 访问策略(源帐户):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ReadInputStream",
"Effect": "Allow",
"Action": [
"kinesis:DescribeStream",
"kinesis:GetRecords",
"kinesis:GetShardIterator",
"kinesis:ListShards",
"kinesis:DescribeStreamSummary",
"kinesis:RegisterStreamConsumer"
],
"Resource": "<Kinesis Stream arn>"
}
]
}
汇账户角色(源账户)的信任关系:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "<ARN for Cross Account Stream Access Role on sink Account>"
},
"Action": "sts:AssumeRole"
}
]
}
Source Account Role Assumption Policy (Sink Account):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AssumeRoleInSourceAccount",
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "<ARN for Kinesis Access Role on source account>"
}
]
}
Lambda AWS 服务(接收账户)的信任关系:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
C#代码
我正在通过 lambda 函数在接收器帐户上与 AWS 用户一起运行以下代码:
private static async Task ReadFromKinesisStream(ILambdaContext context)
{
//create config that points to Kinesis region
AmazonKinesisConfig config = new AmazonKinesisConfig();
config.RegionEndpoint = Amazon.RegionEndpoint.USEast1;
var secretKey = "<Secret key of user on sink account>";
var accessKey = "<Access key of user on sink account>";
var assumeRole = "<arn on Cross Account Stream Access Role on sink Account>";
var assumedRoleSessionName = "<AWS User name that corresponds to secret key and access key on sink account>";
BasicAWSCredentials basicAwsCredentials = new BasicAWSCredentials(accessKey, secretKey);
AssumeRoleAWSCredentials roleAwsCredentials = new AssumeRoleAWSCredentials(basicAwsCredentials, assumeRole, assumedRoleSessionName);
AmazonKinesisClient client = new AmazonKinesisClient(roleAwsCredentials, Amazon.RegionEndpoint.USEast1);
DescribeStreamRequest describeRequest = new DescribeStreamRequest();
describeRequest.StreamARN = "arn:aws:kinesis:us-east-1:<source account ID>:stream/<Kinesis stream name>";
DescribeStreamResponse describeResponse = await client.DescribeStreamAsync(describeRequest);
// Previously mentioned exception occurs on line above.
.
.
.
}
我自己和另一位工程师在过去两天搜索了几个教程和 AWS 文档,但尚未找到任何解决上述异常的方法。
有谁知道 AWS 角色设置或 C# 代码有什么不正确的地方,以至于我收到了这个异常?
Kinesis 不支持跨账户lambda 读取。 这里是建议的解决方法。
我们弄清楚了需要做什么才能让接收账户上的 IAM 用户承担源账户上的“Kinesis 访问角色”。我们发现我们无法使用接收账户上 IAM 用户的凭证直接承担源 AWS 账户上的“Kinesis 访问角色”。我们必须以编程方式让 IAM 用户首先在接收器帐户上承担“跨帐户流访问角色”。
在C#代码中,我们必须:
修改后的代码如下所示:
private static async Task ReadFromKinesisStream(ILambdaContext context)
{
//create config that points to Kinesis region
AmazonKinesisConfig config = new AmazonKinesisConfig();
config.RegionEndpoint = Amazon.RegionEndpoint.USEast1;
var secretKey = "<Secret key of user on sink account>";
var accessKey = "<Access key of user on sink account>";
var assumeSinkAcctRole = "<arn of Cross Account Stream Access Role on sink account>";
var assumeSourceAcctRole = "<arn of Kinesis Access Role on source account>";
var assumedRoleSessionName = "<AWS User name that corresponds to secret key and access key on sink account>";
BasicAWSCredentials basicAwsCredentials = new BasicAWSCredentials(accessKey, secretKey);
AssumeRoleAWSCredentials sinkAcctRoleAwsCredentials = new AssumeRoleAWSCredentials(basicAwsCredentials, assumeSinkAcctRole, assumedRoleSessionName);
AssumeRoleAWSCredentials sourceAcctRoleAwsCredentials = new AssumeRoleAWSCredentials(sinkAcctRoleAwsCredentials, assumeSourceAcctRole, assumedRoleSessionName);
AmazonKinesisClient client = new AmazonKinesisClient(sourceAcctRoleAwsCredentials, Amazon.RegionEndpoint.USEast1);
DescribeStreamRequest describeRequest = new DescribeStreamRequest();
describeRequest.StreamARN = "arn:aws:kinesis:us-east-1:<source account ID>:stream/<Kinesis stream name>";
DescribeStreamResponse describeResponse = await client.DescribeStreamAsync(describeRequest);
.
.
.
}