LoginSignup
3
0

API Gateway(HTTP API) で IP アドレス制限する

Last updated at Posted at 2023-12-20

HTTP API ではリソースポリシーが使えない

REST API で IP アドレス制限するには、通常、リソースポリシーを使います。
https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/apigateway-resource-policies-examples.html#apigateway-resource-policies-source-ip-address-example

でも、後発の HTTP API では、リソースポリシーが未実装です。
AWS WAF も未対応なので、そっちで IP アドレス制限することもできません。

Lambda Authorizer でできる

昔、REST API にリソースポリシーがなかった頃、IP アドレスで制限するには、Lambda Authorizer を利用していました。
その方法を試してみたところ、HTTP API でも利用できました。

  1. HTTP API の Lambda Authorizer のレスポンスモードを IAM ポリシーにする
    スクリーンショット 2023-12-14 17.13.00.png
  2. Lambda Authorizer が返す IAM ポリシーの Condition に IpAddressaws:SourceIp を追加する
exports.handler = async function (event, context) {
    const response = {
        principalId: "hoge",
        policyDocument: {
            Version: "2012-10-17",
            Statement: [
                {
                    Effect: "Allow",
                    Action: "execute-api:Invoke",
                    Resource: event.routeArn,
                    Condition: {
                        IpAddress: {
                             "aws:SourceIp": ["192.168.0.1/32"]
                        }
                    }
                }
            ]
        }
    }
    return response;
};

この例では、192.168.0.1 からのリクエストのみ許可されます。

制限したい IP アドレスが 1 つだけなら、Lambda Authorizer のロジックで判定してもあまり変わらないですが、IP アドレスが複数だったり、CIDR のホスト部が 32 より小さい場合、ロジックがややこしくなります。

その点、この方法だと AWS 側が判定してくれるので楽です。

他の条件も試してみる

これができるなら、他の 条件キー も使えるのではと、やってみました。

aws:CurrentTime

exports.handler = async function (event, context) {
    const response = {
        principalId: "hoge",
        policyDocument: {
            Version: "2012-10-17",
            Statement: [
                {
                    Effect: "Allow",
                    Action: "execute-api:Invoke",
                    Resource: event.routeArn,
                    Condition: {
                        DateGreaterThan: {
                            "aws:CurrentTime": "2023-12-05T18:10:00+09:00"
                        }
                    }
                }
            ]
        }
    }
    return response;
};

2023/12/05 18:10 より前では Forbidden でしたが、その日時を過ぎるとアクセスできました。
2023/12/25T00:00:00+09:00 に設定して、日本時間でクリスマスになったら公開するとか使い所がありそう。

逆に DateLessThan を使うと、その日時まで公開することもできますね。
期間限定のサイトとかに使えそう。

aws:Referer

exports.handler = async function (event, context) {
    const response = {
        principalId: "hoge",
        policyDocument: {
            Version: "2012-10-17",
            Statement: [
                {
                    Effect: "Allow",
                    Action: "execute-api:Invoke",
                    Resource: event.routeArn,
                    Condition: {
                        StringLike: {
                            "aws:Referer": ["http://example.com/*"]
                        }
                    }
                }
            ]
        }
    }
    return response;
};

エラーは起きないですが、無視されるようで、使えず。

一方で、Rest API のリソースポリシーでは使えました。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
                "execute-api:/*"
            ],
            "Condition": {
                "StringLike": {
                   "aws:Referer": ["http://example.com/*"]
                }
            }
        }
    ]
}

aws:UserAgent

exports.handler = async function (event, context) {
    const response = {
        principalId: "hoge",
        policyDocument: {
            Version: "2012-10-17",
            Statement: [
                {
                    Effect: "Allow",
                    Action: "execute-api:Invoke",
                    Resource: event.routeArn,
                    Condition: {
                        StringLike: {
                            "aws:UserAgent": ["Mozilla/*"]
                        }
                    }
                }
            ]
        }
    }
    return response;
};

こっちもダメ。
でも Rest API のリソースポリシーは OK。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
                "execute-api:/*"
            ],
            "Condition": {
                "StringLike": {
                   "aws:UserAgent": ["Mozilla/*"]
                }
            }
        }
    ]
}

まとめ

AWS のグローバル条件キーはたくさんありますが、HTTP API では IP アドレス制限と期間限定以外に使えそうなものはあまりなさそうでした。残念。

結局何が言いたいかというと、HTTP API でもリソースポリシーと WAF を早く実装してください 🙏 > AWS

3
0
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
3
0