Exercise 3.3 - Deploying a WAF policy through AS3


Demonstrate building an Application Service through an AS3 declaration where a WAF policy gets added.


Make sure the BIG-IP configuration is clean, run exercise 3.2-as3-delete before proceeding

Step 1

In exercise 3.0-as3-intro it is explained how AS3 works.

Throughout this exercise we will use three files. Create the two files below

  1. waf_tenant_base.j2
    "class": "AS3",
    "action": "deploy",
    "persist": true,
    "declaration": {
        "class": "ADC",
        "schemaVersion": "3.2.0",
        "id": "testid",
        "label": "test-label",
        "remark": "test-remark",
            "class": "Tenant",
            {{ as3_app_body }}

waf_tenat_base.j2 - is an F5 provided standard template and will include the pointer towards thesecond jinja2 template which includes the actual AS3 schema.

  1. waf_as3_template.j2
"web_app": {
    "class": "Application",
    "template": "http",
    "serviceMain": {
        "class": "Service_HTTP",
        "virtualAddresses": [
        "pool": "app_pool",
        "policyWAF": {
          "use": "new_asm_policy"
    "app_pool": {
        "class": "Pool",
        "monitors": [
        "members": [
                "servicePort": 80,
                "serverAddresses": [
                    {% set comma = joiner(",") %}
                    {% for mem in pool_members %}
                        {{comma()}} "{{  hostvars[mem]['ansible_host']  }}"
                    {% endfor %}

    "new_asm_policy": {
      "class": "WAF_Policy",
      "url": "https://raw.githubusercontent.com/f5devcentral/FAS-ansible-workshop-101/master/3.3-as3-asm/Test_WAF_Policy.xml",
      "ignoreChanges": true

Most of the template is already explained in exercise 3.0-as3-intro. Compared to the original a WAF policy has been added to the

  • url defines the URL where to pull the ASM policy from.


Step 3

Using your text editor of choice create a new file called waf-as3.yml:

Step 4

Enter the following play definition into waf-as3.yml:

- name: Deploy WAF profile using AS3
  hosts: lb
  connection: local
  gather_facts: false

    pool_members: "{{ groups['webservers'] }}"

Step 5

Append the following to the waf-as3.yml Playbook.


- set_fact:
    server: "{{private_ip}}"
    user: "{{ansible_user}}"
    password: "{{ansible_ssh_pass}}"
    server_port: 8443
    validate_certs: no

 - name: Provision BIG-IP with ASM module
     provider: "{{provider}}"
     module: "asm"
     level: "nominal"

The provider gets set and the ASM module gets provisioned to level ‘nominal’.

Step 6

Append the following to the waf-as3.yml playbook.

     as3_app_body: "{{ lookup('template', 'waf_as3_template.j2', split_lines=False) }}"

as3_app_body will get defined via set_fact and renders the waf_as3_template.j2 that is provided.

Step 6

Append the following to the waf-as3.yml Playbook.

- name: PUSH AS3
     url: "https://{{ ansible_host }}:8443/mgmt/shared/appsvcs/declare"
     method: POST
     body: "{{ lookup('template','waf_tenant_base.j2', split_lines=False) }}"
     status_code: 200
     timeout: 300
     body_format: json
     force_basic_auth: yes
     user: "{{ ansible_user }}"
     password: "{{ ansible_ssh_pass }}"
     validate_certs: no
  delegate_to: localhost

Pushing AS3 has been explained in exercise 3.0-as3-intro. Basically the uri parameter gets used to create the REST body. The declaration uses ‘waf_tenant_base.j2’ as the body.

Step 7

Run the playbook - exit back into the command line of the control host and execute the following:

[student1@ansible ~]$ ansible-playbook waf-as3.yml

Playbook Output

The output will look as follows.

PLAY [Deploy WAF profile using AS3] ********************************************************************************************************************

TASK [set_fact] ****************************************************************************************************************************************
ok: [f5]

TASK [Provision BIG-IP with ASM module] ****************************************************************************************************************
changed: [f5]

TASK [CREATE AS3 JSON BODY] ****************************************************************************************************************************
ok: [f5]

TASK [PUSH AS3] ****************************************************************************************************************************************
ok: [f5 -> localhost]

PLAY RECAP *********************************************************************************************************************************************
f5                         : ok=4    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0


The finished Ansible Playbook is provided here for an Answer key. Click here: asm_as3.

Verifying the Solution

Login to the F5 with your web browser to see what was configured. Grab the IP information for the F5 load balancer from the lab_inventory/hosts file, and type it in like so: https://X.X.X.X:8443/

  1. Click on the Local Traffic on the lefthand menu
  2. Click on Virtual Servers.
  3. On the top right, click on the drop down menu titled Partition and select WorkshopExample
  4. The Virtual Server serviceMain will be displayed.
  5. Click on serviceMain and select the tab Security and click Policies. The Application Security policy is enabled and the used policy: new_asm_policy

You have finished this exercise, section 3 and made it tyo the end of FAS-ansible-workshop-101!.