Scenario #6: Manage an F5 BIG-IP Advanced WAF Policy with Policy Builder on multiple devices¶
The goal of this lab is to manage Policy Builder Suggestions an F5 BIG-IP Advanced WAF Policy from on multiple devices or clusters. Use cases include:
Multiple devices serving and protecting the same application in multiple datacenters, application spanning across multiple clouds, and other similar environments. By nature, each standalone device or clusters can see different traffic patterns; therefore, you can have different suggestions. The goal is to consolidate the suggestions, before enforcing them.
Production BIG-IP systems protecting the application; therefore, seeing the real life traffic flow for seeding the Policy Builder, but first validating all changes in the test environment, before enforcing the policy in your production environment.
Note
These two use cases are not mutually exclusive and you can manage both within a single workflow.
Pre-requisites¶
On the BIG-IP:
BIG-IP version 16.1 or newer
Advanced WAF Provisioned
Credentials with REST API access
An Advanced WAF Policy with Policy Builder enabled and Manual traffic Learning
On Terraform:
Using F5 BIG-IP provider version 1.16.0 or newer
Using Hashicorp versions following Releases and versioning
Policy Creation¶
Create 4 files:
variables.tf
inputs.auto.tfvars
main.tf
outputs.tf
1variable prod_dc1_bigip {}
2variable prod_cloud_bigip {}
3variable qa_bigip {}
4variable username {}
5variable password {}
1prod_dc1_bigip = "10.1.1.8"
2prod_cloud_bigip = "10.1.1.7"
3qa_bigip = "10.1.1.9"
4username = "admin"
5password = "WhatisYourPassword?"
1terraform {
2 required_providers {
3 bigip = {
4 source = "F5Networks/bigip"
5 version = "1.15"
6 }
7 }
8}
9
10provider "bigip" {
11 alias = "prod1"
12 address = var.prod_dc1_bigip
13 username = var.username
14 password = var.password
15}
16
17provider "bigip" {
18 alias = "prod2"
19 address = var.prod_cloud_bigip
20 username = var.username
21 password = var.password
22}
23
24provider "bigip" {
25 alias = "qa"
26 address = var.qa_bigip
27 username = var.username
28 password = var.password
29}
30
31resource "bigip_waf_policy" "P1S6" {
32 provider = bigip.prod1
33 application_language = "utf-8"
34 partition = "Common"
35 name = "scenario6"
36 enforcement_mode = "blocking"
37 template_name = "POLICY_TEMPLATE_RAPID_DEPLOYMENT"
38}
39
40resource "bigip_waf_policy" "P2S6" {
41 provider = bigip.prod2
42 application_language = "utf-8"
43 partition = "Common"
44 name = "scenario6"
45 enforcement_mode = "blocking"
46 template_name = "POLICY_TEMPLATE_RAPID_DEPLOYMENT"
47}
48
49resource "bigip_waf_policy" "QAS6" {
50 provider = bigip.qa
51 application_language = "utf-8"
52 partition = "Common"
53 name = "scenario6"
54 enforcement_mode = "blocking"
55 template_name = "POLICY_TEMPLATE_RAPID_DEPLOYMENT"
56}
1output "P1S6Id" {
2 value = bigip_waf_policy.P1S6.policy_id
3}
4output "P1S6JSON" {
5 value = bigip_waf_policy.P1S6.policy_export_json
6}
7output "P2S6Id" {
8 value = bigip_waf_policy.P2S6.policy_id
9}
10output "P2S6JSON" {
11 value = bigip_waf_policy.P2S6.policy_export_json
12}
13output "QAS6Id" {
14 value = bigip_waf_policy.QAS6.policy_id
15}
16output "QAS6JSON" {
17 value = bigip_waf_policy.QAS6.policy_export_json
18}
Simulate a WAF Policy workflow¶
The following is a typical workflow:
On each BIG-IP, there is a scenario6.vs Virtual Server.
Create and associate the same WAF Policy to these Virtual Servers.
Run traffic on Production devices. Make sure you are not running the same requests on both Production devices: get distinct suggestions.
Test the suggestions from Prod1 and Prod2 devices on the QA device and check that the application is not broken.
Enforce suggestions on the Production devices.
Note
There are some changes that may be specific to the QA environment, such as setting Trusted IP addresses. So we will make the specific tuning first.
Policy creation and association.
Plan and apply your new Terraform project.
foo@bar:~$ terraform init foo@bar:~$ terraform plan -out scenario6 foo@bar:~$ terraform apply "scenario6"
Go on your WebUI and associate the WAF Policies to the
scenario6.vs
Virtual Servers (do it manually, but it can also be done using thebigip_as3
terraform resource from the same TerraformF5Networks/bigip
provider).Running real life traffic.
Run both legitimate AND illegitimate traffic against your two production BIG-IP devices (scenario6 virtual servers on PROD1 and PROD2 BIG-IPs). Try to throw different attacks on each devices so we make sure we collect different Policy Builder suggestions (checkout the recommended steps described on Module5).
You may need to run the same request multiple times to make sure you get a satisfying learning score.
Collect and test the Policy Builder suggestions.
Create a pb_suggestions.tf file:
data "bigip_waf_pb_suggestions" "S6_22AUG20221800_P1" { provider = bigip.prod1 policy_name = "scenario6" partition = "Common" minimum_learning_score = 100 } data "bigip_waf_pb_suggestions" "S6_22AUG20221800_P2" { provider = bigip.prod2 policy_name = "scenario6" partition = "Common" minimum_learning_score = 100 } output "PB_S6_22AUG20221800_P1" { value = data.bigip_waf_pb_suggestions.S6_22AUG20221800_P1.json } output "PB_S6_22AUG20221800_P2" { value = data.bigip_waf_pb_suggestions.S6_22AUG20221800_P2.json }
Update the main.tf file on the scenario6 QA WAF Policy resource:
resource "bigip_waf_policy" "QAS6" { provider = bigip.qa application_language = "utf-8" name = "scenario6" partition = "Common" template_name = "POLICY_TEMPLATE_FUNDAMENTAL" type = "security" policy_import_json = data.http.scenario6.body modifications = [data.bigip_waf_pb_suggestions.S6_22AUG20221800_P1.json, data.bigip_waf_pb_suggestions.S6_22AUG20221800_P2.json] }
Note
There are obviously some redundant learning suggestions on both data sources but the Declarative WAF API automatically removes them.
Test your application through the QA device.
For UDF users: check
https://qa.f5demo.fch
and see that the application is not broken and attacks are blocked.Enforce suggestions on the Production devices. In a real life scenario, use one of the following ways to perform this step:
The QA device WAF Policy should be 100% consistent with production devices.
QA.WAF == PROD.WAF
This is the easiest way. After validating the suggestions and removing the potential False Positives, just output the JSON policy from QA and refer to it as a
policy_import_json
argument in the production BIG-IPs.In this case, update the main.tf file:
resource "bigip_waf_policy" "P1S6" { provider = bigip.prod1 application_language = "utf-8" partition = "Common" name = "scenario6" enforcement_mode = "blocking" template_name = "POLICY_TEMPLATE_RAPID_DEPLOYMENT" policy_import_json = bigip_waf_policy.QAS6.policy_export_json } resource "bigip_waf_policy" "P2S6" { provider = bigip.prod2 application_language = "utf-8" partition = "Common" name = "scenario6" enforcement_mode = "blocking" template_name = "POLICY_TEMPLATE_RAPID_DEPLOYMENT" policy_import_json = bigip_waf_policy.QAS6.policy_export_json } resource "bigip_waf_policy" "QAS6" { provider = bigip.qa application_language = "utf-8" partition = "Common" name = "scenario6" enforcement_mode = "blocking" template_name = "POLICY_TEMPLATE_RAPID_DEPLOYMENT" }
Plan and apply:
foo@bar:~$ terraform plan -out scenario6 foo@bar:~$ terraform apply "scenario6"
The QA device WAF Policy may have settings differences with production devices (for example, Trusted IP exceptions).
QA.WAF != PROD.WAF
In this case, you must manage the learning suggestions as a separate modifications entity that has to move between WAF Policies. The learning suggestions, when imported into the QA WAF Policy, are de-duplicated and ingested into the WAF Policy. However, they remain in a dedicated space of the Declarative REST JSON: the modifications array. The goal is to import only this section back to the production devices, so any differences in the core entities are not affected.
resource "bigip_waf_policy" "P1S6" { provider = bigip.prod1 application_language = "utf-8" partition = "Common" name = "scenario6" enforcement_mode = "blocking" template_name = "POLICY_TEMPLATE_RAPID_DEPLOYMENT" policy_import_json = bigip_waf_policy.QAS6.policy_export_json.modifications } resource "bigip_waf_policy" "P2S6" { provider = bigip.prod2 application_language = "utf-8" partition = "Common" name = "scenario6" enforcement_mode = "blocking" template_name = "POLICY_TEMPLATE_RAPID_DEPLOYMENT" policy_import_json = bigip_waf_policy.QAS6.policy_export_json.modifications } resource "bigip_waf_policy" "QAS6" { provider = bigip.qa application_language = "utf-8" partition = "Common" name = "scenario6" enforcement_mode = "blocking" template_name = "POLICY_TEMPLATE_RAPID_DEPLOYMENT" }
Plan and apply:
foo@bar:~$ terraform plan -out scenario6 foo@bar:~$ terraform apply "scenario6"
What’s Next?