Set Up App Protect WAF Configuration Management

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


This documentation applies to NGINX Management Suite Instance Manager 2.6.0 and later.


Overview

NGINX Management Suite Instance Manager provides configuration management for NGINX App Protect WAF. This topic provides instructions for setting up Instance Manager to manage App Protect WAF configurations.

Prerequisites

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

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. To enable this functionality, you’ll need to install the WAF compiler package on the NGINX Management Suite host. If you’ll be continuing with WAF compilation on the data plane host, installation of the NGINX App Protect WAF compiler on the NGINX Management Suite host is not necessary.

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

  • Each NGINX App Protect version has a corresponding compiler version. You must install the 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 compiler package for each on the management plane host. Instance Manager will use the correct 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 Compiler version:

NGINX App Protect WAF Release version WAF Compiler
NGINX App Protect WAF 4.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 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 compiler, then restart the nms-integrations service:

sudo apt-get install -f nms-nap-compiler-v4.2.0
sudo systemctl restart nms-integrations

RHEL 8.1 or later

  1. Download the file dependencies.repo to /etc/yum.repos.d, enable the codeready-builder repository through subscription manager, and install the 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 -f nms-nap-compiler-v4.2.0
    
  2. Restart the nms-integrations service:

    sudo systemctl restart nms-integrations
    

RHEL 7.4 or later; CentOS

  1. Download the file dependencies.repo to /etc/yum.repos.d, enable the RHEL 7 server repositories, and install the 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 -f nms-nap-compiler-v4.2.0
    
  2. Restart the nms-integrations service:

    sudo systemctl restart nms-integrations
    

Oracle Linux 7.4 or later

  1. Download the file dependencies.repo to /etc/yum.repos.d, enable the ol8_codeready_builder repository, and install the 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 -f nms-nap-compiler-v4.2.0
    
  2. Restart the nms-integrations service:

    sudo systemctl restart nms-integrations
    

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 NGINX Management Suite 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 compiler package and transfer it to the NGINX Management Suite host.

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

    • Debian or Ubuntu:
    sudo apt-get install -f /path/to/nms-nap-compiler-<version>_focal_amd64.deb
    
    • RHEL, CentOS, or Oracle Linux:
    sudo yum install -f /path/to/nms-nap-compiler-<version>_el8.ngx.x86_64.rpm
    
  9. Restart the nms-integrations service:

    sudo systemctl restart nms-integrations
    

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 utililites 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"'

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

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.

    You can install the NGINX Agent using curl, wget, or any command-line tool for transferring data with URLs. If the NGINX Management Suite host is not set up with valid TLS certificates, you can use the available insecure flags of those tools. See the following examples:

    • Secure:

      curl https://<NMS-FQDN>/install/nginx-agent | sudo sh -s -- --skip-verify false
      
    • Insecure:

      curl -k https://<NMS-FQDN>/install/nginx-agent | sudo sh
      

      When installing the NGINX Agent with the install script, you can optionally set the instance-group by using the --instance-group flag.

      The following example shows how to download and run the script with the optional flag:

      curl https://<NMS-FQDN>/install/nginx-agent > install.sh
      sudo sh ./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
      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
      

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:/etc/nms;" 
    nginx_app_protect:
       report_interval: 15s              
       precompiled_publication: true
    ...
    
  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. Log in to the NGINX Management Suite user interface and go to Modules > Instance Manager.
  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.

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 reqest 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.

You can find additional example configurations that are tailored for NGINX features in the NGINX App Protect WAF Configuration Guide.

  1. Log in to the NGINX Management Suite user interface and go to Modules > Instance Manager.

  2. Select Instances or Instance Groups.

  3. Select Edit Config from the Actions menu for the desired instance or instance group.

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

  5. If you want to use the default policies, select Apply Security, then select the Copy icon to copy the security policy snippet that you want to add to your configuration.

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

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

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

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 there are any existing security policies referenced in the file, change the file extension from .json to .tgz if precompiled publication is enabled.

    • If you want to use the default policies, paste either of the security policy snippets below into an http, server, or location context in the configuration file. If multiple policies have been published, the most granular will apply.

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

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

    Before sending an updated configuration to an instance group, make sure all of the instances the group have the same NGINX App Protect WAF version installed. The deployment will fail if the instances are running different versions.

    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. Log in to the NGINX Management Suite user interface and go to Modules > Instance Manager.
  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.

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.