Manage Your App Protect WAF Configs

Learn how to use NGINX Management Suite Instance Manager to secure your applications with NGINX App Protect WAF security policies.

Overview

Instance Manager helps you manage your NGINX App Protect WAF configurations, making it easy to stay secure. This guide shows you how to set up Instance Manager to configure and manage NGINX App Protect WAF.

Before You Begin

Complete the following prerequisites before proceeding with this guide.

  • You have one or more instances of NGINX App Protect WAF installed and running. See Support for NGINX App Protect WAF for a list of supported versions.

    Note:
    If you are using configuration management and the NGINX Management Suite Security Monitoring module, follow the instructions in the setup guide to set up your NGINX App Protect instances before proceeding with this guide.
  • You have Instance Manager v2.6.0 or later installed, licensed, and running. If you have a subscription to NGINX App Protect WAF, you can find your Instance Manager license in the subscription details section of MyF5.

Limitations

Important:
App Protect WAF Config management is currently not supported when deploying Instance Manager on Kubernetes.

Instance Manager does not support the following NGINX App Protect features:


Install the WAF Compiler

Instance Manager can use the NGINX App Protect WAF compiler to “pre-compile” security configurations before syncing them to managed data plane instances. You’ll need to install the WAF compiler package on the NGINX Management Suite host to enable this functionality. If you’ll be continuing with WAF compilation on the data plane host, installing the WAF compiler on the NGINX Management Suite host is not necessary.

Be sure to download and install the correct WAF compiler version for your environment:

  • Each NGINX App Protect version has a corresponding WAF compiler version. You must install the WAF compiler that matches the version of NGINX App Protect that you have running.
  • If you have different NGINX App Protect versions running, install the correct WAF compiler package for each on the management plane host. Instance Manager will use the correct WAF compiler for each version to bundle the security configurations.
  • You can create instance groups to keep track of and manage all instances that have the same version installed.

For more information about the WAF compiler, refer to the Security Bundle Compilation section of the Policy Configuration overview topic.

WAF Compiler and Supported App Protect Versions

The following table shows the NGINX App Protect WAF Release version and its corresponding WAF compiler version:

NGINX App Protect WAF Release version WAF Compiler
NGINX App Protect WAF 4.8.1 nms-nap-compiler-v4.815.0
NGINX App Protect WAF 4.8.0 nms-nap-compiler-v4.762.0
NGINX App Protect WAF 4.7.0 nms-nap-compiler-v4.641.0
NGINX App Protect WAF 4.6.0 nms-nap-compiler-v4.583.0
NGINX App Protect WAF 4.5.0 nms-nap-compiler-v4.457.0
NGINX App Protect WAF 4.4.0 nms-nap-compiler-v4.402.0
NGINX App Protect WAF 4.3.0 nms-nap-compiler-v4.279.0
NGINX App Protect WAF 4.2.0 nms-nap-compiler-v4.218.0
NGINX App Protect WAF 4.1.0 nms-nap-compiler-v4.100.1
NGINX App Protect WAF 4.0.0 nms-nap-compiler-v4.2.0
NGINX App Protect WAF 3.12.2 nms-nap-compiler-v3.1088.2

Note:
  • The install commands in this guide use an example version to show the correct command format.

    Be sure to replace the version string in the example with the correct version to suit your needs. You can find the package versions in the NGINX App Protect WAF Release Notes.

  • The WAF compiler installs to the /opt directory. Set the permission level for the directory as appropriate to allow write access by the owner (for example, 0755).

Debian or Ubuntu

Install the WAF compiler, then restart the nms-integrations service:

sudo apt-get install nms-nap-compiler-v4.815.0
Note:
  • If you want to have more than one version of the nms-nap-compiler installed on your system at once, you’ll need to append -o Dpkg::Options::="--force-overwrite" to the nms-nap-compiler installation commands after your initial nms-nap-compiler installation. For example, the installation command would look like this:
sudo apt-get install nms-nap-compiler-v4.815.0 -o Dpkg::Options::="--force-overwrite"

RHEL 8.1 or later

Download the file dependencies.repo to /etc/yum.repos.d, enable the codeready-builder repository through subscription manager, and install the WAF compiler package:

sudo wget -P /etc/yum.repos.d https://cs.nginx.com/static/files/dependencies.repo
sudo subscription-manager repos --enable codeready-builder-for-rhel-8-x86_64-rpms
sudo yum install nms-nap-compiler-v4.815.0

RHEL 7.4 or later; CentOS

Download the file dependencies.repo to /etc/yum.repos.d, enable the RHEL 7 server repositories, and install the WAF compiler package.

sudo wget -P /etc/yum.repos.d https://cs.nginx.com/static/files/dependencies.repo
sudo yum-config-manager --enable rhui-REGION-rhel-server-optional rhui-REGION-rhel-server-releases rhel-7-server-optional-rpms
sudo yum install nms-nap-compiler-v4.815.0

Amazon Linux 2 LTS

Download the files nms-amazon2.repo and app-protect-7.repo to /etc/yum.repos.d, enable the Extra Packages for Enterprise (EPEL) repository, and install the WAF compiler package:

sudo wget -P /etc/yum.repos.d https://cs.nginx.com/static/files/nms-amazon2.repo
sudo wget -P /etc/yum.repos.d https://cs.nginx.com/static/files/app-protect-7.repo
sudo amazon-linux-extras enable epel
sudo yum clean metadata
sudo yum install epel-release
sudo yum install nms-nap-compiler-v4.815.0

Oracle Linux 7.4 or later

Download the file dependencies.repo to /etc/yum.repos.d, enable the ol8_codeready_builder repository, and install the WAF compiler package:

sudo wget -P /etc/yum.repos.d https://cs.nginx.com/static/files/dependencies.repo
sudo yum-config-manager --enable ol8_codeready_builder
sudo yum install nms-nap-compiler-v4.815.0

Download from MyF5

If you are not able to access the public NGINX repository, you can download all of the required packages from MyF5.

