エンジニア

2021.08.31

AWS WAF v2 ManagedRulesの個別設定をコード化してみた

AWS WAF v2 ManagedRulesの個別設定をコード化してみた

初めまして。2020年にラボに入社したモチです。
いくつかAWSインフラを構築させて頂いたので、AWS WAFについてブログを書いてみます。
※ 当時使用していたslsの抜粋です。

背景

アプリケーションの仕様上、AWSManagedRulesの一部ルールだけブロックさせたくない、という要件が多々あります。
AWS CloudFormation(以下CFn)で設定する例があまりなく、AWSサポートにCLIかCFnで設定できますか?と聞いてみました。”AWS::WAFv2::WEbACL”では、ExcludedRulesを使用すると指定が可能とのこと。

公式ガイドにもちゃんと書いてありました。
基本はブロックで、一部ルールだけカウントに変更することができます。

ExcludedRules
The rules whose actions are set to COUNT by the web ACL, regardless of the action that is configured in the rule. This effectively excludes the rule from acting on web requests. “

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-wafv2-webacl-managedrulegroupstatement.html#cfn-wafv2-webacl-managedrulegroupstatement-excludedrules

やりたいこと

AWSManagedRulesCommonRuleSetを基本ブロック、SizeRestrictions_BODYのみをカウントにしたい。
↓こうしたい


CloudFormationで書いてみる

ManagedRuleGroupStatementのExcludedRulesで設定します。

WAFv2RuleWithAWSManagedRules: 
  Type: AWS::WAFv2::WebACL 
  Properties:
    Name: WAFv2_WebACL 
    Scope: REGIONAL 
    Description: This is a WAFv2 WebACL 
    DefaultAction: 
      Allow: {} 
    VisibilityConfig: 
      CloudWatchMetricsEnabled: true 
      SampledRequestsEnabled: true 
      MetricName: WAFv2_WebACLMetric

    Rules:
      - Name: AWS-AWSManagedRulesCommonRuleSet 
        Priority: 0 
        Statement: 
          ManagedRuleGroupStatement: 
            VendorName: AWS 
            Name: AWSManagedRulesCommonRuleSet 
            ExcludedRules:
              - SizeRestrictions_BODY 
        OverrideAction: 
          None: {}
        VisibilityConfig: 
          CloudWatchMetricsEnabled: true 
          SampledRequestsEnabled: true 
          MetricName: AWSManagedRulesCommonRuleSet

簡単にできちゃいました!

ついでにScopeDownStatementも試してみる①

特定のパス(以下の例は/admin)を許可する場合
※ ②では複数パスの指定方法をご紹介します

WAFv2RuleWithAWSManagedRules: 
  Type: AWS::WAFv2::WebACL 
  Properties:
    Name: WAFv2_WebACL 
    Scope: REGIONAL 
    Description: This is a WAFv2 WebACL 
    DefaultAction: 
      Allow: {} 
    VisibilityConfig: 
      CloudWatchMetricsEnabled: true 
      SampledRequestsEnabled: true 
      MetricName: WAFv2_WebACLMetric

    Rules:
      - Name: AWS-AWSManagedRulesCommonRuleSet 
        Priority: 0 
        Statement: 
          ManagedRuleGroupStatement: 
            VendorName: AWS 
            Name: AWSManagedRulesCommonRuleSet 
            ExcludedRules:
              - SizeRestrictions_BODY 
            ScopeDownStatement:
              NotStatement:
                Statement:
                  ByteMatchStatement:
                    FieldToMatch:
                      UriPath: {}
                    PositionalConstraint: STARTS_WITH
                    SearchString: "/admin/"
                    TextTransformations:
                      - Priority: 0
                        Type: NONE
        OverrideAction: 
          None: {}
        VisibilityConfig: 
          CloudWatchMetricsEnabled: true 
          SampledRequestsEnabled: true 
          MetricName: AWSManagedRulesCommonRuleSet

これもできました!
※ この設定はルールの編集画面でしか見れないようです

ついでにScopeDownStatementも試してみる②

上記設定後に、許可したいパスが増えました。
、、が、上記画面の通り、①の設定方法だとパスを1つしか指定できません。困った。
そこでまたAWSサポートに問い合わせてみたところ、ラベルを使用すれば実現できるとのこと。

さすがAWSさん、拡張性を考えてくれていました。
タグではなくラベルなんですね。

/admin及び/testを許可する場合、

  • /adminをカウントするRuleを作成、ラベルを付与
  • /testをカウントするRuleを作成、adminと同じラベルを付与
  • AWSManagedRulesCommonRuleSetでこのラベルを許可するよう設定
WAFv2RuleWithAWSManagedRules: 
  Type: AWS::WAFv2::WebACL 
  Properties:
    Name: WAFv2_WebACL 
    Scope: REGIONAL 
    Description: This is a WAFv2 WebACL 
    DefaultAction: 
      Allow: {} 
    VisibilityConfig: 
      CloudWatchMetricsEnabled: true 
      SampledRequestsEnabled: true 
      MetricName: WAFv2_WebACLMetric

    Rules:

      # /admin/配下を対象外とする
      - Name: admin-Exclusion
          Priority: 0
          Statement:
            NotStatement:
              Statement:
                ByteMatchStatement:
                  FieldToMatch:
                    UriPath: {}
                  PositionalConstraint: STARTS_WITH
                  SearchString: "/admin/"
                  TextTransformations:
                    - Priority: 0
                      Type: NONE
          Action:
            Count: {}
          VisibilityConfig:
            CloudWatchMetricsEnabled: false
            SampledRequestsEnabled: false
            MetricName: adminExclusion
          RuleLabels:
            - Name: Exclusion

      # /test/配下を対象外とする
        - Name: compound-Exclusion
          Priority: 1
          Statement:
            NotStatement:
              Statement:
                ByteMatchStatement:
                  FieldToMatch:
                    UriPath: {}
                  PositionalConstraint: STARTS_WITH
                  SearchString: "/test/"
                  TextTransformations:
                    - Priority: 0
                      Type: NONE
          Action:
            Count: {} 
          VisibilityConfig:
            CloudWatchMetricsEnabled: false
            SampledRequestsEnabled: false
            MetricName: compoundExclusion
          RuleLabels:
            - Name: Exclusion

      # AWSManagedRulesCommonRuleSet
         - Name: AWS-AWSManagedRulesCommonRuleSet
          Priority: 100
          Statement:
            ManagedRuleGroupStatement:
              VendorName: AWS
              Name: AWSManagedRulesCommonRuleSet
              ExcludedRules: 
                - SizeRestrictions_BODY
              ScopeDownStatement:
                NotStatement:
                  Statement:
                    LabelMatchStatement:
                      Scope: LABEL
                      Key: Exclusion
          OverrideAction:
            None: {}
          VisibilityConfig:
            CloudWatchMetricsEnabled: false
            SampledRequestsEnabled: true
            MetricName: AWSManagedRulesCommonRuleSet

これもできました!

同じことで悩んでいる方のお力になれますように!

一覧に戻る