Manage WAF Security Policies

Learn how to use NGINX Management Suite Instance Manager to manage NGINX App Protect WAF security policies.

Overview

With the Instance Manager browser interface or REST API, you can easily manage, update, and deploy security policies, attack signatures, and threat campaigns to your NGINX App Protect WAF instances.


Before You Begin

Complete the following prerequisites before proceeding with this guide:

How to Access the Web Interface

This guide provides instructions on how to complete tasks using the Instance Manager web interface.

To access the web interface, go to the FQDN for your NGINX Management Suite host in a web browser and log in. Once you’re logged in, select “Instance Manager” from the Launchpad menu.

How to Access the REST API

You can interact with the Instance Manager REST API using tools such as curl or Postman. The API URL follows the format https://<NMS_FQDN>/api/nim/<API_VERSION>.

Remember to include your authentication information with each call, as outlined in the API Overview topic.


Create a Security Policy


To create a security policy using the Instance Manager web interface:

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

  2. On the left menu, select App Protect.

  3. On the Security Policies page, select Create.

  4. On the Create Policy page, fill out the necessary fields:

    • Name: Provide a name for the policy.

    • Description: (Optional) Add a short description for the policy.

    • Enter Policy: Type or paste the policy in JSON format into the form provided. The editor will validate the JSON for accuracy.

      For more information about creating custom policies, refer to the NGINX App Protect WAF Declarative Policy guide and the Policy Authoring and Tuning section of the config guide.

  5. Select Save.

To upload a new security policy, send an HTTP POST request to the Security Policies API endpoint.

Important:
Before sending a security policy to Instance Manager, you need to encode it using base64. Submitting a policy in its original JSON format will result in an error.

Method Endpoint
POST /api/platform/v1/security/policies

For example:

curl -X POST https://{{NMS_FQDN}}/api/platform/v1/security/policies \
    -H "Authorization: Bearer xxxxx.yyyyy.zzzzz" \
    -d @ignore-xss-example.json
JSON Request
{
  "metadata": {
    "name": "ignore-cross-site-scripting",
    "displayName": "Ignore cross-site scripting",
    "description": "Ignore cross-site scripting is a security policy that intentionally ignores cross site scripting."
  },
  "content": "ewoJInBvbGljeSI6IHsKCQkibmFtZSI6ICJzaW1wbGUtYmxvY2tpbmctcG9saWN5IiwKCQkic2lnbmF0dXJlcyI6IFsKCQkJewoJCQkJInNpZ25hdHVyZUlkIjogMjAwMDAxODM0LAoJCQkJImVuYWJsZWQiOiBmYWxzZQoJCQl9CgkJXSwKCQkidGVtcGxhdGUiOiB7CgkJCSJuYW1lIjogIlBPTElDWV9URU1QTEFURV9OR0lOWF9CQVNFIgoJCX0sCgkJImFwcGxpY2F0aW9uTGFuZ3VhZ2UiOiAidXRmLTgiLAoJCSJlbmZvcmNlbWVudE1vZGUiOiAiYmxvY2tpbmciCgl9Cn0="
}
JSON Response
{
  "metadata": {
    "created": "2022-04-10T23:19:58.502Z",
    "description": "string",
    "displayName": "Ignore cross-site scripting",
    "modified": "2022-04-12T23:19:58.502Z",
    "name": "ignore-cross-site-scripting",
    "revisionTimestamp": "2022-04-12T23:19:58.502Z",
    "uid": "21daa130-4ba4-442b-bc4e-ab294af123e5"
  },
  "selfLink": {
    "rel": "/api/platform/v1/services/environments/prod"
  }
}

Update a Security Policy

To update a security policy, send an HTTP POST request to the Security Policies API endpoint, /api/platform/v1/security/policies.

You can use the optional isNewRevision parameter to indicate whether the updated policy is a new version of an existing policy.

Method Endpoint
POST /api/platform/v1/security/policies?isNewRevision=true
PUT /api/platform/v1/security/policies/{system_id_string}

For example:

curl -X POST https://{{NMS_FQDN}}/api/platform/v1/security/policies?isNewRevision=true \
    -H "Authorization: Bearer xxxxx.yyyyy.zzzzz" \
    -d @update-xss-policy.json

You can update a specific policy by sending an HTTP PUT request to the Security Policies API endpoint that includes the policy’s unique identifier (UID).

To find the UID, send an HTTP GET request to the Security Policies API endpoint. This returns a list of all Security Policies that contains the unique identifier for each policy.

