AWS CDK - 无法在 Lambda 中承担细粒度授权的角色

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

我对 AWS 的具体情况相当陌生,所以请原谅我提出一个愚蠢的问题。 我一直在寻找答案,但没有找到任何可以回答我的问题的问题。

我正在构建一个项目,并尝试使用此 AWS 教程正确获得权限:https://aws.amazon.com/blogs/apn/partitioning-pooled-multi-tenant-saas-data-with-亚马逊-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": "访问被拒绝", "errorMessage": "用户:arn:aws:sts::xxx:assumed-role/ProjectStack-createUserServiceRoleB9D8AADE-GRDI6MWXA5MY/ProjectStack-createUserC6ED88E6-K0S95UXTN9MH 无权对资源执行:sts:AssumeRole:arn:aws:iam:: xxx:角色/ProjectStack-TenantUserRoleB79B8D3A-11N644X7UF0SR”, “痕迹”: [ “AccessDenied:用户:arn:aws:sts::xxx:assumed-role/ProjectStack-createUserServiceRoleB9D8AADE-GRDI6MWXA5MY/ProjectStack-createUserC6ED88E6-K0S95UXTN9MH 无权对资源执行:sts:AssumeRole:arn:aws:iam::xxx:角色/ProjectStack-TenantUserRoleB79B8D3A-11N644X7UF0SR”,

目标是始终根据用户上下文解析权限,那么我应该在 CDK 堆栈中做什么才能使我的所有 Lambda 能够执行必须执行的操作?

amazon-web-services amazon-iam serverless aws-cdk aws-serverless
2个回答
9
投票

正如@Maurice 所描述的,应该信任角色而不是服务主体(

lambda.amazonaws.com
)。 以下是CDK代码。

TenantUserRole
apiRole
信任,并由
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"
            }
        ]
    }
}

如何将信任策略与 IAM 角色结合使用

在 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'}})


1
投票

对于谁是校长的问题,似乎存在误解。

当您在 Lambda 函数中尝试调用其他 AWS API 操作时,实际上不是执行调用的服务

lambda.amazonaws.com
,而是 Lambda 函数所承担的角色。

这意味着您需要允许该函数使用的角色来承担该角色,而不是允许服务

lambda.amazonaws.com
承担您的
TenantUserRole

您需要配置假设角色策略以及 lambda 函数角色的权限,以允许其调用

sts:AssumeRole

© www.soinside.com 2019 - 2024. All rights reserved.