Skip to content

Latest commit

 

History

History
294 lines (207 loc) · 12 KB

File metadata and controls

294 lines (207 loc) · 12 KB
title Build and use the compiler tool
weight 200
toc true
f5-content-type how-to
f5-product F5WAFN

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]({{< ref "/waf/policies/attack-signatures.md" >}}), 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.

{{< call-out class="note" title="Alternatives to the compiler tool">}}

If you are using a virtual machine/bare-metal installation, read the [Update F5 WAF for NGINX signatures]({{< ref "/waf/install/update-signatures.md" >}}) topic.

If you are using a Helm-based Kubernetes deployment, read the [Kubernetes operations improvements (Early access)]({{< ref "/waf/install/kubernetes-plm.md" >}}) topic.

{{< /call-out >}}

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.

For more information about policies, read the [Configure policies]({{< ref "/waf/policies/configuration.md" >}}) topic.

Before you begin

To complete this guide, you will need the following prerequisites:

Download your subscription credentials

{{< include "licensing-and-reporting/download-certificates-from-myf5.md" >}}

Configure Docker for the F5 Container Registry

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

Create the Dockerfile

This example Dockerfile is based on a Debian image.

# syntax=docker/dockerfile:1
ARG BASE_IMAGE=private-registry.nginx.com/nap/waf-compiler:{{< version-waf-compiler >}}
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

{{< call-out class="note" >}}

You can can upgrade or downgrade one of the Signatures by specifying a specific version, such as app-protect-attack-signatures-2020.04.30.

{{< /call-out >}}

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>

Build the container image

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 .

{{< call-out class="warning" >}}

Never upload your F5 WAF for NGINX images to a public container registry such as Docker Hub. Doing so violates your license agreement.

{{< /call-out >}}

Update security packages in the compiler image

To use newer attack signatures, bot signatures, or threat campaigns with the compiler workflow, rebuild your compiler image with the updated security packages, then recompile your policy bundles.

Updating the compiler image alone does not update a running F5 WAF for NGINX deployment. The Enforcer continues to use the signatures contained in the currently deployed policy bundle until you deploy a newly compiled bundle and apply the updated configuration.

To apply updated signatures from a compiler image:

  1. Rebuild the compiler image with the updated security packages:
    • app-protect-attack-signatures
    • app-protect-bot-signatures
    • app-protect-threat-campaigns
  2. Recompile all policy bundles with the rebuilt compiler image.
  3. Replace or mount the updated bundle in your F5 WAF for NGINX deployment.
  4. Apply the updated configuration:
    • If only the F5 WAF for NGINX configuration changed, and nginx.conf and its included files did not change, use [apreload]({{< ref "/waf/configure/apreload.md" >}}).
    • If nginx.conf, any included NGINX file, or any App Protect directive in nginx.conf changed, reload NGINX.

A full NGINX restart is not required.

Using the compiler

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.

Compile a security policy

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

{{< call-out class="warning" >}}

Ensure that the output directory is writable, otherwise you may encounter a permission denied error.

{{< /call-out >}}

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-<version-tag>: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-<version-tag>: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.

Compile a logging profile

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

View 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

Debugging bundle errors

When [configuring policies]({{< ref "/waf/policies/configuration.md">}}), you may run into problems.

There are ways to remediate them based on the context:

{{< table >}}

Description Solution
Expected declarative policy Ensure the JSON of the policy is well-formed
Policy Bundles version is older than the local version You must recompile all your bundles from scratch when installing security updates.
Policy Bundles version is newer than the local version You must recompile all your bundles from scratch when installing security updates.
Found mixed content of compiled and raw configuration Only pre-compiled bundles can be used in NGINX configuration: compile JSON to bundles first.
Compiler is required, but not installed: Missing /opt/app_protect/bin/config_set_compiler Only pre-compiled bundles can be used in NGINX configuration: compile JSON to bundles first.
Policy Bundles have differing global states Recompile all of your bundles from scratch with your custom compiler. Bundles must be compiled with the same compiler: you cannot mix default and custom bundles.
Policy Bundles have differing cookie seeds Recompile all of your bundles from scratch with your custom compiler. Bundles must be compiled with the same compiler: you cannot mix default and custom bundles.
Duplicate policy name found Don't compile multiple policies with the same name, or one policy to multiple bundles. Each policy can be compiled once but a bundle can be re-used.
Duplicate logging profile name found Don't compile the same logging profile to multiple bundles. Each profile can be compiled once but a bundle can be re-used.
Timeout waiting for enforcer Likely an internal issue: [contact Support]({{< ref "/waf/support.md" >}})

{{< /table >}}

Global settings

The global settings allows configuration of the following items:

cookie-protection

Name 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).

user-defined-signatures

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"
            }
        ]
    }
}

{{< call-out class="warning" >}}

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.

{{< /call-out >}}

Using the compiler in a CI/CD process

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