Take the steps below to download the WAF compiler, Attack Signatures, and Threat Campaigns packages from MyF5.

  1. Log in to MyF5.

  2. Go to Resources > Downloads.

  3. Select Group/Product Family: NGINX.

  4. Select Product Line: NGINX App Protect.

  5. Select a Product version.

  6. Select the Linux distribution, distribution version, and Architecture.

  7. Download the WAF compiler package and transfer it to the NGINX Management Suite host.

  8. Run the appropriate command on the host to install the WAF compiler package from the file.

    • Debian or Ubuntu:
    sudo apt-get install -f /path/to/nms-nap-compiler-<version>_focal_amd64.deb
    
    Note:

    For Debian or Ubuntu, if you want to have more than one version of the nms-nap-compiler installed on your system at once, you’ll need to append -o Dpkg::Options::="--force-overwrite" to the nms-nap-compiler installation commands after your initial nms-nap-compiler installation. For example, the installation command would look like this:

    sudo apt-get install -f /path/to/nms-nap-compiler-<version>_focal_amd64.deb -o Dpkg::Options::="--force-overwrite"
    
    • RHEL, CentOS, or Oracle Linux:
    sudo yum install -f /path/to/nms-nap-compiler-<version>_el8.ngx.x86_64.rpm
    

Automatically Download and Install New WAF Compiler

Once a version of the NGINX App Protect WAF compiler is manually installed on Instance Manager, the system will automatically download and install a new WAF compiler when it detects that an update is required. This typically happens when the NGINX App Protect WAF version on the data plane has been upgraded or when a new data plane with a different NGINX App Protect WAF version is added.

To enable the automatic download and installation of a new WAF compiler, you need to upload your NGINX App Protect WAF certificate and key to Instance Manager. This upload needs to be done only once. By providing the certificate and key, Instance Manager can securely fetch and install the latest WAF compiler from the NGINX repository.

If the automatic download and install of the new WAF compiler step fails, when publishing the NGINX configuration, the error message

missing the specific compiler, please install it and try again.

will appear. This happens if the NGINX App Protect WAF certificate and key are missing or not working, or if Instance Manager cannot connect to the NGINX Repository. Please check /var/log/nms/nms.log for errors.

If you see the following error, your NGINX App Protect WAF certificate and key are missing, invalid, or have expired:

error when creating the nginx repo retriever - NGINX repo certificates not found

Also, please refer to Install the WAF Compiler for details on how to manually install the new WAF compiler.


Set Up Attack Signatures and Threat Campaigns

NGINX App Protect provides predefined Attack Signatures to protect your application against all attack types identified by the system. As new Attack Signatures are identified, they will become available for download so that your system will always have the most up-to-date protection.

Threat Campaigns is a threat intelligence feature included in an NGINX App Protect WAF subscription. The feature includes frequent update feeds containing contextual information about active attack campaigns currently being observed by F5 Threat Labs that NGINX App Protect WAF can provide protection against. Just like Attack Signatures, the Threat Campaign patterns are updated regularly. Unlike Attack Signatures, the NGINX App Protect WAF installation does not include any Threat Campaigns and you need to install them in order for the protection to take effect. Due to the highly dynamic nature of those campaigns the updates are issued far more frequently than the Attack Signatures. You need to install those updates close to the time they are issued in order to get the most effective protection.

In order to take advantage of new Attack Signature and Threat Campaign packages, you need to upload these packages to NGINX Management Suite.

You can either configure Instance Manager to download new versions automatically, or manage the files manually by downloading the packages from MyF5 and then uploading them to Instance Manager by using the REST API.

Automatically Download Latest Packages

Upload NGINX App Protect WAF Certificate and Key

You will need to use your NGINX repo certificates to setup automatic retrieval of Attack Signatures and Threat Campaigns packages. When you upload your NGINX App Protect WAF certificate and key to NGINX Instance Manager, you are letting NGINX Instance Manager access the NGINX repo to get Attack Signature and Threat Campaign files on your behalf.

  1. Log in to MyF5 and go to My Products and Plans > Subscriptions to download the SSL certificate (nginx-repo.crt) and private key (nginx-repo.key) for your NGINX App Protect subscription.

  2. Create a JSON file, similar to the example below, that contains the text from your crt and key files. You will need to replace all of the newlines in the crt and key output with \n.

    {
        "name": "nginx-repo",
        "nginxResourceType": "NginxRepo",
        "certPEMDetails": {
            "caCerts": [],
            "password": "",
            "privateKey": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDt71QRqMl/7/rv\n[CONTENT SNIPPED]\n-----END PRIVATE KEY-----\n",
            "publicCert": "-----BEGIN CERTIFICATE-----\nMIIEPzCCAyegAwIBAgIRANydR2VZ+mlt75SkttRyQTkwDQYJKoZIhvcNAQELBQAw\n[CONTENT SNIPPED]\n-----END CERTIFICATE-----",
            "type": "PEM"
        }
    }
    
  3. Send an HTTP POST request to the Instance Manager REST API to upload the repo certificate and key.

    Example request
    curl -X POST 'https://{{NMS_FQDN}}//api/platform/v1/certs'  \
        --header "Authorization: Bearer xxxxx.yyyyy.zzzzz"      \
        --header "Content-Type: application/json"                \
        -d@nginx-repo-certs.json
    
    Example response
    {
        "certAssignmentDetails": [],
        "certMetadata": [
            {
            "authorityKeyIdentifier": "<FINGERPRINT>",
            "commonName": "<SUBSCRIPTION NAME>",
            "expired": false,
            "expiry": 59789838,
            "issuer": "C=US, ST=Washington, L=Seattle,  Inc., O=F5 Networks\\, OU=Certificate Authority, CN=F5 PRD Issuing Certificate Authority TEEM V1",
            "publicKeyType": "RSA (2048 bit)",
            "serialNumber": "<SERIAL NUMBER>",
            "signatureAlgorithm": "SHA256-RSA",
            "subject": "CN=<SUBSCRIPTION NAME>",
            "subjectAlternativeName": "",
            "subjectKeyIdentifier": "<FINGERPRINT>",
            "thumbprint": "<THUMBPRINT>",
            "thumbprintAlgorithm": "SHA256-RSA",
            "validFrom": "2021-12-21T16:57:55Z",
            "validTo": "2024-12-20T00:00:00Z",
            "version": 3
            }
        ],
        "certPEMDetails": {
            "caCerts": [],
            "password": "**********",
            "privateKey": "**********",
            "publicCert": "[CONTENT SNIPPED]",
            "type": "PEM"
        },
        "created": "2023-01-27T23:42:41.587760092Z",
        "modified": "2023-01-27T23:42:41.587760092Z",
        "name": "nginx-repo",
        "serialNumber": "<SERIAL NUMBER>",
        "uid": "d08d9f54-58dd-447a-a71d-6fa5aa0d880c",
        "validFrom": "2021-12-21T16:57:55Z",
        "validTo": "2024-12-20T00:00:00Z"
        }
    

