Open11

AWSCLIをWAFのカスタムレスポンスでメンテナンス画面を表示する

daichodaicho

既にWAFはTerraformで構築済みなので、変更だけであれば下記を実施すれば良い

$ WAF_ACL_NAME='test-waf-acl'
$ WAF_ACL_ID='xxxxxxxxxx'

# 現在のWebACLの設定を取得する
$ aws wafv2 get-web-acl --name "${WAF_ACL_NAME}" --scope=CLOUDFRONT --region us-east-1 --id "${WAF_ACL_ID}" > webacl.json

# JSON内のRulesに追加したいルールを追加する
$ vim webacl.json

# LockTokenを取得する
$ LockToken=$(cat webacl.json | jq -r .LockToken)

# webacl.json からRulesのみ抽出したJSONを生成する
$ cat webacl.json | jq .WebACL.Rules > webacl_rule.json

# WebACLをアップデートする
$ /usr/local/bin/aws --scope=CLOUDFRONT --region us-east-1 wafv2 update-web-acl --name "${WAF_ACL_NAME}" --id "${WAF_ACL_ID}" --rules file://webacl_rule.json --lock-token "${LockToken}" --visibility-config "SampledRequestsEnabled=true,CloudWatchMetricsEnabled=true,MetricName=${WAF_ACL_NAME}-metric" --default-action Allow={}
daichodaicho

今回の環境では別のルールでIP制限を行っていたため、その下にメンテナンス画面用のルールを追記した。具体的に準備した webacl_rule.json は下記の通りです

webacl_rule.json
[
  {
    "Name": "BlockIpsExceptWhitelist",
    "Priority": 0,
    "Statement": {
      "NotStatement": {
        "Statement": {
          "IPSetReferenceStatement": {
            "ARN": "arn:aws:wafv2:us-east-1:xxxxxx:global/ipset/allow-ip-limit/xxxxx"
          }
        }
      }
    },
    "Action": {
      "Block": {}
    },
    "VisibilityConfig": {
      "SampledRequestsEnabled": true,
      "CloudWatchMetricsEnabled": true,
      "MetricName": "BlockIpsExceptWhitelist"
    }
  },
  {
    "Name": "EnableMaintenance",
    "Priority": 1,
    "Statement": {
      "NotStatement": {
        "Statement": {
          "IPSetReferenceStatement": {
            "ARN": "arn:aws:wafv2:us-east-1:xxxxxx:global/ipset/allow-ip-maintenance/xxxxxx"
          }
        }
      }
    },
    "Action": {
      "Block": {
        "CustomResponse": {
          "ResponseCode": 503,
          "CustomResponseBodyKey": "maintenance-body"
        }
      }
    },
    "VisibilityConfig": {
      "SampledRequestsEnabled": true,
      "CloudWatchMetricsEnabled": true,
      "MetricName": "EnableMaintenance"
    }
  }
]
daichodaicho

上記のJSONを読み込ませたところエラー発生。カスタムレスポンスボディが見つからない様子

$ /usr/local/bin/aws --scope=CLOUDFRONT --region us-east-1 wafv2 update-web-acl --name "${WAF_ACL_NAME}" --id "${WAF_ACL_ID}" --rules file://webacl_rule.json --lock-token "${LockToken}" --visibility-config "SampledRequestsEnabled=false,CloudWatchMetricsEnabled=false,MetricName=${WAF_ACL_NAME}-metric" --default-action Allow={}

An error occurred (WAFInvalidParameterException) when calling the UpdateWebACL operation: Error reason: AWS WAF couldn't find a resource that a parameter references., field: CUSTOM_RESPONSE, parameter: maintenance-body
daichodaicho

カスタムレスポンス用のJSONを準備する

maintenance.json
{
  "maintenance-body": {
    "ContentType": "TEXT_HTML",
    "Content": "<h1>maintenance</h1>"
  }
}
daichodaicho

下記のコマンドでカスタムレスポンスを設定できた

/usr/local/bin/aws --scope=CLOUDFRONT --region us-east-1 --no-cli-pager wafv2 update-web-acl --name "${WAF_ACL_NAME}" --id "${WAF_ACL_ID}" --rules file://webacl_rule.json --custom-response-bodies file://maintenance.json --lock-token "${LockToken}" --visibility-config "SampledRequestsEnabled=false,CloudWatchMetricsEnabled=false,MetricName=${WAF_ACL_NAME}-metric" --default-action Allow={}
daichodaicho

実環境のカスタムレスポンスボディはダブルクォーテーション含んでいる。どのようにカスタムレスポンス用のJSONを生成するのが楽なのか。