IAM ポリシーで特定条件のアクセス制限をかけつつ、AWS サービスのアクセスは許可したいときの対処方法

2021.06.04

困っていた内容

IAM ポリシーの条件で "aws:SourceIp" を指定し、IP 制限をかけました。その後、CloudFormation など AWS サービスがユーザーに代わって AWS 環境を操作するサービスで、IP 制限によるエラーが出ました。

アクセス元(ソース)IP の制限は残しつつ、AWS サービスが AWS リソースへアクセスすることを許可するには、どう対応すればいいでしょうか?

どう対応すればいいの?

IAM ポリシーで "aws:SrouceIp" を指定する "Condition" ブロック内に、以下のポリシーを追加することで、サービス利用者のアクセスは特定の IP アドレスでアクセス制限をかけつつ、AWS サービスのアクセスは許可することができます。

{
    "Bool": {"aws:ViaAWSService": "false"}
}

"aws:ViaAWSService" は AWS サービスがユーザーに代わってリクエストを実行したかどうかを判定する条件キーです。CloudFormation などの AWS サービスがアクセスした際は、値が "true" になります。

この条件キーは以下のように使用します。

{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Deny",
        "Action": "*",
        "Resource": "*",
        "Condition": {
            "NotIpAddress": {
                "aws:SourceIp": [
                    "192.0.2.0/24",
                    "203.0.113.0/24"
                ]
            },
            "Bool": {"aws:ViaAWSService": "false"}
        }
    }
}

AWS: 送信元 IP に基づいて AWS へのアクセスを拒否する - AWS Identity and Access Managementより

ポリシーの読み解き方

上記のポリシーを見てややこしいと思われる方がきっといるはず(わからなくて普通)ですので、簡単に Condition ブロックの判定方法を補足します。

"Condition": {
    "NotIpAddress": {
        "aws:SourceIp": [
            "192.0.2.0/24",
            "203.0.113.0/24"
        ]
    },
    "Bool": {"aws:ViaAWSService": "false"}
}

まず、上記の "Condition" ブロック内は AND 判定、"aws:SourceIp" ブロック内は OR 判定です。

CloudFormation などの AWS サービスがユーザーに代わってリクエストを実行した際は、"Bool": {"aws:ViaAWSService": "false"}(AWS サービスのアクセスではないこと)が必ず偽と判定されるため、上述のポリシー(アクセス元 IP アドレスの制限)は無効になります。

サービス利用者(ユーザー)がリクエストを実行した際は、"Bool": {"aws:ViaAWSService": "false"} が必ず真と判定されるため、AND 条件のアクセス元 IP アドレスの判定によって結果が決まります。

if True && <アクセス元 IP がリストに含まれるか> のような条件式を想像してみるとわかりやすいかもしれないです。

参考資料

このキーを使用して、AWS サービスがユーザーに代わって別のサービスにリクエストを実行するかどうか確認します。

サービスが IAM プリンシパルの認証情報を使用し、プリンシパルに代わってリクエストを実行すると、リクエストコンテキストキーは true を返します。サービスがサービスロールまたはサービスリンクロールを使用してプリンシパルに代わって呼び出しを行う場合、コンテキストキーは false を返します。リクエストコンテキストキーは、プリンシパルが直接呼び出しを行ったときも false を返します。