Enable automatic downloads

Instance Manager can automatically download the latest Attack Signature and Threat Campaign versions. To enable automatic downloads, take the steps below.

  1. Log in to the management plane host using SSH.

  2. Open the /etc/nms/nms.conf file for editing.

  3. Adjust the app_protect_security_update options, shown in the example below, to enable and configure automatic downloads:

    integrations:
      # enable this for integrations on tcp
      # address: 127.0.0.1:8037
      address: unix:/var/run/nms/integrations.sock
      # Dqlite config
      dqlite:
        addr: 127.0.0.1:7892
      app_protect_security_update:
        # Enable this setting to automatically retrieve the latest Attack Signatures and Threat Campaigns.
        enable: true
        # Enable this setting to specify how often, in hours, the latest Attack Signatures and Threat Campaigns are retrieved.
        # The default interval is 6 hours, the maximum interval is 48 hours, and the minimum is 1 hour.
        interval: 6
        # Enable this setting to specify how many updates to download for the latest Attack Signatures and Threat Campaigns.
        # By default, the 10 latest updates are downloaded. The maximum value is 20, and the minimum value is 1.
        number_of_updates: 10
    
  4. Save the changes and close the file.

  5. Restart the nms-integrations service:

    sudo systemctl restart nms-integrations
    

If you do not see the latest Attack Signatures and Threat Campaigns packages downloaded as expected, please check /var/log/nms/nms.log for errors.

If you see the following error, your NGINX App Protect WAF certificate and key are invalid or have expired:

error when creating the nginx repo retriever - NGINX repo certificates not found

Manually Update Packages

Download packages from MyF5

  1. Log in to MyF5, then go to Resources > Downloads.

  2. Select Group/Product Family: NGINX.

  3. Select Product Line: NGINX App Protect.

  4. Select a Product version (a version that matches your WAF compiler version).

  5. Select your Linux Distribution, Version and Architecture.

  6. Find and download the deb or rpm package starting with “app-protect-attack-signatures” for Attack Signatures and “app-protect-threat-campaigns” for Threat Campaigns.

  7. Using utilities such as az or rpm2cpio|cpio to extract the following 3 files from the package:

    • signatures.bin.tgz for Attack Signatures or threat_campaigns.bin.tgz for Threat Campaigns
    • signature_update.yaml for Attack Signatures or threat_campaign_update.yamlfor Threat Campaigns
    • version
  8. Using a file archive utility, such as tar, bundle the three files into a single .tgz file. For example:

    tar –czvf attack-signatures.tgz signatures.bin.tgz signature_update.yaml version
    

Upload packages to Instance Manager

You will need to use the Instance Manager REST API to upload the bundled Attack Signatures and Threat Campaigns.

Attack Signatures Example
curl -X POST 'https://{{NMS_FQDN}}//api/platform/v1/security/attack-signatures' \
    --header "Authorization: Bearer xxxxx.yyyyy.zzzzz"      \
    --form 'revisionTimestamp="2022.11.16"'                 \
    --form 'filename=@"/attack-signatures.tgz"'
Threat Campaigns Example
curl -X POST 'https://{{NMS_FQDN}}//api/platform/v1/security/threat-campaigns' \
    --header "Authorization: Bearer xxxxx.yyyyy.zzzzz"      \
    --form 'revisionTimestamp="2022.11.15"'                 \
    --form 'filename=@"/threat-campaigns.tgz"'
Important:
The bundle you upload for Attack Signatures or Threat Campaigns must correspond to the OS of your Instance Manager. For example, if your Instance Manager is running on ubuntu-20.04, then the bundle you upload for Attack Signatures or Threat Campaigns needs to be created from the ubuntu-20.04 packages.

Update the Security Monitoring Signature Database

The Security Monitoring module’s analytics dashboards make use of a Signature Database to provide more information on Attack Signatures that have triggered Security Violations, such as the Signature’s name, accuracy, and risk level.

To ensure that the dashboards show the most up-to-date information, you need to update the Security Monitoring Signature Database


Setup Compiler Resource Pruning

You can configure the following compiler resources to prune automatically:

  • Compiled Security Policies
  • Compiled Security Log Profiles
  • Attack Signatures
  • Threat Campaigns

In the case of compiled security policies and compiled security log profiles, the definition of the security policy and/or security log profile is not removed. Only the compiled bundles associated with those resources are removed.

