ブログに戻る

フォロー&ご登録

10分以内に Fastly Next-Gen WAF のデプロイを完了する方法

Brooks Cunningham

Senior Security Strategist, Fastly

まずはじめに

Web や API のエンドポイントを保護しようとする際に組織が直面する主な問題として、セキュリティソリューションの複雑さや管理の難しさと、デプロイに時間と手間がかかるという2つが挙げられます。 

脅威の状況がダイナミックに発展する中、DevOps チームは素早くポリシーやルール (カスタムシグナルやレート制限ルールなど) を変更してアプリケーションに対するセキュリティ脅威に対応できる必要があります。 

深刻化が進む Web の脅威に対抗するには、強力なセキュリティポリシーが必要ですが、それにはスピードと自動化が欠かせません。攻撃を防ぐためには、人によるミスを回避しながら迅速にルールを更新して脅威の状況にすぐに適応できることが重要です。このブログ記事では、IaC (Infrastructure-as-Code) を含む、効果的な統合型のアプローチをご紹介します。

次世代ソリューションの Fastly Next-Gen WAF (NGWAF) は、上記の2つの問題を解決できます。NGWAF では、セットアップ後すぐに誤検知を排除しながら脅威の検出を開始でき、ルールや正規表現パターンなどの設定や調整、管理は不要です。NGWAF が Gartner によって5年連続で「Customers’ Choice」で選ばれている</u>背景には理由があるのです。また、NGWAF はすぐに簡単にデプロイできます。以下では、Terraform を使って素早く簡単に NGWAF のエッジデプロイを作成する方法をご紹介します。

Terraform は、IT インフラのデプロイと管理を行うツールとして、ますます人気が高まっています。Terraform を使用することで、NGWAF をエッジにデプロイしてこれまで以上に簡単に Web や API のエンドポイントを保護することが可能になります。ただし、この記事では、Terraform よりも、インフラストラクチャのプロビジョニングを簡単に行うステップを紹介することを主な目的としています。 

用語についての簡単な説明

