#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
с успехом (учетные данные есть). В связанной статье AWSboto3.session
используется результат изassumeRole
результата, и я полагаю, что это причина, но я не могу найти, как это сделать в Node
Ответ №2:
Похоже, существует недопонимание относительно того, кто является принципалом.
Когда вы находитесь внутри лямбда-функции, пытающейся вызвать другие операции AWS API, на самом деле вызов выполняет не служба lambda.amazonaws.com
, а роль, которую принимает на себя лямбда-функция.
Это означает, что вместо того, чтобы разрешать службе lambda.amazonaws.com
брать на себя вашу TenantUserRole
роль, вам нужно разрешить роль, которую использует функция, для принятия этой роли.
Вам необходимо настроить как политику предполагаемой роли, так и разрешения роли лямбда-функций, чтобы разрешить ее вызов sts:AssumeRole
.
Комментарии:
1. Не могли бы вы, пожалуйста, объяснить с помощью кода CDK? Я в какой-то степени понимаю, но не знаю, как перевести это на CDK?