5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

TerraformでAWS WAFを基礎から学ぶ(基本のルール設定編)

Posted at

はじめに

AWS WAF はフルマネージドで便利なファイアウォールであり、インターネットに面したゲートウェイ機能を有するシステムをお手軽に構築するなら、ほぼ必須で使うことになるサービスだろう(自前で手塩にかけて育てたWAFを持っているのであれば話は別だろうけど)。

ということで、お手軽に使える AWS WAF をお手軽に Terraform で構築しつつ基礎を理解していく。
インテグレーションは API Gateway を使う。
今回作る「IPアドレス制限」だけであれば、API Gateway のリソースポリシーを使った方が手っ取り早い。あくまでも練習のためにやっていると考えていただきたい。

IPアドレス制限する AWS WAF の基本セット

今回の構成では、ブラックリスト形式で実施する。
ルール設定に必要になる Terraform のリソースは以下の2種類。

  • aws_wafv2_web_acl
  • aws_wafv2_ip_set

今回の設定は練習であり、マネージメントコンソールにも注意書きがあるように、ブラックリストとしては実質的に意味がないということは留意しておくこと。

When a request comes through a CDN or other proxy network, the source IP address identifies the proxy and the original IP address is sent in a header. Use caution with the option, IP address in header, because headers can be handled inconsistently by proxies and they can be modified to bypass inspection.

Web ACL 本体とルールの設定

Web ACL は以下のように定義する。

resource "aws_wafv2_web_acl" "iprestriction" {
  name        = local.webacl_name
  description = "TEST IP Adress Restriction"
  scope       = "REGIONAL"

  default_action {
    allow {}
  }

  rule {
    name     = "iprestriction"
    priority = 1

    action {
      block {}
    }

    statement {
      ip_set_reference_statement {
        arn = aws_wafv2_ip_set.test.arn
      }
    }

    visibility_config {
      cloudwatch_metrics_enabled = false
      metric_name                = local.webacl_iprestriction_metric_name
      sampled_requests_enabled   = false
    }
  }

  visibility_config {
    cloudwatch_metrics_enabled = false
    metric_name                = local.webacl_metric_name
    sampled_requests_enabled   = false
  }
}

visibility_config は今の段階では使わないものの、必須パラメータなので設定しておく。
default_action も必須パラメータで、ここでブラックリストにするかホワイトリストにするかを指定するようなイメージだ。デフォルトが allow であればブラックリストといった感じだ。

IPアドレスリストの設定

aws_wafv2_web_acl 側でIPアドレス制限を直接書くのではなく、IPアドレスセットのリソースを準備し、それと比較するようなかたちになっている。おそらく、複数のルール間でお手軽に共通化ができるように、という思想なのだろうと推測。

resource "aws_wafv2_ip_set" "test" {
  name               = "test"
  description        = "TEST IP set"
  scope              = "REGIONAL"
  ip_address_version = "IPV4"

  addresses = [
    "xxx.xxx.xxx.xxx/32",
  ]
}

アドレスはCIDRで指定する。今回はIPアドレスを1つだけ block したいので、/32 を指定する。

API Gateway とインテグレーションする

さて、せっかくルールを作ってもインテグレーションしなければ意味がない。
インテグレーションには以下の Terraform リソースを使う。

  • aws_wafv2_web_acl_association

使い方は簡単で、API Gateway と AWS WAF の ARN を繋ぐだけで良い。
API Gateway は REST API そのものではなくてステージと連動するという点だけ注意だ。

resource "aws_wafv2_web_acl_association" "iprestriction" {
  resource_arn = aws_api_gateway_stage.prod.arn
  web_acl_arn  = aws_wafv2_web_acl.iprestriction.arn
}

動作確認する

さて、本当にこれでIPアドレス制限されるのかを試してみよう。

IPアドレスリストに設定していないIPアドレスでアクセスした場合、

{
  "data": {
    "hoge": "hige"
  },
  "errorMessage": ""
}

と正しく取得され、リストに設定したIPアドレスでアクセスすると

{"message":"Forbidden"}

と表示される。その他、curl -i で取得されるヘッダ情報としては以下。
HTTPステータスコードは 403 として返却される。

HTTP/2 403 
content-type: application/json
content-length: 23
date: Sun, 06 Dec 2020 02:57:37 GMT
x-amzn-requestid: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
x-amzn-errortype: ForbiddenException
x-amz-apigw-id: xxxxxxxxxxxxxxxx
x-cache: Error from cloudfront
via: 1.1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.cloudfront.net (CloudFront)
x-amz-cf-pop: NRT12-C4
x-amz-cf-id: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

API Gateway の HTTPステータスコードやワーディングの変更

API Gateway とインテグレーションする場合は、HTTP ステータスコードや応答の JSON はゲートウェイのレスポンスで変更可能だ。api_gateway_gateway_response リソースの response_type = "WAF_FILTERED" を使えば Terraform でもできる(詳細は記事を参照)。

API Gateway のログ出力

API Gateway とインテグレーションする場合は、AWS WAF とのやり取りをアクセスログに出力することができる。アクセスログの設定に関する詳細は、手前味噌だがこの記事が分かりやすいと思う。

AWS WAF に関連する項目の出力例は以下の通り。

  "waf_response_code": "$context.wafResponseCode",
  "webacl_arn": "$context.webaclArn",
  "waf_error": "$context.waf.error",
  "waf_latency": "$context.waf.latency",
  "waf_status": "$context.waf.status",

これで実際に出力されたアクセスログを確認すると、以下のように出力される。

allow した場合
    "waf_response_code": "WAF_ALLOW",
    "webacl_arn": "arn:aws:wafv2:ap-northeast-1:xxxxxxxxxxxx:regional/webacl/waf-iprestrict-test-webacl/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "waf_error": "-",
    "waf_latency": "7",
    "waf_status": "200"
block した場合
    "waf_response_code": "WAF_BLOCK",
    "webacl_arn": "arn:aws:wafv2:ap-northeast-1:xxxxxxxxxxxx:regional/webacl/waf-iprestrict-test-webacl/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "waf_error": "-",
    "waf_latency": "7",
    "waf_status": "403"

AWS マネージメントコンソールでの確認

上記で作ったリソースをマネージメントコンソールで確認すると以下のようになる。

キャプチャ1.png

iprestriction のルールを選択して、右上の Edit ボタンを押すと、以下のようにルール編集画面で設定内容を確認できる。

キャプチャ2.png
キャプチャ3.png
キャプチャ4.png

API Gateway とのインテグレーションに関する設定は以下。

キャプチャ5.png

IPアドレスリストに関する設定は以下。

キャプチャ6.png
キャプチャ7.png

基本のルール設定編はここまで。

5
3
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
5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?