【アップデート】AWS WAFv2でAWSマネージドルールグループ内のルールのアクションが個別に変更できるようになりました
みなさん、こんにちは。
AWS事業本部コンサルティング部の芦沢(@ashi_ssan)です。
アップデートにより、AWS WAFv2でAWSマネージドルールグループ内のルールのアクションが個別に変更できるようになりました。
アップデートの発表がAWSのアップデートブログになっていなかったため、AWS公式ドキュメントのDocument historyから変更内容を紹介します。
※例によって日本語版のドキュメントは更新されていないので英語版のドキュメントから引用します。
・Change
Action overrides in rule groups
・Description
You can now override the actions of the rules in a rule group to any rule action setting. As with the prior Count action override, you can apply your overrides to all rules in a rule group and to individual rules.
引用:https://docs.aws.amazon.com/waf/latest/developerguide/doc-history.html
アップデート内容
これまでAWSマネージドルールグループ内のルールは、デフォルト設定であるBlock(検知したリクエストを遮断する)もしくはCount(検知しても遮断せずログにのみ記録する)のどちらかしか設定できませんでした。
今回のアップデートによって存在するすべてのルールアクション(Allow / Block / Count / CAPTCHA / Challenge
)から選択して設定することができるようになりました1。
マネジメントコンソール上からみてわかる変更点と、APIのJSONから見るとはじめてわかる変更点の2つがありますので、それぞれ紹介していきます。
マネジメントコンソールから見るアップデート
こちらがアップデート後のマネジメントコンソールです。
四角で囲っている箇所がアップデートされているところです。
以前は以下のようにトグル形式で切り替える形となっていました。
画像のようにChoose rule action override
のトグルをクリックしてルール毎に個別にアクションを設定できます。空欄の状態であればデフォルトのアクションはBlockの設定になるはずです。
Override all rule actions欄にアクションを入力すると、すべてのルールに入力したアクションが補完されます。
Remove all overridesをクリックすると、現在入力しているルールがすべて削除されます。便利ですね。
API JSONから見るアップデート
CloudFormationを使っている方ならお馴染みの記法ですが、アップデートによりExcludedRules
だったステートメントをRuleActionOverrides
に置き換えられるようになりました。
AWS公式ドキュメントから引用するとこのようになります。
以前は以下のようにExcludedRules
を使用してName欄で該当のルール名を指定することで、ルールのデフォルトのアクションであるBlockからCountへ切り替えることができました。
"ManagedRuleGroupStatement": { "VendorName": "AWS", "Name": "AWSManagedRulesAdminProtectionRuleSet", "ExcludedRules": [ { "Name": "AdminProtection_URIPATH" } ]
RuleActionOverrides
では、Nameの他にActionToUseという項目が増えアクション名を指定できるようになっています。例ではCountを指定していますがAllowやCAPTCHAなど他のアクションも指定できそうです。
"ManagedRuleGroupStatement": { "VendorName": "AWS", "Name": "AWSManagedRulesAdminProtectionRuleSet", "RuleActionOverrides": [ { "Name": "AdminProtection_URIPATH", "ActionToUse": { "Count": {} } } ]
今後はどちらを使えばいいのかについてですが、公式ドキュメントに以下とあるようにコンソール上のAPIの操作とCloudFormationでの操作に一貫性が生まれるRuleActionOverrides
を利用した方がよさそうです。既存のExcludedRules
も一応そのまま使えるようです。
We recommend that you update all of your ExcludedRules settings in your JSON listings to RuleActionOverrides settings with the action set to Count. The API accepts either setting, but you'll get consistency in your JSON listings, between your console work and your API work, if you only use the new RuleActionOverrides setting. 引用:https://docs.aws.amazon.com/waf/latest/developerguide/web-acl-rule-group-override-options.html
やってみた その1
試しに以前作成したCloudFormationテンプレートをもとにテンプレートを一部改変し、実行できるか検証してみます。
まずは基本的な記法は変更せず以下のテンプレートをそのまま実行してみました(ExcludedRules
を利用した記法)
テンプレートはこちらです(クリックで開きます)
AWSTemplateFormatVersion: '2010-09-09' Parameters: Prefix: Type: String Default: test Description: "Fill in the name of the system name." Env: Type: String Default: develop Description: "Fill in the name of the environment." Scope: Type: String Default: REGIONAL AllowedValues: - REGIONAL - CLOUDFRONT Description: "Select in the scope of waf(REGIONAL or CLOUDFRONT)" # WebAclAssociationResourceArn: # Type: String # Default: "arn:aws:elasticloadbalancing:ap-northeast-1:XXXXXXXXXXXX:loadbalancer/app/XXXXXXXXXXXX" # Description: Enter RegionalResource(ALB,APIGateway,AppSync) ARN or CloudFront ARN to associate with WEBACL. Resources: # ------------------------------------------------------------# # S3 # ------------------------------------------------------------# S3BucketForWaflog: Type: AWS::S3::Bucket Properties: BucketName: !Sub aws-waf-logs-${Env}-${Prefix}-${AWS::AccountId} AccessControl: Private PublicAccessBlockConfiguration: BlockPublicAcls: True BlockPublicPolicy: True IgnorePublicAcls: True RestrictPublicBuckets: True S3BucketForAthenaQuery: Type: AWS::S3::Bucket Properties: BucketName: !Sub athena-query-results-${Env}-${Prefix}-${AWS::AccountId} AccessControl: Private PublicAccessBlockConfiguration: BlockPublicAcls: True BlockPublicPolicy: True IgnorePublicAcls: True RestrictPublicBuckets: True # ------------------------------------------------------------# # WAF v2 # ------------------------------------------------------------# WebAcl: Type: AWS::WAFv2::WebACL Properties: Name: !Sub ${Env}-${Prefix}-web-acl Scope: !Ref Scope DefaultAction: Allow: {} VisibilityConfig: CloudWatchMetricsEnabled: true SampledRequestsEnabled: true MetricName: !Sub ${Env}-${Prefix}-web-acl Rules: - Name: AWS-AWSManagedRulesCommonRuleSet Priority: 1 Statement: ManagedRuleGroupStatement: VendorName: AWS Name: AWSManagedRulesCommonRuleSet ExcludedRules: - Name: NoUserAgent_HEADER - Name: UserAgent_BadBots_HEADER - Name: SizeRestrictions_QUERYSTRING - Name: SizeRestrictions_Cookie_HEADER - Name: SizeRestrictions_BODY - Name: SizeRestrictions_URIPATH - Name: EC2MetaDataSSRF_BODY - Name: EC2MetaDataSSRF_COOKIE - Name: EC2MetaDataSSRF_URIPATH - Name: EC2MetaDataSSRF_QUERYARGUMENTS - Name: GenericLFI_QUERYARGUMENTS - Name: GenericLFI_URIPATH - Name: GenericLFI_BODY - Name: RestrictedExtensions_URIPATH - Name: RestrictedExtensions_QUERYARGUMENTS - Name: GenericRFI_QUERYARGUMENTS - Name: GenericRFI_BODY - Name: GenericRFI_URIPATH - Name: CrossSiteScripting_COOKIE - Name: CrossSiteScripting_QUERYARGUMENTS - Name: CrossSiteScripting_BODY - Name: CrossSiteScripting_URIPATH OverrideAction: None: {} VisibilityConfig: CloudWatchMetricsEnabled: true SampledRequestsEnabled: true MetricName: AWS-AWSManagedRulesCommonRuleSet WAFLogConfig: Type: AWS::WAFv2::LoggingConfiguration Properties: LogDestinationConfigs: - !GetAtt S3BucketForWaflog.Arn ResourceArn: !GetAtt WebAcl.Arn #WebACLAssociation: # Type: AWS::WAFv2::WebACLAssociation # Properties: # ResourceArn: !Ref WebAclAssociationResourceArn # WebACLArn: !GetAtt WebAcl.Arn
特に問題なく実行完了できました。
ルールを確認してみると、すべてのルールでUse action defined in the rule
と表記されていました。これはルールのデフォルトのアクションであるBlockとなっている場合の表記だと思われます。本来は全ルールに対してExcluded RuleでCountに指定しているのでこの状態はおかしいですね。
想定通りCountで指定できているのか表示どおりBlockとなっているかわからなかったため、試しにNoUserAgent_HEADER
で検知させるように以下のようなリクエストを送信してみました。
curl -H 'User-Agent: ' http://[test_domain]
リクエストはブロックされませんでした。
> curl -H 'User-Agent: ' http://devio-stg-alb-1234567.ap-northeast-1.elb.amazonaws.com <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <title>Test Page for the Apache HTTP Server</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <style type="text/css"> /*<![CDATA[*/ body { (以下略)
Sampled Requestでも、Metric name: NoUserAgent_HEADER
でCOUNT
と表示されていますね。
Edit
からルールの状態を確認してみます。
ExcludedRulesで指定したルールはすべてCountと設定されていました。
緑で囲った箇所で注記されているように「ExcludedRulesで指定されたルールは、RuleActionOverridesに自動置換されて設定される」とのことです。
Automatically converted the JSON for your Count rule action overrides from the old, “ExcludedRules” settings to the updated “RuleActionOverrides” settings. For details, download your web ACL as JSON and review the settings.
コンソール上と実際に設定に乖離があるのは、公式ドキュメントに記載されていたような「コンソール上のAPIの操作とCloudFormationでの操作に一貫性が」保たれていない状態になっていると想定します。検証結果からもRuleActionOverridesを利用するようにした方がよさそうであることがわかりました。
やってみた その2
続いて、先ほど利用したテンプレートのExcludedRulesをRuleActionOverridesに置き換えて実行してみます。
テンプレートはこちらです(クリックで開きます)
AWSTemplateFormatVersion: '2010-09-09' Parameters: Prefix: Type: String Default: test Description: "Fill in the name of the system name." Env: Type: String Default: develop Description: "Fill in the name of the environment." Scope: Type: String Default: REGIONAL AllowedValues: - REGIONAL - CLOUDFRONT Description: "Select in the scope of waf(REGIONAL or CLOUDFRONT)" # WebAclAssociationResourceArn: # Type: String # Default: "arn:aws:elasticloadbalancing:ap-northeast-1:XXXXXXXXXXXX:loadbalancer/app/XXXXXXXXXXXX" # Description: Enter RegionalResource(ALB,APIGateway,AppSync) ARN or CloudFront ARN to associate with WEBACL. Resources: # ------------------------------------------------------------# # S3 # ------------------------------------------------------------# S3BucketForWaflog: Type: AWS::S3::Bucket Properties: BucketName: !Sub aws-waf-logs-${Env}-${Prefix}-${AWS::AccountId} AccessControl: Private PublicAccessBlockConfiguration: BlockPublicAcls: True BlockPublicPolicy: True IgnorePublicAcls: True RestrictPublicBuckets: True S3BucketForAthenaQuery: Type: AWS::S3::Bucket Properties: BucketName: !Sub athena-query-results-${Env}-${Prefix}-${AWS::AccountId} AccessControl: Private PublicAccessBlockConfiguration: BlockPublicAcls: True BlockPublicPolicy: True IgnorePublicAcls: True RestrictPublicBuckets: True # ------------------------------------------------------------# # WAF v2 # ------------------------------------------------------------# WebAcl: Type: AWS::WAFv2::WebACL Properties: Name: !Sub ${Env}-${Prefix}-web-acl Scope: !Ref Scope DefaultAction: Allow: {} VisibilityConfig: CloudWatchMetricsEnabled: true SampledRequestsEnabled: true MetricName: !Sub ${Env}-${Prefix}-web-acl Rules: - Name: AWS-AWSManagedRulesCommonRuleSet Priority: 1 Statement: ManagedRuleGroupStatement: VendorName: AWS Name: AWSManagedRulesCommonRuleSet RuleActionOverrides: - Name: NoUserAgent_HEADER ActionToUse: Count: {} - Name: UserAgent_BadBots_HEADER ActionToUse: Count: {} - Name: SizeRestrictions_QUERYSTRING ActionToUse: Count: {} - Name: SizeRestrictions_Cookie_HEADER ActionToUse: Count: {} - Name: SizeRestrictions_BODY ActionToUse: Count: {} - Name: SizeRestrictions_URIPATH ActionToUse: Count: {} - Name: EC2MetaDataSSRF_BODY ActionToUse: Count: {} - Name: EC2MetaDataSSRF_COOKIE ActionToUse: Count: {} - Name: EC2MetaDataSSRF_URIPATH ActionToUse: Count: {} - Name: EC2MetaDataSSRF_QUERYARGUMENTS ActionToUse: Count: {} - Name: GenericLFI_QUERYARGUMENTS ActionToUse: Count: {} - Name: GenericLFI_URIPATH ActionToUse: Count: {} - Name: GenericLFI_BODY ActionToUse: Count: {} - Name: RestrictedExtensions_URIPATH ActionToUse: Count: {} - Name: RestrictedExtensions_QUERYARGUMENTS ActionToUse: Count: {} - Name: GenericRFI_QUERYARGUMENTS ActionToUse: Count: {} - Name: GenericRFI_BODY ActionToUse: Count: {} - Name: GenericRFI_URIPATH ActionToUse: Count: {} - Name: CrossSiteScripting_COOKIE ActionToUse: Count: {} - Name: CrossSiteScripting_QUERYARGUMENTS ActionToUse: Count: {} - Name: CrossSiteScripting_BODY ActionToUse: Count: {} - Name: CrossSiteScripting_URIPATH ActionToUse: Count: {} OverrideAction: None: {} VisibilityConfig: CloudWatchMetricsEnabled: true SampledRequestsEnabled: true MetricName: AWS-AWSManagedRulesCommonRuleSet WAFLogConfig: Type: AWS::WAFv2::LoggingConfiguration Properties: LogDestinationConfigs: - !GetAtt S3BucketForWaflog.Arn ResourceArn: !GetAtt WebAcl.Arn #WebACLAssociation: # Type: AWS::WAFv2::WebACLAssociation # Properties: # ResourceArn: !Ref WebAclAssociationResourceArn # WebACLArn: !GetAtt WebAcl.Arn
結果はうまくいかず。。。
以下のハイライト箇所がうまく書けていないところまではわかったのですが、今回は断念。また再チャレンジしてみます。
Rules: - Name: AWS-AWSManagedRulesCommonRuleSet Priority: 1 Statement: ManagedRuleGroupStatement: VendorName: AWS Name: AWSManagedRulesCommonRuleSet RuleActionOverrides: - Name: NoUserAgent_HEADER ActionToUse: Count: {}
WAFv2のAPIとしては対応しているのでできるはずです。
まとめ
- AWSマネージドルールの各ルールのアクションを上書きして、すべてのルールアクション(
Allow / Block / Count / CAPTCHA / Challenge
)から選択して設定することができるようになった - APIとしては、これまであった
ExcludedRules
の置き換えとしてRuleActionOverrides
が登場- CFn等で
ExcludedRules
は変わらず使用可能だが、コンソール上の操作ではRuleActionOverrides
で設定される。 - 一貫性の観点から
ExcludedRules
の利用は非推奨。ExcludedRules
を利用するとコンソール上の表示ではデフォルト(Block)のように見えるが実際の設定はCountであるような状態になってしまう。
- CFn等で
さいごに
アップデートによって、これまでBlockもしくはCountの指定しかできなかったAWSマネージドルールの各ルールのアクションがより柔軟に設定できるようになりました。
丸っとよしなにルール設定をしてくれるマネージドルールは便利ですが、細かい設定などの小回りが利かないところが欠点としてありました。 アップデートを機にAWSマネージドルールでCount、Block以外のCAPTCHAのようなアクションを利用することも可能になりました。
この記事が誰かに役に立てば幸いです。
以上、AWS事業本部コンサルティング部の芦沢(@ashi_ssan)でした。
- Challengeは新しくアップデートで追加されたルールアクションです、別途ブログにするつもりです。 ↩