Build and use the compiler tool
Information architecture noteThis page replaces V5 F5 WAF for NGINX Compiler page.
Does this exclusively work with V5 versions?
This document describes how to use the F5 WAF for NGINX compiler, a tool for converting security policies and logging profiles from JSON to a bundle file that F5 WAF can process and apply.
You can use it to get the latest security updates for Attack Signatures, Threat Campaigns and Bot Signatures. The compiler is packaged as a Docker image and can executed using the Docker CLI or as part of a continuous integration/ continuous delivery (CI/CD) pipeline.
One or more bundle files can be referenced in the NGINX configuration file, and you can configure global settings such as the cookie seed and user-defined signatures.
To complete this guide, you will need the following prerequisites:
- An active F5 WAF for NGINX subscription (Purchased or trial)
- Credentials to the MyF5 Customer Portal, provided by email from F5, Inc.
- Docker
- Log in to MyF5.
- Go to My Products & Plans > Subscriptions to see your active subscriptions.
- Find your NGINX subscription, and select the Subscription ID for details.
- Download the SSL Certificate and Private Key files from the subscription page.
Create a directory and copy your certificate and key to this directory:
mkdir -p /etc/docker/certs.d/private-registry.nginx.com
cp <path-to-your-nginx-repo.crt> /etc/docker/certs.d/private-registry.nginx.com/client.cert
cp <path-to-your-nginx-repo.key> /etc/docker/certs.d/private-registry.nginx.com/client.key
Log in to the Docker registry:
docker login private-registry.nginx.com
This example Dockerfile is based on a Debian image.
# 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 can upgrade or downgrade one of the Signatures by specifying a specific version, such as app-protect-attack-signatures-2020.04.30.
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.
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>
{
"name": "nap/waf-compiler",
"tags": [
"1.0.0",
"5.1.0",
"5.2.0"
]
}
The jq command was used to format the example output.
Run the following command to build your image, where waf-compiler-<version-tag>:custom
is an example of the image tag:
sudo docker build --no-cache --platform linux/amd64 \
--secret id=nginx-crt,src=nginx-repo.crt \
--secret id=nginx-key,src=nginx-repo.key \
-t waf-compiler-<version-tag>:custom .
Never upload your F5 WAF for NGINX images to a public container registry such as Docker Hub. Doing so violates your license agreement.
This section uses version-tag
as a placeholder in its examples, following the previous section. Ensure that all input files are accessible to UID 101.
To compile a security policy from a JSON file and create a policy bundle, run the following command:
docker run --rm \
-v $(pwd):$(pwd) \
waf-compiler-<version-tag>:custom \
-p $(pwd)/policy.json -o $(pwd)/compiled_policy.tgz
Ensure that the output directory is writable, otherwise you may encounter a permission denied error.
To use multiple policy bundles within a single NGINX configuration, you must supply a global settings JSON file.
This ensures that all bundles have a common foundation such as cookie seed and user-defined signatures.
An example global_settings.json
might look as follows:
{
"waf-settings": {
"cookie-protection": {
"seed": "<seed value>"
}
}
}
To compile a policy with global settings, add the -g
parameter:
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
You can incorporate the source of the policy (as policy.json
) or logging profile (as logging_profile.json
) into the final bundle using the -include-source
parameter.
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
This will transform any configuration that relies on external references into an inline configuration within the bundled source.
Additionally, 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.
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
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
The global settings allows configuration of the following items:
Field Name | Reference | Type | Description |
---|---|---|---|
seed | string | The seed value is used by F5 WAF for NGINX 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). |
Field Name | Reference | Type | Description |
---|---|---|---|
$ref | Yes | string | Path to the file that contains the user defined signatures. |
{
"waf-settings": {
"cookie-protection": {
"seed": "80miIOiSeXfvNBiDJV4t"
},
"user-defined-signatures": [
{
"$ref": "file:///policies/uds.json"
}
]
}
}
When deploying multiple scalability instances (Such as Kubernetes deployment replicas), ensure that all policy bundles are compiled with the same global settings and security updates.
When executing commands inside the compiler container, ensure that you use /opt/app_protect/bin/apcompile
as the compiler binary.
This is particularly important if you’re overriding the default entry point as part of a CI/CD process.
/opt/app_protect/bin/apcompile -g /path/to/global_settings.json -p /path/to/policy.json -o /path/to/compiled_policy.tgz