こんにちは、Mashです。
今回は AWS IAM(Identity and Access Management)についての記事になります。
私の本業にて新規取り扱い商材のプロジェクトが発足しまして、その技術検証基盤はAWS EC2を利用することになりました。
後述しますが、検証の下準備としてある程度権限を絞ったIAMユーザを新規作成する必要がありましたので、その際のあれこれをブログに残しておきたいと思い、本記事執筆に至ります。
- AWS IAMを避けてきて「さっぱりわからん。。けどちょっと勉強しておきたい」なひと
- ざっくりIAMポリシーの書き方を理解したいひと
- 権限を絞ったEC2アクセス許可(できるIAMユーザ作成)を実現したいひと
前提
まずは状況のご説明から。
背景
もともと私が本籍を置く所属チームではAWSをガッツリ利用していました。また(良し悪しは置いておいて)、AWSを比較的自由に利用できる権限も与えられている状況です。
今回いろいろワケあって、冒頭触れた新規商材プロジェクトは、わたしたちが利用しているAWSアカウントの範囲内で技術検証を行うことになりました。
ここで問題になるのがAWSのアクセス権限です。
新規プロジェクトの参画メンバーは全く別のチームの方も多く、セキュリティ面やコスト管理、操作ミス等の観点で、既存利用者と同等の権限を与えるわけにはいきません。
イメージとしては↓このような感じ。赤枠で囲まれたユーザには限定した権限でAWSを利用してもらうことが今回のゴールです。

要件整理
このような背景の中、新たに 権限を絞ったIAMユーザ を作成する必要が発生したのでまずは要件を整理してみました。
そして、要件を実現できたかどうか結論も先に記載しておきます。
要件 | 実現可否 |
---|---|
Prjメンバーは多数いるため、ポリシー管理は極力ラクにする | ○ |
不要なサービスは利用不可とする(今回はEC2周辺のみでOK) | ○ |
EC2インスタンス作成時に特定タグの付与を強制する | ○ |
操作ミスを防止するために、プロジェクトに関連するリソースのみ AWSコンソールには表示し、既存EC2リソースは表示しない | × |
操作ミスを防止するために、既存EC2リソースへの操作は禁止とする | ○ |
利用者自身にIAMユーザのパスワードを管理させる | ○ |
5勝1敗となりました。
いざ、IAMで実装
それでは前述要件に対してどのような実装をしたか、ご説明していきます。
Prjメンバーは多数いるため、ポリシー管理は極力ラクにする
今回プロジェクトメンバーは多数いましたので、追跡性向上のため個々にIAMユーザを作成しました。
こうなると問題になるのが、IAMポリシーの管理です。
今後プロジェクトを進める中で必ずIAMの権限(IAMポリシー)をチューニングする必要が発生します。
各IAMユーザ毎にポリシーを修正していたら、それだけで日が暮れてしまいます。
そんなときは IAMグループ を利用します。
IAMグループはその名の通り、IAMユーザをグループ管理する機能です。
IAMグループに対してIAMポリシーをアタッチできるので、ポリシーチューニングが一箇所で完結します。