Include the UID for the security policy in your PUT request to update the policy. Once the policy update is accepted, the WAF compiler will create a new, updated bundle.

For example:

curl -X PUT https://{{NMS_FQDN}}/api/platform/v1/security/policies/23139e0a-4ac8-49f9-b7a0-0577b42c70c7 \
    -H "Authorization: Bearer xxxxx.yyyyy.zzzzz" \
    --Content-Type application/json -d @update-xss-policy.json

After you have pushed an updated security policy, you can publish it to selected instances or instance groups.


Delete a Security Policy


To delete a security policy using the Instance Manager web interface:

  1. Go to the FQDN for your NGINX Management Suite host in a web browser and log in. Then, from the Launchpad menu, select Instance Manager.
  2. On the left menu, select App Protect.
  3. On the Security Policies page, select the Actions menu (represented by an ellipsis, ) for the policy you want to delete. Select Delete to remove the policy.

To delete a security policy, send an HTTP DELETE request to the Security Policies API endpoint that includes the unique identifier for the policy that you want to delete.

Method Endpoint
DELETE /api/platform/v1/security/policies/{security-policy-uid}

For example:

curl -X DELETE https://{{NMS_FQDN}}/api/platform/v1/security/policies/23139e0a-4ac8-49f9-b7a0-0577b42c70c7 \
    -H "Authorization: Bearer xxxxx.yyyyy.zzzzz

Publish Updates to Instances

The Publish API lets you distribute security policies, attack signatures, and/or threat campaigns to instances and instance groups.

Tip:
Use this endpoint after you’ve added or updated security policies, attack signatures, and/or threat campaigns.
Method Endpoint
POST /api/platform/v1/security/publish

When making a request to the Publish API, make sure to include all the necessary information for your specific use case:

  • Instance and/or Instance Group UID(s) to push the bundle to
  • Threat Campaign version and UID
  • Attack Signature version and UID
  • Security Policy UID(s)

For example:

curl -X PUT https://{{NMS_FQDN}}/api/platform/v1/security/publish -H "Authorization: Bearer xxxxx.yyyyy.zzzzz"
JSON Request
{
  "publications": [
    {
      "attackSignatureLibrary": {
        "uid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "versionDateTime": "2022.10.02"
      },
      "instanceGroups": [
        "3fa85f64-5717-4562-b3fc-2c963f66afa6"
      ],
      "instances": [
        "3fa85f64-5717-4562-b3fc-2c963f66afa6"
      ],
      "policyContent": {
        "name": "default-enforcement",
        "uid": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
      },
      "threatCampaign": {
        "uid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "versionDateTime": "2022.10.01"
      }
    }
  ]
}
JSON Response
{
  "deployments": [
    {
      "deploymentUID": "ddc781ca-15d6-46c9-86ea-e7bdb91e8dec",
      "links": {
        "rel": "/api/platform/v1/security/deployments/ddc781ca-15d6-46c9-86ea-e7bdb91e8dec"
      },
      "result": "Publish security content request Accepted"
    }
  ]
}

Check for Compilation Errors

If you encounter any compilation errors when publishing an NGINX configuration that references a security policy, the Instance Manager REST API can provide further details about the error. To access this information, use the Instances API endpoint and method as indicated.

To retrieve the details of an instance, send an HTTP GET request to the Instance API endpoint, providing the the unique system and instance identifiers.

Method Endpoint
GET /api/platform/v1/systems/{system-uid}/instances/{instance-id}

You can locate the compiler-related error message in the response within these fields:

  • error: lastDeploymentDetails -> details -> error
  • failMessage: lastDeploymentDetails -> details -> failure -> failMessage

The example below shows a call to the instances endpoint and the corresponding JSON response containing a compiler error message.

