尝试跨 AWS 账户访问 Kinesis 流时出现拒绝访问错误

问题描述 投票:0回答:2

我正在尝试从另一个 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# 代码有什么不正确的地方,以至于我收到了这个异常?

c# aws-lambda amazon-iam amazon-kinesis
2个回答
0
投票

Kinesis 不支持跨账户lambda 读取。 这里是建议的解决方法。


0
投票

我们弄清楚了需要做什么才能让接收账户上的 IAM 用户承担源账户上的“Kinesis 访问角色”。我们发现我们无法使用接收账户上 IAM 用户的凭证直接承担源 AWS 账户上的“Kinesis 访问角色”。我们必须以编程方式让 IAM 用户首先在接收器帐户上承担“跨帐户流访问角色”。

在C#代码中,我们必须:

  1. 为接收器帐户上的 IAM 用户创建一个 AWS 凭证对象。
  2. 使用这些凭据通过 AssumeRoleAWSCredentials 类在接收器帐户上承担“跨账户流访问角色”,该类为该承担的角色创建凭据。
  3. 使用“跨账户流访问角色”的凭据通过 AssumeRoleAWSCredentials 类在源账户上承担“Kinesis 访问角色”。
  4. 使用为“Kinesis 访问角色”创建的凭据创建 AmazonKinesisClient。

修改后的代码如下所示:

    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);
                                            .
                                            .
                                            .
   }
© www.soinside.com 2019 - 2024. All rights reserved.