概要
IAMユーザを使用できるプリンシパルをIPやソースのVPCエンドポイントで絞りたいです。
※プリンシパル:AWSのリソースに対してアクションやオペレーションを実行できる人、もしくはアプリケーションのこと
要件を満たすIAM ポリシーを作成する
やりたいこと:プログラム経由(CLI、SDK等)のIAMを使うプリンシパルが以下の場合はアクセスを許可したい
- アカウントAのVPCエンドポイントを経由している
- 特定のパブリックIP
- AWSのサービス
つまり1 or 2 or 3であればIAMが使えます。
ソースIPを絞りたい場合、こちらの公式ドキュメントを参考にIAMポリシーを作成しました。
また、経由するVPCエンドポイントを絞るのは「StringNotEquals」と「aws:SourceVpce」の組み合わせを使いました。
以下が完成したIAMポリシーです。
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Deny",
"Action": "*",
"Resource": "*",
"Condition": {
"StringNotEquals": {
"aws:SourceVpce": [
"<アカウントAのVPCエンドポイント>"
]
},
"NotIpAddress": {
"aws:SourceIp": [
"<アカウントAのEC2のパブリックIP>"
]
},
"Bool": {
"aws:ViaAWSService": "false"
}
}
}
}
これは以下の3つのAND条件となります。
- アカウントAのVPCエンドポイントを経由していない
- 特定のパブリックIPではない
- AWSのサービスではない
なぜこんなややこしい書き方をするかというと、
IAMポリシーのConditionに対する評価ロジックはAND条件となるためです。
つまり、この章の初めに記載したOR条件ではポリシーを記述することができず、中学生・高校生の時にやった集合でいうところの対偶(正反対)の条件に書き換える必要がありました。
検証
念のため、以下の条件で動作検証をしてみました。
- Account Aのプライベートサブネット上に存在するEC2へuser Aのクレデンシャルを登録してAccount BのS3へアクセスできる(図のオレンジの経路)
- Account Aのパブリックサブネット上に存在するEC2へuser Aのクレデンシャルを登録してAccount BのS3へアクセスできる(図の水色の経路)
以下コマンドでアカウントBのバケットへアクセスすることができました。
aws s3 ls s3://バケット名
また、逆にIAMポリシーのConditionに記述しているIPやVPCエンドポイントのIDを存在しないものに書き換えた場合、アクセスができなくなりました。
おわりに
IAMポリシーのCondition句「StringNotEquals」や「NotIpAddress」といったNotのDenyは分かりづらいですが、整理して考えることができれば大変柔軟が効くポリシーを書くことができます。
機会があれば使ってみてください!