AWS CDK — не может взять на себя роль в Lambda для точной авторизации

#amazon-web-services #amazon-iam #serverless #aws-cdk #aws-serverless

#amazon-web-services #amazon-iam #бессерверный #aws-cdk #aws-бессерверный

Вопрос:

Я довольно новичок в специфике 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:

{ «Тип ошибки»: «Доступ запрещен», «Сообщение об ошибке»: «Пользователь: arn:aws:sts::xxx:assumed-role/ProjectStack-createUserServiceRoleB9D8AADE-GRDI6MWXA5MY/ProjectStack-createUserC6ED88E6- K0S95UXTN9MH не авторизован для выполнения: sts:AssumeRole на ресурсе: arn:aws:iam ::xxx:role/ProjectStack-TenantUserRoleB79B8D3A-11N644X7UF0SR», «трассировка»: [ «Доступ запрещен: Пользователь: arn:aws:sts::xxx:assumed-role/ProjectStack-createUserServiceRoleB9D8AADE-GRDI6MWXA5MY/ProjectStack-createUserC6ED88E6- K0S95UXTN9MH не авторизован для выполнения: sts:AssumeRole на ресурсе: arn:aws:iam::xxx:role/ProjectStack-TenantUserRoleB79B8D3A-11N644X7UF0SR»,

Цель состоит в том, чтобы всегда разрешать разрешения на основе пользовательского контекста, так что же мне делать в моем стеке CDK, чтобы все мои лямбды выполняли то, что должно быть сделано?

Ответ №1:

Как описано @Maurice, роль должна быть доверенной вместо участника службы ( llambda.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 client, а затем использовать этот клиент для выполнения вызова 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. Я думаю, что часть, которая позволяет apiRole вызывать sts:AssumeRole в роли TenantUserRole, отсутствует, но OP должен быть в состоянии это выяснить 🙂

2. @Морис, я хотел поделиться trust policy примером, и он может легко согласиться с политикой. Я могу добавить и это, если потребуется. Я взял пример из его поста, где разрешено принципалом службы, как он упомянул <я создал роль и политику>

3. Это справедливо — я просто хотел отметить, что это приближает OP к их цели, но они все равно будут видеть запрет доступа, пока они также не добавят разрешения роли assumpt в apiRole.

4. конечно, @Maurice, я добавил и вторую часть, просто чтобы сделать оба ваших пункта действительными. Большое спасибо за рецензирование поста. Хорошего вам дня!

5. Благодаря этому ответу я почти на месте. Проблема, с которой я сталкиваюсь, заключается в том, что когда я вызываю DynamoDB, я получаю сообщение об ошибке, которое apiRole не разрешает вызывать Dynamo, в то время как в начале Lambda я вызываю assumeRole с успехом (учетные данные есть). В связанной статье AWS boto3.session используется результат из assumeRole результата, и я полагаю, что это причина, но я не могу найти, как это сделать в Node

Ответ №2:

Похоже, существует недопонимание относительно того, кто является принципалом.

Когда вы находитесь внутри лямбда-функции, пытающейся вызвать другие операции AWS API, на самом деле вызов выполняет не служба lambda.amazonaws.com , а роль, которую принимает на себя лямбда-функция.

Это означает, что вместо того, чтобы разрешать службе lambda.amazonaws.com брать на себя вашу TenantUserRole роль, вам нужно разрешить роль, которую использует функция, для принятия этой роли.

Вам необходимо настроить как политику предполагаемой роли, так и разрешения роли лямбда-функций, чтобы разрешить ее вызов sts:AssumeRole .

Комментарии:

1. Не могли бы вы, пожалуйста, объяснить с помощью кода CDK? Я в какой-то степени понимаю, но не знаю, как перевести это на CDK?