Hasura Console の Data タブで 403 Forbidden 発生

2023-01-18
山下 徳光
#
Hasura
#
#

開発環境のHasura ConsoleでDataタブを開くと 403 Forbidden エラーが発生しました。

原因と対応をメモしておきます。

エラーレスポンスは以下です。JSONではなくHTMLで返却されています。

HTTP/2 403
server: awselb/2.0date: Wed, 18 Jan 2023 06:43:38 GMT
content-type: text/html
content-length: 520

<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
</body>
</html>
<!-- a padding to disable MSIE and Chrome friendly error page >
<!-- a padding to disable MSIE and Chrome friendly error page >
<!-- a padding to disable MSIE and Chrome friendly error page >
<!-- a padding to disable MSIE and Chrome friendly error page >
<!-- a padding to disable MSIE and Chrome friendly error page >
<!-- a padding to disable MSIE and Chrome friendly error page >

原因

AWS WAF の AWSManagedRulesCommonRuleSet#SizeRestrictions_BODY の制限にかかっていたことが原因でした。


* コアルールセット \(CRS\) マネージドルールグループ


具体的には、Hasura Console の Dataタブを開いた際に実行しているAPIの /v2/query のボディサイズが約13KBだったために、SizeRestrictions_BODY の制限である 8KB を超過してエラーになっていました。

リクエストボディの内容は以下です。実際にはargs内のsqlの値が長めのSQLクエリになっています。

{
  "type": "bulk",
  "source": "app",
  "args": [
    {
      "type": "run_sql",
      "args": {
        "source": "app",
        "sql": "SELECT...",
        "cascade": false,
        "read_only": true
      }
    },
    {
      "type": "run_sql",
      "args": {
        "source": "app",
        "sql": "SELECT...",
        "cascade": false,
        "read_only": true
      }
    },
    {
      "type": "run_sql",
      "args": {
        "source": "app",
        "sql": "SELECT...",
        "cascade": false,
        "read_only": true
      }
    },
    {
      "type": "run_sql",
      "args": {
        "source": "app",
        "sql": "SELECT...",
        "cascade": false,
        "read_only": true
      }
    },
    {
      "type": "run_sql",
      "args": {
        "source": "app",
        "sql": "SELECT...",
        "cascade": false,
        "read_only": true
      }
    }
  ]
}

対応

次の対応方法を考えました。


1. 特定のIPアドレスをWAFのホワイトリストに追加

2. AWSManagedRulesCommonRuleSet#SizeRestrictions_BODYを無効化


今回はそもそもHasura ConsoleにIPアドレス制限をかけているため、(1)で対応します。

以下はAWS CDKでWAFにIPアドレス許可ルールを追加するサンプルです。

const allowIpSets = new CfnIPSet(this.scope, "XXX", {
  name: "XXX",
  ipAddressVersion: "IPV4",
  scope: "REGIONAL",
  addresses: ["1.2.3.4/32"],
});

