AWS CDK:如何创建可以由多个委托人担任的 IAM 角色?
AWS CDK: How to create an IAM role that can be assumed by multiple principals?
我正在部署 CloudFront 将使用的 Lambda 函数。因此,函数的执行角色需要由 edgelambda.amazonaws.com 和 lambda.amazonaws.com 承担。如果我手动执行此操作,策略将如下所示:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"edgelambda.amazonaws.com",
"lambda.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}
在 AWS CDK 中进行设置时,iam.Role
class 仅允许您最初指定一个假设主体,例如:
lambda_role = iam.Role(
self,
"lambda_redirect_role",
assumed_by=iam.ServicePrincipal("edgelambda.amazonaws.com"),
managed_policies=[
iam.ManagedPolicy.from_aws_managed_policy_name("service-role/AWSLambdaBasicExecutionRole"),
iam.ManagedPolicy.from_aws_managed_policy_name("AWSXrayWriteOnlyAccess")
],
)
所以我试图找到 best/cleanest 添加第二个主体的方法。文档说我可以使用 assume_role_policy 检索策略文档然后对其进行操作。
所以我试过了:
policy = lambda_role.assume_role_policy
policy.add_statements(
iam.PolicyStatement(
actions=["sts:AssumeRole"],
effect=iam.Effect.ALLOW,
principals=[
iam.ServicePrincipal("lambda.amazonaws.com")
]
)
)
但这给了我这个不太理想的政策:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "edgelambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
},
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
我已尝试在策略中操纵现有语句,但我不知道如何将其恢复到角色定义中:
policy = lambda_role.assume_role_policy
# This gives us a read-only policy so we need to do
# some manipulation in order to add the lambda principal
policy_json = policy.to_json()
print(policy_json)
# That gets us a dict (even though it says json) so now
# we extract the one and only statement ...
statement = policy_json["Statement"][0]
# Turn it back into a CDK object we can manipulate
statement_obj = iam.PolicyStatement.from_json(statement)
# Add the extra principal
statement_obj.add_principals(
iam.ServicePrincipal("lambda.amazonaws.com")
)
# Put it all back ...
policy_json["Statement"][0] = statement_obj.to_json()
policy.from_json(policy_json)
有没有办法使用 CDK 获得“更清晰”的政策声明,或者我是否坚持使用它当前生成的两个声明?
这可以使用 CompositePrincipal:
lambda_role = iam.Role(
self,
"lambda_redirect_role",
assumed_by=iam.CompositePrincipal(
iam.ServicePrincipal("edgelambda.amazonaws.com"),
iam.ServicePrincipal("lambda.amazonaws.com"),
),
...
)
我正在部署 CloudFront 将使用的 Lambda 函数。因此,函数的执行角色需要由 edgelambda.amazonaws.com 和 lambda.amazonaws.com 承担。如果我手动执行此操作,策略将如下所示:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"edgelambda.amazonaws.com",
"lambda.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}
在 AWS CDK 中进行设置时,iam.Role
class 仅允许您最初指定一个假设主体,例如:
lambda_role = iam.Role(
self,
"lambda_redirect_role",
assumed_by=iam.ServicePrincipal("edgelambda.amazonaws.com"),
managed_policies=[
iam.ManagedPolicy.from_aws_managed_policy_name("service-role/AWSLambdaBasicExecutionRole"),
iam.ManagedPolicy.from_aws_managed_policy_name("AWSXrayWriteOnlyAccess")
],
)
所以我试图找到 best/cleanest 添加第二个主体的方法。文档说我可以使用 assume_role_policy 检索策略文档然后对其进行操作。
所以我试过了:
policy = lambda_role.assume_role_policy
policy.add_statements(
iam.PolicyStatement(
actions=["sts:AssumeRole"],
effect=iam.Effect.ALLOW,
principals=[
iam.ServicePrincipal("lambda.amazonaws.com")
]
)
)
但这给了我这个不太理想的政策:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "edgelambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
},
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
我已尝试在策略中操纵现有语句,但我不知道如何将其恢复到角色定义中:
policy = lambda_role.assume_role_policy
# This gives us a read-only policy so we need to do
# some manipulation in order to add the lambda principal
policy_json = policy.to_json()
print(policy_json)
# That gets us a dict (even though it says json) so now
# we extract the one and only statement ...
statement = policy_json["Statement"][0]
# Turn it back into a CDK object we can manipulate
statement_obj = iam.PolicyStatement.from_json(statement)
# Add the extra principal
statement_obj.add_principals(
iam.ServicePrincipal("lambda.amazonaws.com")
)
# Put it all back ...
policy_json["Statement"][0] = statement_obj.to_json()
policy.from_json(policy_json)
有没有办法使用 CDK 获得“更清晰”的政策声明,或者我是否坚持使用它当前生成的两个声明?
这可以使用 CompositePrincipal:
lambda_role = iam.Role(
self,
"lambda_redirect_role",
assumed_by=iam.CompositePrincipal(
iam.ServicePrincipal("edgelambda.amazonaws.com"),
iam.ServicePrincipal("lambda.amazonaws.com"),
),
...
)