To enable automatic compiler resource pruning, please follow these steps:

  1. Log in to the management plane host using SSH.

  2. Open the /etc/nms/nms.conf file for editing.

  3. Update the policy_manager field to contain the desired time to live values for each resource type; see the following snippet for an example of adding the necessary fields under integrations->policy_manager:

    integrations:
    address: unix:/var/run/nms/integrations.sock
    dqlite:
        addr: 127.0.0.1:7892
    policy_manager:
        # Time to live for attack signatures. If the attack signatures exceed their TTL and are not deployed to an instance or
        # instance group they will be deleted from the database. Duration unit can be seconds (s), minutes (m), or hours (h).
        attack_signatures_ttl: 336h
        # Time to live for compiled bundles, this includes compiled security policies and compiled log profiles. If a compiled
        # bundle exceeds its TTL and is not deployed to an instance or instance group it will be deleted from the database. Note
        # that the compiled bundle is deleted, not the definition of it (i.e. the security policy or log profile definition).
        # Duration unit can be seconds (s), minutes (m), or hours (h).
        compiled_bundles_ttl: 336h
        # Time to live for threat campaigns. If the threat campaigns exceed their TTL and are not deployed to an instance or
        # instance group they will be deleted from the database. Duration unit can be seconds (s), minutes (m), or hours (h).
        threat_campaigns_ttl: 1440h
    app_protect_security_update:
        enable: true
        interval: 6
        number_of_updates: 10
    
  4. Save the changes and close the file.

  5. Restart the nms-integrations service:

    sudo systemctl restart nms-integrations
    

The compiler resource pruning process occurs once upon start-up of the nms-integrations service and once every 24 hours after the nms-integrations service has been started.


Onboard NGINX App Protect WAF Instances

To onboard your NGINX App Protect WAF instances to Instance Manager, you need to install and configure NGINX Agent.

