NGINX App Protect WAF Compiler

Overview

The F5 NGINX App Protect WAF v5 Compiler is a tool that compiles security policies and logging profiles from JSON format to a bundle file that the Enforcer can consume and apply. The bundle file is then referenced in the nginx configuration file. The compiler is packaged as a Docker image and can be run using the Docker CLI or involved during a CI/CD process.

Use Cases

Building Compiler Image

Important:
Regularly rebuild your compiler image and recompile security policies to ensure you are using the latest security updates.
  1. Download Certificates

    Log in to My F5 and download the following two files from your active NGINX App Protect WAF subscription:

    nginx-repo.key
    nginx-repo.crt
    
  2. Configure Docker to interact with the F5 Container Registry at private-registry.nginx.com:

    sudo mkdir -p /etc/docker/certs.d/private-registry.nginx.com
    sudo cp <path-to-your-nginx-repo.crt> /etc/docker/certs.d/private-registry.nginx.com/client.cert
    sudo cp <path-to-your-nginx-repo.key> /etc/docker/certs.d/private-registry.nginx.com/client.key
    
    Note:
    Please note that the file extension for the certificate file has changed from .crt to .cert
  3. Create the Dockerfile:

    # syntax=docker/dockerfile:1
    ARG BASE_IMAGE=private-registry.nginx.com/nap/waf-compiler:<version-tag>
    FROM ${BASE_IMAGE}
    
    # Installing packages as root
    USER root
    
    ENV DEBIAN_FRONTEND="noninteractive"
    
    RUN --mount=type=secret,id=nginx-crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode=0644 \
        --mount=type=secret,id=nginx-key,dst=/etc/ssl/nginx/nginx-repo.key,mode=0644 \
        apt-get update \
        && apt-get install -y \
            apt-transport-https \
            lsb-release \
            ca-certificates \
            wget \
            gnupg2 \
            ubuntu-keyring \
        && wget -qO - https://cs.nginx.com/static/keys/app-protect-security-updates.key | gpg --dearmor | \
        tee /usr/share/keyrings/app-protect-security-updates.gpg >/dev/null \
        && printf "deb [signed-by=/usr/share/keyrings/app-protect-security-updates.gpg] \
        https://pkgs.nginx.com/app-protect-security-updates/ubuntu `lsb_release -cs` nginx-plus\n" | \
        tee /etc/apt/sources.list.d/nginx-app-protect.list \
        && wget -P /etc/apt/apt.conf.d https://cs.nginx.com/static/files/90pkgs-nginx \
        && apt-get update \
        && apt-get install -y \
            app-protect-attack-signatures \
            app-protect-bot-signatures \
            app-protect-threat-campaigns \
        && apt-get clean \
        && rm -rf /var/lib/apt/lists/*
    
    # non-root default user (UID 101)
    USER nginx
    

You can use the Docker registry API to list the available image tags. Replace <path-to-your-nginx-repo.key> with the location of your client key and <path-to-your-nginx-repo.crt> with the location of your client certificate. The optional jq command is used to format the JSON output for easier reading and requires the jq JSON processor to be installed.

curl -s https://private-registry.nginx.com/v2/nap/waf-compiler/tags/list --key <path-to-your-nginx-repo.key> --cert <path-to-your-nginx-repo.crt> |jq
{
  "name": "nap/waf-compiler",
  "tags": [
    "1.0.0",
    "5.1.0",
    "5.2.0"
  ]
}
  1. Build the image

    Run the command below to build your image, where waf-compiler-<version-tag>:custom is an example of the image tag:

    sudo docker build --no-cache \
    --secret id=nginx-crt,src=nginx-repo.crt \
    --secret id=nginx-key,src=nginx-repo.key \
    -t waf-compiler-<version-tag>:custom .
    
Note:
Never upload your NGINX App Protect WAF images to a public container registry such as Docker Hub. Doing so violates your license agreement.

Usage

This section assumes that you built a customized compiler image - waf-compiler-<version-tag>:custom.

Make sure that input files are accessible to UID 101.

Policy Compilation

To compile a security policy from a JSON file and create a policy bundle, execute the following command:

docker run --rm \
 -v $(pwd):$(pwd) \
 waf-compiler-<version-tag>:custom \
 -p $(pwd)/policy.json -o $(pwd)/compiled_policy.tgz

However, to utilize multiple policy bundles within a single NGINX configuration, it’s necessary to supply a global settings JSON file. This ensures that all bundles have a common foundation, including cookie seed, user-defined signatures, and more.

For instance:

global_settings.json:

{
    "waf-settings": {
        "cookie-protection": {
            "seed": "80miIOiSeXfvNBiDJV4t"
        }
    }
}

Compilation with global settings:

docker run --rm \
 -v $(pwd):$(pwd) \
 waf-compiler-1.0.0:custom \
 -g $(pwd)/global_settings.json -p $(pwd)/policy.json -o $(pwd)/compiled_policy.tgz

Using -include-source, you can incorporate the source of the policy (as policy.json) or logging profile (as logging_profile.json) into the final bundle. This process transforms any configuration that relies on external references into an inline configuration within the bundled source. Furthermore, when -include-source is combined with -full-export, the policy.json within the bundle will contain the entire source policy, including any default settings from the base template.

docker run --rm \
 -v $(pwd):$(pwd) \
 waf-compiler-1.0.0:custom \
 -include-source -full-export -g $(pwd)/global_settings.json -p $(pwd)/policy.json -o $(pwd)/compiled_policy.tgz

Logging Profile Compilation

To compile a logging profile, execute the command below:

docker run \
 -v $(pwd):$(pwd) \
 waf-compiler-<version-tag>:custom \
 -l $(pwd)/log_01.json -o $(pwd)/log01.tgz

Bundle Information

To view information about a bundle file, such as attack signatures versions, use the following command:

docker run \
 -v $(pwd):$(pwd) \
 waf-compiler-<version-tag>:custom \
 -dump -bundle $(pwd)/compiled_policy.tgz

Global Settings

The global settings allows configuration of the following items:

waf-settings

Field Name Type Description
cookie-protection object Defines the cookie protection settings.
user-defined-signatures array of objects Defines user defined signatures.
Field Name Type Description
seed string The seed value is used by F5 NGINX App Protect WAF to generate the encryption key for the cookies it creates. These cookies are used for various purposes such as validating the integrity of the cookies generated by the application. Use a random alphanumeric string of at least 20 characters length (but not more than 1000 characters).

user-defined-signatures

Field Name Reference Type Description
$ref Yes string Path to the file that contains the user defined signatures.

Example

{
    "waf-settings": {
        "cookie-protection": {
            "seed": "80miIOiSeXfvNBiDJV4t"
        },
        "user-defined-signatures": [
            {
                "$ref": "file:///policies/uds.json"
            }
        ]
    }
}

Horizontal Scaling

When deploying multiple scalability instances, such as Kubernetes deployment replicas, it is essential to ensure that all policy bundles are compiled with the same global settings and security updates.

WAF Compiler in CI/CD

When executing commands inside the compiler container, especially if it’s part of a CI/CD process and you’re overriding the default entrypoint, ensure that you use /opt/app_protect/bin/apcompile as the compiler binary.

For example:

/opt/app_protect/bin/apcompile -g /path/to/global_settings.json -p /path/to/policy.json -o /path/to/compiled_policy.tgz

Last modified September 25, 2024