0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【AWS】WAFを使って特定のエンドポイントにのみIP制限をかける方法

0
Posted at

概要

AWS WAFを使って、特定のエンドポイントにのみIP制限をかける方法を紹介します。

  • Lambda関数が複数のエンドポイント(例:/hoge/foo)を持っている
  • /hoge にはIP制限をかけたい(特定IPからのみアクセス可能)
  • /foo は全てのIPからアクセス可能にしたい

色々と試行錯誤しましたが、
結論、WAFのルールで正規表現パターンとIPセットを組み合わせることで実現できます。

設計方針

WAFのルール評価順序を活用します。

優先度 ルール名 条件 アクション
1 allow-api-for-ipset /hoge パス かつ 許可IPリスト Allow
2 allow-api-for-all-ips /foo パス Allow
- DefaultAction 上記に該当しない全て Block

サンプルコード(Cloudformation)

 Resources:
  ######
  # ApiGateway作成などは省略
  ######

  # /hoge パスにマッチする正規表現パターン
 HogeApiPathRegexPatternSet:
    Type: AWS::WAFv2::RegexPatternSet
    Properties:
      Name: !Sub "${Env}-HogeApiPathPattern"
      Scope: REGIONAL
      RegularExpressionList:
        - "^/(?:[^/]+/)?hoge(/.*)?$"

  # /foo パスにマッチする正規表現パターン
 FooApiPathRegexPatternSet:
    Type: AWS::WAFv2::RegexPatternSet
    Properties:
      Name: !Sub "${Env}-FooApiPathPattern"
      Scope: REGIONAL
      RegularExpressionList:
        - "^/(?:[^/]+/)?foo(/.*)?$"

  # WebACL本体
 ApiGatewayWebACL:
    Type: AWS::WAFv2::WebACL
    Properties:
      Name: !Sub "${Env}-WebACL"
      Scope: REGIONAL
      DefaultAction:
        Block: {}
      VisibilityConfig:
        SampledRequestsEnabled: true
        CloudWatchMetricsEnabled: true
        MetricName: !Sub "${Env}-WebACL"
      Rules:
        - Name: "allow-api-for-ipset"
          Priority: 1
          Action:
            Allow: {}
          Statement:
            AndStatement:
              Statements:
                - IPSetReferenceStatement:
                    Arn: !GetAtt AllowedIPSet.Arn
                - RegexPatternSetReferenceStatement:
                    Arn: !GetAtt HogeApiPathRegexPatternSet.Arn
                    FieldToMatch:
                      UriPath: {}
                    TextTransformations:
                      - Priority: 0
                        Type: NONE
          VisibilityConfig:
            SampledRequestsEnabled: true
            CloudWatchMetricsEnabled: true
            MetricName: "allow-api-for-ipset"
        - Name: "allow-api-for-all-ips"
          Priority: 2
          Action:
            Allow: {}
          Statement:
            RegexPatternSetReferenceStatement:
              Arn: !GetAtt FooApiPathRegexPatternSet.Arn
              FieldToMatch:
                UriPath: {}
              TextTransformations:
                - Priority: 0
                  Type: NONE
          VisibilityConfig:
            SampledRequestsEnabled: true
            CloudWatchMetricsEnabled: true
            MetricName: "allow-api-for-all-ips"

  # 許可IPリスト 
  AllowedIPSet:
    Type: AWS::WAFv2::IPSet
    Properties:
      Name: !Sub "${Env}-AllowedIPSet"
      Scope: REGIONAL
      IPAddressVersion: IPV4
      Addresses: 
        - !Ref AllowedIPCIDR # Parameterで対象のIPを設定してある前提とします

  # WebACLをAPI Gatewayに関連付け
  ApiGatewayWebACLAssociation:
    Type: AWS::WAFv2::WebACLAssociation
    Properties:
      # ApiGatewayRestApiという名前でApiGatewayが作成してある前提とします
      ResourceArn: !Sub "arn:aws:apigateway:${AWS::Region}::/restapis/${ApiGatewayRestApi}/stages/${Env}"
      WebACLArn: !GetAtt ApiGatewayWebACL.Arn

これにより、以下の動作となります。

  • /hoge → AllowedIPからのみアクセス可能
  • /foo → 全てのIPからアクセス可能
  • その他のパス → 全てブロック

正規表現パターン

設定した

"^/(?:[^/]+/)?hoge(/.*)?$"

は、具体的には以下のようなパスが含まれます。

  • /hoge
  • /hoge/xxx
  • /v1/hoge
  • /v1/hoge/xxx

参考

以下のように書くとエラーになります。

  RegularExpressionList:                  
    - RegexString: "^/[^/]+/hoge(/.*)?$" 

エラーメッセージはこちら。

Model validation failed (#/RegularExpressionList/0: expected type: String, found: JSONObject)

これは、オブジェクト形式になっているからでした。
正しくは、文字列のリストとして記述すると、エラーが解消されました。

  RegularExpressionList:      
    - "^/[^/]+/hoge(/.*)?$"
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?