let priority = 0;
new CfnWebACL(this.scope, "XXX", {
  defaultAction: {
    allow: {},
  },
  scope: "REGIONAL",
  name: "XXX",
  visibilityConfig: {
    sampledRequestsEnabled: false,
    cloudWatchMetricsEnabled: true,
    metricName: `XXX`,
  },
  rules: [
    {
      priority: priority++,
      name: `XXX`,
      action: { allow: {} },
      visibilityConfig: {
        sampledRequestsEnabled: false,
        cloudWatchMetricsEnabled: true,
        metricName: "XXX",
      },
      statement: {
        ipSetReferenceStatement: {
          arn: allowIpSets.attrArn,
        },
      },
    },
  // ...

さいごに

最初はHasuraのDBユーザーの権限を疑いましたが、そもそもレスポンスがHTMLで返却されている時点で、Hasura側の問題ではないと気がつくべきでした。事実ベースで仮説を立てるのが大事ですね。

開発環境のHasura ConsoleでDataタブを開くと 403 Forbidden エラーが発生しました。

原因と対応をメモしておきます。

エラーレスポンスは以下です。JSONではなくHTMLで返却されています。

HTTP/2 403
server: awselb/2.0date: Wed, 18 Jan 2023 06:43:38 GMT
content-type: text/html
content-length: 520

<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
</body>
</html>
<!-- a padding to disable MSIE and Chrome friendly error page >
<!-- a padding to disable MSIE and Chrome friendly error page >
<!-- a padding to disable MSIE and Chrome friendly error page >
<!-- a padding to disable MSIE and Chrome friendly error page >
<!-- a padding to disable MSIE and Chrome friendly error page >
<!-- a padding to disable MSIE and Chrome friendly error page >

原因

AWS WAF の AWSManagedRulesCommonRuleSet#SizeRestrictions_BODY の制限にかかっていたことが原因でした。


* コアルールセット \(CRS\) マネージドルールグループ


具体的には、Hasura Console の Dataタブを開いた際に実行しているAPIの /v2/query のボディサイズが約13KBだったために、SizeRestrictions_BODY の制限である 8KB を超過してエラーになっていました。

リクエストボディの内容は以下です。実際にはargs内のsqlの値が長めのSQLクエリになっています。

{
  "type": "bulk",
  "source": "app",
  "args": [
    {
      "type": "run_sql",
      "args": {
        "source": "app",
        "sql": "SELECT...",
        "cascade": false,
        "read_only": true
      }
    },
    {
      "type": "run_sql",
      "args": {
        "source": "app",
        "sql": "SELECT...",
        "cascade": false,
        "read_only": true
      }
    },
    {
      "type": "run_sql",
      "args": {
        "source": "app",
        "sql": "SELECT...",
        "cascade": false,
        "read_only": true
      }
    },
    {
      "type": "run_sql",
      "args": {
        "source": "app",
        "sql": "SELECT...",
        "cascade": false,
        "read_only": true
      }
    },
    {
      "type": "run_sql",
      "args": {
        "source": "app",
        "sql": "SELECT...",
        "cascade": false,
        "read_only": true
      }
    }
  ]
}

対応

次の対応方法を考えました。


1. 特定のIPアドレスをWAFのホワイトリストに追加

2. AWSManagedRulesCommonRuleSet#SizeRestrictions_BODYを無効化


今回はそもそもHasura ConsoleにIPアドレス制限をかけているため、(1)で対応します。

以下はAWS CDKでWAFにIPアドレス許可ルールを追加するサンプルです。

const allowIpSets = new CfnIPSet(this.scope, "XXX", {
  name: "XXX",
  ipAddressVersion: "IPV4",
  scope: "REGIONAL",
  addresses: ["1.2.3.4/32"],
});

let priority = 0;
new CfnWebACL(this.scope, "XXX", {
  defaultAction: {
    allow: {},
  },
  scope: "REGIONAL",
  name: "XXX",
  visibilityConfig: {
    sampledRequestsEnabled: false,
    cloudWatchMetricsEnabled: true,
    metricName: `XXX`,
  },
  rules: [
    {
      priority: priority++,
      name: `XXX`,
      action: { allow: {} },
      visibilityConfig: {
        sampledRequestsEnabled: false,
        cloudWatchMetricsEnabled: true,
        metricName: "XXX",
      },
      statement: {
        ipSetReferenceStatement: {
          arn: allowIpSets.attrArn,
        },
      },
    },
  // ...

さいごに

最初はHasuraのDBユーザーの権限を疑いましたが、そもそもレスポンスがHTMLで返却されている時点で、Hasura側の問題ではないと気がつくべきでした。事実ベースで仮説を立てるのが大事ですね。

株式会社グランドリームでは、AWSを駆使した開発からUI/UXデザインまで、Webアプリケーションに関するすべての要望に応えます。
まずは一度お気軽にご相談ください。

お問い合わせはこちら