はじめに
AWS CDKにおいて個人的に「これいいよね」、「これ便利だよね」ってものをご紹介できればと思います。
「あ、これ使ってみたいかも」とか思われたらAWS CDKのご利用をご検討頂ければと思います。
今回は「IAM Grant Method」です。
※ 本ブログに記載した内容は個人の見解であり、所属する会社、組織とは全く関係ありません。
IAM Grant Methodとは
CDKで用意しているシナリオに沿って、対象のRoleに簡単にPolicyを投入出来ます。
ようは、このリソースをこんな感じで触りたいというシナリオに沿ったPolicyを自動生成し、Roleにアタッチするためのものになります。
言葉だけだと分かり辛いので、ユースケースに沿ってご紹介させて頂きます。
ユースケース
ユースケースイメージ
上記イメージのようにWebFargateからMainSQSにメッセージSend(Producer)、BatchFargateはMainSQSからReceive(Consumer)としたい場合の構成を例にとります。
PolicyとRoleを整理すると以下のようになります。
Policy
Policy名 | 許可するAction | Resource |
---|---|---|
WebFargate-Policy | sqs:SendMessage, sqs:GetQueueAttributes, sqs:GetQueueUrl | MainSQS |
BatchFargate-Policy | sqs:ChangeMessageVisibility, sqs:DeleteMessage, sqs:ReceiveMessage, sqs:GetQueueAttributes, sqs:GetQueueUrl | MainSQS |
Role
Role名 | アタッチするリソース | アタッチするPolicy |
---|---|---|
WebFargate-Role | WebFargate | WebFargate-Policy |
BatchFargate-Role | BatchFargate | BatchFargate-Policy |
どのようなDeploy手段であれPolicyを検討するために処理の流れを意識して、上記のような情報整理をされると思います。
ユースケースに対してCloudFormationでの実装イメージ
MainSQS
"mainSQS": {
"Type": "AWS::SQS::Queue",
"Properties": {
"QueueName": "MainSQS"
},
}
WebFargateからSQSにメッセージSend(Producer)の場合
"webFargateRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "ecs-tasks.amazonaws.com"
}
}
],
"Version": "2012-10-17"
},
"RoleName": "WebFargateRole"
}
},
"webFargateRoleDefaultPolicy": {
"Type": "AWS::IAM::Policy",
"Properties": {
"PolicyDocument": {
"Statement": [
{
"Action": [
"sqs:GetQueueAttributes",
"sqs:GetQueueUrl",
"sqs:SendMessage"
],
"Effect": "Allow",
"Resource": {
"Fn::GetAtt": [
"mainSQS",
"Arn"
]
}
}
],
"Version": "2012-10-17"
},
"PolicyName": "webFargateRoleDefaultPolicy",
"Roles": [
{
"Ref": "webFargateRole"
}
]
}
},
BatchFargateはSQSからReceive(Consumer)の場合
"batchFargateRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "ecs-tasks.amazonaws.com"
}
}
],
"Version": "2012-10-17"
},
"RoleName": "BatchFargateRole"
}
},
"batchFargateRoleDefaultPolicy": {
"Type": "AWS::IAM::Policy",
"Properties": {
"PolicyDocument": {
"Statement": [
{
"Action": [
"sqs:ChangeMessageVisibility",
"sqs:DeleteMessage",
"sqs:GetQueueAttributes",
"sqs:GetQueueUrl",
"sqs:ReceiveMessage"
],
"Effect": "Allow",
"Resource": {
"Fn::GetAtt": [
"mainSQS",
"Arn"
]
}
}
],
"Version": "2012-10-17"
},
"PolicyName": "batchFargateRoleDefaultPolicy",
"Roles": [
{
"Ref": "batchFargateRole"
}
]
}
},
上記イメージのようになかなか、書く量が多いですね。めんどくさいですね。
これに対して、「IAM Grant Method」を使うとすごくシンプルかつサクッと書けてしまいます。
ユースケースに対してAWS CDKでの実装イメージ
「IAM Grant Method」には様々なシナリオが用意されています。
選んだシナリオに沿って、Policyが構成され、対象にアタッチされます。
MainSQS
const mainQueue = new sqs.Queue(this, 'SQS', {
queueName: "MainSQS",
encryption: sqs.QueueEncryption.KMS,
encryptionMasterKey: key
});
WebFargateからSQSにメッセージSend(Producer)の場合
const webFargateRole = new iam.Role(this, `webFargateRole`, { // Role生成
assumedBy: new iam.ServicePrincipal(`ecs-tasks.amazonaws.com`),
roleName: "WebFargateRole"
})
mainQueue.grantSendMessages(webFargateRole); // Grant Method
上段でWebFargate用のRoleを生成しています。
そのうえで、WebFargateはMainSQSに対してMesseageをSendするので、SQSが持つ「grantSendMessages Method」を利用しています。
MainSQSの「grantSendMessages Method」を利用することにより、MainSQSに対する以下Actionを許可する設定が自動で、WebFargate用のRoleのDefalutPolicyに与えられます。
- sqs:GetQueueAttributes
- sqs:GetQueueUrl
- sqs:SendMessage
ようは、上段のCloudFormationと同レベルのDefalutPolicyが生成され、Roleにアタッチされます。
BatchFargateはSQSからReceive(Consumer)の場合
const batchFargateRole = new iam.Role(this, `batchFargateRole`, { // Role生成
assumedBy: new iam.ServicePrincipal(`ecs-tasks.amazonaws.com`),
roleName: "BatchFargateRole"
})
mainQueue.grantConsumeMessages(batchFargateRole); // Grant Method
上段でBatchargate用のRoleを生成しています。
そのうえで、BatchFargateはMainSQSに対して、MessageをReceiveするので、SQSが持つ[grantConsumeMessages Method」を利用しています。
MainSQSの「grantConsumeMessages Method」を利用することにより、MainSQSに対する以下Actionを許可する設定が自動で、BatchFargate用のRolのDefalutPolicyに与えられます。
- sqs:ChangeMessageVisibility
- sqs:DeleteMessage
- sqs:GetQueueAttributes
- sqs:GetQueueUrl
- sqs:ReceiveMessage
ようは、上段のCloudFormationと同レベルのDefalutPolicyが生成され、Roleにアタッチされます。
利用する際のポイント
AWS CDKのAPPを書く時は、基本的にベストプラクティスに従って使い勝手を考慮し、Constructsコードに分割し、Stackコードでつなげていく構成を取ると思います。
今回のユースケースイメージでは、「MainSQS」、「WebFargate関連リソース」、「BatchFargate関連リソース」全て同一Constructsコードで書いてしまっていますが、実際は以下のように別Constructsコードで書くことが多いと思います。
Stackコードイメージ
~~略~~
// NW Constructsコードのリソース生成
const nw = new nw(this, "usercase-nw", {
});
// MainSQS Constructsコードのリソース生成
const sqs = new sqs(this, "usecase-sqs", {
});
// WebFargate Constructsコードのリソース生成
const webfargate = new webfargate(this, "usecase-webfargate", {
vpc: nw.vpc,
mainsqs: sqs.mainsqs,
});
// BatchFargate Constructsコードのリソース生成
const batchfargate = new batchfargate(this, "usecase-batchfargate", {
vpc: nw.vpc,
mainsqs: sqs.mainsqs,
});
上記Stackコードイメージの場合、MainSQSが先に生成され、その後「WebFargate関連リソース」、「BatchFargate関連リソース」(「それぞれのFargateにアタッチされるIAM Role(TaskRole)を含む)が生成されます。
IAM Grant Methodを利用する場合、シナリオに沿った権限を与えたいリソースとRoleそれぞれが必要になります。
よって、今回の場合「MainSQS」のあとに生成されるConstructsでないと IAM Grant Methodは利用できません。
このようにStackコードで生成される後段で書く必要があり、Constructsコード分割、Stackコード構成検討の際に意識しておく必要があります。
また、複数人で1APPを書くときは、「基本的にRoleを生成する側でIAM Grant Methodを書く」等決めておくとスムーズに進みます。
まとめ
以上より、IAM Grant Metodを用いることにより、シナリオに沿ったPolicy設定が簡単にできることをご紹介させて頂きました。
付随するメリットですが、このリソースはどのリソースに対してどんなことするの?ということさえ整理しておけばいいので、概要設計的なイメージだけで十分です。
つまり、ユースケースイメージのようなイメージが処理フロー毎にあるだけで使えます。
検討のためのPolicyやRoleの整理は必要ありません。
正直これだけで嬉しいですよね。
ご興味を持って頂けたらAWS CDKでDeployを試してみてください。
しかし、CDKが用意したシナリオに沿っている必要があります。つまり、「シナリオで定義されている許可Actionでは足りない」、「余計なActionは許可したくない」というケースではちょっと使いづらいです。
そういった課題に対応するためにシナリオが定義されていない「grant Method」が用意されています。
このMethodでは、許可するActionをこのMethodに渡すとそのActionを許可する形でPolicyが生成されます。
また、お遊びで、エスケープハッチを活用すれば、若干力技ですが、対応可能です。
その力技に関しては以下別記事でご紹介しておりますので、ご興味あれば、合わせてご参照ください。
【AWS CDK】エスケープハッチ IAM Policyの上書
※ 本ブログに記載した内容は個人の見解であり、所属する会社、組織とは全く関係ありません。