场景 1:您在同一个堆栈中创建角色和策略,并且该策略不会在任何其他堆栈中重复使用。
在这种情况下,使用 iam.Policy 并将其附加在行内:
export class CdkGetLogicalIdExampleStack extends cdk.Stack {
role: iam.IRole;
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const policy = new iam.Policy(this, 'policy', {
policyName: 'policy',
statements: [
new iam.PolicyStatement({
actions: ["s3:*"],
resources: ['*'],
effect: iam.Effect.ALLOW
})
]
});
this.role = new iam.Role(this, 'my-role', {
roleName: 'my-role',
assumedBy: new iam.AccountPrincipal(this.account),
});
// Alternatively: this.role.attachInlinePolicy(policy);
policy.attachToRole(this.role);
}
}
角色作为堆栈的属性保存,因此在测试中很容易引用它:
test('Empty Stack', () => {
const app = new cdk.App();
const stack = new CdkGetLogicalIdExample.CdkGetLogicalIdExampleStack(app, 'MyTestStack');
const roleId = stack.getLogicalId(stack.role.node.findChild('Resource') as cdk.CfnElement);
expectCDK(stack).to(haveResource("AWS::IAM::Policy", {
"PolicyDocument": {
"Statement": [
{
"Action": "s3:*",
"Effect": "Allow",
"Resource": "*"
}
],
"Version": "2012-10-17"
},
"PolicyName": "policy",
"Roles": [
{
"Ref": roleId
}
]
}));
});
场景 2:您正在创建一个可在各种堆栈中使用的策略,因此您希望将其设为托管策略。
测试这个场景稍微复杂一些,因为iam.ManagedPolicy 实现了IManagedPolicy 接口,它只提供了managedPolicyArn 属性(我使用的是CDK 1.124.0)。
尽管如此,iam.ManagedPolicy 扩展了 cdk.Resource,所以我们可以通过以下方式欺骗 TypeScript 的转换机制:
export class CdkGetLogicalIdExampleStack extends cdk.Stack {
// note the type here
managedPolicy: cdk.Resource | iam.IManagedPolicy;
role: iam.IRole;
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
this.managedPolicy = new iam.ManagedPolicy(this, 'managed-policy', {
managedPolicyName: 'managed-policy',
document: new iam.PolicyDocument({
statements: [
new iam.PolicyStatement({
actions: ["dynamodb:*"],
resources: ["*"],
effect: iam.Effect.ALLOW
})
]
})
});
this.role = new iam.Role(this, 'my-role', {
roleName: 'my-role',
assumedBy: new iam.AccountPrincipal(this.account),
});
// here we need to cast to iam.IManagedPolicy
this.role.addManagedPolicy(this.managedPolicy as iam.IManagedPolicy);
}
}
现在,可以进行测试了,因为我们可以将managedPolicy 属性作为cdk.Resource 访问:
const roleId = stack.getLogicalId(stack.role.node.findChild('Resource') as cdk.CfnElement);
// here we do the casting to cdk.Resource
const managedPolicyResource = stack.managedPolicy as cdk.Resource;
const managedPolicyId = stack.getLogicalId(managedPolicyResource.node.findChild('Resource') as cdk.CfnElement);
expectCDK(stack).to(haveResource("AWS::IAM::ManagedPolicy", {
"PolicyDocument": {
"Statement": [
{
"Action": "dynamodb:*",
"Effect": "Allow",
"Resource": "*"
}
],
"Version": "2012-10-17"
},
"Description": "",
"ManagedPolicyName": "managed-policy",
"Path": "/"
}));
expectCDK(stack).to(haveResource("AWS::IAM::Role", {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"AWS": {
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":iam::",
{
"Ref": "AWS::AccountId"
},
":root"
]
]
}
}
}
],
"Version": "2012-10-17"
},
"ManagedPolicyArns": [
{
"Ref": managedPolicyId
}
],
"RoleName": "my-role"
}));
通过这种方式,您可以测试您的策略是否包含所有必要的数据以及角色和策略之间的关系是否正确。
您可以访问完整的工作示例here。