ここでは、以下で使用されるいくつかの用語について、簡単にご説明します。詳細については、Fastly のオンラインドキュメント (https://docs.fastly.com/signalsciences/using-signal-sciences/corp-management/</u>) をご覧ください。

  • Site - https://docs.fastly.com/signalsciences/using-signal-sciences/web-interface/about-the-site-overview-page/</u> 

    • 「Site」は「Corp」に属し、リクエストと設定のセットで構成されます。リクエストは、Site のアクセスキーと秘密鍵を使用して設定されたエージェントを通じて受信されます。設定には、エージェントルール (例 : リクエストに XSS のタグを付ける、ブロックリストと許可リストのルール、ブロックルール)、メンバーリスト、統合機能、その他の設定オプションが含まれます。理論的には、特定のアプリケーションまたはドメインのマッピング (例 : app1.example.com と app2.example.com) として Site を考えることができますが、複数のアプリケーションが同じサイトキーを共有したり、ひとつのアプリケーションを複数の Site に分割したりすることも可能です (例 : example.com と example.com/admin)。

  • Corp - https://docs.fastly.com/signalsciences/using-signal-sciences/web-interface/about-the-corp-overview-page/</u> 

    • 「Corp」は「Corporation」の意味で、サイトとユーザーのセットで構成されています。ユーザーは、Corp レベルで認証され、同一 Corp に属するそれぞれの Site のメンバーが含まれます。

  • エッジデプロイ - https://docs.fastly.com/signalsciences/install-guides/edge/edge-deployment/</u> 

    • エッジデプロイのメソッドによって、Signal Sciences をエッジセキュリティサービスとして Fastly のエッジクラウドプラットフォームに追加できます。自社のホスト環境に変更を加える必要は一切ありません。

デプロイの構造を決定する

お客様から「どの NGWAF Site をエッジ統合にリンクすべきか」、「エッジ統合のために新しい NGWAF Site を作成する必要があるか」と、よく聞かれます。NGWAF では、お客様の組織に最適な構造をお選びいただけます。既存の Site を簡単に使用することもできますし、この特定のデプロイオプションのために、新しい Site を作成することも可能です。これらのオプションの詳細については、エッジにデプロイする NGWAF の Corp と Site の構成を設計する方法を詳しく記したこちらの記事</u>をご覧ください。NGWAF の使用を開始する最もシンプルな方法は、既存の NGWAF Site を使用することです。

Fastly は、このプロセスに必要なものをすべて提供しています。

  1. サービスの作成と管理の権限を持つ Fastly Edge API キー https://docs.fastly.com/ja/guides/using-api-tokens#creating-api-tokens</u> 

  2. Corp Admin の権限を持つ</u> NextGen WAF API キー

  3. NextGen WAF の Corp と Site https://docs.fastly.com/signalsciences/using-signal-sciences/corp-management/</u> 

Next-Gen WAF をエッジにデプロイする

以下の Terraform 設定を使用してエッジに NGWAF をデプロイできます。

# Terraform 0.13+ requires providers to be declared in a "required_providers" block
# https://registry.terraform.io/providers/fastly/fastly/latest/docs
terraform {
 required_providers {
   fastly = {
     source  = "fastly/fastly"
     version = ">= 3.0.4"
   }
   sigsci = {
     source = "signalsciences/sigsci"
     version = ">= 1.2.18"
   }
 }
}
# Fastly Edge VCL configuration
variable "FASTLY_API_KEY" {
   type        = string
   description = "This is API key for the Fastly VCL edge configuration."
}
#### VCL Service variables - Start
variable "USER_VCL_SERVICE_DOMAIN_NAME" {
 type = string
 description = "Frontend domain for your service. Try 'YOURNAME.global.ssl.fastly.net' to get up and running quickly."
 default = "brooks-ngwaf-tf-demo.global.ssl.fastly.net"
}
variable "USER_VCL_SERVICE_BACKEND_HOSTNAME" {
 type          = string
 description   = "hostname used for backend."
 default       = "http-me.glitch.me"
}
# Controls the percentage of traffic sent to NGWAF
variable "Edge_Security_dictionary" {
 type = string
 default = "Edge_Security"
}
variable "NGWAF_CORP" {
 type          = string
 description   = "Corp name for NGWAF"
}
variable "NGWAF_SITE" {
 type          = string
 description   = "Site name for NGWAF"
}
#### VCL Service variables - End
#### NGWAF variables - Start
variable "NGWAF_EMAIL" {
   type        = string
   description = "Email address associated with the token for the NGWAF API."
}
variable "NGWAF_TOKEN" {
   type        = string
   description = "Secret token for the NGWAF API."
   sensitive   = true
}
#### NGWAF variables - End
# Configure the Fastly Provider
provider "fastly" {
 api_key = var.FASTLY_API_KEY
}
#### Fastly VCL Service - Start
resource "fastly_service_vcl" "frontend-vcl-service" {
 name = "Frontend VCL Service - NGWAF edge deploy"
 domain {
   name    = var.USER_VCL_SERVICE_DOMAIN_NAME
   comment = "Frontend VCL Service - NGWAF edge deploy"
 }
 backend {
   address = var.USER_VCL_SERVICE_BACKEND_HOSTNAME
   name = "vcl_service_origin_1"
   port    = 443
   use_ssl = true
   ssl_cert_hostname = var.USER_VCL_SERVICE_BACKEND_HOSTNAME
   ssl_sni_hostname = var.USER_VCL_SERVICE_BACKEND_HOSTNAME
   override_host = var.USER_VCL_SERVICE_BACKEND_HOSTNAME
 }
 #### NGWAF Dynamic Snippets - MANAGED BY FASTLY - Start
  dynamicsnippet {
    name     = "ngwaf_config_init"
    type     = "init"
    priority = 0
  }
  dynamicsnippet {
    name     = "ngwaf_config_miss"
    type     = "miss"
    priority = 9000
  }
  dynamicsnippet {
    name     = "ngwaf_config_pass"
    type     = "pass"
    priority = 9000
  }
  dynamicsnippet {
    name     = "ngwaf_config_deliver"
    type     = "deliver"
    priority = 9000
  }
 #### NGWAF Dynamic Snippets - MANAGED BY FASTLY - End
 dictionary {
   name       = var.Edge_Security_dictionary
 }
 lifecycle {
   ignore_changes = [
     product_enablement,
   ]
 }
 force_destroy = true
}
resource "fastly_service_dictionary_items" "edge_security_dictionary_items" {
 for_each = {
 for d in fastly_service_vcl.frontend-vcl-service.dictionary : d.name => d if d.name == var.Edge_Security_dictionary
 }
 service_id = fastly_service_vcl.frontend-vcl-service.id
 dictionary_id = each.value.dictionary_id
 items = {
   Enabled: "100"
 }
}
resource "fastly_service_dynamic_snippet_content" "ngwaf_config_init" {
 for_each = {
 for d in fastly_service_vcl.frontend-vcl-service.dynamicsnippet : d.name => d if d.name == "ngwaf_config_init"
 }
 service_id = fastly_service_vcl.frontend-vcl-service.id
 snippet_id = each.value.snippet_id
 content = "### Fastly managed ngwaf_config_init"
 manage_snippets = false
}
resource "fastly_service_dynamic_snippet_content" "ngwaf_config_miss" {
 for_each = {
 for d in fastly_service_vcl.frontend-vcl-service.dynamicsnippet : d.name => d if d.name == "ngwaf_config_miss"
 }
 service_id = fastly_service_vcl.frontend-vcl-service.id
 snippet_id = each.value.snippet_id
 content = "### Fastly managed ngwaf_config_miss"
 manage_snippets = false
}
resource "fastly_service_dynamic_snippet_content" "ngwaf_config_pass" {
 for_each = {
 for d in fastly_service_vcl.frontend-vcl-service.dynamicsnippet : d.name => d if d.name == "ngwaf_config_pass"
 }
 service_id = fastly_service_vcl.frontend-vcl-service.id
 snippet_id = each.value.snippet_id
 content = "### Fastly managed ngwaf_config_pass"
 manage_snippets = false
}
resource "fastly_service_dynamic_snippet_content" "ngwaf_config_deliver" {
  for_each = {
  for d in fastly_service_vcl.frontend-vcl-service.dynamicsnippet : d.name => d if d.name == "ngwaf_config_deliver"
  }
  service_id = fastly_service_vcl.frontend-vcl-service.id
  snippet_id = each.value.snippet_id
  content = "### Fastly managed ngwaf_config_deliver"
  manage_snippets = false
}
#### Fastly VCL Service - End
#### NGWAF Edge deploy - Start
provider "sigsci" {
  corp = var.NGWAF_CORP
  email = var.NGWAF_EMAIL
  auth_token = var.NGWAF_TOKEN
  fastly_api_key = var.FASTLY_API_KEY
}
resource "sigsci_edge_deployment" "ngwaf_edge_site_service" {
 # https://registry.terraform.io/providers/signalsciences/sigsci/latest/docs/resources/edge_deployment
 site_short_name = var.NGWAF_SITE
}
resource "sigsci_edge_deployment_service" "ngwaf_edge_service_link" {
 # https://registry.terraform.io/providers/signalsciences/sigsci/latest/docs/resources/edge_deployment_service
 site_short_name = var.NGWAF_SITE
 fastly_sid      = fastly_service_vcl.frontend-vcl-service.id
 activate_version = true
 percent_enabled = 100
 depends_on = [
   sigsci_edge_deployment.ngwaf_edge_site_service,
   fastly_service_vcl.frontend-vcl-service,
   fastly_service_dictionary_items.edge_security_dictionary_items,
   fastly_service_dynamic_snippet_content.ngwaf_config_init,
   fastly_service_dynamic_snippet_content.ngwaf_config_miss,
   fastly_service_dynamic_snippet_content.ngwaf_config_pass,
   fastly_service_dynamic_snippet_content.ngwaf_config_deliver,
 ]
}
resource "sigsci_edge_deployment_service_backend" "ngwaf_edge_service_backend_sync" {
  site_short_name = var.NGWAF_SITE
  fastly_sid      = fastly_service_vcl.frontend-vcl-service.id
  fastly_service_vcl_active_version = fastly_service_vcl.frontend-vcl-service.active_version
  depends_on = [
    sigsci_edge_deployment_service.ngwaf_edge_service_link,
  ]
}
#### NGWAF Edge deploy - End
output "love_laugh_live_ngwaf" {
  value = <<tfmultiline
  #### Click the URL to go to the service ####
  https://cfg.fastly.com/${fastly_service_vcl.frontend-vcl-service.id}
  #### Send a test request with curl. ####
  curl -i "https://${var.USER_VCL_SERVICE_DOMAIN_NAME}/anything/whydopirates?likeurls=theargs" -d foo=bar
  #### Send an test as cmd exe request with curl. ####
  curl -i "https://${var.USER_VCL_SERVICE_DOMAIN_NAME}/anything/myattackreq?i=../../../../etc/passwd'" -d foo=bar
  #### Troubleshoot the logging configuration if necessary. ####
  curl https://api.fastly.com/service/${fastly_service_vcl.frontend-vcl-service.id}/logging_status -H fastly-key:$FASTLY_API_KEY
  tfmultiline
 description = "Output hints on what to do next."
 depends_on = [
   sigsci_edge_deployment_service.ngwaf_edge_service_link
 ]
}

上記の要件のすべて (Fastly Edge API キー、NGWAF API キー、権限、NGWAF の Corp/Site) が揃ったら、後は「terraform apply」を実行してリクエストを送信し、新しいデプロイのために作成したこのデプロイをテストします。幸い、(お客様の作業を楽にするために) テストリクエストが Terraform に組み込まれています。これで、他のデプロイオプションと同様に、Fastly NGWAF のコンソールでアプリケーションのセキュリティ設定を管理することも、Terraform を使用し続けることもできます。

仕組みについて

Signal Sciences の Terraform プロバイダーは次の2つを実行します。

  1. NGWAF のエッジサービスを作成する

  2. NGWAF のエッジサービスを VCL サービスにリンクする

VCL サービスと NGWAF のエッジサービスをリンクすることで、以下が実行されます。 

  • Edge Dictionary の作成 

  • Fastly が管理する動的スニペットの作成

  • VCL サービスで設定されたオリジンと NGWAF のエッジサービスの同期化

最初に「terraform apply」を実行する際に、3つの動的スニペットと一緒に VCL サービスが作成されます。これらすべてに「managed = false」が設定されており、これらのリソースは Terraform の外で管理されることを意味しています (https://registry.terraform.io/providers/fastly/fastly/latest/docs/resources/service_dynamic_snippet_content#manage_snippets</u>)。この場合「Terraform の外」は、Fastly でこれらのスニペットが管理され、必要に応じて変更できることを意味します。

おめでとうございます!

このようにシンプルなプロセスで、サイトは保護されている状態になりました。今回は、Terraform を使用して 新しい VCL サービスに対して NGWAF のエッジデプロイを簡単にプロビジョニングする方法を解説しました。既存の Fastly サービスで Terraform を使用する方法については、また別の機会にブログでご紹介します。ご意見、ご質問等がございましたら、お気軽にご連絡ください。