不要なサービスは利用不可とする(今回はEC2周辺のみでOK)
さて、ここから本題のIAMポリシーの作り込みに入ります。
まず前提として抑えておく必要があるのは、IAMのポリシー判定においては「暗黙的なDeny」が存在する点です。
つまりデフォルト状態(明示的な「許可」が与えられていない状態)ではなにも行うことができません。
セキュリティに関する機能では一般的な考え方ですね。
上記前提を踏まえると、今回の要件「不要なサービスは利用不可とする(今回はEC2周辺のみでOK)」は、いいかえると「EC2周辺へのアクセスを許可する」ことになります。
それではポリシーを作成してみましょう。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowFullAccessEC2", "Effect": "Allow", "Action": "ec2:*", "Resource": "*" } ] }
上記でEC2に対するフルアクセスを許可しています。
EC2インスタンス作成時に特定タグの付与を強制する
つづいてAWS管理コンソール上で検索しやすくしたりコスト管理をしやすくするために、EC2インスタンスへのタグづけを強制したいと考えました。
現時点では条件無くEC2に対する操作が許可されていますので、「タグ指定が無いEC2インスタンス作成はDeny」というポリシーを追加します。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowFullAccessEC2", "Effect": "Allow", "Action": "ec2:*", "Resource": "*" }, { "Sid": "DenyCreateEC2WithoutProjectTag", "Effect": "Deny", "Action": "ec2:RunInstances", "Resource": "arn:aws:ec2:*:*:instance/*", "Condition": { "StringNotLike": { "aws:RequestTag/Project": "AAA" } } }, { "Sid": "DenyCreateEC2WithoutNameTag", "Effect": "Deny", "Action": "ec2:RunInstances", "Resource": "arn:aws:ec2:*:*:instance/*", "Condition": { "StringNotLike": { "aws:RequestTag/Name": "*" } } } ] }
2つポリシーが追加されています。
“ec2:RunInstances” がEC2作成アクションを意味していて、それぞれConditionセクションで
- タグ名 Project、値 AAA が付与されていなければDeny
- タグ名 Name、値は任意 が付与されていなければDeny
としています。
この2つのポリシーはAND条件ですので、どちらか一方でも条件を満たしていない場合はEC2作成がエラーになります。
※二重否定になっているのであまりスマートではないかも。。
操作ミスを防止するために、既存EC2リソースへの操作は禁止とする
当プロジェクトメンバーが操作を誤って関係のないEC2インスタンスを削除したり停止したりしないように制限を加えたいと思います。
前項でプロジェクトメンバーが作成するEC2に対して Project / AAA タグの付与を強制できましたので、これを使いましょう。
つまり「タグProject/AAAが付与されていないEC2インスタンスの操作はDeny」ですね。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowFullAccessEC2", "Effect": "Allow", "Action": "ec2:*", "Resource": "*" }, { "Sid": "DenyCreateEC2WithoutProjectTag", "Effect": "Deny", "Action": "ec2:RunInstances", "Resource": "arn:aws:ec2:*:*:instance/*", "Condition": { "StringNotLike": { "aws:RequestTag/Project": "AAA" } } }, { "Sid": "DenyCreateEC2WithoutNameTag", "Effect": "Deny", "Action": "ec2:RunInstances", "Resource": "arn:aws:ec2:*:*:instance/*", "Condition": { "StringNotLike": { "aws:RequestTag/Name": "*" } } }, { "Sid": "DenyOpeEC2WithoutProjectTag", "Effect": "Deny", "Action": [ "ec2:Terminate*", "ec2:Start*", "ec2:Reboot*", "ec2:Delete*", "ec2:Stop*" ], "Resource": "*", "Condition": { "StringNotEquals": { "ec2:ResourceTag/Project": "AAA" } } } ] }
Project / AAA タグがついていないリソースに関して、Terminate(削除)、Start(起動)、Reboot(再起動)、Stop(停止)、Delete(セキュリティグループなどの削除)を禁止しています。
利用者自身にIAMユーザのパスワードを管理させる
最後に、IAMユーザ作成時に「次回のサインインで新しいパスワードを作成する必要があります」というフラグがあります。
プロジェクトメンバーへIAMユーザを配布後、パスワード管理は彼らに委ねたいためこのフラグをONにしたいのですが、これまで記載したポリシーだと権限が不足しているようで、下記のようにIAMへの権限を追加しました。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowFullAccessEC2", "Effect": "Allow", "Action": "ec2:*", "Resource": "*" }, { "Sid": "DenyCreateEC2WithoutProjectTag", "Effect": "Deny", "Action": "ec2:RunInstances", "Resource": "arn:aws:ec2:*:*:instance/*", "Condition": { "StringNotLike": { "aws:RequestTag/Project": "AAA" } } }, { "Sid": "DenyCreateEC2WithoutNameTag", "Effect": "Deny", "Action": "ec2:RunInstances", "Resource": "arn:aws:ec2:*:*:instance/*", "Condition": { "StringNotLike": { "aws:RequestTag/Name": "*" } } }, { "Sid": "DenyOpeEC2WithoutProjectTag", "Effect": "Deny", "Action": [ "ec2:Terminate*", "ec2:Start*", "ec2:Reboot*", "ec2:Delete*", "ec2:Stop*" ], "Resource": "*", "Condition": { "StringNotEquals": { "ec2:ResourceTag/Project": "AAA" } } }, { "Sid": "AllowChangeOwnPassword", "Effect": "Allow", "Action": [ "iam:ChangePassword" ], "Resource": [ "arn:aws:iam::*:user/${aws:username}" ] }, { "Sid": "AllowGetAccountPasswordPolicy", "Effect": "Allow", "Action": [ "iam:GetAccountPasswordPolicy" ], "Resource": "*" } ] }
自分自身(${aws:username})のパスワード変更とパスワードポリシーの参照がAllowになっています。
まとめ
以上、やりたいことは90点で実現できました。
冒頭記載の通り、ほんとうはプロジェクトに関連したリソースのみAWSコンソール上に表示されるようにしたかったのですが、いまのところ実現できていません。
また、作成したIAMポリシーが2重否定が繰り返される書き方になっており、ちょっと直感的ではないなーと、課題ありです。
もし今後ブラッシュアップできたらアップデート版を公開させていただきます。
今回は以上です。
それじゃあまたね。