Install NGINX Agent

  1. Use SSH to connect to the NGINX App Protect WAF instance. Take the steps below for each instance to download and install NGINX Agent from the management plane host.

  2. Download the NGINX Agent package from the NGINX Management Suite host and run the agent install script.

    Tip:
    You can add instances with the same version of NGINX App Protect installed to an instance group by running the agent install command on each instance with the optional `–instance-group`` flag.

    Note: To complete this step, make sure that gpg is installed on your system. You can install NGINX Agent using various command-line tools like curl or wget. If your NGINX Management Suite host is not set up with valid TLS certificates, you can use the insecure flags provided by those tools. See the following examples:

    • Secure:

      curl https://<NMS_FQDN>/install/nginx-agent | sudo sh
         
    • Insecure:

      curl --insecure https://<NMS_FQDN>/install/nginx-agent | sudo sh
         

      You can add your NGINX instance to an existing instance group or create one using --instance-group or -g flag when installing NGINX Agent.

      The following example shows how to download and run the script with the optional --instance-group flag adding the NGINX instance to the instance group my-instance-group:

      curl https://<NMS_FQDN>/install/nginx-agent > install.sh; chmod u+x install.sh
         sudo ./install.sh --instance-group my-instance-group
         

      By default, the install script attempts to use a secure connection when downloading packages. If, however, the script cannot create a secure connection, it uses an insecure connection instead and logs the following warning message:

      Warning: An insecure connection will be used during this nginx-agent installation
         

      To require a secure connection, you can set the optional flag skip-verify to false.

      The following example shows how to download and run the script with an enforced secure connection:

      curl https://<NMS_FQDN>/install/nginx-agent > install.sh chmod u+x install.sh; chmod u+x install.sh
         sudo sh ./install.sh --skip-verify false
         

    • Secure:

      wget https://<NMS_FQDN>/install/nginx-agent -O - | sudo sh -s --skip-verify false
         
    • Insecure:

      wget --no-check-certificate https://<NMS_FQDN>/install/nginx-agent -O - | sudo sh
         

      When you install the NGINX Agent, you can use the --instance-group or -g flag to add your NGINX instance to an existing instance group or to a new group that you specify.

      The following example downloads and runs the NGINX Agent install script with the optional --instance-group flag, adding the NGINX instance to the instance group my-instance-group:

      wget https://gnms1.npi.f5net.com/install/nginx-agent -O install.sh ; chmod u+x install.sh
         sudo ./install.sh --instance-group my-instance-group
         

Configure NGINX Agent

  1. Edit the NGINX Agent configuration file (/etc/nginx-agent/nginx-agent.conf) to allow access to the /etc/app-protect directory and enable reporting.

    • The agent needs access to any directories where NGINX App Protect configuration files are stored on the data plane host.
    • The report_interval is the length of time the agent waits between checks for changes to NGINX App Protect WAF configurations.
    • precompiled_publication enables the publication of precompiled NGINX App Protect security policies and log profiles.
    ...
    config_dirs: "/etc/nginx:/usr/local/etc/nginx:/usr/share/nginx/modules:/etc/nms:/etc/app_protect"
    extensions:
      - nginx-app-protect
    nginx_app_protect:
       report_interval: 15s
       precompiled_publication: true
    ...
    
    Note:

    You can use the NGINX Agent installation script to add these fields:

    # Download install script via API
    curl https://<NMS_FQDN>/install/nginx-agent > install.sh
    
    # Specify the -m | --nginx-app-protect-mode flag to set up management of NGINX App Protect on
    # the instance. In the example below we specify 'precompiled-publication' for the flag value
    # which will make the config field 'precompiled_publication' set to 'true', if you would like to
    # set the config field 'precompiled_publication' to 'false' you can specify 'none' as the flag value.
    sudo sh ./install.sh --nginx-app-protect-mode precompiled-publication
    
  2. Restart NGINX Agent.

    sudo systemctl restart nginx-agent
    

Verify Installation

You should now be able to view your NGINX App Protect WAF instances in the Instance Manager user interface. Take the steps below to verify that NGINX Agent is installed and reporting data to Instance Manager.

  1. In a web browser, go to the FQDN for your NGINX Management Suite host and log in. Then, select Instance Manager from the Launchpad menu.

  2. Select Instances.

  3. You should see the installed version listed in the NGINX App Protect column.

  4. Select the instance, then scroll to the App Protect Details section. There, you should see the “App Protect WAF” status and “Build” should match the version installed on the instance.

See Also:
You can use tools such as curl or Postman to interact with the Instance Manager REST API. The API URL follows the format https://<NMS_FQDN>/api/[nim|platform]/<API_VERSION> and must include authentication information with each call. For more information about authentication options, please refer to the API Overview.

You can query the Instance Manager REST API to verify the following information:

  • NGINX App Protect WAF version
  • NGINX App Protect WAF running status
  • Total number of instances with NGINX App Protect WAF installed, out of the total number of NGINX instances
Method Endpoint
GET /api/platform/v1/instances
GET /api/platform/v1/systems
  • Send an HTTP GET request to the /api/platform/v1/systems endpoint to find out what version of NGINX App Protect is running. This response will also show the Threat Campaign and Attack Signature package versions running on each instance.

    JSON response
    {
    "count": 3,
    "items": [
        [...]
        "appProtect": {
        "attackSignatureVersion": "2022.11.16",
        "status": "active",
        "threatCampaignVersion": "2022.11.15",
        "version": "build-3.954.0"
        },
        [...]
    ]
    }
    
  • Send an HTTP GET request to the /api/platform/v1/instances endpoint to find out the number of instances with NGINX App Protect WAF installed. The total count will be in the nginxAppProtectWAFCount field in the response.

    For example:

    JSON response
    {
    "count": 3,
    "items": [
        [...]
    ],
    "nginxAppProtectWAFCount": 2,
    "nginxPlusCount": 3
    }
    


Onboard Security Policies

Instance Manager provides the same default security policies as NGINX App Protect WAF:

  • NGINX Default Policy: provides OWASP Top 10 and Bot security protection.
  • NGINX Strict Policy: contains more restrictive criteria for blocking traffic than the default policy.

If you want to use the out-of-the-box policies, you can proceed to the next section: Add WAF configuration to NGINX Instances.

Continue in this section if you have custom security policies that you want to upload to Instance Manager.

Upload Custom Security Policies

If you onboarded NGINX App Protect WAF instances with existing security configurations, you’ll need to use the Instance Manager REST API to onboard the security policies referenced in the nginx.conf on your NGINX App Protect instances.

To do so, take the steps below for each policy:

  1. Use base64 to encode the JSON policy.

    For example:

    base64 -i ./ignore-xss-policy-example.json
    
    ignore-xss-policy-example.json
    {
        "policy": {
            "name": "ignore-xss",
            "template": {
                "name": "POLICY_TEMPLATE_NGINX_BASE"
            },
            "applicationLanguage": "utf-8",
            "enforcementMode": "blocking",
            "signatures": [
                {
                    "signatureId": 200001475,
                    "enabled": false
                },
                {
                    "signatureId": 200000098,
                    "enabled": false
                },
                {
                    "signatureId": 200001148,
                    "enabled": false
                },
                {
                    "signatureId": 200001480,
                    "enabled": false
                },
                {
                    "signatureId": 200001088,
                    "enabled": false
                }
            ],
            "bot-defense": {
                "settings": {
                    "isEnabled": false
                }
            },
            "headers": [
                {
                    "name": "*",
                    "type": "wildcard",
                    "decodeValueAsBase64": "disabled"
                },
                {
                    "name": "*-bin",
                    "type": "wildcard",
                    "decodeValueAsBase64": "required"
                },
                {
                    "name": "Referer",
                    "type": "explicit",
                    "decodeValueAsBase64": "disabled"
                },
                {
                    "name": "Authorization",
                    "type": "explicit",
                    "decodeValueAsBase64": "disabled"
                },
                {
                    "name": "Transfer-Encoding",
                    "type": "explicit",
                    "decodeValueAsBase64": "disabled"
                }
            ],
            "cookies": [
                {
                    "name": "*",
                    "type": "wildcard",
                    "decodeValueAsBase64": "disabled"
                }
            ],
            "parameters": [
                {
                    "name": "*",
                    "type": "wildcard",
                    "decodeValueAsBase64": "disabled"
                }
            ]
        }
    }
    
  2. Create a JSON request body that contains the encoded policy.

    For example:

    {
    "metadata": {
        "name": "ignore-xss-example",
        "displayName": "Ignore Cross Site Scripting example",
        "description": "Security policy that intentionally ignores cross site scripting"
    },
    "content":
        "ewogICAgInBvbGljeSI6IHsKICAgICAgICAibmFtZSI6ICJpZ25vcmUteHNzIiwKICAgICAgICAidGVtcGxhdGUiOiB7CiAgICAgICAgICAgICJuYW1lIjogIlBPTElDWV9URU1QTEFURV9OR0lOWF9CQVNFIgogICAgICAgIH0sCiAgICAgICAgImFwcGxpY2F0aW9uTGFuZ3VhZ2UiOiAidXRmLTgiLAogICAgICAgICJlbmZvcmNlbWVudE1vZGUiOiAiYmxvY2tpbmciLAogICAgICAgICJzaWduYXR1cmVzIjogWwogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAic2lnbmF0dXJlSWQiOiAyMDAwMDE0NzUsCiAgICAgICAgICAgICAgICAiZW5hYmxlZCI6IGZhbHNlCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJzaWduYXR1cmVJZCI6IDIwMDAwMDA5OCwKICAgICAgICAgICAgICAgICJlbmFibGVkIjogZmFsc2UKICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgInNpZ25hdHVyZUlkIjogMjAwMDAxMTQ4LAogICAgICAgICAgICAgICAgImVuYWJsZWQiOiBmYWxzZQogICAgICAgICAgICB9LAogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAic2lnbmF0dXJlSWQiOiAyMDAwMDE0ODAsCiAgICAgICAgICAgICAgICAiZW5hYmxlZCI6IGZhbHNlCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJzaWduYXR1cmVJZCI6IDIwMDAwMTA4OCwKICAgICAgICAgICAgICAgICJlbmFibGVkIjogZmFsc2UKICAgICAgICAgICAgfQogICAgICAgIF0sCiAgICAgICAgImJvdC1kZWZlbnNlIjogewogICAgICAgICAgICAic2V0dGluZ3MiOiB7CiAgICAgICAgICAgICAgICAiaXNFbmFibGVkIjogZmFsc2UKICAgICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgImhlYWRlcnMiOiBbCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJuYW1lIjogIioiLAogICAgICAgICAgICAgICAgInR5cGUiOiAid2lsZGNhcmQiLAogICAgICAgICAgICAgICAgImRlY29kZVZhbHVlQXNCYXNlNjQiOiAiZGlzYWJsZWQiCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJuYW1lIjogIiotYmluIiwKICAgICAgICAgICAgICAgICJ0eXBlIjogIndpbGRjYXJkIiwKICAgICAgICAgICAgICAgICJkZWNvZGVWYWx1ZUFzQmFzZTY0IjogInJlcXVpcmVkIgogICAgICAgICAgICB9LAogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAibmFtZSI6ICJSZWZlcmVyIiwKICAgICAgICAgICAgICAgICJ0eXBlIjogImV4cGxpY2l0IiwKICAgICAgICAgICAgICAgICJkZWNvZGVWYWx1ZUFzQmFzZTY0IjogImRpc2FibGVkIgogICAgICAgICAgICB9LAogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAibmFtZSI6ICJBdXRob3JpemF0aW9uIiwKICAgICAgICAgICAgICAgICJ0eXBlIjogImV4cGxpY2l0IiwKICAgICAgICAgICAgICAgICJkZWNvZGVWYWx1ZUFzQmFzZTY0IjogImRpc2FibGVkIgogICAgICAgICAgICB9LAogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAibmFtZSI6ICJUcmFuc2Zlci1FbmNvZGluZyIsCiAgICAgICAgICAgICAgICAidHlwZSI6ICJleHBsaWNpdCIsCiAgICAgICAgICAgICAgICAiZGVjb2RlVmFsdWVBc0Jhc2U2NCI6ICJkaXNhYmxlZCIKICAgICAgICAgICAgfQogICAgICAgIF0sCiAgICAgICAgImNvb2tpZXMiOiBbCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJuYW1lIjogIioiLAogICAgICAgICAgICAgICAgInR5cGUiOiAid2lsZGNhcmQiLAogICAgICAgICAgICAgICAgImRlY29kZVZhbHVlQXNCYXNlNjQiOiAiZGlzYWJsZWQiCiAgICAgICAgICAgIH0KICAgICAgICBdLAogICAgICAgICJwYXJhbWV0ZXJzIjogWwogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAibmFtZSI6ICIqIiwKICAgICAgICAgICAgICAgICJ0eXBlIjogIndpbGRjYXJkIiwKICAgICAgICAgICAgICAgICJkZWNvZGVWYWx1ZUFzQmFzZTY0IjogImRpc2FibGVkIgogICAgICAgICAgICB9CiAgICAgICAgXQogICAgfQp9CiAgICAgICAgCg=="
      }
    
  3. Send an HTTP POST request to the /api/platform/v1/security/policies endpoint to create the policy on Instance Manager.

    For example:

    curl -X POST https://{{NMS_FQDN}}/api/platform/v1/security/policies \
    -H "Authorization: Bearer xxxxx.yyyyy.zzzzz" --ContentType application/json \
    -d '{"content": "ewogICAgInBvbGljeSI6[CONTENT_SNIPPED]QogICAgfQp9CiAgICAgICAgCg==", \
    "metadata": {"description": "Ignore cross-site scripting is a security policy that intentionally ignores cross site scripting.", \
    "displayName": "Ignore cross-site scripting example", "name": "ignore-xss-example"}}'
    

    You should receive a success response similar to the example below:

    {
        "metadata": {
            "created": "2022-12-16T03:41:53.516Z",
            "description": "Security policy that intentionally ignores cross site scripting",
            "displayName": "Ignore Cross Site Scripting example",
            "modified": "2022-12-16T03:47:34.465920964Z",
            "name": "ignore-xss-example",
            "revisionTimestamp": "2022-12-16T03:41:53.516Z",
            "uid": "23139e0a-4ac8-49f9-b7a0-0577b42c70c7"
        },
        "selfLink": {
            "rel": "/api/platform/v1/security/policies/23139e0a-4ac8-49f9-b7a0-0577b42c70c7"
        }
    }
    
  4. Verify that your policies have been onboarded by sending an HTTP GET request to the /api/platform/v1/security/policies endpoint:

    curl -X GET https://{{NMS_FQDN}}/api/platform/v1/security/policies \
    -H "Authorization: Bearer xxxxx.yyyyy.zzzzz"
    

    You should receive a success response similar to the example below:

    Example response
    {
        "items": [
            {
                "content": "",
                "metadata": {
                    "created": "2022-12-14T00:04:07.646Z",
                    "description": "The default policy provides OWASP Top 10 and Bot security protection",
                    "displayName": "NGINX Default Policy",
                    "modified": "2022-12-14T00:04:07.646Z",
                    "name": "NginxDefaultPolicy",
                    "revisionTimestamp": "2022-12-14T00:04:07.646Z",
                    "uid": "ae7d2ffc-972d-4951-a7ba-2340e1b8fe1c"
                }
            },
            {
                "content": "",
                "metadata": {
                    "created": "2022-12-14T00:04:07.65Z",
                    "description": "The strict policy contains more restrictive criteria for blocking traffic than the default policy",
                    "displayName": "NGINX Strict Policy",
                    "modified": "2022-12-14T00:04:07.65Z",
                    "name": "NginxStrictPolicy",
                    "revisionTimestamp": "2022-12-14T00:04:07.65Z",
                    "uid": "94665634-0d7e-4b72-87e8-491d951c8510"
                }
            },
            {
                "content": "",
                "metadata": {
                    "created": "2022-12-16T03:41:53.516Z",
                    "description": "Security policy that intentionally ignores cross site scripting",
                    "displayName": "Ignore Cross Site Scripting example",
                    "modified": "2022-12-16T03:47:34Z",
                    "name": "ignore-xss-example",
                    "revisionTimestamp": "2022-12-16T03:41:53.516Z",
                    "uid": "23139e0a-4ac8-49f9-b7a0-0577b42c70c7"
                }
            }
        ]
    }
    

Add WAF Configuration to NGINX Instances

The NGINX App Protect WAF Configuration Guide provides information about how and where to add the directives that allow you to add security to your instances. Instance Manager ships with the same reference policies as NGINX App Protect WAF:

  • NGINX Default Policy (NginxDefaultPolicy.tgz): Provides OWASP Top 10 and Bot security protection out of the box.
  • NGINX Strict Policy (NginxStrictPolicy.tgz): Contains more restrictive criteria for blocking traffic than the default policy, with a higher risk of false positives.

You can use either of these policies as-is. Many users treat the reference policy as starting point and customize it to suit the needs of their applications. The Security Monitoring dashboards provide insights that can help you fine-tune your security policies.

When using Instance Manager to manage your WAF configuration, keep the following in mind:

  • Instance Manager can compile JSON security policies into a .tgz bundle.

  • You can reference custom policy files using the app_protect_policy_file directive.

    Important:
    If you already have JSON security policies referenced in your NGINX configuration, you can keep them as-is if precompiled publication is not enabled in the NGINX Agent. However, you’ll need to change the file extension for the referenced files from .json to .tgz if precompiled publication is enabled. The file name for the compiled bundle will be the same as the original file. Instance Manager does not support both .json and .tgz files within a single NGINX configuration
  • If you are using custom policies, be sure NGINX Agent has permission to access the location(s) where the policies are stored on the data plane. To do so, edit the NGINX Agent configuration file on the data plane host and add the custom file path to the config_dirs setting.

  • Instance Manager uses the NGINX App Protect WAF default log profiles. You can specify the desired log profile by using the app_protect_security_log directive. Instance Manager does not support the use of custom log profiles.

The examples in this guide use the default path for NGINX App Protect configuration files. If you have these files stored elsewhere on your data plane instance(s), be sure to use the correct file path when setting up your configuration.

Edit the NGINX configuration

By using the Instance Manager web interface or REST API, add the NGINX App Protect WAF configurations to the appropriate context in your NGINX configuration.

The example below shows the directives added to a location block:

...
server {
  ...

  location / {
  ##Enable NGINX App Protect
  app_protect_enable on;
  ## Reference to a custom security policy bundle
  app_protect_policy_file /etc/nms/ignore-xss.tgz;
  ## enable logging
  app_protect_security_log_enable on;
  ## Reference to the log profile bundle
  app_protect_security_log /etc/nms/log-default.tgz;
  ...
}
Note:

If you’re using the NGINX Management Suite Security Monitoring module, you should already have the app_protect_security_log directive set to reference the secops_dashboard.tgz file as shown below. Do not change this setting.

app_protect_security_log "/etc/nms/secops_dashboard.tgz" syslog:server=127.0.0.1:514

Refer to the Security Monitoring setup guide to learn more.

Additional example configurations tailored for NGINX features can be found in the NGINX App Protect WAF Configuration Guide.


  1. In a web browser, go to the FQDN for your NGINX Management Suite host and log in. Then, select Instance Manager from the Launchpad menu.

  2. On the left menu, select Instances or Instance Groups.

  3. Select Edit Config from the Actions menu (represented by an ellipsis, ...) for the desired instance or instance group.

  4. If precompiled publication is enabled, change the file extension from .json to .tgz if there are any referenced security policies in the file.

  5. If you want to apply the default security policy, select Apply Security and then copy the desired policy snippet by selecting Copy.

  6. Paste the snippet into an http, server, or location context in the configuration.

    If multiple policies have been published, the most granular policy will apply.

  7. Select Publish to immediately push the updated configuration to the selected instance or instance group.

See Also:
You can use tools such as curl or Postman to interact with the Instance Manager REST API. The API URL follows the format https://<NMS_FQDN>/api/[nim|platform]/<API_VERSION> and must include authentication information with each call. For more information about authentication options, please refer to the API Overview.

Method Endpoint
GET /api/platform/v1/systems/{systemUID}/instances
POST /api/platform/v1/security/{systemUID}/instances/{nginxUID}/config
  1. Send an HTTP GET request to the /api/platform/v1/systems/{systemUID}/instances endpoint. This returns a list of all instances from which you can find the unique identifier (UID) of the instance that you want to update.

  2. Add the desired configurations to your nginx.conf file, or to any other configuration file that’s within the context defined in the NGINX Agent config_dirs setting.

    • At a minimum, you should add app_protect_enable on;.

    • If precompiled publication is enabled, change the file extension from .json to .tgz if there are any referenced security policies in the file.

    • If you’d like to use the default security policies, paste either of the policy snippets below into an http, server, or location context in the configuration file. The most granular policy will be applied if multiple policies have been published.

      app_protect_policy_file /etc/nms/NginxDefaultPolicy.tgz;
      app_protect_policy_file /etc/nms/NginxStrictPolicy.tgz;
      
  3. Encode the configuration file using base64:

    base64 -i /etc/nginx/nginx.conf
    
  4. Provide the encoded string in configFiles.files.contents, as shown below.

    Important! Before deploying an updated configuration to an instance group, ensure that all instances in the group have the same version of NGINX App Protect WAF installed. Otherwise, the deployment may fail.

    curl -X POST https://{{NMS_FQDN}}/api/platform/v1/systems/{systemUID}/instances/{nginxUID}/config -H "Authorization: Bearer xxxxx.yyyyy.zzzzz" \
        --Content-Type application/json -d @
    
    JSON Response
    {
    "auxFiles": {
        "files": [
        {
            "contents": "PCFET0NUWVBFIGh0bWw+CjxodG1sPgo8aGVhZD4KP<EXAMPLE_SNIPPED>",
            "name": "/var/www/html/index.nginx-debian.html"
        }
        ],
    
        "rootDir": "/"
    },
    
    "configFiles": {
        "files": [
        {
            "contents": "dXNlciB3d3ctZGF0YTsKd29ya2VyX3Byb2Nlc3Nlc<EXAMPLE_SNIPPED>",
            "name": "nginx.conf"
        }
        ],
    
        "rootDir": "/etc/nginx"
    },
    
    "configUID": "",
    "ignoreConflict": false,
    "validateConfig": true
    }
    

Verify Configuration

Once you have added the NGINX App Protect WAF directives to your NGINX configuration, you should see the NGINX App Protect WAF status reported as “Active”. Take the steps below to verify the configuration in the Instance Manager web interface.

  1. In a web browser, go to the FQDN for your NGINX Management Suite host and log in. Then, select Instance Manager from the Launchpad menu.

  2. Select Instances.
  3. You should see the installed version listed in the NGINX App Protect column.
  4. Select the instance, then scroll to the App Protect Details section. There, you should see the “App Protect WAF” status is “Active”. The “Build” should match the version installed on the instance.

Troubleshooting

If you’re having issues with NGINX App Protect WAF, we suggest trying the following troubleshooting steps. If none of them helps, please reach out to NGINX Customer Support for further assistance.

Verify that NGINX App Protect WAF is not installed on the NGINX Management Suite host

To ensure no library conflicts arise when installing nms-nap-compiler, verify that NGINX App Protect WAF is not installed on the NGINX Management Suite host. You can do this by taking the following steps:

  1. Open an SSH connection to your NGINX Management Suite host and log in.

  2. Run the following command:

    • Debian-based distributions, run dpkg -s app-protect
    • RPM-based distributions, run rpm -qi grep app-protect

If NGINX App Protect WAF is installed, you’ll need to uninstall it.

Verify the WAF compiler version and NGINX App Protect version match

Each NGINX App Protect WAF version has a corresponding version of the WAF compiler. You must install the correct WAF compiler version for the version of NGINX App Protect WAF running on the managed instance(s). Refer to WAF Compiler and Supported App Protect Versions for compatibility details.

To view the installed version of the WAF compiler:

  1. Open an SSH connection to your NGINX Management Suite host and log in.

  2. Run the following command:

    ls -l /opt/nms-nap-compiler
    
Verify the WAF compiler is running properly

Check if the WAF compiler has been installed and is working properly by viewing the command-line help:

sudo /opt/nms-nap-compiler/app_protect-<version>/bin/apcompile -h

For example, to view the help description for WAF compiler 4.815.0, run the following command:

sudo /opt/nms-nap-compiler/app_protect-4.815.0/bin/apcompile -h

The output looks similar to the following example:

USAGE:
    /opt/nms-nap-compiler/app_protect-4.815.0/bin/apcompile <options>

Examples:
    /opt/nms-nap-compiler/app_protect-4.815.0/bin/apcompile -p /path/to/policy.json -o mypolicy.tgz
    /opt/nms-nap-compiler/app_protect-4.815.0/bin/apcompile -p policyA.json -g myglobal.json -o /path/to/policyA_bundle.tgz
    /opt/nms-nap-compiler/app_protect-4.815.0/bin/apcompile -g myglobalsettings.json --global-state-outfile /path/to/myglobalstate.tgz
    /opt/nms-nap-compiler/app_protect-4.815.0/bin/apcompile -b /path/to/policy_bundle.tgz --dump
    /opt/nms-nap-compiler/app_protect-4.815.0/bin/apcompile -l logprofA.json -o /path/to/logprofA_bundle.tgz
...

Verify NGINX Agent configuration on NGINX App Protect WAF instance

Configure NGINX Agent on your NGINX App Protect WAF instance with settings similar to the following example:

“/etc/nginx-agent/nginx-agent.conf”

# path to aux file dirs can also be added
config_dirs: "/etc/nginx:/usr/local/etc/nginx:/usr/share/nginx/modules:/etc/nms:/etc/app_protect"

# Enable necessary NAP extensions
extensions:
    - nginx-app-protect
    - nap-monitoring

nginx_app_protect:
  # Report interval for NGINX App Protect details - the frequency the NGINX Agent checks NGINX App Protect for changes.
  report_interval: 15s
  # Enable precompiled publication from the NGINX Management Suite (true) or perform compilation on the data plane host (false).
  precompiled_publication: true

nap_monitoring:
  # Buffer size for collector. Will contain log lines and parsed log lines
  collector_buffer_size: 50000
  # Buffer size for processor. Will contain log lines and parsed log lines
  processor_buffer_size: 50000
  # Syslog server IP address the collector will be listening to
  syslog_ip: "127.0.0.1"
  # Syslog server port the collector will be listening to
  syslog_port: 514

Verify access to the NGINX packages repository

To allow Instance Manager to automatically download the latest Attack Signatures and Threat Campaigns, you need to upload the certificate and key files included with your subscription to allow access to the package repository.

If you already uploaded your certificate and key files, use the command below to verify that they allow access to the package repo:

curl --key /etc/ssl/nginx/nginx-repo.key --cert /etc/ssl/nginx/nginx-repo.crt https://pkgs.nginx.com/app-protect-security-updates/index.xml

The output looks similar to the following example:

...
<repositories>
<repository distro="centos" version="6" arch="x86_64" prefix="centos/6/x86_64/">
</repository>
<repository distro="centos" version="7" arch="x86_64" prefix="centos/7/x86_64/">
<package type="rpm">
  <name>app-protect-attack-signatures</name>
  <arch>x86_64</arch>
  <version epoch="0" ver="2019.07.16" rel="1.el7.ngx"/>
<location href="RPMS/app-protect-attack-signatures-2019.07.16-1.el7.ngx.x86_64.rpm"/>
</package>
<package type="rpm">
  <name>app-protect-attack-signatures</name>
  <arch>x86_64</arch>
  <version epoch="0" ver="2020.04.30" rel="1.el7.ngx"/>
<location href="RPMS/app-protect-attack-signatures-2020.04.30-1.el7.ngx.x86_64.rpm"/>
</package>
...

What’s Next

Now that configuration management is set up, you can use the Instance Manager REST API to manage security policies, view system information about your NGINX App Protect WAF instances, and update Attack Signatures and Threat Campaigns. Learn more in Manage App Protect WAF Configuration using the REST API.