curl -X GET "https://{NGINX-INSTANCE-MANAGER-FQDN}/api/platform/v1/systems/b9df6377-2c4f-3266-a64a-e064b0371c73/instances/5663cf4e-a0c7-50c8-b93c-16fd11a0f00b" -H "Authorization: Bearer xxxxx.yyyyy.zzzzz"
JSON Response
{
  "build": {
    "nginxPlus": true,
    "release": "nginx-plus-r28",
    "version": "1.23.2"
  },
  "configPath": "/etc/nginx/nginx.conf",
  "configVersion": {
    "instanceGroup": {
      "createTime": "0001-01-01T00:00:00Z",
      "uid": "",
      "versionHash": ""
    },
    "versions": [
      {
        "createTime": "2023-01-14T10:48:46.319Z",
        "uid": "5663cf4e-a0c7-50c8-b93c-16fd11a0f00b",
        "versionHash": "922e9d40fa6d4dd3a4b721295b8ecd95f73402644cb8d234f9f4f862b8a56bfc"
      }
    ]
  },
  "displayName": "ip-192-0-2-27",
  "links": [
    {
      "rel": "/api/platform/v1/systems/b9df6377-2c4f-3266-a64a-e064b0371c73",
      "name": "system"
    },
    {
      "rel": "/api/platform/v1/systems/b9df6377-2c4f-3266-a64a-e064b0371c73/instances/5663cf4e-a0c7-50c8-b93c-16fd11a0f00b",
      "name": "self"
    },
    {
      "rel": "/api/platform/v1/systems/instances/deployments/b31c6ab1-4a46-4c81-a065-204575145e8e",
      "name": "deployment"
    }
  ],
  "processPath": "/usr/sbin/nginx",
  "registrationTime": "2023-01-14T10:12:31.000Z",
  "startTime": "2023-01-14T10:09:43Z",
  "status": {
    "lastStatusReport": "2023-01-14T11:11:49.323495017Z",
    "state": "online"
  },
  "uid": "5663cf4e-a0c7-50c8-b93c-16fd11a0f00b",
  "version": "1.23.2",
  "appProtect": {
    "attackSignatureVersion": "Available after publishing Attack Signatures from Instance Manager",
    "status": "active",
    "threatCampaignVersion": "Available after publishing Threat Campaigns from Instance Manager",
    "version": "4.2.0"
  },
  "configureArgs": [
    ...
  ],
  "lastDeploymentDetails": {
    "createTime": "2023-01-14T11:10:25.096812852Z",
    "details": {
      "error": "{\"instance:b9df6377-2c4f-3266-a64a-e064b0371c73\":\"failed building config payload: policy compilation failed for deployment b31c6ab1-4a46-4c81-a065-204575145e8e due to integrations service error: the specified compiler (4.2.0) is missing, please install it and try again.\"}",
      "failure": [
        {
          "failMessage": "failed building config payload: policy compilation failed for deployment b31c6ab1-4a46-4c81-a065-204575145e8e due to integrations service error: the specified compiler (4.2.0) is missing, please install it and try again.",
          "name": "ip-192-0-2-27"
        }
      ],
      "pending": [],
      "success": []
    },
    "id": "b31c6ab1-4a46-4c81-a065-204575145e8e",
    "message": "Instance config failed to publish to",
    "status": "finalized",
    "updateTime": "2023-01-14T11:10:25.175145693Z"
  },
  "loadableModules": [
    ...
  ],
  "packages": [
    ...
  ],
  "processId": "10345",
  "ssl": {
    "built": null,
    "runtime": null
  }
}

When you use the Publish API (/security/publish) to publish a security policy, Instance Manager creates a deployment ID for the request. To view the status of the update, or to check for any errors, use the endpoint and method shown below and reference the deployment ID.

Method Endpoint
GET /api/platform/v1/systems/instances/deployments/{deployment-id}

When using this endpoint, you can find the compiler-related error messages in the following fields:

  • error: details -> error
  • failMessage: details -> failure -> failMessage

The example below shows a call to the deployments endpoint and the corresponding JSON response containing a compiler error message.

curl -X GET --url "https://{NGINX-INSTANCE-MANAGER-FQDN}/api/platform/v1/systems/instances/deployments/d38a8e5d-2312-4046-a60f-a30a4aea1fbb" \
    -H "Authorization: Bearer xxxxx.yyyyy.zzzzz"
JSON Response
{
  "createTime": "2023-01-14T04:35:47.566082799Z",
  "details": {
    "error": "{\"instance:8a2092aa-5612-370d-bff0-5d7521e206d6\":\"failed building config payload: policy bundle compilation failed for d38a8e5d-2312-4046-a60f-a30a4aea1fbb, integrations service returned the following error: missing the specified compiler (4.2.0) please install it and try again\"}",
    "failure": [
      {
        "failMessage": "failed building config payload: policy bundle compilation failed for d38a8e5d-2312-4046-a60f-a30a4aea1fbb, integrations service returned the following error: missing the specified compiler (4.2.0) please install it and try again",
        "name": "ip-192-0-2-243"
      }
    ],
    "pending": [],
    "success": []
  },
  "id": "d38a8e5d-2312-4046-a60f-a30a4aea1fbb",
  "message": "Instance config failed to publish to",
  "status": "finalized",
  "updateTime": "2023-01-14T04:35:47.566082799Z"
}