4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【AWS CDK】CDKメリット IAM Grant Methodが熱い

Last updated at Posted at 2023-12-22

はじめに

AWS CDKにおいて個人的に「これいいよね」、「これ便利だよね」ってものをご紹介できればと思います。
「あ、これ使ってみたいかも」とか思われたらAWS CDKのご利用をご検討頂ければと思います。
今回は「IAM Grant Method」です。
※ 本ブログに記載した内容は個人の見解であり、所属する会社、組織とは全く関係ありません。

IAM Grant Methodとは

CDKで用意しているシナリオに沿って、対象のRoleに簡単にPolicyを投入出来ます。
ようは、このリソースをこんな感じで触りたいというシナリオに沿ったPolicyを自動生成し、Roleにアタッチするためのものになります。
言葉だけだと分かり辛いので、ユースケースに沿ってご紹介させて頂きます。

ユースケース

ユースケースイメージ

image.png

上記イメージのように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

usecase-stack.template.json
  "mainSQS": {
   "Type": "AWS::SQS::Queue",
   "Properties": {
    "QueueName": "MainSQS"
   },
  }

WebFargateからSQSにメッセージSend(Producer)の場合

usecase-stack.template.json
  "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)の場合

usecase-stack.template.json
  "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

usecase-role.ts
    const mainQueue = new sqs.Queue(this, 'SQS', {
      queueName: "MainSQS",
      encryption: sqs.QueueEncryption.KMS,
      encryptionMasterKey: key
    });

WebFargateからSQSにメッセージSend(Producer)の場合

usecase-role.ts
    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)の場合

usecase-role.ts
    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コードで書くことが多いと思います。
image.png

Stackコードイメージ

usecase-connections-stack.ts
~~~~
   // 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の上書

※ 本ブログに記載した内容は個人の見解であり、所属する会社、組織とは全く関係ありません。

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?