【问题标题】:AWS CDK - Cannot assume role in Lambda for fine grained authorizationAWS CDK - 无法在 Lambda 中担任细粒度授权角色
【发布时间】:2021-06-02 03:09:35
【问题描述】:

我对 AWS 的细节还很陌生,所以请原谅我提出一个愚蠢的问题。 我一直在寻找答案,但没有找到任何可以回答我的问题的问题。

我正在构建一个项目,并尝试使用此 AWS 教程正确完成权限:https://aws.amazon.com/blogs/apn/partitioning-pooled-multi-tenant-saas-data-with-amazon-dynamodb/

我已创建角色和政策:

const tenantUserRole = new Role(this, "TenantUserRole", {
      assumedBy: new ServicePrincipal("lambda.amazonaws.com"),
    });
table.grantReadWriteData(tenantUserRole);

然后,在我的 Lambda 中,我尝试:

const role = await stsClient.send(
    new AssumeRoleCommand({
      Policy: getPolicy("tenant"),
      RoleArn: process.env.TENANT_ROLE_ARN,
      RoleSessionName: "foo",
    })
  );

这不起作用,因为我在 Lambda 中遇到错误:

{ "errorType": "AccessDenied", “errorMessage”:“用户:arn:aws:sts::xxx:assumed-role/ProjectStack-createUserServiceRoleB9D8AADE-GRDI6MWXA5MY/ProjectStack-createUserC6ED88E6-K0S95UXTN9MH 无权执行:sts:AssumeRole on resource:arn:aws:iam:: xxx:角色/ProjectStack-TenantUserRoleB79B8D3A-11N644X7UF0SR", “痕迹”: [ “AccessDenied:用户:arn:aws:sts::xxx:assumed-role/ProjectStack-createUserServiceRoleB9D8AADE-GRDI6MWXA5MY/ProjectStack-createUserC6ED88E6-K0S95UXTN9MH 无权执行:sts:AssumeRole on resource:arn:aws:iam::xxx:角色/ProjectStack-TenantUserRoleB79B8D3A-11N644X7UF0SR",

目标是始终根据用户上下文解析权限,那么我应该在我的 CDK 堆栈中做些什么来使我的所有 Lambda 都能做必须做的事情?

【问题讨论】:

    标签: amazon-web-services amazon-iam serverless aws-cdk aws-serverless


    【解决方案1】:

    似乎对谁是校长有误解。

    当您在尝试调用其他 AWS API 操作的 Lambda 函数中时,不是实际上是服务 lambda.amazonaws.com 进行调用,而是 Lambda 函数承担的角色。

    这意味着您需要允许该函数使用的角色来承担该角色,而不是允许服务 lambda.amazonaws.com 代入您的 TenantUserRole

    您需要同时配置承担角色策略以及 lambda 函数角色的权限,以允许其调用sts:AssumeRole

    【讨论】:

    • 你能用CDK代码解释一下吗?有点懂但不知道怎么翻译成CDK?
    【解决方案2】:

    正如@Maurice 所述,应该信任该角色而不是服务主体(llambda.amazonaws.com)。 下面是CDK代码。

    TenantUserRoleapiRole 信任,aws lambda 正在使用它

    import * as cdk from '@aws-cdk/core';
    import * as iam from '@aws-cdk/aws-iam';
    
    export class CdkWorkshopStack extends cdk.Stack {
      constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
        super(scope, id, props);
        // aws lambda role
        const lambdaRole = new iam.Role(this, 'apiRole', {
          roleName: 'apiRole',
          assumedBy:  new iam.ServicePrincipal('lambda.amazonaws.com'),
        });
        // trusted by TenantUserRole for access
        const tenantUserRole = new iam.Role(this, 'TenantUserRole', {
          roleName: 'TenantUserRole',
          assumedBy: new iam.ArnPrincipal(lambdaRole.roleArn),
        });
    
        // policy to allow assume role TenantUserRole
        lambdaRole.addToPolicy(
          new iam.PolicyStatement({
            resources: [tenantUserRole.roleArn],
            actions: ['sts:AssumeRole'],
          })
        );
      }
    }
    

    这里看起来像是在角色的信任策略中。

    ❯❯ aws  iam get-role --role-name TenantUserRole
    {
        "Role": {
            "Path": "/",
            "RoleName": "TenantUserRole",
            "RoleId": "AROA2WXKNDTKKGFADASD",
            "Arn": "arn:aws:iam::1234567890:role/TenantUserRole",
            "CreateDate": "2021-03-03T23:34:13+00:00",
            "AssumeRolePolicyDocument": {
                "Version": "2012-10-17",
                "Statement": [
                    {
                        "Effect": "Allow",
                        "Principal": {
                            "AWS": "arn:aws:iam::1234567890:role/apiRole"
                        },
                        "Action": "sts:AssumeRole"
                    }
                ]
            },
            "Description": "",
            "MaxSessionDuration": 3600,
            "RoleLastUsed": {}
        }
    }
    

    允许 aws lambda 角色担任 TenantUserRole 的政策

    ❯❯ aws iam get-role-policy  --role-name apiRole  --policy-name apiRoleDefaultPolicy771DC0DD
    {
        "RoleName": "apiRole",
        "PolicyName": "apiRoleDefaultPolicy771DC0DD",
        "PolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Action": "sts:AssumeRole",
                    "Resource": "arn:aws:iam::1234567890:role/TenantUserRole",
                    "Effect": "Allow"
                }
            ]
        }
    }
    

    How to use trust policies with IAM roles

    在 lambda 中,您需要在假设 TenantUserRole 后使用这些凭据并创建 dynamodb 客户端,然后使用该客户端进行 api 调用 putItem

    import boto3
    
    def lambda_handler(event, context):
        sts = boto3.client('sts')
        // assume TenantUserRole
        creds = sts.assume_role(
            RoleArn='arn:aws:iam::1234567890:role/TenantUserRole',
            RoleSessionName="tempsession"
            )
        // Use Credentials from the assume call to make dynamodb client
        tenant_user_dyanmodb_client = boto3.client(
        'dynamodb',
        aws_access_key_id=creds.get('Credentials').get('AccessKeyId'),
        aws_secret_access_key=creds.get('Credentials').get('SecretAccessKey'),
        aws_session_token=creds.get('Credentials').get('SessionToken')
        )
    
       // call put item
        tenant_user_dyanmodb_client.put_item(TableName='fruitSalad', Item={'fruitName':{'S':'Banana'},'key2':{'N':'value2'}})
    
    

    【讨论】:

    • 我认为允许 apiRole 在 TenantUserRole 上调用 sts:AssumeRole 的部分丢失了,但 OP 应该能够弄清楚 :-)
    • @Maurice 我想分享trust policy 的例子,他可以很容易地接受政策。如果需要,我也可以添加。我从他的帖子中举了一个例子,服务主体允许,正如他提到的那样
    • 这很公平 - 我只是想指出,这使 OP 更接近他们的目标,但他们仍然会看到 AccessDenied,直到他们还将承担角色权限添加到 apiRole。
    • 当然@Maurice 我也添加了第二部分,只是为了让你的观点都有效。非常感谢您审阅帖子。祝你有美好的一天!
    • 感谢这个答案,我快到了。我遇到的问题是,当我调用 DynamoDB 时,我收到一个错误,apiRole 不允许调用 Dynamo,而在 Lambda 的开头,我成功调用了assumeRole(凭据在那里)。在链接的 AWS 文章中,有 boto3.session 使用来自 assumeRole 结果的结果,我想这就是原因,但我在 Node 中找不到如何做到这一点
    猜你喜欢
    • 2018-09-10
    • 2021-08-27
    • 2023-03-13
    • 2018-09-19
    • 2016-03-24
    • 2021-03-09
    • 1970-01-01
    • 2019-12-31
    • 2019-10-19
    相关资源
    最近更新 更多