From e6f936939d917634bd0824d15226c87ac5ac2499 Mon Sep 17 00:00:00 2001 From: Sylvia Wang Date: Fri, 3 Apr 2026 16:10:56 -0700 Subject: [PATCH 01/13] N1C WAF Security Dashboard Release --- .../waf-security-dashboard/_index.md | 18 ++ .../default-log-profile.md | 48 +++ .../set-up-security-monitoring.md | 293 ++++++++++++++++++ 3 files changed, 359 insertions(+) create mode 100644 content/nginx-one-console/waf-security-dashboard/_index.md create mode 100644 content/nginx-one-console/waf-security-dashboard/default-log-profile.md create mode 100644 content/nginx-one-console/waf-security-dashboard/set-up-security-monitoring.md diff --git a/content/nginx-one-console/waf-security-dashboard/_index.md b/content/nginx-one-console/waf-security-dashboard/_index.md new file mode 100644 index 000000000..0dc385580 --- /dev/null +++ b/content/nginx-one-console/waf-security-dashboard/_index.md @@ -0,0 +1,18 @@ +--- +title: F5 WAF for NGINX security monitoring +description: Monitor security events and review WAF dashboards to assess threats +weight: 425 +url: /nginx-one-console/waf-security-dashboard +--- + +Use the Security Monitoring module in NGINX One Console to monitor data from F5 WAF for NGINX instances. Review the security dashboards to assess potential threats and identify opportunities to fine-tune your policies. + +## Dashboard metrics overview + +The security dashboard displays key metrics to help you understand attack patterns and threats. Here's an overview of the main metrics: + +- **Attack Counts** - Track the number of attacks with percentage change comparisons against previous periods +- **Violation Types** - View violations grouped by category (e.g., Protocol Compliance) to understand threat patterns +- **Signatures** - See specific signatures triggered within each violation type across multiple events +- **Event Details** - Access Support IDs, raw request data, triggered signatures, and contextual metadata (Original IP, X-Forwarded-For, Violation Context) +- **Global Filters** - Apply filters by time period, policy, and attack type to instantly update all dashboard widgets diff --git a/content/nginx-one-console/waf-security-dashboard/default-log-profile.md b/content/nginx-one-console/waf-security-dashboard/default-log-profile.md new file mode 100644 index 000000000..d06058066 --- /dev/null +++ b/content/nginx-one-console/waf-security-dashboard/default-log-profile.md @@ -0,0 +1,48 @@ +--- +title: Default log profile +description: Learn about the security dashboard default log profile and how to deploy it +weight: 200 +nd-content-type: concept +nd-product: NONECO +--- + +The default log profile is a pre-configured F5 WAF for NGINX log profile designed specifically for security event monitoring in NGINX One Console. It captures security violation data in a standardized format optimized for analysis and troubleshooting. + +## About the default log profile + +The default log profile is similar to [other log profiles]({{< ref "/nginx-one-console/waf-integration/log-profiles/_index.md" >}}) in structure and function, but has these key characteristics: + +- **Immutable** — The default log profile cannot be edited or deleted. This ensures the security monitoring data format remains consistent across your deployment. +- **Pre-compiled** — NGINX One Console automatically compiles the default log profile for all available WAF compiler versions. This eliminates the need for on-demand compilation during deployment. +- **Standardized format** — It captures all necessary security telemetry fields for the security dashboard, including support IDs, violation details, signature information, and client context. + +## When to use the default log profile + +Use the default log profile when you want to: +- Send security violation data to NGINX One Console for centralized monitoring +- Analyze attack patterns and trends across your NGINX fleet +- Review violation details and raw request data for specific security events +- Generate baseline security metrics and trending reports + +For specialized logging requirements beyond security monitoring, you can create and deploy custom log profiles alongside the default profile. + +## Deploy the default log profile + +To deploy the default log profile to your NGINX instances or Config Sync Groups, follow the same process described in [Deploy log profiles]({{< ref "/nginx-one-console/waf-integration/log-profiles/deploy-log-profiles.md" >}}). + +The default log profile can be deployed using either of these methods: + +1. **Direct deployment** — Go to **WAF** > **Log Profiles**, select the default log profile, and use **Actions** > **Deploy** to send it to your target instances or Config Sync Groups. + +2. **During configuration editing** — When editing an instance or Config Sync Group configuration, you can select the default log profile from **Add File** > **Existing Log Profile** and specify the deployment path. + +Since the default log profile is pre-compiled for all WAF compiler versions, deployment completes immediately without requiring additional compilation. + +For detailed deployment instructions, see [Deploy log profiles]({{< ref "/nginx-one-console/waf-integration/log-profiles/deploy-log-profiles.md" >}}). + +## Next steps + +After deploying the default log profile: +- Monitor security events in the [F5 WAF for NGINX security monitoring dashboard]({{< ref "/nginx-one-console/waf-security-dashboard/" >}}) +- Review security event details and identify attack patterns +- Fine-tune your F5 WAF for NGINX policies based on observed violations diff --git a/content/nginx-one-console/waf-security-dashboard/set-up-security-monitoring.md b/content/nginx-one-console/waf-security-dashboard/set-up-security-monitoring.md new file mode 100644 index 000000000..8d7000519 --- /dev/null +++ b/content/nginx-one-console/waf-security-dashboard/set-up-security-monitoring.md @@ -0,0 +1,293 @@ +--- +title: Set up security monitoring +description: Configure NGINX Plus with F5 WAF for NGINX to forward security events to NGINX One Console +weight: 100 +nd-content-type: how-to +nd-product: NONECO +--- + +This guide walks you through configuring your NGINX Plus data plane to send security telemetry to NGINX One Console. You'll install F5 WAF for NGINX, configure the security dashboard log profile, and set up NGINX Agent to forward security events. + +## Prerequisites + +- NGINX Plus installed and running on your data plane +- Root or sudo access on the data plane system +- NGINX One Console access with permissions to add instances + +## Verify NGINX Plus is running + +Before you begin, confirm that NGINX Plus is installed and running on your system. + +1. Run the following command to check the NGINX Plus service status: + +```bash +sudo systemctl status nginx +``` + +Your output should show that the service is active and running: + +``` +● nginx.service - NGINX Plus - high performance web server + Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: enabled) + Active: active (running) since Wed 2026-03-11 17:26:52 UTC; 1 week 1 day ago + Docs: https://www.nginx.com/resources/ + Main PID: 3682 (nginx) + Tasks: 3 (limit: 4586) + Memory: 4.3M (peak: 4.9M) + CPU: 807ms +``` +If NGINX Plus is not installed, see the [NGINX Plus installation guide]({{< ref "/content/nginx/admin-guide/installing-nginx/installing-nginx-plus.md" >}}). + + +## Install F5 WAF for NGINX + +Install F5 WAF for NGINX on your data plane following the [installation instructions for your operating system]({{< ref "/content/waf/install/virtual-environment.md" >}}). + +After installation, continue with the next section to configure the security dashboard log profile. + +## Configure the security dashboard log profile + +The security dashboard uses the default log profile to capture security violations. This is a pre-configured, immutable log profile that is automatically compiled for all available WAF compiler versions. For more information about the default log profile, see [Default log profile]({{< ref "/nginx-one-console/waf-security-dashboard/default-log-profile.md" >}}). + +To configure the security dashboard, create the `/etc/app_protect/conf/secops_dashboard.json` file with the following content: + +1. Create the file: + +```bash +sudo touch /etc/app_protect/conf/secops_dashboard.json +``` + +2. Add the log profile configuration: + +```bash +sudo tee /etc/app_protect/conf/secops_dashboard.json > /dev/null << 'EOF' +{ + "filter": { + "request_type": "illegal" + }, + "content": { + "format": "user-defined", + "format_string": "%support_id%|%ip_client%|%src_port%|%dest_ip%|%dest_port%|%vs_name%|%policy_name%|%method%|%uri%|%protocol%|%request_status%|%response_code%|%outcome%|%outcome_reason%|%violation_rating%|%blocking_exception_reason%|%is_truncated_bool%|%sig_ids%|%sig_names%|%sig_cves%|%sig_set_names%|%threat_campaign_names%|%sub_violations%|%x_forwarded_for_header_value%|%violations%|%violation_details%|%request%|%geo_location%", + "max_request_size": "2048", + "max_message_size": "64k", + "escaping_characters": [ + { + "from": "|", + "to": "%7C" + } + ] + } +} +EOF +``` + +## Enable F5 WAF for NGINX in your configuration + +Update your NGINX configuration to enable F5 WAF for NGINX and specify the security dashboard log profile. + +### Update the main NGINX configuration + +Edit `/etc/nginx/nginx.conf` and add the `load_module` directive at the top: + +```nginx +user nginx; +worker_processes auto; +load_module modules/ngx_http_app_protect_module.so; +error_log /var/log/nginx/error.log notice; +pid /run/nginx.pid; + +events { + worker_connections 1024; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + keepalive_timeout 65; + + include /etc/nginx/conf.d/*.conf; +} +``` + +### Configure a server block with F5 WAF for NGINX + +Edit `/etc/nginx/conf.d/default.conf` to add the F5 WAF for NGINX directives: + +```nginx +server { + listen 80 default_server; + server_name localhost; + app_protect_enable on; + app_protect_policy_file "/etc/app_protect/conf/NginxStrictPolicy.json"; + app_protect_security_log "/etc/app_protect/conf/secops_dashboard.json" syslog:server=127.0.0.1:1514; + app_protect_security_log_enable on; + + location / { + root /usr/share/nginx/html; + index index.html index.htm; + } + + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } +} +``` + +Make sure you specify port `1514` for the syslog server. NGINX Agent listens on this port to receive security events. + +## Verify your NGINX configuration + +Test your NGINX configuration for syntax errors: + +```bash +sudo nginx -t +``` + +You should see output like this: + +``` +nginx: the configuration file /etc/nginx/nginx.conf syntax is ok +nginx: configuration file /etc/nginx/nginx.conf test is successful +``` + +Restart NGINX Plus to apply the changes: + +```bash +sudo systemctl restart nginx +``` + +Verify NGINX Plus is running after the restart: + +```bash +sudo systemctl status nginx +``` + +## Install NGINX Agent + +NGINX Agent forwards security telemetry from F5 WAF for NGINX to NGINX One Console. + +1. In NGINX One Console, go to **Instances** and select **Add Instance**. + +2. Select **Generate new key**. This generates your data plane key and displays a `curl` command for agent installation. + +3. Copy the `curl` command and run it in your terminal: + +```bash +curl +``` + +Wait a few minutes for the system to appear in NGINX One Console. + +4. Verify the agent is running: + +```bash +sudo systemctl status nginx-agent +``` + +You should see output like this: + +``` +● nginx-agent.service - NGINX Agent + Loaded: loaded (/etc/systemd/system/nginx-agent.service; enabled; preset: enabled) + Active: active (running) since Thu 2026-03-19 23:53:00 UTC; 23s ago + Docs: https://github.com/nginx/agent#readme + Main PID: 24716 (nginx-agent) + Tasks: 8 (limit: 4586) + Memory: 26.0M (peak: 27.2M) + CPU: 414ms +``` + +## Configure NGINX Agent to forward security events + +Enable NGINX Agent to collect and forward security telemetry from F5 WAF for NGINX. + +1. Edit `/etc/nginx-agent/nginx-agent.conf` and add the following telemetry pipeline configuration at the end of the file: + +```yaml +collector: + exporters: + debug: {} + processors: + batch: + "logs": + send_batch_size: 1000 + timeout: 30s + send_batch_max_size: 1000 + pipelines: + logs: + "default-security-events": + receivers: ["tcplog/nginx_app_protect"] + processors: ["batch/logs"] + exporters: ["debug","otlp/default"] +``` + +This configuration batches security events with a 30-second timeout and a maximum batch size of 1000 events. Events are forwarded to NGINX One Console through the `otlp/default` exporter. + +2. Restart NGINX Agent to apply the changes: + +```bash +sudo systemctl restart nginx-agent +``` + +3. Verify NGINX Agent is running: + +```bash +sudo systemctl status nginx-agent +``` + +## Verify the security event pipeline + +Check that NGINX Agent successfully started the syslog receiver: + +```bash +sudo tail /var/log/nginx-agent/agent.log | grep "syslogserver" +``` + +You should see a log entry like this: + +``` +time=2026-03-20T00:05:10.212Z level=INFO msg="Found available local NGINX App Protect syslogserver configured on port 1514" +``` + +To debug security events being sent to NGINX One Console, tail the agent logs: + +```bash +sudo tail /var/log/nginx-agent/opentelemetry-collector-agent.log -f +``` + +## Test security event detection + +Generate test security violations to verify the pipeline is working. + +1. Trigger some violations with these example requests: + +```bash +curl -X SEARCH -k -v 'http://127.0.0.1/helloworld' + +curl -k -v 'http://127.0.0.1/a=' +``` + +You should receive a response indicating the request was rejected: + +```html +Request RejectedThe requested URL was rejected. Please consult with your administrator... +``` + +2. Verify that security events are being sent to NGINX One Console: + +```bash +sudo tail /var/log/nginx-agent/opentelemetry-collector-agent.log -n 200 +``` + +Look for log entries showing the violations being forwarded. + +Your security monitoring setup is now complete. Security events from F5 WAF for NGINX are now being forwarded to NGINX One Console, where you can monitor and analyze them in the security dashboard. From 38062956c98ef00a2c0d03eeb49c36809829f260 Mon Sep 17 00:00:00 2001 From: Sylvia Wang Date: Fri, 3 Apr 2026 16:17:42 -0700 Subject: [PATCH 02/13] add changelog --- content/nginx-one-console/changelog.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/content/nginx-one-console/changelog.md b/content/nginx-one-console/changelog.md index 488f41bb0..b7a5700a1 100644 --- a/content/nginx-one-console/changelog.md +++ b/content/nginx-one-console/changelog.md @@ -9,6 +9,12 @@ nd-docs: DOCS-1394 Stay up-to-date with what's new and improved in the F5 NGINX One Console. +## April 7, 2026 + +### Observability: F5 WAF for NGINX security dashboard + +A new Security Monitoring module provides real-time visibility into F5 WAF for NGINX security events. Monitor attack counts, violation types, and triggered signatures across your WAF instances with customizable dashboards and global filters. + ## March 18, 2026 ### F5 WAF for NGINX: Log profile management From 2da665f8861b7fe28baf31116064992660fc7f80 Mon Sep 17 00:00:00 2001 From: Sylvia Wang Date: Fri, 3 Apr 2026 16:26:04 -0700 Subject: [PATCH 03/13] update reference links --- .../waf-security-dashboard/set-up-security-monitoring.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/nginx-one-console/waf-security-dashboard/set-up-security-monitoring.md b/content/nginx-one-console/waf-security-dashboard/set-up-security-monitoring.md index 8d7000519..c45f28756 100644 --- a/content/nginx-one-console/waf-security-dashboard/set-up-security-monitoring.md +++ b/content/nginx-one-console/waf-security-dashboard/set-up-security-monitoring.md @@ -36,12 +36,12 @@ Your output should show that the service is active and running: Memory: 4.3M (peak: 4.9M) CPU: 807ms ``` -If NGINX Plus is not installed, see the [NGINX Plus installation guide]({{< ref "/content/nginx/admin-guide/installing-nginx/installing-nginx-plus.md" >}}). +If NGINX Plus is not installed, see the [NGINX Plus installation guide]({{< ref "/nginx/admin-guide/installing-nginx/installing-nginx-plus.md" >}}). ## Install F5 WAF for NGINX -Install F5 WAF for NGINX on your data plane following the [installation instructions for your operating system]({{< ref "/content/waf/install/virtual-environment.md" >}}). +Install F5 WAF for NGINX on your data plane following the [installation instructions for your operating system]({{< ref "/waf/install/virtual-environment.md" >}}). After installation, continue with the next section to configure the security dashboard log profile. From 10ad819162ab3fd308585d566a6af1fc236a22f7 Mon Sep 17 00:00:00 2001 From: Sylvia Wang <139922338+sylwang@users.noreply.github.com> Date: Mon, 6 Apr 2026 21:50:17 -0700 Subject: [PATCH 04/13] Apply suggestions from code review Co-authored-by: Travis Martin <33876974+travisamartin@users.noreply.github.com> --- content/nginx-one-console/changelog.md | 2 +- .../set-up-security-monitoring.md | 30 ++++--------------- 2 files changed, 7 insertions(+), 25 deletions(-) diff --git a/content/nginx-one-console/changelog.md b/content/nginx-one-console/changelog.md index b7a5700a1..59f0fe6ee 100644 --- a/content/nginx-one-console/changelog.md +++ b/content/nginx-one-console/changelog.md @@ -13,7 +13,7 @@ Stay up-to-date with what's new and improved in the F5 NGINX One Console. ### Observability: F5 WAF for NGINX security dashboard -A new Security Monitoring module provides real-time visibility into F5 WAF for NGINX security events. Monitor attack counts, violation types, and triggered signatures across your WAF instances with customizable dashboards and global filters. +The new Security Monitoring module gives you real-time visibility into F5 WAF for NGINX security events. You can monitor attack counts, violation types, and triggered signatures across your WAF instances by using customizable dashboards and global filters. ## March 18, 2026 diff --git a/content/nginx-one-console/waf-security-dashboard/set-up-security-monitoring.md b/content/nginx-one-console/waf-security-dashboard/set-up-security-monitoring.md index c45f28756..2a6920717 100644 --- a/content/nginx-one-console/waf-security-dashboard/set-up-security-monitoring.md +++ b/content/nginx-one-console/waf-security-dashboard/set-up-security-monitoring.md @@ -20,13 +20,11 @@ Before you begin, confirm that NGINX Plus is installed and running on your syste 1. Run the following command to check the NGINX Plus service status: -```bash sudo systemctl status nginx ``` Your output should show that the service is active and running: -``` ● nginx.service - NGINX Plus - high performance web server Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: enabled) Active: active (running) since Wed 2026-03-11 17:26:52 UTC; 1 week 1 day ago @@ -36,7 +34,7 @@ Your output should show that the service is active and running: Memory: 4.3M (peak: 4.9M) CPU: 807ms ``` -If NGINX Plus is not installed, see the [NGINX Plus installation guide]({{< ref "/nginx/admin-guide/installing-nginx/installing-nginx-plus.md" >}}). +If you haven’t installed NGINX Plus, follow the [NGINX Plus installation guide]({{< ref "/nginx/admin-guide/installing-nginx/installing-nginx-plus.md" >}}) ## Install F5 WAF for NGINX @@ -47,19 +45,17 @@ After installation, continue with the next section to configure the security das ## Configure the security dashboard log profile -The security dashboard uses the default log profile to capture security violations. This is a pre-configured, immutable log profile that is automatically compiled for all available WAF compiler versions. For more information about the default log profile, see [Default log profile]({{< ref "/nginx-one-console/waf-security-dashboard/default-log-profile.md" >}}). +The security dashboard uses the default log profile to record security violations. This profile is preconfigured and can’t be changed. The system automatically builds it for all supported WAF compiler versions. For more information, see the [Default log profile]({{< ref "/nginx-one-console/waf-security-dashboard/default-log-profile.md" >}}) documentation. To configure the security dashboard, create the `/etc/app_protect/conf/secops_dashboard.json` file with the following content: 1. Create the file: -```bash sudo touch /etc/app_protect/conf/secops_dashboard.json ``` 2. Add the log profile configuration: -```bash sudo tee /etc/app_protect/conf/secops_dashboard.json > /dev/null << 'EOF' { "filter": { @@ -83,7 +79,7 @@ EOF ## Enable F5 WAF for NGINX in your configuration -Update your NGINX configuration to enable F5 WAF for NGINX and specify the security dashboard log profile. +Update your NGINX configuration to turn on F5 WAF for NGINX and set the security dashboard log profile. ### Update the main NGINX configuration @@ -148,26 +144,22 @@ Make sure you specify port `1514` for the syslog server. NGINX Agent listens on Test your NGINX configuration for syntax errors: -```bash sudo nginx -t ``` You should see output like this: -``` nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful ``` Restart NGINX Plus to apply the changes: -```bash sudo systemctl restart nginx ``` Verify NGINX Plus is running after the restart: -```bash sudo systemctl status nginx ``` @@ -181,7 +173,6 @@ NGINX Agent forwards security telemetry from F5 WAF for NGINX to NGINX One Conso 3. Copy the `curl` command and run it in your terminal: -```bash curl ``` @@ -189,13 +180,11 @@ Wait a few minutes for the system to appear in NGINX One Console. 4. Verify the agent is running: -```bash sudo systemctl status nginx-agent ``` You should see output like this: -``` ● nginx-agent.service - NGINX Agent Loaded: loaded (/etc/systemd/system/nginx-agent.service; enabled; preset: enabled) Active: active (running) since Thu 2026-03-19 23:53:00 UTC; 23s ago @@ -208,7 +197,7 @@ You should see output like this: ## Configure NGINX Agent to forward security events -Enable NGINX Agent to collect and forward security telemetry from F5 WAF for NGINX. +Configure NGINX Agent to collect and forward security telemetry from F5 WAF for NGINX. 1. Edit `/etc/nginx-agent/nginx-agent.conf` and add the following telemetry pipeline configuration at the end of the file: @@ -234,13 +223,11 @@ This configuration batches security events with a 30-second timeout and a maximu 2. Restart NGINX Agent to apply the changes: -```bash sudo systemctl restart nginx-agent ``` 3. Verify NGINX Agent is running: -```bash sudo systemctl status nginx-agent ``` @@ -248,29 +235,25 @@ sudo systemctl status nginx-agent Check that NGINX Agent successfully started the syslog receiver: -```bash sudo tail /var/log/nginx-agent/agent.log | grep "syslogserver" ``` You should see a log entry like this: -``` time=2026-03-20T00:05:10.212Z level=INFO msg="Found available local NGINX App Protect syslogserver configured on port 1514" ``` To debug security events being sent to NGINX One Console, tail the agent logs: -```bash sudo tail /var/log/nginx-agent/opentelemetry-collector-agent.log -f ``` ## Test security event detection -Generate test security violations to verify the pipeline is working. +Generate test security violations to verify that the pipeline works. 1. Trigger some violations with these example requests: -```bash curl -X SEARCH -k -v 'http://127.0.0.1/helloworld' curl -k -v 'http://127.0.0.1/a=' @@ -284,10 +267,9 @@ You should receive a response indicating the request was rejected: 2. Verify that security events are being sent to NGINX One Console: -```bash sudo tail /var/log/nginx-agent/opentelemetry-collector-agent.log -n 200 ``` Look for log entries showing the violations being forwarded. -Your security monitoring setup is now complete. Security events from F5 WAF for NGINX are now being forwarded to NGINX One Console, where you can monitor and analyze them in the security dashboard. +Your security monitoring setup is complete. Security events from F5 WAF for NGINX are forwarded to the NGINX One Console, where you can monitor and analyze them in the security dashboard. From 8d182e53132ed4dda241762c99fbab6a69a98981 Mon Sep 17 00:00:00 2001 From: Sylvia Wang Date: Mon, 6 Apr 2026 23:22:53 -0700 Subject: [PATCH 05/13] consolidate security dashboard section --- .../waf-integration/_index.md | 2 + .../waf-security-dashboard/_index.md | 18 ++ .../default-log-profile.md | 48 +++ .../set-up-security-monitoring.md | 293 ++++++++++++++++++ 4 files changed, 361 insertions(+) create mode 100644 content/nginx-one-console/waf-integration/waf-security-dashboard/_index.md create mode 100644 content/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md create mode 100644 content/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md diff --git a/content/nginx-one-console/waf-integration/_index.md b/content/nginx-one-console/waf-integration/_index.md index 8f700d1a0..2e4a1e9b7 100644 --- a/content/nginx-one-console/waf-integration/_index.md +++ b/content/nginx-one-console/waf-integration/_index.md @@ -4,3 +4,5 @@ description: weight: 400 url: /nginx-one-console/waf-integration --- + +Integrate F5 WAF for NGINX with NGINX One Console to centralize security monitoring, log profile management, and WAF policy configuration. diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/_index.md b/content/nginx-one-console/waf-integration/waf-security-dashboard/_index.md new file mode 100644 index 000000000..74ba94e2b --- /dev/null +++ b/content/nginx-one-console/waf-integration/waf-security-dashboard/_index.md @@ -0,0 +1,18 @@ +--- +title: F5 WAF for NGINX security monitoring +description: Monitor security events and review WAF dashboards to assess threats +weight: 425 +url: /nginx-one-console/waf-integration/waf-security-dashboard +--- + +Use the Security Monitoring module in NGINX One Console to monitor data from F5 WAF for NGINX instances. Review the security dashboards to assess potential threats and identify opportunities to fine-tune your policies. + +## Dashboard metrics overview + +The security dashboard displays key metrics to help you understand attack patterns and threats. Here's an overview of the main metrics: + +- **Attack Counts** - Track the number of attacks with percentage change comparisons against previous periods +- **Violation Types** - View violations grouped by category (e.g., Protocol Compliance) to understand threat patterns +- **Signatures** - See specific signatures triggered within each violation type across multiple events +- **Event Details** - Access Support IDs, raw request data, triggered signatures, and contextual metadata (Original IP, X-Forwarded-For, Violation Context) +- **Global Filters** - Apply filters by time period, policy, and attack type to instantly update all dashboard widgets diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md b/content/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md new file mode 100644 index 000000000..bec40b34b --- /dev/null +++ b/content/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md @@ -0,0 +1,48 @@ +--- +title: Default log profile +description: Learn about the security dashboard default log profile and how to deploy it +weight: 200 +nd-content-type: concept +nd-product: NONECO +--- + +The default log profile is a pre-configured F5 WAF for NGINX log profile designed specifically for security event monitoring in NGINX One Console. It captures security violation data in a standardized format optimized for analysis and troubleshooting. + +## About the default log profile + +The default log profile is similar to [other log profiles]({{< ref "/nginx-one-console/waf-integration/log-profiles/_index.md" >}}) in structure and function, but has these key characteristics: + +- **Immutable** — The default log profile cannot be edited or deleted. This ensures the security monitoring data format remains consistent across your deployment. +- **Pre-compiled** — NGINX One Console automatically compiles the default log profile for all available WAF compiler versions. This eliminates the need for on-demand compilation during deployment. +- **Standardized format** — It captures all necessary security telemetry fields for the security dashboard, including support IDs, violation details, signature information, and client context. + +## When to use the default log profile + +Use the default log profile when you want to: +- Send security violation data to NGINX One Console for centralized monitoring +- Analyze attack patterns and trends across your NGINX fleet +- Review violation details and raw request data for specific security events +- Generate baseline security metrics and trending reports + +For specialized logging requirements beyond security monitoring, you can create and deploy custom log profiles alongside the default profile. + +## Deploy the default log profile + +To deploy the default log profile to your NGINX instances or Config Sync Groups, follow the same process described in [Deploy log profiles]({{< ref "/nginx-one-console/waf-integration/log-profiles/deploy-log-profiles.md" >}}). + +The default log profile can be deployed using either of these methods: + +1. **Direct deployment** — Go to **WAF** > **Log Profiles**, select the default log profile, and use **Actions** > **Deploy** to send it to your target instances or Config Sync Groups. + +2. **During configuration editing** — When editing an instance or Config Sync Group configuration, you can select the default log profile from **Add File** > **Existing Log Profile** and specify the deployment path. + +Since the default log profile is pre-compiled for all WAF compiler versions, deployment completes immediately without requiring additional compilation. + +For detailed deployment instructions, see [Deploy log profiles]({{< ref "/nginx-one-console/waf-integration/log-profiles/deploy-log-profiles.md" >}}). + +## Next steps + +After deploying the default log profile: +- Monitor security events in the [F5 WAF for NGINX security monitoring dashboard]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/" >}}) +- Review security event details and identify attack patterns +- Fine-tune your F5 WAF for NGINX policies based on observed violations diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md b/content/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md new file mode 100644 index 000000000..456bf4ba9 --- /dev/null +++ b/content/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md @@ -0,0 +1,293 @@ +--- +title: Set up security monitoring +description: Configure NGINX Plus with F5 WAF for NGINX to forward security events to NGINX One Console +weight: 100 +nd-content-type: how-to +nd-product: NONECO +--- + +This guide walks you through configuring your NGINX Plus data plane to send security telemetry to NGINX One Console. You'll install F5 WAF for NGINX, configure the security dashboard log profile, and set up NGINX Agent to forward security events. + +## Prerequisites + +- NGINX Plus installed and running on your data plane +- Root or sudo access on the data plane system +- NGINX One Console access with permissions to add instances + +## Verify NGINX Plus is running + +Before you begin, confirm that NGINX Plus is installed and running on your system. + +1. Run the following command to check the NGINX Plus service status: + +```bash +sudo systemctl status nginx +``` + +Your output should show that the service is active and running: + +``` +● nginx.service - NGINX Plus - high performance web server + Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: enabled) + Active: active (running) since Wed 2026-03-11 17:26:52 UTC; 1 week 1 day ago + Docs: https://www.nginx.com/resources/ + Main PID: 3682 (nginx) + Tasks: 3 (limit: 4586) + Memory: 4.3M (peak: 4.9M) + CPU: 807ms +``` + +If NGINX Plus is not installed, see the [NGINX Plus installation guide]({{< ref "/nginx/admin-guide/installing-nginx/installing-nginx-plus.md" >}}). + +## Install F5 WAF for NGINX + +Install F5 WAF for NGINX on your data plane following the [installation instructions for your operating system]({{< ref "/waf/install/virtual-environment.md" >}}). + +After installation, continue with the next section to configure the security dashboard log profile. + +## Configure the security dashboard log profile + +The security dashboard uses the default log profile to capture security violations. This is a pre-configured, immutable log profile that is automatically compiled for all available WAF compiler versions. For more information about the default log profile, see [Default log profile]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md" >}}). + +To configure the security dashboard, create the `/etc/app_protect/conf/secops_dashboard.json` file with the following content: + +1. Create the file: + +```bash +sudo touch /etc/app_protect/conf/secops_dashboard.json +``` + +2. Add the log profile configuration: + +```bash +sudo tee /etc/app_protect/conf/secops_dashboard.json > /dev/null << 'EOF' +{ + "filter": { + "request_type": "illegal" + }, + "content": { + "format": "user-defined", + "format_string": "%support_id%|%ip_client%|%src_port%|%dest_ip%|%dest_port%|%vs_name%|%policy_name%|%method%|%uri%|%protocol%|%request_status%|%response_code%|%outcome%|%outcome_reason%|%violation_rating%|%blocking_exception_reason%|%is_truncated_bool%|%sig_ids%|%sig_names%|%sig_cves%|%sig_set_names%|%threat_campaign_names%|%sub_violations%|%x_forwarded_for_header_value%|%violations%|%violation_details%|%request%|%geo_location%", + "max_request_size": "2048", + "max_message_size": "64k", + "escaping_characters": [ + { + "from": "|", + "to": "%7C" + } + ] + } +} +EOF +``` + +## Enable F5 WAF for NGINX in your configuration + +Update your NGINX configuration to turn on F5 WAF for NGINX and set the security dashboard log profile. + +### Update the main NGINX configuration + +Edit `/etc/nginx/nginx.conf` and add the `load_module` directive at the top: + +```nginx +user nginx; +worker_processes auto; +load_module modules/ngx_http_app_protect_module.so; +error_log /var/log/nginx/error.log notice; +pid /run/nginx.pid; + +events { + worker_connections 1024; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + keepalive_timeout 65; + + include /etc/nginx/conf.d/*.conf; +} +``` + +### Configure a server block with F5 WAF for NGINX + +Edit `/etc/nginx/conf.d/default.conf` to add the F5 WAF for NGINX directives: + +```nginx +server { + listen 80 default_server; + server_name localhost; + app_protect_enable on; + app_protect_policy_file "/etc/app_protect/conf/NginxStrictPolicy.json"; + app_protect_security_log "/etc/app_protect/conf/secops_dashboard.json" syslog:server=127.0.0.1:1514; + app_protect_security_log_enable on; + + location / { + root /usr/share/nginx/html; + index index.html index.htm; + } + + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } +} +``` + +Make sure you specify port `1514` for the syslog server. NGINX Agent listens on this port to receive security events. + +## Verify your NGINX configuration + +Test your NGINX configuration for syntax errors: + +```bash +sudo nginx -t +``` + +You should see output like this: + +``` +nginx: the configuration file /etc/nginx/nginx.conf syntax is ok +nginx: configuration file /etc/nginx/nginx.conf test is successful +``` + +Restart NGINX Plus to apply the changes: + +```bash +sudo systemctl restart nginx +``` + +Verify NGINX Plus is running after the restart: + +```bash +sudo systemctl status nginx +``` + +## Install NGINX Agent + +NGINX Agent forwards security telemetry from F5 WAF for NGINX to NGINX One Console. + +1. In NGINX One Console, go to **Instances** and select **Add Instance**. + +2. Select **Generate new key**. This generates your data plane key and displays a `curl` command for agent installation. + +3. Copy the `curl` command and run it in your terminal: + +```bash +curl +``` + +Wait a few minutes for the system to appear in NGINX One Console. + +4. Verify the agent is running: + +```bash +sudo systemctl status nginx-agent +``` + +You should see output like this: + +``` +● nginx-agent.service - NGINX Agent + Loaded: loaded (/etc/systemd/system/nginx-agent.service; enabled; preset: enabled) + Active: active (running) since Thu 2026-03-19 23:53:00 UTC; 23s ago + Docs: https://github.com/nginx/agent#readme + Main PID: 24716 (nginx-agent) + Tasks: 8 (limit: 4586) + Memory: 26.0M (peak: 27.2M) + CPU: 414ms +``` + +## Configure NGINX Agent to forward security events + +Configure NGINX Agent to collect and forward security telemetry from F5 WAF for NGINX. + +1. Edit `/etc/nginx-agent/nginx-agent.conf` and add the following telemetry pipeline configuration at the end of the file: + +```yaml +collector: + exporters: + debug: {} + processors: + batch: + "logs": + send_batch_size: 1000 + timeout: 30s + send_batch_max_size: 1000 + pipelines: + logs: + "default-security-events": + receivers: ["tcplog/nginx_app_protect"] + processors: ["batch/logs"] + exporters: ["debug","otlp/default"] +``` + +This configuration batches security events with a 30-second timeout and a maximum batch size of 1000 events. Events are forwarded to NGINX One Console through the `otlp/default` exporter. + +2. Restart NGINX Agent to apply the changes: + +```bash +sudo systemctl restart nginx-agent +``` + +3. Verify NGINX Agent is running: + +```bash +sudo systemctl status nginx-agent +``` + +## Verify the security event pipeline + +Check that NGINX Agent successfully started the syslog receiver: + +```bash +sudo tail /var/log/nginx-agent/agent.log | grep "syslogserver" +``` + +You should see a log entry like this: + +``` +time=2026-03-20T00:05:10.212Z level=INFO msg="Found available local NGINX App Protect syslogserver configured on port 1514" +``` + +To debug security events being sent to NGINX One Console, tail the agent logs: + +```bash +sudo tail /var/log/nginx-agent/opentelemetry-collector-agent.log -f +``` + +## Test security event detection + +Generate test security violations to verify that the pipeline works. + +1. Trigger some violations with these example requests: + +```bash +curl -X SEARCH -k -v 'http://127.0.0.1/helloworld' + +curl -k -v 'http://127.0.0.1/a=' +``` + +You should receive a response indicating the request was rejected: + +```html +Request RejectedThe requested URL was rejected. Please consult with your administrator... +``` + +2. Verify that security events are being sent to NGINX One Console: + +```bash +sudo tail /var/log/nginx-agent/opentelemetry-collector-agent.log -n 200 +``` + +Look for log entries showing the violations being forwarded. + +Your security monitoring setup is complete. Security events from F5 WAF for NGINX are forwarded to the NGINX One Console, where you can monitor and analyze them in the security dashboard. From a5851ee4368917b06d61044baa48b078f1b81be7 Mon Sep 17 00:00:00 2001 From: Venkat Reddy Marepally <102700175+vrmare@users.noreply.github.com> Date: Tue, 7 Apr 2026 22:06:27 -0700 Subject: [PATCH 06/13] rewrite to follow templates and expand coverage --- .../waf-security-dashboard/_index.md | 19 +- .../dashboard-metrics-reference.md | 184 + .../default-log-profile.md | 95 +- .../find-event-by-support-id.md | 94 + .../query-events-api.md | 72 + .../security-monitoring-overview.md | 89 + .../set-up-security-monitoring.md | 318 +- .../waf-security-dashboard/_index.md | 18 - .../default-log-profile.md | 48 - .../set-up-security-monitoring.md | 275 - static/nginx-one-console/api/one.json | 10006 ++++++++++------ 11 files changed, 7162 insertions(+), 4056 deletions(-) create mode 100644 content/nginx-one-console/waf-integration/waf-security-dashboard/dashboard-metrics-reference.md create mode 100644 content/nginx-one-console/waf-integration/waf-security-dashboard/find-event-by-support-id.md create mode 100644 content/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md create mode 100644 content/nginx-one-console/waf-integration/waf-security-dashboard/security-monitoring-overview.md delete mode 100644 content/nginx-one-console/waf-security-dashboard/_index.md delete mode 100644 content/nginx-one-console/waf-security-dashboard/default-log-profile.md delete mode 100644 content/nginx-one-console/waf-security-dashboard/set-up-security-monitoring.md diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/_index.md b/content/nginx-one-console/waf-integration/waf-security-dashboard/_index.md index 74ba94e2b..761758604 100644 --- a/content/nginx-one-console/waf-integration/waf-security-dashboard/_index.md +++ b/content/nginx-one-console/waf-integration/waf-security-dashboard/_index.md @@ -1,18 +1,17 @@ --- title: F5 WAF for NGINX security monitoring -description: Monitor security events and review WAF dashboards to assess threats +description: Monitor F5 WAF for NGINX security events in NGINX One Console. weight: 425 url: /nginx-one-console/waf-integration/waf-security-dashboard --- -Use the Security Monitoring module in NGINX One Console to monitor data from F5 WAF for NGINX instances. Review the security dashboards to assess potential threats and identify opportunities to fine-tune your policies. +Use the security monitoring module in NGINX One Console to collect, visualize, and query security events from F5 WAF for NGINX instances. Review attacks, violations, and triggered signatures to assess threats and fine-tune your policies. -## Dashboard metrics overview +This section covers: -The security dashboard displays key metrics to help you understand attack patterns and threats. Here's an overview of the main metrics: - -- **Attack Counts** - Track the number of attacks with percentage change comparisons against previous periods -- **Violation Types** - View violations grouped by category (e.g., Protocol Compliance) to understand threat patterns -- **Signatures** - See specific signatures triggered within each violation type across multiple events -- **Event Details** - Access Support IDs, raw request data, triggered signatures, and contextual metadata (Original IP, X-Forwarded-For, Violation Context) -- **Global Filters** - Apply filters by time period, policy, and attack type to instantly update all dashboard widgets +- [Security monitoring overview]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/security-monitoring-overview.md" >}}) — what the security dashboard is, the data pipeline behind it, and what you can do with it. +- [Default log profile]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md" >}}) — the immutable, pre-compiled log profile the dashboard depends on. +- [Set up security monitoring]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md" >}}) — install F5 WAF for NGINX, configure the log profile, and forward events through NGINX Agent. +- [Security dashboard reference]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/dashboard-metrics-reference.md" >}}) — dashboard tabs, global controls, and how each widget maps to an underlying dimension. +- [Find a security event by Support ID]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/find-event-by-support-id.md" >}}) — look up a single security event by its Support ID for quick triage. +- [Query security events through the API]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md" >}}) — list events and run analytics queries programmatically. diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/dashboard-metrics-reference.md b/content/nginx-one-console/waf-integration/waf-security-dashboard/dashboard-metrics-reference.md new file mode 100644 index 000000000..1f9f6a965 --- /dev/null +++ b/content/nginx-one-console/waf-integration/waf-security-dashboard/dashboard-metrics-reference.md @@ -0,0 +1,184 @@ +--- +nd-content-type: reference +nd-docs: DOCS-000 +nd-product: NONECO +title: Security dashboard reference +description: "Tabs, global controls, and widget-to-dimension mapping for the F5 WAF for NGINX security monitoring dashboard." +weight: 400 +toc: true +nd-keywords: "security dashboard, tabs, global filters, widgets, dimensions, F5 WAF for NGINX" +nd-summary: > + Use this reference to look up how the security monitoring dashboard is organized and which underlying dimension each widget reads from. + This article covers the dashboard tabs, the global filter and time controls, and the mapping from widget to API dimension. + Each widget has an in-product tooltip explaining what its values mean; this article focuses on what is not in those tooltips. +nd-audience: operator +--- + +## Overview + +Use this reference to look up how the F5 WAF for NGINX security monitoring dashboard is organized and which underlying dimension each widget reads from. Every widget in the dashboard has an in-product tooltip that explains what the displayed values mean. This article mainly covers the dashboard structure, the global controls that affect every widget, and the mapping you need when you want to reproduce a widget's view through the [analytics API]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md" >}}). + +--- + +## Dashboard layout + +The security dashboard is organized into three tabs. All three tabs share the same global filter bar and time window control at the top of the page, so any filter or time change applies to every widget on every tab. + +| Tab | Purpose | +|:--- |:--- | +| **Main** | High-level summary of WAF activity in the selected window. Shows attack counts, threat intelligence, attack volume over time, and top-N breakdowns by geolocation, policy, IP, violation, and signature. This is the landing tab for triage. | +| **Advanced** | Deeper analytics for tuning and investigation. Use this tab to drill into signature attributes (risk, accuracy, CVE), violation context, and other dimensions that are too detailed for the Main tab. | +| **Event Logs** | A filterable list of individual security events. Open an event to see its support ID, full violation and signature detail, request context, and the raw matched request. This tab is the drill-down target when you want to inspect specific events behind a metric. | + +--- + +## Global controls + +Two controls at the top of the page apply to every widget on every tab. + +### Time window + +Selects the query window for all widgets. The picker offers preset windows from **Last 5 minutes** to **Last 14 days**. You can also select a custom range by highlighting an area of interest on any time-series chart. + +Time-series widgets bucket their data based on the selected window — shorter windows produce finer buckets. + +| Selected window | Default bucket size for time-series widgets | +|:--- |:--- | +| Last 5–30 minutes | 1 minute | +| Last 1–6 hours | 1 minute | +| Last 12–24 hours | 1 hour | +| Last 2–7 days | 1 hour | +| Last 14 days | 6 hours | + +{{< note >}}Security events are retained for **90 days**, but the dashboard time window picker is currently limited to the **last 14 days**. To query the full retention window, use the [analytics API]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md" >}}), which accepts any time range up to 90 days.{{< /note >}} + +### Add Filter + +Applies one or more filter expressions to every widget on every tab. The dashboard supports the following filters: + +| Filter | Description | +|:--- |:--- | +| **Config Sync Group** | Scope events to instances belonging to a specific Config Sync Group. | +| **Country** | Two-letter country code derived from the client IP. | +| **Destination Hostname** | The HTTP `Host` header sent by the client. Use this to scope by the application being attacked. | +| **Hostname** | The NGINX instance hostname (the data plane host). Use this to scope by the data plane producing the events. | +| **Instance** | Scope events to a specific NGINX instance by object identity rather than hostname. | +| **IP Address** | The originating client IP. | +| **Outcome Reason** | The reason F5 WAF for NGINX produced its decision, such as a matched violation or a blocking rule. | +| **Policy** | The F5 WAF for NGINX policy that produced the event. | +| **Request Method** | The HTTP request method (`GET`, `POST`, and so on). | +| **Response Code** | The HTTP response code returned for the request. | +| **Signature Accuracy** | The accuracy level of a triggered signature: `low`, `medium`, or `high`. | +| **Signature CVE** | A CVE identifier referenced by a triggered signature. | +| **Signature ID** | The numeric F5 WAF for NGINX signature ID. | +| **Signature Name** | The name of a triggered signature. | +| **Signature Risk** | The risk level of a triggered signature: `low`, `medium`, or `high`. | +| **Status** | The final WAF decision: `blocked` or `alerted`. | +| **Subviolation** | The sub-violation name within a violation. | +| **Support ID** | The unique identifier F5 WAF for NGINX assigns to each event. | +| **Threat Campaign** | The name of a matched threat campaign. | +| **URI** | The request URI path. | +| **Violation** | The name of a triggered violation. | +| **Violation Context** | Where in the request the violation occurred: `cookie`, `header`, `parameter`, `request`, or `URI`. | +| **Violation Context Key** | The field name (for example, the parameter or header name) where the violation occurred. | +| **Violation Context Value** | The field value where the violation occurred. | +| **Violation Rating** | The numeric severity rating (0–5) F5 WAF for NGINX assigned to the violation. | + +Use filters to scope the dashboard to a specific policy, instance, hostname, country, IP, signature, violation, or any combination. To go from a metric on the dashboard to the underlying events, apply the relevant filter and switch to the **Event Logs** tab. + +Every dashboard filter is also available through the analytics API. To call the same filters from the API, see the [API reference guide]({{< ref "/nginx-one-console/api/api-reference-guide.md" >}}). + +--- + +## Main tab widgets + +Each widget on the Main tab has a tooltip describing what it displays. The table below adds context the tooltips do not cover, such as how rows are counted and what distinct counts each Top-N table reports. + +| Widget | Notes | +|:--- |:--- | +| **All Web Attacks** | Total count of security events for the selected window and filters. | +| **Threat Intelligence** | Unique counts of threat campaigns and signatures observed in the window. | +| **Attack Requests Over Time** | Stacked time series of `blocked` and `alerted` events. Bucket size depends on the selected window. | +| **Top Attack Geolocations** | Highest-volume client countries in the window. | +| **Top WAF Policies** | Each row shows hits, distinct URIs, IPs, and violations for the policy. | +| **Top Attack IP Addresses** | Each row shows hits, distinct URIs, violations, and policies for the client IP. | +| **Top Violations** | Each row shows hits, distinct IPs, URIs, and policies for the violation. | +| **Top Signatures** | Each row shows hits, distinct URIs, IPs, violations, and policies for the signature. | +| **Top Subviolations** | Each row shows hits, distinct IPs, URIs, and policies for the sub-violation. | +| **Top Attack URIs** | Each row shows hits, distinct IPs, violations, and policies for the URI. | +| **Request Methods** | Donut chart showing the share of events for each HTTP method observed in the window. | +| **Response Codes** | Donut chart showing the share of events for each response code observed in the window. | + +To reproduce these widgets through the analytics API, see [Query security events through the API]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md" >}}). + +--- + +## Advanced tab widgets + +The Advanced tab exposes signature- and violation-level analytics for tuning and deeper investigation. Widgets on this tab read from the same data store as the Main tab and respect the same global filters and time window. + +| Widget | Notes | +|:--- |:--- | +| **Signatures** | Total signature hits and unique signature count, with distributions across signature accuracy and risk levels. | +| **Signature Hits Request Status** | Donut chart of `blocked`, `alerted`, and `passed` shares of signature hits. | +| **Violation Context** | Donut chart showing where in the request the violation occurred (`cookie`, `header`, `parameter`, `request`, `URI`). | +| **Signature Hits Over Time** | Time series of signature hit volume. Bucket size depends on the selected window. | +| **Top Signatures** | Same as the Top Signatures widget on the Main tab. Each row shows hits, distinct URIs, IPs, violations, and policies. | +| **Top Signature CVEs** | Each row shows hits, distinct URIs, IPs, violations, and policies for signatures that reference the CVE. | +| **Top Threat Campaigns** | Each row shows hits, distinct URIs, IPs, violations, and policies for the threat campaign. | +| **Top Attacked Instances** | Each row shows hits, distinct URIs, IPs, violations, and policies, scoped to the NGINX instance hostname (not the HTTP `Host` header). | + +To reproduce these widgets through the analytics API, see [Query security events through the API]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md" >}}). + +--- + +## Event Logs tab + +The Event Logs tab lists individual security events matching the global filters and time window. The tab has two parts: + +- A **Security Events** time-series chart at the top showing event volume by request status (`blocked` and `alerted`), the same view as the **Attack Requests Over Time** widget on the Main tab. +- A paginated **events table** below the chart, where each row corresponds to one security event. + +### Events table columns + +| Column | Description | +|:--- |:--- | +| **Status** | The final WAF decision: `blocked` or `alerted`. | +| **URI** | The request URI that triggered the event. | +| **Policy** | The F5 WAF for NGINX policy that produced the event. | +| **Time** | When F5 WAF for NGINX produced the event. | +| **Source Location** | Country derived from the client IP, when available. | +| **Source IP** | The originating client IP. | +| **Violation Rating** | Numeric severity rating (0–5) assigned by F5 WAF for NGINX. | +| **Support ID** | The unique identifier F5 WAF for NGINX assigns to the event. Use this to correlate with raw F5 WAF for NGINX logs on the data plane. | + +To list events with the same columns through the analytics API, see [Query security events through the API]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md" >}}). + +### Pagination + +The table is paginated. Use the controls in the bottom-right of the table to: + +- Change the page size (default `50` rows per page). +- Navigate to a specific page or step through pages with the arrow controls. + +The total event count for the current filter and time window is shown in the bottom-left of the table. + +### Event detail panel + +Selecting a row opens the event detail panel. The panel surfaces every field stored on the event, including: + +- **Triggered violations and signatures** — every violation and signature that fired on the event, with their full attributes. +- **Request context** — method, URL, host, client IP, X-Forwarded-For chain, country, response code, and request status. +- **Raw matched request** — the captured request payload, when available. + + +--- + +## References + +For more information, see: + +- [Security monitoring overview]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/security-monitoring-overview.md" >}}) +- [Set up security monitoring]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md" >}}) +- [Find a security event by Support ID]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/find-event-by-support-id.md" >}}) +- [Query security events through the API]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md" >}}) diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md b/content/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md index bec40b34b..618e6d843 100644 --- a/content/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md +++ b/content/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md @@ -1,48 +1,87 @@ --- -title: Default log profile -description: Learn about the security dashboard default log profile and how to deploy it -weight: 200 nd-content-type: concept +nd-docs: DOCS-000 nd-product: NONECO +title: Default log profile +description: "An immutable, pre-compiled F5 WAF for NGINX log profile that captures the security telemetry the security dashboard needs." +weight: 200 +toc: true +nd-keywords: "default log profile, security dashboard, F5 WAF for NGINX, log profile, security telemetry, NAP log profile" +nd-summary: > + The default log profile is a pre-configured F5 WAF for NGINX log profile that captures security violations in a standardized format for the security monitoring dashboard. + Use it to send security telemetry from your NGINX Plus data planes to NGINX One Console without authoring or compiling a custom log profile. + This document covers what the default log profile is, when to use it, and how it differs from custom log profiles. +nd-audience: operator --- -The default log profile is a pre-configured F5 WAF for NGINX log profile designed specifically for security event monitoring in NGINX One Console. It captures security violation data in a standardized format optimized for analysis and troubleshooting. +The security monitoring dashboard depends on a consistent set of fields being present on every security event. The default log profile is the contract that guarantees that consistency across every data plane forwarding events to NGINX One Console. + +## What is the default log profile? + +The default log profile is a pre-configured, system-managed F5 WAF for NGINX log profile that captures the security telemetry fields the NGINX One Console security monitoring dashboard expects. NGINX One Console ships and maintains it; you cannot edit or delete it. -## About the default log profile +It is similar in structure and function to other [log profiles]({{< ref "/nginx-one-console/waf-integration/log-profiles/_index.md" >}}), but it is treated as a system asset rather than a user-managed resource. The default log profile is the only log profile guaranteed to produce data the security dashboard can render correctly. Custom log profiles can coexist with it and continue to serve other logging destinations (SIEMs, file logs, custom syslog endpoints), but they are not interpreted by the security dashboard. -The default log profile is similar to [other log profiles]({{< ref "/nginx-one-console/waf-integration/log-profiles/_index.md" >}}) in structure and function, but has these key characteristics: +This document covers what the default log profile is and when to use it. For the steps to deploy it as part of setting up an instance, see [Set up security monitoring]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md" >}}). -- **Immutable** — The default log profile cannot be edited or deleted. This ensures the security monitoring data format remains consistent across your deployment. -- **Pre-compiled** — NGINX One Console automatically compiles the default log profile for all available WAF compiler versions. This eliminates the need for on-demand compilation during deployment. -- **Standardized format** — It captures all necessary security telemetry fields for the security dashboard, including support IDs, violation details, signature information, and client context. +--- + +## How to identify it in the console + +In NGINX One Console, go to **WAF** > **Log Profiles**. The default log profile appears in the list as **`secops_dashboard`** with an **F5** badge next to its name. The badge marks it as a system-managed profile created and maintained by F5. -## When to use the default log profile +The available **Actions** on the default log profile are limited compared to a user-created log profile. You can **Deploy**, **Download JSON**, **Manage Bundle**, and **Make a copy**, but **Edit** and **Delete** are not exposed — the profile is system-managed and cannot be modified or removed. -Use the default log profile when you want to: -- Send security violation data to NGINX One Console for centralized monitoring -- Analyze attack patterns and trends across your NGINX fleet -- Review violation details and raw request data for specific security events -- Generate baseline security metrics and trending reports +To see the compiled bundles for the default log profile, open the profile and select **Actions** > **Manage Bundle**. The **Bundles** tab lists every available WAF compiler version with its compilation status (`Compiled` or `Compiling`) and a **Download** action for each compiled bundle. NGINX One Console keeps these bundles up to date automatically — you do not need to compile them yourself. -For specialized logging requirements beyond security monitoring, you can create and deploy custom log profiles alongside the default profile. +If you need a log profile with a different field set or filter rules, use **Make a copy** to create an editable, user-owned log profile based on `secops_dashboard`. The copy is a regular custom log profile and is not used by the security dashboard. -## Deploy the default log profile +--- + +## Key characteristics -To deploy the default log profile to your NGINX instances or Config Sync Groups, follow the same process described in [Deploy log profiles]({{< ref "/nginx-one-console/waf-integration/log-profiles/deploy-log-profiles.md" >}}). +The default log profile has three properties that distinguish it from user-created log profiles. -The default log profile can be deployed using either of these methods: +- **Immutable**: You cannot edit or delete the default log profile. NGINX One Console manages it as a system resource so the security monitoring data format remains consistent across every instance and tenant. +- **Pre-compiled**: NGINX One Console automatically compiles the default log profile for every available WAF compiler version. Deployment completes immediately without an on-demand compilation step. +- **Standardized field set**: It captures every field the security dashboard reads, including the support ID, violation details, signature information, threat campaign matches, request context, and client geolocation. Filters and analytics in the dashboard assume these fields are present. -1. **Direct deployment** — Go to **WAF** > **Log Profiles**, select the default log profile, and use **Actions** > **Deploy** to send it to your target instances or Config Sync Groups. +--- -2. **During configuration editing** — When editing an instance or Config Sync Group configuration, you can select the default log profile from **Add File** > **Existing Log Profile** and specify the deployment path. +## Use cases -Since the default log profile is pre-compiled for all WAF compiler versions, deployment completes immediately without requiring additional compilation. +### Operator: enable security monitoring for an NGINX Plus fleet + +A platform operator wants central visibility into F5 WAF for NGINX events across a fleet of NGINX Plus instances. They deploy the default log profile to every instance, knowing that every event will land in NGINX One Console with the same field set, so dashboard widgets, filters, and analytics behave the same regardless of which instance produced the event. They do not need to author, compile, or version-control a log profile to get the dashboard working. + +### Security engineer: keep dashboard data consistent during a policy change + +A security engineer is rolling out a new WAF policy to a subset of instances and wants the security dashboard to continue showing comparable metrics across the migration. Because the default log profile is immutable and shared, the data format does not change with the policy, and the engineer can compare attack counts and signature trends before and after the rollout without normalizing fields. + +### Operator: combine dashboard monitoring with a custom SIEM pipeline + +An operator already forwards security logs to an external SIEM with a custom log profile that uses a different field layout. They deploy the default log profile alongside the existing custom profile so that NGINX One Console gets the standardized format the dashboard requires, while the SIEM continues to receive the custom format unchanged. + +--- + +## Comparison with custom log profiles + +| | Default log profile | Custom log profile | +|:--- |:--- |:--- | +| **Editable** | No | Yes | +| **Deletable** | No | Yes | +| **Compilation** | Pre-compiled for all WAF compiler versions | Compiled on demand for the target compiler version | +| **Field layout** | Fixed; matches the security dashboard | User-defined | +| **Used by the security dashboard** | Yes | No | +| **Best for** | Sending data to the NGINX One Console security dashboard | Forwarding to SIEMs, custom syslog endpoints, or file logs with a non-standard field set | + +--- -For detailed deployment instructions, see [Deploy log profiles]({{< ref "/nginx-one-console/waf-integration/log-profiles/deploy-log-profiles.md" >}}). +## References -## Next steps +For more information, see: -After deploying the default log profile: -- Monitor security events in the [F5 WAF for NGINX security monitoring dashboard]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/" >}}) -- Review security event details and identify attack patterns -- Fine-tune your F5 WAF for NGINX policies based on observed violations +- [Set up security monitoring]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md" >}}) +- [F5 WAF for NGINX security monitoring overview]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/security-monitoring-overview.md" >}}) +- [Log profiles]({{< ref "/nginx-one-console/waf-integration/log-profiles/_index.md" >}}) +- [Deploy log profiles]({{< ref "/nginx-one-console/waf-integration/log-profiles/deploy-log-profiles.md" >}}) diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/find-event-by-support-id.md b/content/nginx-one-console/waf-integration/waf-security-dashboard/find-event-by-support-id.md new file mode 100644 index 000000000..9c279fdaf --- /dev/null +++ b/content/nginx-one-console/waf-integration/waf-security-dashboard/find-event-by-support-id.md @@ -0,0 +1,94 @@ +--- +nd-content-type: how-to +nd-docs: DOCS-000 +nd-product: NONECO +title: Find a security event by Support ID +description: "Look up an F5 WAF for NGINX security event in NGINX One Console using its Support ID." +weight: 500 +toc: true +nd-keywords: "support ID, security event, F5 WAF for NGINX, security dashboard, troubleshooting, event lookup" +nd-summary: > + Use the Support ID Details page in NGINX One Console to look up a single F5 WAF for NGINX security event by its Support ID. + This is the fastest way to drill from a customer report, an upstream log line, or an alert into the full WAF event record. + This guide covers what a Support ID is, where to find one, and how to use the lookup page. +nd-audience: operator +--- + +## Overview + +Every request that F5 WAF for NGINX inspects is assigned a unique **Support ID**. The Support ID stays with the request through every system that touches it — F5 WAF for NGINX security logs, NGINX access logs (when configured), upstream application logs, and the security monitoring dashboard. NGINX One Console exposes a dedicated **Support ID Details** page so you can paste a Support ID and immediately see the full WAF event record without filtering through the dashboard. + +Use this page when you already know the ID of the event you want to inspect — for example, from a customer support case, a raw F5 WAF for NGINX log line, an alert payload, or an upstream application that captured the ID from a request header. To explore events without a known ID, use the Event Logs tab on the [security monitoring dashboard]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/dashboard-metrics-reference.md#event-logs-tab" >}}) instead. + +--- + +## Before you begin + +Before you begin, ensure you have: + +- **A Support ID**: A numeric Support ID for the event you want to inspect. See [Where to find a Support ID](#where-to-find-a-support-id) below. +- **Security monitoring set up**: F5 WAF for NGINX security events must already be flowing into NGINX One Console for the event to be available. See [Set up security monitoring]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md" >}}). +- **Within the retention window**: Security events are retained for 90 days. Events older than 90 days are no longer available. + +--- + +## Look up an event by Support ID + +1. In NGINX One Console, go to **WAF** > **Support ID Details**. +2. Paste the Support ID into the **Enter a Support ID** field. +3. The page displays the **Security Event** detail panel for the matching event, including the request, source, and raw request data. + +If no event is found, the most likely causes are that the Support ID does not belong to a WAF-inspected request, the event is older than the 90-day retention window, or the Support ID was mistyped. + +--- + +## What the detail panel shows + +The Security Event detail panel surfaces every field stored on the event: + +- **Request** — request method, URI, host, headers, and the **Raw Request** payload as captured by F5 WAF for NGINX. The raw request is the same payload that would appear in a NAP security log on the data plane. +- **Source** — client IP, X-Forwarded-For chain, and a geolocation map showing the country derived from the client IP. +- **Time of Request** — when F5 WAF for NGINX produced the event. +- **Triggered violations and signatures** — every violation and signature that fired on the event, with their full attributes (name, accuracy, risk, CVE, context). +- **Threat campaigns** — any threat campaigns matched by the event. +- **Policy and outcome** — the F5 WAF for NGINX policy that produced the event, the request status (`blocked` or `alerted`), and the outcome reason. + +--- + +## Where to find a Support ID + +A Support ID can come from any system that observed the request: + +- **F5 WAF for NGINX security logs on the data plane** — the Support ID is the first field in every log line emitted by the [default log profile]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md" >}}). +- **F5 WAF for NGINX rejection page** — when F5 WAF for NGINX blocks a request, the response page typically includes the Support ID so the user can quote it back to support. +- **Customer support cases** — end users who hit a Request Rejected page can be asked to provide the Support ID from that page. + +--- + +## Use cases + +### Operator: triage a customer-reported block + +A customer reports that their request was rejected and provides the Support ID from the rejection page. The operator opens **WAF** > **Support ID Details**, pastes the ID, and sees the full event record, including which signature fired and which policy was in effect — enough to decide whether the block was a true positive or a candidate for policy tuning. + +### Security engineer: correlate an upstream incident with WAF activity + +An upstream service surfaces an incident referencing a Support ID extracted from request headers. The engineer pastes the ID into the Support ID Details page to see whether the request was blocked, alerted, or passed by F5 WAF for NGINX, and which violations or signatures it triggered, before deciding whether the incident is WAF-related. + +--- + +## Querying by Support ID through the API + +The same lookup is available through the analytics API. Use the [`getSecurityEvent`]({{< ref "/nginx-one-console/api/api-reference-guide/#operation/getSecurityEvent" >}}) operation to fetch a single event, or [`listSecurityEvents`]({{< ref "/nginx-one-console/api/api-reference-guide/#operation/listSecurityEvents" >}}) with `support_id` in `filter_fields` to look up by Support ID programmatically. + +For more on querying events through the API, see [Query security events through the API]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md" >}}). + +--- + +## References + +For more information, see: + +- [Security dashboard reference]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/dashboard-metrics-reference.md" >}}) +- [Query security events through the API]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md" >}}) +- [Set up security monitoring]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md" >}}) diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md b/content/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md new file mode 100644 index 000000000..f6b215514 --- /dev/null +++ b/content/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md @@ -0,0 +1,72 @@ +--- +nd-content-type: reference +nd-docs: DOCS-000 +nd-product: NONECO +title: Query security events through the API +description: "List F5 WAF for NGINX security events and run analytics queries through the NGINX One Console API." +weight: 600 +toc: true +nd-keywords: "security events API, analytics API, F5 WAF for NGINX, app-protect, NGINX One Console API" +nd-summary: > + Use the NGINX One Console API to list F5 WAF for NGINX security events and run analytics queries against the same data store the security dashboard uses. + This article lists the available operations and points to the API reference for request and response details. + The same filter fields and group-by dimensions used by the dashboard apply to every operation here. +nd-audience: developer +--- + +## Overview + +You can use the NGINX One Console API to query F5 WAF for NGINX security events programmatically. The API exposes the same security event store the security monitoring dashboard reads from, so any view you can build in the dashboard can also be reproduced through the API. Use the API to integrate WAF activity into your own dashboards, automated reports, SIEM enrichment pipelines, or alerting workflows. + +For the full request and response schema of each operation, including the supported filter fields and group-by dimensions, see the [API reference guide]({{< ref "/nginx-one-console/api/api-reference-guide.md" >}}). + +## Events + +Use these operations to list security events and retrieve a single event by ID. + +- [List security events]({{< ref "/nginx-one-console/api/api-reference-guide/#operation/listSecurityEvents" >}}) + - Returns a paginated list of F5 WAF for NGINX security events. Accepts `filter_fields` to narrow results by any of the documented filter fields, a time range for the query window, and standard pagination parameters. +- [Get security event details]({{< ref "/nginx-one-console/api/api-reference-guide/#operation/getSecurityEvent" >}}) + - Returns the full detail for a single security event by ID, including all triggered violations, all triggered signatures, threat campaign matches, and the raw matched request when available. + +--- + +## Attack analytics + +Use these operations to count security events grouped by event-level dimensions. + +- [Query attack analytics]({{< ref "/nginx-one-console/api/api-reference-guide/#operation/queryAttackAnalytics" >}}) + - Returns event counts grouped by an event-level dimension (`request_status`, `ip`, `country`, `policy`, `url`, `hostname`, and others). Supports filter fields, time range, group-by, and limit. +- [Query attack analytics time series]({{< ref "/nginx-one-console/api/api-reference-guide/#operation/queryAttackAnalyticsTimeSeries" >}}) + - Returns the same counts bucketed over time. Use this to drive time-series widgets and trend reports. + +--- + +## Signature analytics + +Use these operations to count security events grouped by attributes of the signatures that fired on them. + +- [Query signature analytics]({{< ref "/nginx-one-console/api/api-reference-guide/#operation/querySignatureAnalytics" >}}) + - Returns event counts grouped by a signature-level dimension (`signature`, `accuracy`, `risk`, `cve`, `request_status`). Filtering on signature-level fields narrows results to events whose matching signatures pass the filter. +- [Query signature analytics time series]({{< ref "/nginx-one-console/api/api-reference-guide/#operation/querySignatureAnalyticsTimeSeries" >}}) + - Returns the same counts bucketed over time. + +--- + +## Violation analytics + +Use this operation to count security events grouped by attributes of the violations they triggered. + +- [Query violation analytics]({{< ref "/nginx-one-console/api/api-reference-guide/#operation/queryViolationAnalytics" >}}) + - Returns event counts grouped by a violation-level dimension (`violation`, `sub_violation`, `context`, `context_key`, `context_value`). + +--- + +## References + +For more information, see: + +- [API reference guide]({{< ref "/nginx-one-console/api/api-reference-guide.md" >}}) +- [Authentication]({{< ref "/nginx-one-console/api/authentication.md" >}}) +- [Dashboard metrics reference]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/dashboard-metrics-reference.md" >}}) +- [Security monitoring overview]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/security-monitoring-overview.md" >}}) \ No newline at end of file diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/security-monitoring-overview.md b/content/nginx-one-console/waf-integration/waf-security-dashboard/security-monitoring-overview.md new file mode 100644 index 000000000..56b068c31 --- /dev/null +++ b/content/nginx-one-console/waf-integration/waf-security-dashboard/security-monitoring-overview.md @@ -0,0 +1,89 @@ +--- +nd-content-type: concept +nd-docs: DOCS-000 +nd-product: NONECO +title: Security monitoring overview +description: "What the F5 WAF for NGINX security monitoring module is, the data pipeline behind it, and what you can do with the data." +weight: 100 +toc: true +nd-keywords: "security monitoring, security dashboard, F5 WAF for NGINX, security events, analytics, NGINX One Console" +nd-summary: > + Security monitoring in NGINX One Console centralizes security events from F5 WAF for NGINX instances and exposes them through dashboards and an analytics API. + Use this document to understand what the dashboard shows, where the data comes from, and how it is scoped and retained. + This document is conceptual; for setup steps see Set up security monitoring. +nd-audience: operator +--- + +Security monitoring brings F5 WAF for NGINX events from every connected instance into a single place in NGINX One Console. Before you set it up, it helps to understand what data the system collects, how it gets there, and how it is organized. + +## What is security monitoring? + +Security monitoring is the NGINX One Console module that ingests F5 WAF for NGINX security events from your data planes, stores them centrally, and exposes them through a security dashboard and an analytics API. It gives you a single view of attacks, violations, and triggered signatures across every NGINX Plus instance you have connected to NGINX One Console. + +This document covers what the module is and how data flows through it. For deployment steps, see [Set up security monitoring]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md" >}}). For details on what each dashboard widget shows, see the [dashboard metrics reference]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/dashboard-metrics-reference.md" >}}). + +--- + +## How security events reach the dashboard + +The data pipeline has four stages: + +1. **Detection.** F5 WAF for NGINX inspects requests on the data plane and produces a security log entry whenever a request matches a violation, signature, or threat campaign. +2. **Forwarding.** F5 WAF for NGINX writes the entry over syslog (port `1514` on localhost) using the [default log profile]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md" >}}). NGINX Agent's OpenTelemetry collector receives it through the `tcplog/nginx_app_protect` receiver. +3. **Transport.** The collector batches events and exports them to NGINX One Console through the `otlp/default` exporter. Batching keeps the upstream call rate low while keeping per-event delivery latency under a minute. +4. **Storage and query.** NGINX One Console parses, indexes, and stores the events. The security dashboard and the analytics API both read from the same store. + +Every event carries the support ID, the policy that matched it, the violation and signature details, and the request context (method, URL, host, client IP, X-Forwarded-For, geolocation). Those fields are what the dashboard groups and filters on. + +--- + +## How data is scoped + +Security events inherit the scope of the instance that produced them. + +- **Tenant**: Events belong to the NGINX One Console tenant the data plane is registered to. Tenants do not see each other's data. +- **Namespace**: Within a tenant, events are partitioned by the namespace the instance lives in. Filters and queries are scoped to the active namespace by default. +- **Instance and policy**: Each event records the instance hostname and the F5 WAF for NGINX policy name that produced it, so you can attribute activity to a specific data plane and a specific policy version. +- **Hostname vs. request host**: The dashboard exposes both the NGINX instance hostname and the HTTP `Host` header from the request as separate filterable fields. Use the instance hostname to scope by data plane; use the request host to scope by the application being attacked. + +--- + +## Retention + +Security events are retained for **90 days**. Queries that reach further back than 90 days return no results. If you need long-term retention, forward events to an external SIEM with a [custom log profile]({{< ref "/nginx-one-console/waf-integration/log-profiles/_index.md" >}}) in addition to the default log profile. + +--- + +## Use cases + +### Operator: triage an active attack + +An operator notices a spike in attack volume on the security dashboard. They use the global filters to narrow down to the affected policy and time window, then drill into the top signatures and attacked endpoints to identify which signatures fired and which URLs were targeted. From a single event, they pull the Support ID, the X-Forwarded-For chain, and the raw request to confirm the source and decide whether to tighten the policy. + +### Security engineer: tune a noisy policy + +A security engineer suspects a policy is producing false positives. They open the security dashboard, filter by policy and blocked requests, and review the breakdown of triggered signatures. The high-volume signatures with low risk and accuracy stand out as candidates for tuning. They cross-check a few events against the raw requests to confirm the signature is firing on legitimate traffic before adjusting the policy. + +### Platform team: report on WAF activity across the fleet + +A platform team needs a weekly summary of WAF activity across hundreds of instances. They use the analytics API to pull attack counts, top signatures, and top violations grouped by instance, then render the result in their own reporting tool. The dashboard remains the interactive surface for ad-hoc investigation; the API is the integration point for automation. + +--- + +## What security monitoring does not cover + +- **Access logs and performance metrics** — security monitoring only ingests F5 WAF for NGINX security events. NGINX access logs and performance telemetry are handled by other parts of NGINX One Console. +- **Policy authoring** — use [WAF policies]({{< ref "/nginx-one-console/waf-integration/policy/_index.md" >}}) to create and deploy F5 WAF for NGINX policies. Security monitoring shows you the effect of those policies, not the policies themselves. +- **Long-term archival** — events expire after 90 days. Forward to an external SIEM if you need longer retention. + +--- + +## References + +For more information, see: + +- [Set up security monitoring]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md" >}}) +- [Default log profile]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md" >}}) +- [Dashboard metrics reference]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/dashboard-metrics-reference.md" >}}) +- [Find a security event by Support ID]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/find-event-by-support-id.md" >}}) +- [Query security events through the API]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md" >}}) diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md b/content/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md index 456bf4ba9..b1676e80c 100644 --- a/content/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md +++ b/content/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md @@ -1,293 +1,123 @@ --- -title: Set up security monitoring -description: Configure NGINX Plus with F5 WAF for NGINX to forward security events to NGINX One Console -weight: 100 nd-content-type: how-to +nd-docs: DOCS-000 nd-product: NONECO +title: Set up security monitoring +description: "Forward F5 WAF for NGINX security events to the NGINX One Console security monitoring dashboard." +weight: 300 +toc: true +nd-keywords: "F5 WAF for NGINX, security monitoring, security dashboard, default log profile, security events" +nd-summary: > + Forward F5 WAF for NGINX security events from an NGINX Plus instance to the NGINX One Console security monitoring dashboard. + You deploy the default log profile through the console, add the WAF directives to your NGINX configuration, and verify events flow into the dashboard. + Repeat these steps for each data plane you want to monitor. +nd-audience: operator --- -This guide walks you through configuring your NGINX Plus data plane to send security telemetry to NGINX One Console. You'll install F5 WAF for NGINX, configure the security dashboard log profile, and set up NGINX Agent to forward security events. - -## Prerequisites - -- NGINX Plus installed and running on your data plane -- Root or sudo access on the data plane system -- NGINX One Console access with permissions to add instances - -## Verify NGINX Plus is running - -Before you begin, confirm that NGINX Plus is installed and running on your system. - -1. Run the following command to check the NGINX Plus service status: - -```bash -sudo systemctl status nginx -``` - -Your output should show that the service is active and running: - -``` -● nginx.service - NGINX Plus - high performance web server - Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: enabled) - Active: active (running) since Wed 2026-03-11 17:26:52 UTC; 1 week 1 day ago - Docs: https://www.nginx.com/resources/ - Main PID: 3682 (nginx) - Tasks: 3 (limit: 4586) - Memory: 4.3M (peak: 4.9M) - CPU: 807ms -``` - -If NGINX Plus is not installed, see the [NGINX Plus installation guide]({{< ref "/nginx/admin-guide/installing-nginx/installing-nginx-plus.md" >}}). - -## Install F5 WAF for NGINX +## Overview -Install F5 WAF for NGINX on your data plane following the [installation instructions for your operating system]({{< ref "/waf/install/virtual-environment.md" >}}). +This guide walks you through enabling F5 WAF for NGINX security monitoring on an NGINX Plus instance that is already connected to NGINX One Console. After you complete the steps, security events appear in the [security monitoring dashboard]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/_index.md" >}}), where you can review attacks, violations, and triggered signatures. -After installation, continue with the next section to configure the security dashboard log profile. +The flow uses the NGINX One Console UI end to end. You deploy the [default log profile]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md" >}}) to the instance, add the F5 WAF for NGINX directives to the NGINX configuration through the console's config editor, and verify the pipeline by triggering test violations. NGINX Agent automatically configures its OpenTelemetry collector to forward security events to NGINX One Console once it sees the correct directives in the NGINX configuration — you do not need to edit the agent configuration by hand. -## Configure the security dashboard log profile - -The security dashboard uses the default log profile to capture security violations. This is a pre-configured, immutable log profile that is automatically compiled for all available WAF compiler versions. For more information about the default log profile, see [Default log profile]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md" >}}). - -To configure the security dashboard, create the `/etc/app_protect/conf/secops_dashboard.json` file with the following content: - -1. Create the file: - -```bash -sudo touch /etc/app_protect/conf/secops_dashboard.json -``` - -2. Add the log profile configuration: - -```bash -sudo tee /etc/app_protect/conf/secops_dashboard.json > /dev/null << 'EOF' -{ - "filter": { - "request_type": "illegal" - }, - "content": { - "format": "user-defined", - "format_string": "%support_id%|%ip_client%|%src_port%|%dest_ip%|%dest_port%|%vs_name%|%policy_name%|%method%|%uri%|%protocol%|%request_status%|%response_code%|%outcome%|%outcome_reason%|%violation_rating%|%blocking_exception_reason%|%is_truncated_bool%|%sig_ids%|%sig_names%|%sig_cves%|%sig_set_names%|%threat_campaign_names%|%sub_violations%|%x_forwarded_for_header_value%|%violations%|%violation_details%|%request%|%geo_location%", - "max_request_size": "2048", - "max_message_size": "64k", - "escaping_characters": [ - { - "from": "|", - "to": "%7C" - } - ] - } -} -EOF -``` - -## Enable F5 WAF for NGINX in your configuration +--- -Update your NGINX configuration to turn on F5 WAF for NGINX and set the security dashboard log profile. +## Before you begin -### Update the main NGINX configuration +Before you begin, ensure you have: -Edit `/etc/nginx/nginx.conf` and add the `load_module` directive at the top: +- **NGINX Plus**: NGINX Plus installed and running on your data plane. See the [NGINX Plus installation guide]({{< ref "/nginx/admin-guide/installing-nginx/installing-nginx-plus.md" >}}). +- **F5 WAF for NGINX installed and loaded**: F5 WAF for NGINX installed on the same host as NGINX Plus, with the `load_module` directive added to `nginx.conf` and `app_protect_enable on;` set in the contexts you want WAF to inspect. See [Install F5 WAF for NGINX]({{< ref "/waf/install/virtual-environment.md" >}}) and [Update configuration files]({{< ref "/waf/install/virtual-environment.md#update-configuration-files" >}}). +- **A WAF policy deployed to the instance**: An F5 WAF for NGINX policy referenced by an `app_protect_policy_file` directive in the same context where you enable WAF. See [WAF policies]({{< ref "/nginx-one-console/waf-integration/policy/_index.md" >}}) for how to create and deploy a policy through NGINX One Console. +- **Instance connected to NGINX One Console**: The data plane is registered with NGINX One Console and NGINX Agent is running on it. See [Add an instance]({{< ref "/nginx-one-console/connect-instances/add-instance.md" >}}). -```nginx -user nginx; -worker_processes auto; -load_module modules/ngx_http_app_protect_module.so; -error_log /var/log/nginx/error.log notice; -pid /run/nginx.pid; +--- -events { - worker_connections 1024; -} +## Deploy the default log profile -http { - include /etc/nginx/mime.types; - default_type application/octet-stream; +The security dashboard relies on the default log profile (`secops_dashboard`) to capture security violations in a standardized format. The default log profile is created and maintained by F5, immutable, and pre-compiled for every available WAF compiler version. It deploys exactly the same way as a custom log profile, and because it is pre-compiled, deployment completes immediately without an on-demand compile. For background, see [Default log profile]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md" >}}). - log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for"'; +1. In NGINX One Console, go to **WAF** > **Log Profiles** and select **`secops_dashboard`**. - access_log /var/log/nginx/access.log main; +2. From **Actions**, select **Deploy**. The **Deploy Log Profile** wizard opens. - sendfile on; - keepalive_timeout 65; +3. In the wizard: - include /etc/nginx/conf.d/*.conf; -} -``` + - Confirm `secops_dashboard` is selected under **Log Profile**. + - Under **Target**, choose **Instance** or **Config Sync Group** and select your target. + - In **Log Profile File Path**, specify the path where the compiled bundle should be deployed on the data plane (for example, `/etc/nginx/secops_dashboard.tgz`). -### Configure a server block with F5 WAF for NGINX +4. Select **Next**. The wizard displays the F5 WAF for NGINX directive snippet to paste into your NGINX configuration, along with the config editor for the target instance. -Edit `/etc/nginx/conf.d/default.conf` to add the F5 WAF for NGINX directives: +5. Open the server block where you want to enable F5 WAF for NGINX (for example, `/etc/nginx/conf.d/default.conf`) and paste the snippet into the `server`, `http`, or `location` context. The snippet looks like this: -```nginx -server { - listen 80 default_server; - server_name localhost; - app_protect_enable on; - app_protect_policy_file "/etc/app_protect/conf/NginxStrictPolicy.json"; - app_protect_security_log "/etc/app_protect/conf/secops_dashboard.json" syslog:server=127.0.0.1:1514; + ```nginx app_protect_security_log_enable on; - - location / { - root /usr/share/nginx/html; - index index.html index.htm; - } - - error_page 500 502 503 504 /50x.html; - location = /50x.html { - root /usr/share/nginx/html; - } -} -``` - -Make sure you specify port `1514` for the syslog server. NGINX Agent listens on this port to receive security events. - -## Verify your NGINX configuration + app_protect_security_log /etc/nginx/secops_dashboard.tgz syslog:server=127.0.0.1:1514; + ``` -Test your NGINX configuration for syntax errors: + Make sure `app_protect_enable on;` and `app_protect_policy_file` are already present in the same context (covered by the prerequisites above). -```bash -sudo nginx -t -``` +6. Review the configuration diff the console shows for the affected files, then select **Publish**. NGINX One Console pushes the updated configuration to the instance and reloads NGINX. -You should see output like this: +For more on the deployment wizard and the alternative **Add File** > **Existing Log Profile** flow, see [Deploy log profiles]({{< ref "/nginx-one-console/waf-integration/log-profiles/deploy-log-profiles.md" >}}). -``` -nginx: the configuration file /etc/nginx/nginx.conf syntax is ok -nginx: configuration file /etc/nginx/nginx.conf test is successful -``` - -Restart NGINX Plus to apply the changes: - -```bash -sudo systemctl restart nginx -``` - -Verify NGINX Plus is running after the restart: - -```bash -sudo systemctl status nginx -``` - -## Install NGINX Agent - -NGINX Agent forwards security telemetry from F5 WAF for NGINX to NGINX One Console. - -1. In NGINX One Console, go to **Instances** and select **Add Instance**. - -2. Select **Generate new key**. This generates your data plane key and displays a `curl` command for agent installation. - -3. Copy the `curl` command and run it in your terminal: - -```bash -curl -``` - -Wait a few minutes for the system to appear in NGINX One Console. - -4. Verify the agent is running: - -```bash -sudo systemctl status nginx-agent -``` - -You should see output like this: - -``` -● nginx-agent.service - NGINX Agent - Loaded: loaded (/etc/systemd/system/nginx-agent.service; enabled; preset: enabled) - Active: active (running) since Thu 2026-03-19 23:53:00 UTC; 23s ago - Docs: https://github.com/nginx/agent#readme - Main PID: 24716 (nginx-agent) - Tasks: 8 (limit: 4586) - Memory: 26.0M (peak: 27.2M) - CPU: 414ms -``` - -## Configure NGINX Agent to forward security events - -Configure NGINX Agent to collect and forward security telemetry from F5 WAF for NGINX. - -1. Edit `/etc/nginx-agent/nginx-agent.conf` and add the following telemetry pipeline configuration at the end of the file: - -```yaml -collector: - exporters: - debug: {} - processors: - batch: - "logs": - send_batch_size: 1000 - timeout: 30s - send_batch_max_size: 1000 - pipelines: - logs: - "default-security-events": - receivers: ["tcplog/nginx_app_protect"] - processors: ["batch/logs"] - exporters: ["debug","otlp/default"] -``` +--- -This configuration batches security events with a 30-second timeout and a maximum batch size of 1000 events. Events are forwarded to NGINX One Console through the `otlp/default` exporter. +## Verify the setup -2. Restart NGINX Agent to apply the changes: +When you select **Publish** in the previous step, NGINX One Console pushes the configuration change to the instance and displays a confirmation toast indicating the publish succeeded. At that point both the F5 WAF for NGINX policy and the default log profile are in place on the data plane, and the security log directive is wired up to NGINX Agent. -```bash -sudo systemctl restart nginx-agent -``` +From this point on, any request that F5 WAF for NGINX inspects on the instance produces a security event that flows to NGINX One Console. To see those events: -3. Verify NGINX Agent is running: +1. In NGINX One Console, go to **WAF** > **Security Dashboard**. +2. As your instance handles traffic, attacks, violations, and triggered signatures appear on the dashboard within about a minute of the request being processed. -```bash -sudo systemctl status nginx-agent -``` +For details on how the dashboard is organized and how to read each widget, see the [security dashboard reference]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/dashboard-metrics-reference.md" >}}). -## Verify the security event pipeline +--- -Check that NGINX Agent successfully started the syslog receiver: +## Troubleshooting -```bash -sudo tail /var/log/nginx-agent/agent.log | grep "syslogserver" -``` +### Publish fails with a configuration validation error -You should see a log entry like this: +**Symptom**: When you select **Publish** in the deployment wizard, NGINX One Console reports a configuration validation error such as `unknown directive "app_protect_enable"`, `unknown directive "app_protect_security_log"`, or a parser error referencing the WAF directives. -``` -time=2026-03-20T00:05:10.212Z level=INFO msg="Found available local NGINX App Protect syslogserver configured on port 1514" -``` +**Cause**: One or more of the F5 WAF for NGINX prerequisites is not in place on the instance — typically the `load_module` line is missing from `nginx.conf`, `app_protect_enable on;` is not set in the context where the security log directive was pasted, or `app_protect_policy_file` references a path the data plane cannot resolve. -To debug security events being sent to NGINX One Console, tail the agent logs: +**Fix**: Re-check the items in [Before you begin](#before-you-begin): -```bash -sudo tail /var/log/nginx-agent/opentelemetry-collector-agent.log -f -``` +- Confirm `load_module modules/ngx_http_app_protect_module.so;` is present in the main context of `nginx.conf`. See [Update configuration files]({{< ref "/waf/install/virtual-environment.md#update-configuration-files" >}}). +- Confirm `app_protect_enable on;` is set in the same `server`, `http`, or `location` context where you pasted the security log snippet. +- Confirm an `app_protect_policy_file` directive references a policy already deployed to the instance. See [WAF policies]({{< ref "/nginx-one-console/waf-integration/policy/_index.md" >}}). -## Test security event detection +Re-run the deployment wizard after fixing the configuration. -Generate test security violations to verify that the pipeline works. +### Publish succeeded but no events appear in the dashboard -1. Trigger some violations with these example requests: +**Symptom**: The publish toast confirmed success, the instance is online in NGINX One Console, but the **WAF > Security Dashboard** shows no events for your instance. -```bash -curl -X SEARCH -k -v 'http://127.0.0.1/helloworld' +**Cause**: The most common causes are that the default log profile is not deployed to that instance, the `app_protect_security_log` directive is in a context that does not handle traffic, or the instance has not yet processed any requests F5 WAF for NGINX would inspect. -curl -k -v 'http://127.0.0.1/a=' -``` +**Fix**: -You should receive a response indicating the request was rejected: +1. Go to **WAF** > **Log Profiles** and confirm `secops_dashboard` is listed as deployed to the target instance under **Deployed To**. +2. Open the instance configuration and confirm the `app_protect_security_log` directive sits in a `server` or `location` block that actually handles request traffic — not in a context the data plane never enters. +3. Confirm the instance is receiving traffic. Until F5 WAF for NGINX inspects a request, the dashboard has nothing to display. +4. Apply a global filter on the dashboard to scope to your instance hostname or policy, in case events are present but hidden by an existing filter. -```html -Request RejectedThe requested URL was rejected. Please consult with your administrator... -``` +If events still do not appear after a request is processed, contact F5 support with the instance hostname and the time window you tested. -2. Verify that security events are being sent to NGINX One Console: +--- -```bash -sudo tail /var/log/nginx-agent/opentelemetry-collector-agent.log -n 200 -``` +## References -Look for log entries showing the violations being forwarded. +For more information, see: -Your security monitoring setup is complete. Security events from F5 WAF for NGINX are forwarded to the NGINX One Console, where you can monitor and analyze them in the security dashboard. +- [Security monitoring overview]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/security-monitoring-overview.md" >}}) +- [Default log profile]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md" >}}) +- [Deploy log profiles]({{< ref "/nginx-one-console/waf-integration/log-profiles/deploy-log-profiles.md" >}}) +- [Add an instance]({{< ref "/nginx-one-console/connect-instances/add-instance.md" >}}) +- [Dashboard metrics reference]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/dashboard-metrics-reference.md" >}}) +- [Find a security event by Support ID]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/find-event-by-support-id.md" >}}) +- [Query security events through the API]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md" >}}) diff --git a/content/nginx-one-console/waf-security-dashboard/_index.md b/content/nginx-one-console/waf-security-dashboard/_index.md deleted file mode 100644 index 0dc385580..000000000 --- a/content/nginx-one-console/waf-security-dashboard/_index.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: F5 WAF for NGINX security monitoring -description: Monitor security events and review WAF dashboards to assess threats -weight: 425 -url: /nginx-one-console/waf-security-dashboard ---- - -Use the Security Monitoring module in NGINX One Console to monitor data from F5 WAF for NGINX instances. Review the security dashboards to assess potential threats and identify opportunities to fine-tune your policies. - -## Dashboard metrics overview - -The security dashboard displays key metrics to help you understand attack patterns and threats. Here's an overview of the main metrics: - -- **Attack Counts** - Track the number of attacks with percentage change comparisons against previous periods -- **Violation Types** - View violations grouped by category (e.g., Protocol Compliance) to understand threat patterns -- **Signatures** - See specific signatures triggered within each violation type across multiple events -- **Event Details** - Access Support IDs, raw request data, triggered signatures, and contextual metadata (Original IP, X-Forwarded-For, Violation Context) -- **Global Filters** - Apply filters by time period, policy, and attack type to instantly update all dashboard widgets diff --git a/content/nginx-one-console/waf-security-dashboard/default-log-profile.md b/content/nginx-one-console/waf-security-dashboard/default-log-profile.md deleted file mode 100644 index d06058066..000000000 --- a/content/nginx-one-console/waf-security-dashboard/default-log-profile.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Default log profile -description: Learn about the security dashboard default log profile and how to deploy it -weight: 200 -nd-content-type: concept -nd-product: NONECO ---- - -The default log profile is a pre-configured F5 WAF for NGINX log profile designed specifically for security event monitoring in NGINX One Console. It captures security violation data in a standardized format optimized for analysis and troubleshooting. - -## About the default log profile - -The default log profile is similar to [other log profiles]({{< ref "/nginx-one-console/waf-integration/log-profiles/_index.md" >}}) in structure and function, but has these key characteristics: - -- **Immutable** — The default log profile cannot be edited or deleted. This ensures the security monitoring data format remains consistent across your deployment. -- **Pre-compiled** — NGINX One Console automatically compiles the default log profile for all available WAF compiler versions. This eliminates the need for on-demand compilation during deployment. -- **Standardized format** — It captures all necessary security telemetry fields for the security dashboard, including support IDs, violation details, signature information, and client context. - -## When to use the default log profile - -Use the default log profile when you want to: -- Send security violation data to NGINX One Console for centralized monitoring -- Analyze attack patterns and trends across your NGINX fleet -- Review violation details and raw request data for specific security events -- Generate baseline security metrics and trending reports - -For specialized logging requirements beyond security monitoring, you can create and deploy custom log profiles alongside the default profile. - -## Deploy the default log profile - -To deploy the default log profile to your NGINX instances or Config Sync Groups, follow the same process described in [Deploy log profiles]({{< ref "/nginx-one-console/waf-integration/log-profiles/deploy-log-profiles.md" >}}). - -The default log profile can be deployed using either of these methods: - -1. **Direct deployment** — Go to **WAF** > **Log Profiles**, select the default log profile, and use **Actions** > **Deploy** to send it to your target instances or Config Sync Groups. - -2. **During configuration editing** — When editing an instance or Config Sync Group configuration, you can select the default log profile from **Add File** > **Existing Log Profile** and specify the deployment path. - -Since the default log profile is pre-compiled for all WAF compiler versions, deployment completes immediately without requiring additional compilation. - -For detailed deployment instructions, see [Deploy log profiles]({{< ref "/nginx-one-console/waf-integration/log-profiles/deploy-log-profiles.md" >}}). - -## Next steps - -After deploying the default log profile: -- Monitor security events in the [F5 WAF for NGINX security monitoring dashboard]({{< ref "/nginx-one-console/waf-security-dashboard/" >}}) -- Review security event details and identify attack patterns -- Fine-tune your F5 WAF for NGINX policies based on observed violations diff --git a/content/nginx-one-console/waf-security-dashboard/set-up-security-monitoring.md b/content/nginx-one-console/waf-security-dashboard/set-up-security-monitoring.md deleted file mode 100644 index 2a6920717..000000000 --- a/content/nginx-one-console/waf-security-dashboard/set-up-security-monitoring.md +++ /dev/null @@ -1,275 +0,0 @@ ---- -title: Set up security monitoring -description: Configure NGINX Plus with F5 WAF for NGINX to forward security events to NGINX One Console -weight: 100 -nd-content-type: how-to -nd-product: NONECO ---- - -This guide walks you through configuring your NGINX Plus data plane to send security telemetry to NGINX One Console. You'll install F5 WAF for NGINX, configure the security dashboard log profile, and set up NGINX Agent to forward security events. - -## Prerequisites - -- NGINX Plus installed and running on your data plane -- Root or sudo access on the data plane system -- NGINX One Console access with permissions to add instances - -## Verify NGINX Plus is running - -Before you begin, confirm that NGINX Plus is installed and running on your system. - -1. Run the following command to check the NGINX Plus service status: - -sudo systemctl status nginx -``` - -Your output should show that the service is active and running: - -● nginx.service - NGINX Plus - high performance web server - Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: enabled) - Active: active (running) since Wed 2026-03-11 17:26:52 UTC; 1 week 1 day ago - Docs: https://www.nginx.com/resources/ - Main PID: 3682 (nginx) - Tasks: 3 (limit: 4586) - Memory: 4.3M (peak: 4.9M) - CPU: 807ms -``` -If you haven’t installed NGINX Plus, follow the [NGINX Plus installation guide]({{< ref "/nginx/admin-guide/installing-nginx/installing-nginx-plus.md" >}}) - - -## Install F5 WAF for NGINX - -Install F5 WAF for NGINX on your data plane following the [installation instructions for your operating system]({{< ref "/waf/install/virtual-environment.md" >}}). - -After installation, continue with the next section to configure the security dashboard log profile. - -## Configure the security dashboard log profile - -The security dashboard uses the default log profile to record security violations. This profile is preconfigured and can’t be changed. The system automatically builds it for all supported WAF compiler versions. For more information, see the [Default log profile]({{< ref "/nginx-one-console/waf-security-dashboard/default-log-profile.md" >}}) documentation. - -To configure the security dashboard, create the `/etc/app_protect/conf/secops_dashboard.json` file with the following content: - -1. Create the file: - -sudo touch /etc/app_protect/conf/secops_dashboard.json -``` - -2. Add the log profile configuration: - -sudo tee /etc/app_protect/conf/secops_dashboard.json > /dev/null << 'EOF' -{ - "filter": { - "request_type": "illegal" - }, - "content": { - "format": "user-defined", - "format_string": "%support_id%|%ip_client%|%src_port%|%dest_ip%|%dest_port%|%vs_name%|%policy_name%|%method%|%uri%|%protocol%|%request_status%|%response_code%|%outcome%|%outcome_reason%|%violation_rating%|%blocking_exception_reason%|%is_truncated_bool%|%sig_ids%|%sig_names%|%sig_cves%|%sig_set_names%|%threat_campaign_names%|%sub_violations%|%x_forwarded_for_header_value%|%violations%|%violation_details%|%request%|%geo_location%", - "max_request_size": "2048", - "max_message_size": "64k", - "escaping_characters": [ - { - "from": "|", - "to": "%7C" - } - ] - } -} -EOF -``` - -## Enable F5 WAF for NGINX in your configuration - -Update your NGINX configuration to turn on F5 WAF for NGINX and set the security dashboard log profile. - -### Update the main NGINX configuration - -Edit `/etc/nginx/nginx.conf` and add the `load_module` directive at the top: - -```nginx -user nginx; -worker_processes auto; -load_module modules/ngx_http_app_protect_module.so; -error_log /var/log/nginx/error.log notice; -pid /run/nginx.pid; - -events { - worker_connections 1024; -} - -http { - include /etc/nginx/mime.types; - default_type application/octet-stream; - - log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for"'; - - access_log /var/log/nginx/access.log main; - - sendfile on; - keepalive_timeout 65; - - include /etc/nginx/conf.d/*.conf; -} -``` - -### Configure a server block with F5 WAF for NGINX - -Edit `/etc/nginx/conf.d/default.conf` to add the F5 WAF for NGINX directives: - -```nginx -server { - listen 80 default_server; - server_name localhost; - app_protect_enable on; - app_protect_policy_file "/etc/app_protect/conf/NginxStrictPolicy.json"; - app_protect_security_log "/etc/app_protect/conf/secops_dashboard.json" syslog:server=127.0.0.1:1514; - app_protect_security_log_enable on; - - location / { - root /usr/share/nginx/html; - index index.html index.htm; - } - - error_page 500 502 503 504 /50x.html; - location = /50x.html { - root /usr/share/nginx/html; - } -} -``` - -Make sure you specify port `1514` for the syslog server. NGINX Agent listens on this port to receive security events. - -## Verify your NGINX configuration - -Test your NGINX configuration for syntax errors: - -sudo nginx -t -``` - -You should see output like this: - -nginx: the configuration file /etc/nginx/nginx.conf syntax is ok -nginx: configuration file /etc/nginx/nginx.conf test is successful -``` - -Restart NGINX Plus to apply the changes: - -sudo systemctl restart nginx -``` - -Verify NGINX Plus is running after the restart: - -sudo systemctl status nginx -``` - -## Install NGINX Agent - -NGINX Agent forwards security telemetry from F5 WAF for NGINX to NGINX One Console. - -1. In NGINX One Console, go to **Instances** and select **Add Instance**. - -2. Select **Generate new key**. This generates your data plane key and displays a `curl` command for agent installation. - -3. Copy the `curl` command and run it in your terminal: - -curl -``` - -Wait a few minutes for the system to appear in NGINX One Console. - -4. Verify the agent is running: - -sudo systemctl status nginx-agent -``` - -You should see output like this: - -● nginx-agent.service - NGINX Agent - Loaded: loaded (/etc/systemd/system/nginx-agent.service; enabled; preset: enabled) - Active: active (running) since Thu 2026-03-19 23:53:00 UTC; 23s ago - Docs: https://github.com/nginx/agent#readme - Main PID: 24716 (nginx-agent) - Tasks: 8 (limit: 4586) - Memory: 26.0M (peak: 27.2M) - CPU: 414ms -``` - -## Configure NGINX Agent to forward security events - -Configure NGINX Agent to collect and forward security telemetry from F5 WAF for NGINX. - -1. Edit `/etc/nginx-agent/nginx-agent.conf` and add the following telemetry pipeline configuration at the end of the file: - -```yaml -collector: - exporters: - debug: {} - processors: - batch: - "logs": - send_batch_size: 1000 - timeout: 30s - send_batch_max_size: 1000 - pipelines: - logs: - "default-security-events": - receivers: ["tcplog/nginx_app_protect"] - processors: ["batch/logs"] - exporters: ["debug","otlp/default"] -``` - -This configuration batches security events with a 30-second timeout and a maximum batch size of 1000 events. Events are forwarded to NGINX One Console through the `otlp/default` exporter. - -2. Restart NGINX Agent to apply the changes: - -sudo systemctl restart nginx-agent -``` - -3. Verify NGINX Agent is running: - -sudo systemctl status nginx-agent -``` - -## Verify the security event pipeline - -Check that NGINX Agent successfully started the syslog receiver: - -sudo tail /var/log/nginx-agent/agent.log | grep "syslogserver" -``` - -You should see a log entry like this: - -time=2026-03-20T00:05:10.212Z level=INFO msg="Found available local NGINX App Protect syslogserver configured on port 1514" -``` - -To debug security events being sent to NGINX One Console, tail the agent logs: - -sudo tail /var/log/nginx-agent/opentelemetry-collector-agent.log -f -``` - -## Test security event detection - -Generate test security violations to verify that the pipeline works. - -1. Trigger some violations with these example requests: - -curl -X SEARCH -k -v 'http://127.0.0.1/helloworld' - -curl -k -v 'http://127.0.0.1/a=' -``` - -You should receive a response indicating the request was rejected: - -```html -Request RejectedThe requested URL was rejected. Please consult with your administrator... -``` - -2. Verify that security events are being sent to NGINX One Console: - -sudo tail /var/log/nginx-agent/opentelemetry-collector-agent.log -n 200 -``` - -Look for log entries showing the violations being forwarded. - -Your security monitoring setup is complete. Security events from F5 WAF for NGINX are forwarded to the NGINX One Console, where you can monitor and analyze them in the security dashboard. diff --git a/static/nginx-one-console/api/one.json b/static/nginx-one-console/api/one.json index e9a1c7a9c..eb6b71ef2 100644 --- a/static/nginx-one-console/api/one.json +++ b/static/nginx-one-console/api/one.json @@ -92,6 +92,11 @@ "name": "Templates", "description": "**⚠️ Experimental API** - This API is in active development and subject to breaking changes.\n\n* Import, list, and retrieve NGINX configuration templates.\n* Generate and preview full NGINX configurations by composing templates, before saving it as a staged config.\n", "x-displayName": "Templates" + }, + { + "name": "NGINX One App Protect", + "description": "Security analytics endpoints for NGINX One App Protect.\n", + "x-displayName": "NGINX One App Protect" } ], "paths": { @@ -4405,14 +4410,14 @@ } } }, - "/app-protect/policies": { + "/app-protect/log-profiles": { "get": { "tags": [ - "NGINX App Protect" + "WAF Log Profiles" ], - "summary": "List NGINX App Protect policies", - "description": "Returns a list of NGINX App Protect policies along with deployment details.", - "operationId": "listNapPolicies", + "summary": "List WAF log profiles", + "description": "Returns a list of WAF log profiles.", + "operationId": "listWafLogProfiles", "parameters": [ { "$ref": "#/components/parameters/Paginated" @@ -4427,10 +4432,10 @@ "$ref": "#/components/parameters/SortDirection" }, { - "$ref": "#/components/parameters/SortNameNapPoliciesDep" + "$ref": "#/components/parameters/SortNameNapLogProfilesDep" }, { - "$ref": "#/components/parameters/SortNameNapPolicies" + "$ref": "#/components/parameters/SortNameNapLogProfiles" }, { "$ref": "#/components/parameters/FilterOperands" @@ -4439,78 +4444,16 @@ "$ref": "#/components/parameters/FilterValues" }, { - "$ref": "#/components/parameters/FilterFieldNapPolicy" - } - ], - "responses": { - "200": { - "description": "Successfully returned NGINX App Protect policies.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NapPolicyListResponse" - } - } - } - }, - "400": { - "description": "Request cannot be processed due to invalid input or parameters. Verify the request format and provided data.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "401": { - "description": "Access denied.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "500": { - "description": "An unexpected error occurred on the server. Please try the request again later.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } + "$ref": "#/components/parameters/FilterFieldNapLogProfile" } - } - }, - "patch": { - "x-nginx-one-action": "bulk", - "x-nginx-one-entity": "NGINX App Protect Policies", - "tags": [ - "NGINX App Protect" ], - "summary": "Bulk operation on multiple Nap policy", - "operationId": "bulkNAPPolicy", - "description": "Performs bulk operation on one or more Nap policy, only delete is supported.", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NapPolicyBulkRequest" - } - } - } - }, "responses": { "200": { - "description": "Batch request completed.", + "description": "Successfully returned WAF log profiles.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/NapBulkResponse" + "$ref": "#/components/schemas/NapLogProfileListResponse" } } } @@ -4538,31 +4481,29 @@ } }, "post": { - "x-nginx-one-action": "create", - "x-nginx-one-entity": "NGINX App Protect Policies", "tags": [ - "NGINX App Protect" + "WAF Log Profiles" ], - "summary": "Create NGINX App Protect policy", - "description": "Creates NGINX App Protect policy.", - "operationId": "createNapPolicy", + "summary": "Create WAF log profile", + "description": "Creates a WAF log profile.", + "operationId": "createWafLogProfile", "requestBody": { "required": true, "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/NapPolicy" + "$ref": "#/components/schemas/NapLogProfileCreateRequest" } } } }, "responses": { "201": { - "description": "Successfully created NGINX App Protect policy.", + "description": "Successfully created WAF log profile.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/NapPolicyMetadata" + "$ref": "#/components/schemas/NapLogProfileMetadata" } } } @@ -4600,24 +4541,22 @@ } } }, - "/app-protect/policies/{nap_policy_object_id}": { + "/app-protect/log-profiles/{nap_log_profile_object_id}": { "delete": { "tags": [ - "NGINX App Protect" + "WAF Log Profiles" ], - "x-nginx-one-action": "delete", - "x-nginx-one-entity": "NGINX App Protect Policies", - "summary": "Delete NGINX App Protect policy", - "description": "Deletes NGINX App Protect policy.", - "operationId": "deleteNapPolicy", + "summary": "Delete WAF log profile", + "description": "Deletes a WAF log profile.", + "operationId": "deleteWafLogProfile", "parameters": [ { - "$ref": "#/components/parameters/NapPolicyParamObjectID" + "$ref": "#/components/parameters/NapLogProfileParamObjectID" } ], "responses": { "204": { - "description": "Successfully deleted NGINX App Protect policy." + "description": "Successfully deleted WAF log profile." }, "400": { "description": "Request cannot be processed due to invalid input or parameters. Verify the request format and provided data.", @@ -4640,7 +4579,7 @@ } }, "404": { - "description": "The NGINX App Protect policy with the specified nap_policy_object_id was not found. Check that the nap_policy_object_id provided is correct and corresponds to an existing resource.", + "description": "The WAF log profile with the specified nap_log_profile_object_id was not found. Check that the nap_log_profile_object_id provided is correct and corresponds to an existing resource.", "content": { "application/json": { "schema": { @@ -4663,23 +4602,23 @@ }, "get": { "tags": [ - "NGINX App Protect" + "WAF Log Profiles" ], - "summary": "Get NGINX App Protect policy details", - "description": "Returns NGINX App Protect policy summary.", - "operationId": "getNapPolicy", + "summary": "Get WAF log profile details", + "description": "Returns WAF log profile details.", + "operationId": "getWafLogProfile", "parameters": [ { - "$ref": "#/components/parameters/NapPolicyParamObjectID" + "$ref": "#/components/parameters/NapLogProfileParamObjectID" } ], "responses": { "200": { - "description": "Successfully returned NGINX App Protect policy details.", + "description": "Successfully returned WAF log profile details.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/NapPolicyObject" + "$ref": "#/components/schemas/NapLogProfileObjectDetails" } } } @@ -4705,7 +4644,7 @@ } }, "404": { - "description": "The NGINX App Protect policy with the specified nap_policy_object_id was not found. Check that the nap_policy_object_id provided is correct and corresponds to an existing resource.", + "description": "The WAF log profile with the specified nap_log_profile_object_id was not found. Check that the nap_log_profile_object_id provided is correct and corresponds to an existing resource.", "content": { "application/json": { "schema": { @@ -4728,16 +4667,14 @@ }, "put": { "tags": [ - "NGINX App Protect" + "WAF Log Profiles" ], - "x-nginx-one-action": "update", - "x-nginx-one-entity": "NGINX App Protect Policies", - "summary": "Update NGINX App Protect policy details", - "description": "Update NGINX App Protect policy details.", - "operationId": "updateNapPolicy", + "summary": "Update WAF log profile details", + "description": "Updates WAF log profile details.", + "operationId": "updateWafLogProfile", "parameters": [ { - "$ref": "#/components/parameters/NapPolicyParamObjectID" + "$ref": "#/components/parameters/NapLogProfileParamObjectID" } ], "requestBody": { @@ -4745,18 +4682,18 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/NapPolicy" + "$ref": "#/components/schemas/NapLogProfileUpdateRequest" } } } }, "responses": { - "201": { - "description": "Successfully created an NGINX App Protect policy version.", + "200": { + "description": "Successfully updated WAF log profile details.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/NapPolicyMetadata" + "$ref": "#/components/schemas/NapLogProfileMetadata" } } } @@ -4782,7 +4719,7 @@ } }, "404": { - "description": "The NGINX App Protect policy with the specified nap_policy_object_id was not found. Check that the nap_policy_object_id provided is correct and corresponds to an existing resource.", + "description": "The WAF log profile with the specified nap_log_profile_object_id was not found. Check that the nap_log_profile_object_id provided is correct and corresponds to an existing resource.", "content": { "application/json": { "schema": { @@ -4804,17 +4741,95 @@ } } }, - "/app-protect/policies/{nap_policy_object_id}/deployments": { + "/app-protect/log-profiles/{nap_log_profile_object_id}/compile": { "get": { + "x-feature-flag": "log-profile-deployment", "tags": [ - "NGINX App Protect" + "WAF Log Profiles" ], - "summary": "List NGINX App Protect deployments", - "description": "Returns NGINX App Protect deployments, providing details such as:\n * Target of the deployment, either an instance or CSG\n * Time of deployment\n * Enforcement mode\n * Policy version\n * Threat campaign\n * Attack signature\n * Bot signature\n", - "operationId": "listNapPolicyDeployments", + "summary": "Compile WAF log profile", + "description": "Compiles a WAF log profile and returns the request status or compiled bundle.", + "operationId": "compileWafLogProfile", "parameters": [ { - "$ref": "#/components/parameters/NapPolicyParamObjectID" + "$ref": "#/components/parameters/NapCompileNapRelease" + }, + { + "$ref": "#/components/parameters/NapCompileDownload" + }, + { + "$ref": "#/components/parameters/NapLogProfileParamObjectID" + } + ], + "responses": { + "200": { + "description": "WAF log profile compiled successfully, when `download` is `true`.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NapCompileStatus" + } + }, + "application/gzip": { + "schema": { + "type": "string", + "format": "binary", + "example": "log_all.tar.gz" + } + } + } + }, + "202": { + "description": "Accepted the WAF log profile compile request.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NapCompileStatus" + } + } + } + }, + "400": { + "description": "WAF log profile compilation failed, when `download` is `true`.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NapCompileStatus" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "500": { + "description": "An unexpected error occurred on the server. Please try the request again later.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/app-protect/log-profiles/{nap_log_profile_object_id}/deployments": { + "get": { + "x-feature-flag": "log-profile-deployment", + "tags": [ + "WAF Log Profiles" + ], + "summary": "List WAF log profile deployments", + "description": "Returns a list of WAF log profile deployments, providing details such as:\n * Target of the deployment, either an instance or CSG\n * Time of deployment\n * Deployment status\n", + "operationId": "listWafLogProfileDeployments", + "parameters": [ + { + "$ref": "#/components/parameters/NapLogProfileParamObjectID" }, { "$ref": "#/components/parameters/Paginated" @@ -4829,10 +4844,7 @@ "$ref": "#/components/parameters/SortDirection" }, { - "$ref": "#/components/parameters/SortNameNapPolicyDeploymentsDep" - }, - { - "$ref": "#/components/parameters/SortNameNapPolicyDeployments" + "$ref": "#/components/parameters/SortNameNapLogProfileDeployments" }, { "$ref": "#/components/parameters/FilterOperands" @@ -4841,16 +4853,16 @@ "$ref": "#/components/parameters/FilterValues" }, { - "$ref": "#/components/parameters/FilterFieldNapPolicyDeployment" + "$ref": "#/components/parameters/FilterFieldNapLogProfileDeployment" } ], "responses": { "200": { - "description": "Successfully returned NGINX App Protect deployments.", + "description": "Successfully returned WAF log profile deployments.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/NapPolicyDeploymentsListResponse" + "$ref": "#/components/schemas/NapLogProfileDeploymentsListResponse" } } } @@ -4876,7 +4888,7 @@ } }, "404": { - "description": "The NGINX App Protect policy with the specified nap_policy_object_id was not found. Check that the nap_policy_object_id provided is correct and corresponds to an existing resource.", + "description": "The WAF log profile with the specified nap_log_profile_object_id was not found. Check that the nap_log_profile_object_id provided is correct and corresponds to an existing resource.", "content": { "application/json": { "schema": { @@ -4898,32 +4910,56 @@ } } }, - "/app-protect/policies/{nap_policy_object_id}/version": { + "/app-protect/policies": { "get": { "tags": [ "NGINX App Protect" ], - "summary": "Get the latest NGINX App Protect policy version details", - "description": "Returns the latest NGINX App Protect policy version details.", - "operationId": "getLatestNapPolicyVersion", + "summary": "List NGINX App Protect policies", + "description": "Returns a list of NGINX App Protect policies along with deployment details.", + "operationId": "listNapPolicies", "parameters": [ { - "$ref": "#/components/parameters/NapPolicyParamObjectID" + "$ref": "#/components/parameters/Paginated" + }, + { + "$ref": "#/components/parameters/Limit" + }, + { + "$ref": "#/components/parameters/Offset" + }, + { + "$ref": "#/components/parameters/SortDirection" + }, + { + "$ref": "#/components/parameters/SortNameNapPoliciesDep" + }, + { + "$ref": "#/components/parameters/SortNameNapPolicies" + }, + { + "$ref": "#/components/parameters/FilterOperands" + }, + { + "$ref": "#/components/parameters/FilterValues" + }, + { + "$ref": "#/components/parameters/FilterFieldNapPolicy" } ], "responses": { "200": { - "description": "Successfully returned NGINX App Protect policy version details.", + "description": "Successfully returned NGINX App Protect policies.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/NapPolicyVersionDetails" + "$ref": "#/components/schemas/NapPolicyListResponse" } } } }, - "401": { - "description": "Access denied.", + "400": { + "description": "Request cannot be processed due to invalid input or parameters. Verify the request format and provided data.", "content": { "application/json": { "schema": { @@ -4932,8 +4968,8 @@ } } }, - "404": { - "description": "The NGINX App Protect policy version with the specified nap_policy_object_id was not found. Check that the nap_policy_object_id provided is correct and corresponds to an existing resource.", + "401": { + "description": "Access denied.", "content": { "application/json": { "schema": { @@ -4953,61 +4989,39 @@ } } } - } - }, - "/app-protect/policies/{nap_policy_object_id}/versions": { - "get": { + }, + "patch": { + "x-nginx-one-action": "bulk", + "x-nginx-one-entity": "NGINX App Protect Policies", "tags": [ "NGINX App Protect" ], - "summary": "List NGINX App Protect policy versions", - "description": "Returns NGINX App Protect policy versions.", - "operationId": "listNapPolicyVersions", - "parameters": [ - { - "$ref": "#/components/parameters/NapPolicyParamObjectID" - }, - { - "$ref": "#/components/parameters/Paginated" - }, - { - "$ref": "#/components/parameters/Limit" - }, - { - "$ref": "#/components/parameters/Offset" - }, - { - "$ref": "#/components/parameters/SortDirection" - }, - { - "$ref": "#/components/parameters/SortNameNapPolicyVersionsDep" - }, - { - "$ref": "#/components/parameters/SortNameNapPolicyVersions" - }, - { - "$ref": "#/components/parameters/FilterOperands" - }, - { - "$ref": "#/components/parameters/FilterValues" - }, - { - "$ref": "#/components/parameters/FilterFieldNapPolicyVersion" + "summary": "Bulk operation on multiple Nap policy", + "operationId": "bulkNAPPolicy", + "description": "Performs bulk operation on one or more Nap policy, only delete is supported.", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NapPolicyBulkRequest" + } + } } - ], + }, "responses": { "200": { - "description": "Successfully returned the NGINX App Protect policy versions.", + "description": "Batch request completed.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/NapPolicyVersionsListResponse" + "$ref": "#/components/schemas/NapBulkResponse" } } } }, - "400": { - "description": "Request cannot be processed due to invalid input or parameters. Verify the request format and provided data.", + "401": { + "description": "Access denied.", "content": { "application/json": { "schema": { @@ -5016,8 +5030,50 @@ } } }, - "401": { - "description": "Access denied.", + "500": { + "description": "An unexpected error occurred on the server. Please try the request again later.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + }, + "post": { + "x-nginx-one-action": "create", + "x-nginx-one-entity": "NGINX App Protect Policies", + "tags": [ + "NGINX App Protect" + ], + "summary": "Create NGINX App Protect policy", + "description": "Creates NGINX App Protect policy.", + "operationId": "createNapPolicy", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NapPolicy" + } + } + } + }, + "responses": { + "201": { + "description": "Successfully created NGINX App Protect policy.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NapPolicyMetadata" + } + } + } + }, + "400": { + "description": "Request cannot be processed due to invalid input or parameters. Verify the request format and provided data.", "content": { "application/json": { "schema": { @@ -5026,8 +5082,8 @@ } } }, - "404": { - "description": "The NGINX App Protect policy with the specified nap_policy_object_id was not found. Check that the nap_policy_object_id provided is correct and corresponds to an existing resource.", + "401": { + "description": "Access denied.", "content": { "application/json": { "schema": { @@ -5049,27 +5105,34 @@ } } }, - "/app-protect/policies/{nap_policy_object_id}/versions/{nap_policy_version_object_id}": { + "/app-protect/policies/{nap_policy_object_id}": { "delete": { - "x-nginx-one-action": "delete", - "x-nginx-one-entity": "NGINX App Protect Policy Version", "tags": [ "NGINX App Protect" ], - "summary": "Delete NGINX App Protect policy version", - "description": "Deletes the NGINX App Protect policy version.", - "operationId": "deleteNapPolicyVersion", + "x-nginx-one-action": "delete", + "x-nginx-one-entity": "NGINX App Protect Policies", + "summary": "Delete NGINX App Protect policy", + "description": "Deletes NGINX App Protect policy.", + "operationId": "deleteNapPolicy", "parameters": [ { "$ref": "#/components/parameters/NapPolicyParamObjectID" - }, - { - "$ref": "#/components/parameters/NapPolicyVersionParamObjectID" } ], "responses": { "204": { - "description": "Successfully deleted the NGINX App Protect policy version." + "description": "Successfully deleted NGINX App Protect policy." + }, + "400": { + "description": "Request cannot be processed due to invalid input or parameters. Verify the request format and provided data.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } }, "401": { "description": "Access denied.", @@ -5082,7 +5145,7 @@ } }, "404": { - "description": "The NGINX App Protect policy version with the specified nap_policy_version_object_id and nap_policy_version_object_id was not found. Check that the object IDs provided are correct and corresponds to existing resources.", + "description": "The NGINX App Protect policy with the specified nap_policy_object_id was not found. Check that the nap_policy_object_id provided is correct and corresponds to an existing resource.", "content": { "application/json": { "schema": { @@ -5107,24 +5170,31 @@ "tags": [ "NGINX App Protect" ], - "summary": "Get the specified NGINX App Protect policy version details", - "description": "Returns the specified NGINX App Protect policy version details.", - "operationId": "getNapPolicyVersion", + "summary": "Get NGINX App Protect policy details", + "description": "Returns NGINX App Protect policy summary.", + "operationId": "getNapPolicy", "parameters": [ { "$ref": "#/components/parameters/NapPolicyParamObjectID" - }, - { - "$ref": "#/components/parameters/NapPolicyVersionParamObjectID" } ], "responses": { "200": { - "description": "Successfully returned NGINX App Protect policy version details.", + "description": "Successfully returned NGINX App Protect policy details.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/NapPolicyVersionDetails" + "$ref": "#/components/schemas/NapPolicyObject" + } + } + } + }, + "400": { + "description": "Request cannot be processed due to invalid input or parameters. Verify the request format and provided data.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" } } } @@ -5140,7 +5210,7 @@ } }, "404": { - "description": "The NGINX App Protect policy version with the specified nap_policy_version_object_id and nap_policy_version_object_id was not found. Check that the object IDs provided are correct and corresponds to existing resources.", + "description": "The NGINX App Protect policy with the specified nap_policy_object_id was not found. Check that the nap_policy_object_id provided is correct and corresponds to an existing resource.", "content": { "application/json": { "schema": { @@ -5160,140 +5230,97 @@ } } } - } - }, - "/app-protect/signature-sets": { - "get": { + }, + "put": { "tags": [ "NGINX App Protect" ], - "summary": "List NGINX App Protect signature sets", - "description": "Returns NGINX App Protect signature sets. Signature sets are predefined or user-defined groups of detection mechanisms (signatures) \nthat identify specific attack types, such as SQL injection, Cross-Site Scripting (XSS), or other web-based threats.\n", - "operationId": "listSignatureSets", + "x-nginx-one-action": "update", + "x-nginx-one-entity": "NGINX App Protect Policies", + "summary": "Update NGINX App Protect policy details", + "description": "Update NGINX App Protect policy details.", + "operationId": "updateNapPolicy", "parameters": [ { - "$ref": "#/components/parameters/Paginated" - }, - { - "$ref": "#/components/parameters/Limit" - }, - { - "$ref": "#/components/parameters/Offset" - }, - { - "$ref": "#/components/parameters/SortDirection" - }, - { - "$ref": "#/components/parameters/SortNameNapSignatureSets" - }, - { - "$ref": "#/components/parameters/FilterOperands" - }, - { - "$ref": "#/components/parameters/FilterValues" - }, - { - "$ref": "#/components/parameters/FilterFieldNapSignatureSets" + "$ref": "#/components/parameters/NapPolicyParamObjectID" } ], - "responses": { - "200": { - "description": "Successfully returned signature sets.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NapSignatureSetListResponse" - } + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NapPolicy" } } - }, - "401": { - "$ref": "#/components/responses/Unauthorized" - }, - "500": { - "$ref": "#/components/responses/InternalServerErr" - } - } - } - }, - "/app-protect/signature-sets/{signatureSetObjectID}": { - "get": { - "tags": [ - "NGINX App Protect" - ], - "summary": "Retrieve a NGINX App Protect signature set", - "description": "Returns a NGINX App Protect signature set. Signature sets are predefined or user-defined groups of detection \nmechanisms (signatures) that identify specific attack types, such as SQL injection, Cross-Site Scripting (XSS), \nor other web-based threats.\n", - "operationId": "getSignatureSet", - "parameters": [ - { - "$ref": "#/components/parameters/NapSignatureSetObjectID" } - ], + }, "responses": { - "200": { - "description": "Successfully returned Signature Sets.", + "201": { + "description": "Successfully created an NGINX App Protect policy version.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/NapSignatureSet" + "$ref": "#/components/schemas/NapPolicyMetadata" } } } }, - "401": { - "$ref": "#/components/responses/Unauthorized" - }, - "500": { - "$ref": "#/components/responses/InternalServerErr" - } - } - } - }, - "/app-protect/signature-sets/{signatureSetObjectID}/signatures": { - "get": { - "tags": [ - "NGINX App Protect" - ], - "summary": "List NGINX App Protect signatures in the specified signature set.", - "description": "Returns a list of signatures in the NGINX App Protect signature set.\n", - "operationId": "listSignatureSetSignatures", - "parameters": [ - { - "$ref": "#/components/parameters/NapSignatureSetObjectID" - } - ], - "responses": { - "200": { - "description": "Successfully returned signatures for signature set.", + "400": { + "description": "Request cannot be processed due to invalid input or parameters. Verify the request format and provided data.", "content": { "application/json": { "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/NapSignatureMeta" - } + "$ref": "#/components/schemas/Error" } } } }, "401": { - "$ref": "#/components/responses/Unauthorized" + "description": "Access denied.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "The NGINX App Protect policy with the specified nap_policy_object_id was not found. Check that the nap_policy_object_id provided is correct and corresponds to an existing resource.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } }, "500": { - "$ref": "#/components/responses/InternalServerErr" + "description": "An unexpected error occurred on the server. Please try the request again later.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } } } } }, - "/app-protect/signatures": { + "/app-protect/policies/{nap_policy_object_id}/deployments": { "get": { "tags": [ "NGINX App Protect" ], - "summary": "List Signatures", - "description": "Returns signatures. A signature is a predefined detection rule that identifies specific attack patterns or\ncharacteristics commonly associated with web application security threats.\n", - "operationId": "listSignatures", + "summary": "List NGINX App Protect deployments", + "description": "Returns NGINX App Protect deployments, providing details such as:\n * Target of the deployment, either an instance or CSG\n * Time of deployment\n * Enforcement mode\n * Policy version\n * Threat campaign\n * Attack signature\n * Bot signature\n", + "operationId": "listNapPolicyDeployments", "parameters": [ + { + "$ref": "#/components/parameters/NapPolicyParamObjectID" + }, { "$ref": "#/components/parameters/Paginated" }, @@ -5307,7 +5334,10 @@ "$ref": "#/components/parameters/SortDirection" }, { - "$ref": "#/components/parameters/SortNameNapSignatures" + "$ref": "#/components/parameters/SortNameNapPolicyDeploymentsDep" + }, + { + "$ref": "#/components/parameters/SortNameNapPolicyDeployments" }, { "$ref": "#/components/parameters/FilterOperands" @@ -5316,71 +5346,132 @@ "$ref": "#/components/parameters/FilterValues" }, { - "$ref": "#/components/parameters/FilterFieldNapSignatures" + "$ref": "#/components/parameters/FilterFieldNapPolicyDeployment" } ], "responses": { "200": { - "description": "Successfully returned list of signatures.", + "description": "Successfully returned NGINX App Protect deployments.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/NapSignatureListResponse" + "$ref": "#/components/schemas/NapPolicyDeploymentsListResponse" + } + } + } + }, + "400": { + "description": "Request cannot be processed due to invalid input or parameters. Verify the request format and provided data.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" } } } }, "401": { - "$ref": "#/components/responses/Unauthorized" + "description": "Access denied.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "The NGINX App Protect policy with the specified nap_policy_object_id was not found. Check that the nap_policy_object_id provided is correct and corresponds to an existing resource.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } }, "500": { - "$ref": "#/components/responses/InternalServerErr" + "description": "An unexpected error occurred on the server. Please try the request again later.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } } } } }, - "/app-protect/signatures/{signatureID}": { + "/app-protect/policies/{nap_policy_object_id}/version": { "get": { "tags": [ "NGINX App Protect" ], - "summary": "Retrieve a NGINX App Protect signature.", - "description": "A signature is a predefined detection rule that identifies specific attack patterns or characteristics commonly \nassociated with web application security threats.\n", + "summary": "Get the latest NGINX App Protect policy version details", + "description": "Returns the latest NGINX App Protect policy version details.", + "operationId": "getLatestNapPolicyVersion", "parameters": [ { - "$ref": "#/components/parameters/NapSignatureID" + "$ref": "#/components/parameters/NapPolicyParamObjectID" } ], - "operationId": "getSignature", "responses": { "200": { - "description": "Successfully returned the specified signature.", + "description": "Successfully returned NGINX App Protect policy version details.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/NapSignature" + "$ref": "#/components/schemas/NapPolicyVersionDetails" } } } }, "401": { - "$ref": "#/components/responses/Unauthorized" + "description": "Access denied.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "The NGINX App Protect policy version with the specified nap_policy_object_id was not found. Check that the nap_policy_object_id provided is correct and corresponds to an existing resource.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } }, "500": { - "$ref": "#/components/responses/InternalServerErr" + "description": "An unexpected error occurred on the server. Please try the request again later.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } } } } }, - "/app-protect/log-profiles": { + "/app-protect/policies/{nap_policy_object_id}/versions": { "get": { "tags": [ - "WAF Log Profiles" + "NGINX App Protect" ], - "summary": "List WAF log profiles", - "description": "Returns a list of WAF log profiles.", - "operationId": "listWafLogProfiles", + "summary": "List NGINX App Protect policy versions", + "description": "Returns NGINX App Protect policy versions.", + "operationId": "listNapPolicyVersions", "parameters": [ + { + "$ref": "#/components/parameters/NapPolicyParamObjectID" + }, { "$ref": "#/components/parameters/Paginated" }, @@ -5394,10 +5485,10 @@ "$ref": "#/components/parameters/SortDirection" }, { - "$ref": "#/components/parameters/SortNameNapLogProfilesDep" + "$ref": "#/components/parameters/SortNameNapPolicyVersionsDep" }, { - "$ref": "#/components/parameters/SortNameNapLogProfiles" + "$ref": "#/components/parameters/SortNameNapPolicyVersions" }, { "$ref": "#/components/parameters/FilterOperands" @@ -5406,16 +5497,26 @@ "$ref": "#/components/parameters/FilterValues" }, { - "$ref": "#/components/parameters/FilterFieldNapLogProfile" + "$ref": "#/components/parameters/FilterFieldNapPolicyVersion" } ], "responses": { "200": { - "description": "Successfully returned WAF log profiles.", + "description": "Successfully returned the NGINX App Protect policy versions.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/NapLogProfileListResponse" + "$ref": "#/components/schemas/NapPolicyVersionsListResponse" + } + } + } + }, + "400": { + "description": "Request cannot be processed due to invalid input or parameters. Verify the request format and provided data.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" } } } @@ -5430,6 +5531,16 @@ } } }, + "404": { + "description": "The NGINX App Protect policy with the specified nap_policy_object_id was not found. Check that the nap_policy_object_id provided is correct and corresponds to an existing resource.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, "500": { "description": "An unexpected error occurred on the server. Please try the request again later.", "content": { @@ -5441,37 +5552,32 @@ } } } - }, - "post": { + } + }, + "/app-protect/policies/{nap_policy_object_id}/versions/{nap_policy_version_object_id}": { + "delete": { + "x-nginx-one-action": "delete", + "x-nginx-one-entity": "NGINX App Protect Policy Version", "tags": [ - "WAF Log Profiles" + "NGINX App Protect" ], - "summary": "Create WAF log profile", - "description": "Creates a WAF log profile.", - "operationId": "createWafLogProfile", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NapLogProfileCreateRequest" - } - } + "summary": "Delete NGINX App Protect policy version", + "description": "Deletes the NGINX App Protect policy version.", + "operationId": "deleteNapPolicyVersion", + "parameters": [ + { + "$ref": "#/components/parameters/NapPolicyParamObjectID" + }, + { + "$ref": "#/components/parameters/NapPolicyVersionParamObjectID" } - }, + ], "responses": { - "201": { - "description": "Successfully created WAF log profile.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NapLogProfileMetadata" - } - } - } + "204": { + "description": "Successfully deleted the NGINX App Protect policy version." }, - "400": { - "description": "Request cannot be processed due to invalid input or parameters. Verify the request format and provided data.", + "401": { + "description": "Access denied.", "content": { "application/json": { "schema": { @@ -5480,8 +5586,8 @@ } } }, - "401": { - "description": "Access denied.", + "404": { + "description": "The NGINX App Protect policy version with the specified nap_policy_version_object_id and nap_policy_version_object_id was not found. Check that the object IDs provided are correct and corresponds to existing resources.", "content": { "application/json": { "schema": { @@ -5501,31 +5607,29 @@ } } } - } - }, - "/app-protect/log-profiles/{nap_log_profile_object_id}": { - "delete": { + }, + "get": { "tags": [ - "WAF Log Profiles" + "NGINX App Protect" ], - "summary": "Delete WAF log profile", - "description": "Deletes a WAF log profile.", - "operationId": "deleteWafLogProfile", + "summary": "Get the specified NGINX App Protect policy version details", + "description": "Returns the specified NGINX App Protect policy version details.", + "operationId": "getNapPolicyVersion", "parameters": [ { - "$ref": "#/components/parameters/NapLogProfileParamObjectID" + "$ref": "#/components/parameters/NapPolicyParamObjectID" + }, + { + "$ref": "#/components/parameters/NapPolicyVersionParamObjectID" } ], "responses": { - "204": { - "description": "Successfully deleted WAF log profile." - }, - "400": { - "description": "Request cannot be processed due to invalid input or parameters. Verify the request format and provided data.", + "200": { + "description": "Successfully returned NGINX App Protect policy version details.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Error" + "$ref": "#/components/schemas/NapPolicyVersionDetails" } } } @@ -5541,7 +5645,7 @@ } }, "404": { - "description": "The WAF log profile with the specified nap_log_profile_object_id was not found. Check that the nap_log_profile_object_id provided is correct and corresponds to an existing resource.", + "description": "The NGINX App Protect policy version with the specified nap_policy_version_object_id and nap_policy_version_object_id was not found. Check that the object IDs provided are correct and corresponds to existing resources.", "content": { "application/json": { "schema": { @@ -5561,238 +5665,140 @@ } } } - }, + } + }, + "/app-protect/signature-sets": { "get": { "tags": [ - "WAF Log Profiles" + "NGINX App Protect" ], - "summary": "Get WAF log profile details", - "description": "Returns WAF log profile details.", - "operationId": "getWafLogProfile", + "summary": "List NGINX App Protect signature sets", + "description": "Returns NGINX App Protect signature sets. Signature sets are predefined or user-defined groups of detection mechanisms (signatures) \nthat identify specific attack types, such as SQL injection, Cross-Site Scripting (XSS), or other web-based threats.\n", + "operationId": "listSignatureSets", "parameters": [ { - "$ref": "#/components/parameters/NapLogProfileParamObjectID" + "$ref": "#/components/parameters/Paginated" + }, + { + "$ref": "#/components/parameters/Limit" + }, + { + "$ref": "#/components/parameters/Offset" + }, + { + "$ref": "#/components/parameters/SortDirection" + }, + { + "$ref": "#/components/parameters/SortNameNapSignatureSets" + }, + { + "$ref": "#/components/parameters/FilterOperands" + }, + { + "$ref": "#/components/parameters/FilterValues" + }, + { + "$ref": "#/components/parameters/FilterFieldNapSignatureSets" } ], "responses": { "200": { - "description": "Successfully returned WAF log profile details.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NapLogProfileObjectDetails" - } - } - } - }, - "400": { - "description": "Request cannot be processed due to invalid input or parameters. Verify the request format and provided data.", + "description": "Successfully returned signature sets.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Error" + "$ref": "#/components/schemas/NapSignatureSetListResponse" } } } }, "401": { - "description": "Access denied.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "404": { - "description": "The WAF log profile with the specified nap_log_profile_object_id was not found. Check that the nap_log_profile_object_id provided is correct and corresponds to an existing resource.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } + "$ref": "#/components/responses/Unauthorized" }, "500": { - "description": "An unexpected error occurred on the server. Please try the request again later.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } + "$ref": "#/components/responses/InternalServerErr" } } - }, - "put": { + } + }, + "/app-protect/signature-sets/{signatureSetObjectID}": { + "get": { "tags": [ - "WAF Log Profiles" + "NGINX App Protect" ], - "summary": "Update WAF log profile details", - "description": "Updates WAF log profile details.", - "operationId": "updateWafLogProfile", + "summary": "Retrieve a NGINX App Protect signature set", + "description": "Returns a NGINX App Protect signature set. Signature sets are predefined or user-defined groups of detection \nmechanisms (signatures) that identify specific attack types, such as SQL injection, Cross-Site Scripting (XSS), \nor other web-based threats.\n", + "operationId": "getSignatureSet", "parameters": [ { - "$ref": "#/components/parameters/NapLogProfileParamObjectID" + "$ref": "#/components/parameters/NapSignatureSetObjectID" } ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NapLogProfileUpdateRequest" - } - } - } - }, "responses": { "200": { - "description": "Successfully updated WAF log profile details.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NapLogProfileMetadata" - } - } - } - }, - "400": { - "description": "Request cannot be processed due to invalid input or parameters. Verify the request format and provided data.", + "description": "Successfully returned Signature Sets.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Error" + "$ref": "#/components/schemas/NapSignatureSet" } } } }, "401": { - "description": "Access denied.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "404": { - "description": "The WAF log profile with the specified nap_log_profile_object_id was not found. Check that the nap_log_profile_object_id provided is correct and corresponds to an existing resource.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } + "$ref": "#/components/responses/Unauthorized" }, "500": { - "description": "An unexpected error occurred on the server. Please try the request again later.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } + "$ref": "#/components/responses/InternalServerErr" } } } }, - "/app-protect/log-profiles/{nap_log_profile_object_id}/compile": { + "/app-protect/signature-sets/{signatureSetObjectID}/signatures": { "get": { - "x-feature-flag": "log-profile-deployment", "tags": [ - "WAF Log Profiles" + "NGINX App Protect" ], - "summary": "Compile WAF log profile", - "description": "Compiles a WAF log profile and returns the request status or compiled bundle.", - "operationId": "compileWafLogProfile", + "summary": "List NGINX App Protect signatures in the specified signature set.", + "description": "Returns a list of signatures in the NGINX App Protect signature set.\n", + "operationId": "listSignatureSetSignatures", "parameters": [ { - "$ref": "#/components/parameters/NapLogProfileCompileNapRelease" - }, - { - "$ref": "#/components/parameters/NapLogProfileCompileDownload" - }, - { - "$ref": "#/components/parameters/NapLogProfileParamObjectID" + "$ref": "#/components/parameters/NapSignatureSetObjectID" } ], "responses": { "200": { - "description": "WAF log profile compiled successfully, when `download` is `true`.", + "description": "Successfully returned signatures for signature set.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/NapCompileStatus" - } - }, - "application/gzip": { - "schema": { - "type": "string", - "format": "binary", - "example": "log_all.tar.gz" + "type": "array", + "items": { + "$ref": "#/components/schemas/NapSignatureMeta" + } } } } }, - "202": { - "description": "Accepted the WAF log profile compile request.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NapCompileStatus" - } - } - } - }, - "400": { - "description": "WAF log profile compilation failed, when `download` is `true`.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NapCompileStatus" - } - } - } - }, - "401": { - "$ref": "#/components/responses/Unauthorized" - }, - "404": { - "$ref": "#/components/responses/NotFound" + "401": { + "$ref": "#/components/responses/Unauthorized" }, "500": { - "description": "An unexpected error occurred on the server. Please try the request again later.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } + "$ref": "#/components/responses/InternalServerErr" } } } }, - "/app-protect/log-profiles/{nap_log_profile_object_id}/deployments": { + "/app-protect/signatures": { "get": { - "x-feature-flag": "log-profile-deployment", "tags": [ - "WAF Log Profiles" + "NGINX App Protect" ], - "summary": "List WAF log profile deployments", - "description": "Returns a list of WAF log profile deployments, providing details such as:\n * Target of the deployment, either an instance or CSG\n * Time of deployment\n * Deployment status\n", - "operationId": "listWafLogProfileDeployments", + "summary": "List Signatures", + "description": "Returns signatures. A signature is a predefined detection rule that identifies specific attack patterns or\ncharacteristics commonly associated with web application security threats.\n", + "operationId": "listSignatures", "parameters": [ - { - "$ref": "#/components/parameters/NapLogProfileParamObjectID" - }, { "$ref": "#/components/parameters/Paginated" }, @@ -5806,7 +5812,7 @@ "$ref": "#/components/parameters/SortDirection" }, { - "$ref": "#/components/parameters/SortNameNapLogProfileDeployments" + "$ref": "#/components/parameters/SortNameNapSignatures" }, { "$ref": "#/components/parameters/FilterOperands" @@ -5815,59 +5821,58 @@ "$ref": "#/components/parameters/FilterValues" }, { - "$ref": "#/components/parameters/FilterFieldNapLogProfileDeployment" + "$ref": "#/components/parameters/FilterFieldNapSignatures" } ], "responses": { "200": { - "description": "Successfully returned WAF log profile deployments.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NapLogProfileDeploymentsListResponse" - } - } - } - }, - "400": { - "description": "Request cannot be processed due to invalid input or parameters. Verify the request format and provided data.", + "description": "Successfully returned list of signatures.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Error" + "$ref": "#/components/schemas/NapSignatureListResponse" } } } }, "401": { - "description": "Access denied.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } + "$ref": "#/components/responses/Unauthorized" }, - "404": { - "description": "The WAF log profile with the specified nap_log_profile_object_id was not found. Check that the nap_log_profile_object_id provided is correct and corresponds to an existing resource.", + "500": { + "$ref": "#/components/responses/InternalServerErr" + } + } + } + }, + "/app-protect/signatures/{signatureID}": { + "get": { + "tags": [ + "NGINX App Protect" + ], + "summary": "Retrieve a NGINX App Protect signature.", + "description": "A signature is a predefined detection rule that identifies specific attack patterns or characteristics commonly \nassociated with web application security threats.\n", + "parameters": [ + { + "$ref": "#/components/parameters/NapSignatureID" + } + ], + "operationId": "getSignature", + "responses": { + "200": { + "description": "Successfully returned the specified signature.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Error" + "$ref": "#/components/schemas/NapSignature" } } } }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, "500": { - "description": "An unexpected error occurred on the server. Please try the request again later.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } + "$ref": "#/components/responses/InternalServerErr" } } } @@ -6012,6 +6017,11 @@ } } }, + "/templates/{templateObjectID}/copy": {}, + "/templates/{templateObjectID}/submissions": {}, + "/templates/{templateObjectID}/versions": {}, + "/templates/{templateObjectID}/versions/{templateVersionObjectID}": {}, + "/templates/{templateVersionObjectID}/config": {}, "/templates/import": { "post": { "tags": [ @@ -6093,7 +6103,7 @@ }, "responses": { "200": { - "description": "Returned only when the `preview_only` flag is set to `true`.\nResponds with the rendered NGINX configuration that can be used for preview or to create/replace a staged configuration manually.\n\nNote: If `preview_only` is `false` or omitted, this operation is not yet supported and will return an error instead.\n", + "description": "Returned only when the `preview_only` flag is set to `true`.\nResponds with the rendered NGINX configuration that can be used for preview or to create/replace a staged configuration manually.\n", "content": { "application/json": { "schema": { @@ -6102,14 +6112,40 @@ } } }, + "202": { + "description": "The template submission has been accepted and is being processed.\nPublication status(es) can be retrieved by querying the appropriate publications endpoint for the target object.\n", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TemplateSubmissionResponse" + }, + "examples": { + "staged_config_outcome": { + "summary": "Example successful response for a target submission that creates a staged config", + "value": { + "object_id": "tmplsm_frBobKIAQ_21grAwV83VYz", + "target_results": [ + { + "staged_config_status": { + "status": "succeeded" + }, + "target_object_id": "sc_cEoiYCVJRuekVpYOvV1raA" + } + ] + } + } + } + } + } + }, "400": { "$ref": "#/components/responses/InvalidRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, - "405": { - "description": "This operation is not yet implemented. Please use the action for preview (`action=preview`) or partial (`action=partial`).\n", + "409": { + "description": "The submission cannot be completed due to one or more template validation errors. See the error details for more information.\n", "content": { "application/json": { "schema": { @@ -6123,226 +6159,1791 @@ } } } - } - }, - "components": { - "parameters": { - "Paginated": { - "name": "paginated", - "in": "query", - "schema": { - "type": "boolean", - "default": true - }, - "description": "A boolean indicating if the results should be presented as a paginated list. Defaults to `true`. \nWhen set to `false` a maximum of 3000 results are returned.\n", - "required": false - }, - "Limit": { - "name": "limit", - "in": "query", - "schema": { - "type": "integer", - "minimum": 0 - }, - "description": "An integer that specifies the maximum number of items to be returned. \nSetting this to `0` will result in no items being returned, but a total count will still be provided. \nThis parameter is not applicable if `paginated` is `false`.\n", - "required": false - }, - "Offset": { - "name": "offset", - "in": "query", - "schema": { - "type": "integer", - "minimum": 1 - }, - "description": "An integer that specifies the starting position of the results, starting at `1`.\nThis parameter is not applicable if `paginated` is `false`.\n" - }, - "FilterFieldDataPlaneKeys": { - "name": "filter_fields", - "in": "query", - "description": "Filter options for data plane keys; used in conjunction with other filter parameters having the same array length.\n\nWhen filtering on `status`, only the following `filter_values` are supported:\n * revoked\n * expired\n * valid\n", - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/FilterNameDataPlaneKeys" + }, + "/app-protect/analytics/attacks": { + "post": { + "tags": [ + "NGINX One App Protect" + ], + "summary": "Query attack analytics", + "operationId": "queryAttackAnalytics", + "description": "Returns attack analytics with optional dimensional breakdown.\n\n**Response behavior:**\n- Without `group_by`: Returns `total` count for the time range\n- With `group_by`: Returns breakdown for that dimension, `total` is omitted\n\n**Response structure by dimension type:**\n- **Fixed enum dimensions** (`request_status`, `request_method`): Returns object with known keys and counts\n- **Dynamic dimensions** (`ip`, `country`, `policy`, `url`, etc.): Returns array of items with cross-dimension context in `distinct` object\n\n**Filter behavior:**\n- All filters are combined with AND logic\n- Use the `in` operator to achieve OR within a single dimension\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AttacksQueryRequest" + }, + "examples": { + "total_only": { + "summary": "Get total attack count (no group_by)", + "value": { + "start_time": "now-24h" + } + }, + "by_request_status": { + "summary": "Get breakdown by request status", + "value": { + "start_time": "now-24h", + "group_by": "request_status" + } + }, + "by_request_outcome_reason": { + "summary": "Get breakdown by request outcome reason", + "value": { + "start_time": "now-24h", + "group_by": "request_outcome_reason" + } + }, + "top_ips": { + "summary": "Top 10 attacking IPs", + "value": { + "start_time": "now-24h", + "group_by": "ip", + "limit": 10 + } + }, + "filtered_top_ips": { + "summary": "Top 10 attacking IPs for blocked requests", + "value": { + "start_time": "now-24h", + "group_by": "ip", + "filter": [ + { + "field": "request_status", + "operator": "=", + "values": [ + "blocked" + ] + } + ], + "order_by": { + "field": "count", + "direction": "desc" + }, + "limit": 10 + } + } + } + } } - } - }, - "FilterOperands": { - "name": "filter_ops", - "in": "query", - "description": "An array of strings defining the operands for filtering, to be used in conjunction with `filter_fields` and `filter_values`. \nAll filter parameters must have matching array lengths. Currently, the only supported operand is `\"IN\"`.\n", - "schema": { - "$ref": "#/components/schemas/FilterOperands" - } - }, - "FilterValues": { - "name": "filter_values", - "in": "query", - "description": "An array of strings containing the keywords for filtering. \nMultiple keywords can be chained using the `|` character. \nEnsure this parameter's array length matches those of `filter_fields` and `filter_ops` for effective filtering.\nThe total length of the filter string should not exceed 1024 characters.\n", - "schema": { - "type": "array", - "items": { - "type": "string", - "example": "value1|value2|value3", - "minLength": 1, - "maxLength": 1024 + }, + "responses": { + "200": { + "description": "Successfully returned attack analytics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AttacksQueryResponse" + }, + "examples": { + "without_group_by": { + "summary": "Without group_by - returns total and threat_campaigns", + "value": { + "query_metadata": { + "start_time": "2024-01-15T00:00:00Z", + "end_time": "2024-01-15T23:59:59Z" + }, + "total": 1500, + "threat_campaigns": 3 + } + }, + "by_request_status": { + "summary": "With group_by=request_status (fixed enum)", + "value": { + "query_metadata": { + "start_time": "2024-01-15T00:00:00Z", + "end_time": "2024-01-15T23:59:59Z" + }, + "request_status": { + "blocked": 1200, + "alerted": 200, + "passed": 100 + } + } + }, + "by_request_outcome_reason": { + "summary": "With group_by=request_outcome_reason (fixed enum)", + "value": { + "query_metadata": { + "start_time": "2024-01-15T00:00:00Z", + "end_time": "2024-01-15T23:59:59Z" + }, + "request_outcome_reason": { + "SECURITY_NGINX_VIOLATION": 121, + "SECURITY_WAF_BYPASS": 100, + "SECURITY_WAF_FLAGGED": 200, + "SECURITY_WAF_OK": 0, + "SECURITY_WAF_VIOLATION": 88, + "SECURITY_WAF_VIOLATION_TRANSPARENT": 0 + } + } + }, + "by_ip": { + "summary": "With group_by=ip (dynamic dimension with distinct counts)", + "value": { + "query_metadata": { + "start_time": "2024-01-15T00:00:00Z", + "end_time": "2024-01-15T23:59:59Z" + }, + "ip": [ + { + "value": "203.0.113.42", + "count": 450, + "distinct": { + "ips": 1, + "urls": 3, + "violations": 5, + "policies": 1 + }, + "country": "CN" + }, + { + "value": "198.51.100.7", + "count": 320, + "distinct": { + "ips": 1, + "urls": 2, + "violations": 3, + "policies": 1 + }, + "country": "RU" + } + ] + } + }, + "by_country": { + "summary": "With group_by=country (dynamic dimension)", + "value": { + "query_metadata": { + "start_time": "2024-01-15T00:00:00Z", + "end_time": "2024-01-15T23:59:59Z" + }, + "country": [ + { + "value": "CN", + "count": 500, + "distinct": { + "ips": 15, + "urls": 8, + "violations": 12, + "policies": 3 + } + }, + { + "value": "RU", + "count": 300, + "distinct": { + "ips": 8, + "urls": 5, + "violations": 7, + "policies": 2 + } + } + ] + } + }, + "by_policy": { + "summary": "With group_by=policy (Top WAF Policies)", + "value": { + "query_metadata": { + "start_time": "2024-01-15T00:00:00Z", + "end_time": "2024-01-15T23:59:59Z" + }, + "policy": [ + { + "value": "strict-policy", + "count": 850, + "distinct": { + "ips": 42, + "urls": 15, + "violations": 18, + "policies": 1 + } + }, + { + "value": "default-policy", + "count": 450, + "distinct": { + "ips": 28, + "urls": 10, + "violations": 12, + "policies": 1 + } + } + ] + } + }, + "by_request_method": { + "summary": "With group_by=request_method (Request Methods)", + "value": { + "query_metadata": { + "start_time": "2024-01-15T00:00:00Z", + "end_time": "2024-01-15T23:59:59Z" + }, + "request_method": { + "get": 800, + "post": 500, + "put": 50, + "delete": 20 + } + } + }, + "by_response_code": { + "summary": "With group_by=response_code (simple array)", + "value": { + "query_metadata": { + "start_time": "2024-01-15T00:00:00Z", + "end_time": "2024-01-15T23:59:59Z" + }, + "response_code": [ + { + "code": "403", + "count": 450 + }, + { + "code": "200", + "count": 320 + }, + { + "code": "500", + "count": 80 + } + ] + } + }, + "by_url": { + "summary": "With group_by=url (Top Attack URIs)", + "value": { + "query_metadata": { + "start_time": "2024-01-15T00:00:00Z", + "end_time": "2024-01-15T23:59:59Z" + }, + "url": [ + { + "value": "/api/login", + "count": 320, + "distinct": { + "ips": 15, + "urls": 1, + "violations": 8, + "policies": 2 + } + }, + { + "value": "/admin", + "count": 180, + "distinct": { + "ips": 8, + "urls": 1, + "violations": 5, + "policies": 1 + } + } + ] + } + }, + "by_hostname": { + "summary": "With group_by=hostname", + "value": { + "query_metadata": { + "start_time": "2024-01-15T00:00:00Z", + "end_time": "2024-01-15T23:59:59Z" + }, + "hostname": [ + { + "value": "nginx-host-01.example.com", + "count": 854, + "distinct": { + "ips": 543, + "urls": 768, + "violations": 312, + "policies": 816 + } + }, + { + "value": "nginx-host-02.example.com", + "count": 96, + "distinct": { + "ips": 753, + "urls": 351, + "violations": 232, + "policies": 96 + } + } + ] + } + }, + "by_threat_campaign": { + "summary": "With group_by=threat_campaign", + "value": { + "query_metadata": { + "start_time": "2024-01-15T00:00:00Z", + "end_time": "2024-01-15T23:59:59Z" + }, + "threat_campaign": [ + { + "value": "CVE-2021-44228", + "count": 1240, + "distinct": { + "ips": 34, + "urls": 12, + "violations": 8, + "policies": 3 + } + }, + { + "value": "Log4Shell", + "count": 870, + "distinct": { + "ips": 21, + "urls": 7, + "violations": 5, + "policies": 2 + } + } + ] + } + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/InvalidRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "500": { + "$ref": "#/components/responses/InternalServerErr" } } - }, - "DataPlaneKeyParamObjectID": { - "name": "data_plane_key_id", - "in": "path", - "schema": { - "$ref": "#/components/schemas/DataPlaneKeyObjectID" - }, - "description": "A globally unique identifier for the data plane key.\n", - "required": true - }, - "FilterFieldCertificates": { - "name": "filter_fields", - "in": "query", - "description": "Filter options for certificates; used in conjunction with other filter parameters having the same array length.\n", - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/FilterNameCertificates" + } + }, + "/app-protect/analytics/attacks/time-series": { + "post": { + "tags": [ + "NGINX One App Protect" + ], + "summary": "Query attack analytics time series", + "operationId": "queryAttackAnalyticsTimeSeries", + "description": "Returns attack analytics as time-series data for charting.\n\n**Response behavior:**\n- Without `group_by`: Returns `total` series (aggregate counts over time)\n- With `group_by`: Returns dimensional breakdown series, `total` is omitted\n\nData is returned with each dimension value as a separate series array,\nmaking it easy to plot directly. The bucket size is determined by the\n`resolution` field or auto-selected based on the time range.\n\n**Supported dimensions for time-series:**\n- `request_status` - Returns `blocked`, `alerted`, `passed` series\n\n**Time alignment:** All series arrays contain the same timestamps, aligned to the\nresolution boundary. Buckets with no events are zero-filled.\n\n**Filter behavior:**\n- All filters are combined with AND logic\n- Use the `in` operator to achieve OR within a single dimension\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AttacksTimeSeriesQueryRequest" + }, + "examples": { + "total_over_time": { + "summary": "Total attacks over time (no group_by)", + "value": { + "start_time": "now-6h", + "resolution": "15m" + } + }, + "by_request_status": { + "summary": "Breakdown by request status", + "value": { + "start_time": "now-6h", + "resolution": "15m", + "group_by": "request_status" + } + }, + "by_request_outcome_reason": { + "summary": "Breakdown by request outcome reason", + "value": { + "start_time": "now-6h", + "resolution": "15m", + "group_by": "request_outcome_reason" + } + }, + "filtered_blocked": { + "summary": "Blocked attacks only (filtered, no breakdown)", + "value": { + "start_time": "now-6h", + "resolution": "15m", + "filter": [ + { + "field": "request_status", + "operator": "=", + "values": [ + "blocked" + ] + } + ] + } + }, + "filtered_reason_transparent": { + "summary": "Attacks with transparent reason only", + "value": { + "start_time": "now-6h", + "resolution": "15m", + "filter": [ + { + "field": "request_outcome_reason", + "operator": "=", + "values": [ + "SECURITY_WAF_VIOLATION_TRANSPARENT" + ] + } + ] + } + } + } + } } - } - }, - "SortDirection": { - "name": "sort_dir", - "in": "query", - "description": "Sorting direction for the criteria and the resulting collection returned. Defaults to descending if not specified.\n", - "schema": { - "type": "string", - "enum": [ - "Ascending", - "Descending" - ], - "x-enum-varnames": [ - "ascending", - "descending" - ] - } - }, - "SortNameCertificatesDep": { - "name": "sort_certificates", - "in": "query", - "deprecated": true, - "description": "Sort certificates by enumerate value(s). Ordinal position determines primary, secondary, etc.\n", - "schema": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "name", - "subject_name", - "not_before", - "not_after" - ], - "x-enum-varnames": [ - "sort_name_certificates_name", - "sort_name_certificates_subject_name", - "sort_name_certificates_not_before", - "sort_name_certificates_not_after" - ] + }, + "responses": { + "200": { + "description": "Successfully returned attack analytics time series.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AttacksTimeSeriesQueryResponse" + }, + "examples": { + "without_group_by": { + "summary": "Without group_by - returns total series only", + "value": { + "query_metadata": { + "start_time": "2024-01-15T00:00:00Z", + "end_time": "2024-01-15T06:00:00Z", + "resolution": "1h" + }, + "total": [ + { + "timestamp": "2024-01-15T00:00:00Z", + "count": 150 + }, + { + "timestamp": "2024-01-15T01:00:00Z", + "count": 180 + }, + { + "timestamp": "2024-01-15T02:00:00Z", + "count": 95 + }, + { + "timestamp": "2024-01-15T03:00:00Z", + "count": 210 + }, + { + "timestamp": "2024-01-15T04:00:00Z", + "count": 175 + }, + { + "timestamp": "2024-01-15T05:00:00Z", + "count": 130 + } + ] + } + }, + "with_group_by": { + "summary": "With group_by=request_status - returns dimensional breakdown", + "description": "All series have aligned timestamps. Note the zero-filled bucket at 02:00\nfor `passed` where no events occurred.\n", + "value": { + "query_metadata": { + "start_time": "2024-01-15T00:00:00Z", + "end_time": "2024-01-15T03:00:00Z", + "resolution": "1h" + }, + "request_status": { + "blocked": [ + { + "timestamp": "2024-01-15T00:00:00Z", + "count": 120 + }, + { + "timestamp": "2024-01-15T01:00:00Z", + "count": 150 + }, + { + "timestamp": "2024-01-15T02:00:00Z", + "count": 80 + } + ], + "passed": [ + { + "timestamp": "2024-01-15T00:00:00Z", + "count": 10 + }, + { + "timestamp": "2024-01-15T01:00:00Z", + "count": 15 + }, + { + "timestamp": "2024-01-15T02:00:00Z", + "count": 0 + } + ], + "alerted": [ + { + "timestamp": "2024-01-15T00:00:00Z", + "count": 20 + }, + { + "timestamp": "2024-01-15T01:00:00Z", + "count": 15 + }, + { + "timestamp": "2024-01-15T02:00:00Z", + "count": 10 + } + ] + } + } + }, + "no_data": { + "summary": "No data in time range - returns zero-filled buckets", + "description": "When no attacks occurred in the queried time range, time buckets are still\ngenerated based on the resolution with count as 0.\n", + "value": { + "query_metadata": { + "start_time": "2024-01-15T00:00:00Z", + "end_time": "2024-01-15T03:00:00Z", + "resolution": "1h" + }, + "total": [ + { + "timestamp": "2024-01-15T00:00:00Z", + "count": 0 + }, + { + "timestamp": "2024-01-15T01:00:00Z", + "count": 0 + }, + { + "timestamp": "2024-01-15T02:00:00Z", + "count": 0 + } + ] + } + }, + "no_data_with_group_by": { + "summary": "No data with group_by - returns zero-filled series for each dimension", + "description": "All dimension values have aligned timestamps with count: 0.\nThis ensures charts can render empty series correctly.\n", + "value": { + "query_metadata": { + "start_time": "2024-01-15T00:00:00Z", + "end_time": "2024-01-15T03:00:00Z", + "resolution": "1h" + }, + "request_status": { + "blocked": [ + { + "timestamp": "2024-01-15T00:00:00Z", + "count": 0 + }, + { + "timestamp": "2024-01-15T01:00:00Z", + "count": 0 + }, + { + "timestamp": "2024-01-15T02:00:00Z", + "count": 0 + } + ], + "alerted": [ + { + "timestamp": "2024-01-15T00:00:00Z", + "count": 0 + }, + { + "timestamp": "2024-01-15T01:00:00Z", + "count": 0 + }, + { + "timestamp": "2024-01-15T02:00:00Z", + "count": 0 + } + ], + "passed": [ + { + "timestamp": "2024-01-15T00:00:00Z", + "count": 0 + }, + { + "timestamp": "2024-01-15T01:00:00Z", + "count": 0 + }, + { + "timestamp": "2024-01-15T02:00:00Z", + "count": 0 + } + ] + } + } + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/InvalidRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "500": { + "$ref": "#/components/responses/InternalServerErr" } } - }, - "SortNameCertificates": { - "name": "sort_fields", - "in": "query", - "description": "Sort certificates by enumerate value(s). Ordinal position determines primary, secondary, etc.\n", - "schema": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "name", - "subject_name", - "not_before", - "not_after" - ], - "x-enum-varnames": [ - "sort_name_certificates_name", - "sort_name_certificates_subject_name", - "sort_name_certificates_not_before", - "sort_name_certificates_not_after" - ] + } + }, + "/app-protect/analytics/signatures": { + "post": { + "tags": [ + "NGINX One App Protect" + ], + "summary": "Query signature analytics", + "operationId": "querySignatureAnalytics", + "description": "Returns signature analytics with optional dimensional breakdown.\n\n**Response behavior:**\n- Without `group_by`: Returns `total` (signature hits) and `unique` (distinct signatures) for the time range\n- With `group_by`: Returns breakdown for that dimension, `total` and `unique` are omitted\n\n**Response structure by dimension type:**\n- **Fixed enum dimensions** (`request_status`, `accuracy`, `risk`): Returns object with known keys and counts\n- **Dynamic dimensions** (`signature`, `cve`): Returns array of items sorted by count descending\n\n**Filter behavior:**\n- All filters are combined with AND logic\n- Use the `in` operator to achieve OR within a single dimension\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SignaturesQueryRequest" + }, + "examples": { + "total_only": { + "summary": "Get total signature hits and unique count (no group_by)", + "value": { + "start_time": "now-24h" + } + }, + "by_request_status": { + "summary": "Signature hits by request status", + "value": { + "start_time": "now-24h", + "group_by": "request_status" + } + }, + "by_accuracy": { + "summary": "Signature hits by accuracy level", + "value": { + "start_time": "now-24h", + "group_by": "accuracy" + } + }, + "by_risk": { + "summary": "Signature hits by risk level", + "value": { + "start_time": "now-24h", + "group_by": "risk" + } + }, + "top_signatures": { + "summary": "Top 5 signatures by hit count", + "value": { + "start_time": "now-24h", + "group_by": "signature", + "limit": 5 + } + }, + "top_cves": { + "summary": "Top 5 CVEs by hit count", + "value": { + "start_time": "now-24h", + "group_by": "cve", + "limit": 5 + } + }, + "filtered_blocked_signatures": { + "summary": "Top signatures for blocked requests only", + "value": { + "start_time": "now-24h", + "group_by": "signature", + "filter": [ + { + "field": "request_status", + "operator": "=", + "values": [ + "blocked" + ] + } + ], + "limit": 10 + } + } + } + } } - } - }, - "CertificateParamObjectID": { - "name": "certificateObjectID", - "in": "path", - "schema": { - "$ref": "#/components/schemas/CertificateObjectID" - }, - "description": "A globally unique identifier for the certificate.\n", - "required": true - }, - "DeleteFromDataPlanesParamFlag": { - "name": "deleteFromDataPlanes", - "in": "query", - "schema": { - "type": "boolean" }, - "description": "Flag indicating whether the certificate should be deleted from its associated data planes.\n" - }, - "FilterFieldCertificateDeployments": { - "name": "filter_fields", - "in": "query", - "description": "Filter options for certificate deployments; used in conjunction with other filter parameters having the same array length.\n", - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/FilterNameCertificateDeployments" - } - } - }, - "SortNameCertificateDeploymentsDep": { - "name": "sort_certificate_deployments", - "in": "query", - "deprecated": true, - "description": "Sort certificate deployments by enumerate value(s). Ordinal position determines primary, secondary, etc.\n", - "schema": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "name" - ], - "x-enum-varnames": [ - "sort_name_certificate_deployments_name" - ] + "responses": { + "200": { + "description": "Successfully returned signature analytics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SignaturesQueryResponse" + }, + "examples": { + "without_group_by": { + "summary": "Without group_by - returns total and unique only", + "value": { + "query_metadata": { + "start_time": "2024-01-15T00:00:00Z", + "end_time": "2024-01-15T06:00:00Z" + }, + "total": 1270, + "unique": 19 + } + }, + "by_request_status": { + "summary": "With group_by=request_status", + "value": { + "query_metadata": { + "start_time": "2024-01-15T00:00:00Z", + "end_time": "2024-01-15T06:00:00Z" + }, + "request_status": { + "blocked": 1080, + "alerted": 122, + "passed": 68 + } + } + }, + "by_accuracy": { + "summary": "With group_by=accuracy", + "value": { + "query_metadata": { + "start_time": "2024-01-15T00:00:00Z", + "end_time": "2024-01-15T06:00:00Z" + }, + "accuracy": { + "low": 150, + "medium": 420, + "high": 700 + } + } + }, + "by_risk": { + "summary": "With group_by=risk", + "value": { + "query_metadata": { + "start_time": "2024-01-15T00:00:00Z", + "end_time": "2024-01-15T06:00:00Z" + }, + "risk": { + "low": 200, + "medium": 350, + "high": 520, + "critical": 200 + } + } + }, + "by_signature": { + "summary": "With group_by=signature", + "value": { + "query_metadata": { + "start_time": "2024-01-15T00:00:00Z", + "end_time": "2024-01-15T06:00:00Z" + }, + "signature": [ + { + "signature_id": "200001834", + "name": "Unix hidden (dot-file)", + "count": 141, + "accuracy": "high", + "risk": "medium" + }, + { + "signature_id": "200001475", + "name": "PHP injection attempt", + "count": 99, + "accuracy": "high", + "risk": "high" + }, + { + "signature_id": "200000098", + "name": "XSS script tag end (Parameter)", + "count": 85, + "accuracy": "medium", + "risk": "high" + }, + { + "signature_id": "200001088", + "name": "Directory Traversal attempt", + "count": 72, + "accuracy": "high", + "risk": "critical" + }, + { + "signature_id": "200002550", + "name": "SQL injection attempt", + "count": 65, + "accuracy": "high", + "risk": "critical" + } + ] + } + }, + "by_cve": { + "summary": "With group_by=cve (Top Signature CVEs table)", + "value": { + "query_metadata": { + "start_time": "2024-01-15T00:00:00Z", + "end_time": "2024-01-15T06:00:00Z" + }, + "cve": [ + { + "value": "CVE-2021-44228", + "count": 450 + }, + { + "value": "CVE-2021-1234", + "count": 320 + }, + { + "value": "CVE-2021-5678", + "count": 180 + }, + { + "value": "CVE-2020-9484", + "count": 95 + }, + { + "value": "CVE-2019-11043", + "count": 72 + } + ] + } + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/InvalidRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "500": { + "$ref": "#/components/responses/InternalServerErr" } } - }, - "SortNameCertificateDeployments": { - "name": "sort_fields", - "in": "query", - "description": "Sort certificate deployments by enumerate value(s). Ordinal position determines primary, secondary, etc.\n", - "schema": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "name" - ], - "x-enum-varnames": [ - "sort_name_certificate_deployments_name" - ] + } + }, + "/app-protect/analytics/signatures/time-series": { + "post": { + "tags": [ + "NGINX One App Protect" + ], + "summary": "Query signature analytics time series", + "operationId": "querySignatureAnalyticsTimeSeries", + "description": "Returns signature analytics as time-series data for charting.\n\n**Response behavior:**\n- Without `group_by`: Returns `total` series (aggregate signature hits over time)\n- With `group_by`: Returns dimensional breakdown series, `total` is omitted\n\nData is returned with each dimension value as a separate series array,\nmaking it easy to plot directly. The bucket size is determined by the\n`resolution` field or auto-selected based on the time range.\n\n**Supported dimensions for time-series:**\n- `request_status` - Returns `blocked`, `alerted`, `passed` series\n- `accuracy` - Returns `low`, `medium`, `high` series\n- `risk` - Returns `low`, `medium`, `high`, `critical` series\n\n**Time alignment:** All series arrays contain the same timestamps, aligned to the\nresolution boundary. Buckets with no events are zero-filled.\n\n**Filter behavior:**\n- All filters are combined with AND logic\n- Use the `in` operator to achieve OR within a single dimension\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SignaturesTimeSeriesQueryRequest" + }, + "examples": { + "total_over_time": { + "summary": "Total signature hits over time (no group_by)", + "value": { + "start_time": "now-6h", + "resolution": "15m" + } + }, + "by_request_status": { + "summary": "Signature hits by request status over time", + "value": { + "start_time": "now-6h", + "resolution": "1h", + "group_by": "request_status" + } + }, + "by_accuracy": { + "summary": "Signature hits by accuracy over time", + "value": { + "start_time": "now-6h", + "resolution": "1h", + "group_by": "accuracy" + } + }, + "by_risk": { + "summary": "Signature hits by risk over time", + "value": { + "start_time": "now-6h", + "resolution": "1h", + "group_by": "risk" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Successfully returned signature analytics time series.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SignaturesTimeSeriesQueryResponse" + }, + "examples": { + "without_group_by": { + "summary": "Without group_by - returns total series only", + "value": { + "query_metadata": { + "start_time": "2024-01-15T00:00:00Z", + "end_time": "2024-01-15T06:00:00Z", + "resolution": "1h" + }, + "total": [ + { + "timestamp": "2024-01-15T00:00:00Z", + "count": 150 + }, + { + "timestamp": "2024-01-15T01:00:00Z", + "count": 180 + }, + { + "timestamp": "2024-01-15T02:00:00Z", + "count": 95 + }, + { + "timestamp": "2024-01-15T03:00:00Z", + "count": 210 + }, + { + "timestamp": "2024-01-15T04:00:00Z", + "count": 175 + }, + { + "timestamp": "2024-01-15T05:00:00Z", + "count": 130 + } + ] + } + }, + "by_request_status": { + "summary": "With group_by=request_status", + "description": "All series have aligned timestamps. Note the zero-filled bucket at 02:00\nfor `passed` where no events occurred.\n", + "value": { + "query_metadata": { + "start_time": "2024-01-15T00:00:00Z", + "end_time": "2024-01-15T03:00:00Z", + "resolution": "1h" + }, + "request_status": { + "blocked": [ + { + "timestamp": "2024-01-15T00:00:00Z", + "count": 120 + }, + { + "timestamp": "2024-01-15T01:00:00Z", + "count": 150 + }, + { + "timestamp": "2024-01-15T02:00:00Z", + "count": 80 + } + ], + "passed": [ + { + "timestamp": "2024-01-15T00:00:00Z", + "count": 10 + }, + { + "timestamp": "2024-01-15T01:00:00Z", + "count": 15 + }, + { + "timestamp": "2024-01-15T02:00:00Z", + "count": 0 + } + ], + "alerted": [ + { + "timestamp": "2024-01-15T00:00:00Z", + "count": 20 + }, + { + "timestamp": "2024-01-15T01:00:00Z", + "count": 15 + }, + { + "timestamp": "2024-01-15T02:00:00Z", + "count": 10 + } + ] + } + } + }, + "by_accuracy": { + "summary": "With group_by=accuracy", + "value": { + "query_metadata": { + "start_time": "2024-01-15T00:00:00Z", + "end_time": "2024-01-15T03:00:00Z", + "resolution": "1h" + }, + "accuracy": { + "low": [ + { + "timestamp": "2024-01-15T00:00:00Z", + "count": 15 + }, + { + "timestamp": "2024-01-15T01:00:00Z", + "count": 20 + }, + { + "timestamp": "2024-01-15T02:00:00Z", + "count": 12 + } + ], + "medium": [ + { + "timestamp": "2024-01-15T00:00:00Z", + "count": 45 + }, + { + "timestamp": "2024-01-15T01:00:00Z", + "count": 55 + }, + { + "timestamp": "2024-01-15T02:00:00Z", + "count": 38 + } + ], + "high": [ + { + "timestamp": "2024-01-15T00:00:00Z", + "count": 90 + }, + { + "timestamp": "2024-01-15T01:00:00Z", + "count": 105 + }, + { + "timestamp": "2024-01-15T02:00:00Z", + "count": 40 + } + ] + } + } + }, + "by_risk": { + "summary": "With group_by=risk", + "value": { + "query_metadata": { + "start_time": "2024-01-15T00:00:00Z", + "end_time": "2024-01-15T03:00:00Z", + "resolution": "1h" + }, + "risk": { + "low": [ + { + "timestamp": "2024-01-15T00:00:00Z", + "count": 20 + }, + { + "timestamp": "2024-01-15T01:00:00Z", + "count": 25 + }, + { + "timestamp": "2024-01-15T02:00:00Z", + "count": 15 + } + ], + "medium": [ + { + "timestamp": "2024-01-15T00:00:00Z", + "count": 40 + }, + { + "timestamp": "2024-01-15T01:00:00Z", + "count": 50 + }, + { + "timestamp": "2024-01-15T02:00:00Z", + "count": 30 + } + ], + "high": [ + { + "timestamp": "2024-01-15T00:00:00Z", + "count": 60 + }, + { + "timestamp": "2024-01-15T01:00:00Z", + "count": 75 + }, + { + "timestamp": "2024-01-15T02:00:00Z", + "count": 35 + } + ], + "critical": [ + { + "timestamp": "2024-01-15T00:00:00Z", + "count": 30 + }, + { + "timestamp": "2024-01-15T01:00:00Z", + "count": 30 + }, + { + "timestamp": "2024-01-15T02:00:00Z", + "count": 10 + } + ] + } + } + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/InvalidRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "500": { + "$ref": "#/components/responses/InternalServerErr" + } + } + } + }, + "/app-protect/analytics/violations": { + "post": { + "tags": [ + "NGINX One App Protect" + ], + "summary": "Query violation analytics", + "operationId": "queryViolationAnalytics", + "description": "Returns violation analytics with optional dimensional breakdown.\n\n**Response behavior:**\n- Without `group_by`: Returns `total` (violation occurrences) and `unique` (distinct violation types)\n- With `group_by`: Returns breakdown for that dimension, `total` and `unique` are omitted\n\n**Response structure by dimension type:**\n- **Fixed enum dimensions** (`context`): Returns object with known keys (header, cookie, parameter, uri, request, other)\n- **Dynamic dimensions** (`violation`, `sub_violation`): Returns array of items with cross-dimension context\n\n**Filter behavior:**\n- All filters are combined with AND logic\n- Use the `in` operator to achieve OR within a single dimension\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ViolationsQueryRequest" + }, + "examples": { + "total_only": { + "summary": "Get total violation occurrences and unique count (no group_by)", + "value": { + "start_time": "now-24h" + } + }, + "by_violation": { + "summary": "Top violations by occurrence count", + "value": { + "start_time": "now-24h", + "group_by": "violation", + "limit": 10 + } + }, + "by_sub_violation": { + "summary": "Top sub-violations by occurrence count", + "value": { + "start_time": "now-24h", + "group_by": "sub_violation", + "limit": 10 + } + }, + "by_context": { + "summary": "Violation context breakdown", + "value": { + "start_time": "now-24h", + "group_by": "context" + } + }, + "filtered_by_policy": { + "summary": "Top violations for a specific policy", + "value": { + "start_time": "now-24h", + "group_by": "violation", + "filter": [ + { + "field": "policy", + "operator": "=", + "values": [ + "app_protect_default_policy" + ] + } + ], + "limit": 10 + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Successfully returned violation analytics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ViolationsQueryResponse" + }, + "examples": { + "without_group_by": { + "summary": "Without group_by - returns total and unique only", + "value": { + "query_metadata": { + "start_time": "2024-01-15T00:00:00Z", + "end_time": "2024-01-15T23:59:59Z" + }, + "total": 4320, + "unique": 5 + } + }, + "by_violation": { + "summary": "With group_by=violation", + "value": { + "query_metadata": { + "start_time": "2024-01-15T00:00:00Z", + "end_time": "2024-01-15T23:59:59Z" + }, + "violation": [ + { + "value": "Bot Client Detected", + "count": 1080, + "distinct": { + "ips": 1, + "urls": 1, + "policies": 1 + } + }, + { + "value": "Violation Rating Threat detected", + "count": 960, + "distinct": { + "ips": 1, + "urls": 1, + "policies": 1 + } + }, + { + "value": "Attack signature detected", + "count": 840, + "distinct": { + "ips": 1, + "urls": 1, + "policies": 1 + } + }, + { + "value": "Illegal meta character in value", + "count": 480, + "distinct": { + "ips": 1, + "urls": 1, + "policies": 1 + } + }, + { + "value": "Illegal HTTP status in response", + "count": 120, + "distinct": { + "ips": 1, + "urls": 1, + "policies": 1 + } + } + ] + } + }, + "by_sub_violation": { + "summary": "With group_by=sub_violation", + "value": { + "query_metadata": { + "start_time": "2024-01-15T00:00:00Z", + "end_time": "2024-01-15T23:59:59Z" + }, + "sub_violation": [ + { + "value": "N/A", + "count": 1080, + "distinct": { + "ips": 1, + "urls": 1, + "policies": 1 + } + } + ] + } + }, + "by_context": { + "summary": "With group_by=context", + "value": { + "query_metadata": { + "start_time": "2024-01-15T00:00:00Z", + "end_time": "2024-01-15T23:59:59Z" + }, + "context": { + "cookie": 0, + "header": 130, + "parameter": 1426, + "request": 302, + "uri": 0, + "other": 2462 + } + } + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/InvalidRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "500": { + "$ref": "#/components/responses/InternalServerErr" + } + } + } + }, + "/app-protect/events": { + "get": { + "tags": [ + "NGINX One App Protect" + ], + "summary": "List security events", + "operationId": "listSecurityEvents", + "description": "Returns a paginated list of security events.\n\n**Filtering:**\n- Use the `filter_fields`, `filter_values`, and `filter_ops` parameters to filter events by various dimensions\n- All filter parameters must have matching array lengths\n- `support_id` is unique per event, so filtering by it returns a single-item list\n- Time range filtering via `start_time` and `end_time` is recommended to limit results\n- Multiple filter values can be chained using the `|` character (e.g., `blocked|alerted`)\n\n**Pagination:**\n- Results are paginated using standard Nginx One Console pagination\n- Results are sorted by timestamp descending (most recent first) by default\n\n**Response:**\n- Returns summary fields suitable for list display\n- Use `GET /app-protect/events/{id}` for full event details including raw request\n", + "parameters": [ + { + "name": "start_time", + "in": "query", + "description": "Beginning of the time range (inclusive).\nAccepts ISO 8601 format or relative offset (e.g., `now-24h`).\n", + "schema": { + "type": "string" + }, + "example": "now-24h" + }, + { + "name": "end_time", + "in": "query", + "description": "End of the time range (exclusive).\nDefaults to current time if not specified.\n", + "schema": { + "type": "string" + }, + "example": "now" + }, + { + "$ref": "#/components/parameters/FilterFieldSecurityEvents" + }, + { + "$ref": "#/components/parameters/FilterValues" + }, + { + "$ref": "#/components/parameters/FilterOperands" + }, + { + "$ref": "#/components/parameters/Paginated" + }, + { + "$ref": "#/components/parameters/Offset" + }, + { + "$ref": "#/components/parameters/Limit" + } + ], + "responses": { + "200": { + "description": "Successfully returned list of security events.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SecurityEventListResponse" + }, + "example": { + "total": 1080, + "count": 1, + "start_index": 1, + "items_per_page": 100, + "items": [ + { + "timestamp": "2024-01-22T12:13:25Z", + "support_id": "1844305495056427365", + "request_status": "blocked", + "policy_name": "app_protect_default_policy", + "client_ip": "192.168.1.100", + "url": "/api/users", + "method": "POST", + "response_code": 403, + "country_code": "US", + "violation_rating": 5, + "instance_object_id": "inst_8Iwn7dT7RF-PRLxkSt5EYQ", + "csg_object_id": "csg_-uvR3F2TQGm18jnl7bpaGw" + } + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/InvalidRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "500": { + "$ref": "#/components/responses/InternalServerErr" + } + } + } + }, + "/app-protect/events/{id}": { + "get": { + "tags": [ + "NGINX One App Protect" + ], + "summary": "Get security event by supportID", + "operationId": "getSecurityEvent", + "description": "Returns a specific security event by its support ID.\n\n**Response:**\n- Returns full event details including:\n - Request metadata (headers, method, URL, response code)\n - WAF enforcement details (policy, outcome, violation_rating)\n - All triggered violations with context\n - All matched signatures with details\n - Raw HTTP request (if available and not truncated)\n - Threat campaign associations\n", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "The support ID of the security event.", + "schema": { + "type": "string", + "minLength": 1 + }, + "example": "1844305495056427365" + } + ], + "responses": { + "200": { + "description": "Successfully returned the security event.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SecurityEvent" + }, + "example": { + "id": "d1cd4806-3519-4c72-a0e4-63fd611ee6fb", + "timestamp": "2024-01-22T12:13:25Z", + "support_id": "1844305495056427365", + "version": "v1.0", + "system_id": "31ed9d05-9cb0-48c3-9f97-d63b1b6dd342", + "parent_hostname": "nginx-host-01", + "instance_object_id": "inst_8Iwn7dT7RF-PRLxkSt5EYQ", + "csg_object_id": "csg_-uvR3F2TQGm18jnl7bpaGw", + "http": { + "hostname": "example.com", + "remote_addr": "192.168.1.100", + "remote_port": 54321, + "server_addr": "10.0.0.1", + "server_port": 443, + "uri": "/", + "request_method": "GET", + "response_code": 403 + }, + "x_forwarded_for_header_value": "203.0.113.42", + "country_code": "US", + "policy_name": "app_protect_default_policy", + "request_status": "blocked", + "request_outcome": "rejected", + "request_outcome_reason": "SECURITY_WAF_VIOLATION", + "violation_rating": 5, + "blocking_exception_reason": "", + "is_truncated": false, + "signatures": [ + { + "id": 200001834, + "name": "XSS script tag end (Parameter)", + "accuracy": "high", + "risk": "high", + "cve": "", + "blocking_mask": "0x0", + "buffer": "param", + "offset": 0, + "length": 42 + } + ], + "violations": [ + { + "name": "Illegal meta character in value", + "sub_name": "", + "context": "parameter", + "detail_name": "VIOL_PARAMETER_VALUE_METACHAR", + "detail_context": "parameter", + "field_name": "param", + "field_value": "" + }, + { + "name": "Attack signature detected", + "sub_name": "", + "context": "parameter", + "detail_name": "VIOL_ATTACK_SIGNATURE", + "detail_context": "parameter", + "field_name": "param", + "field_value": "" + }, + { + "name": "Violation Rating Threat detected", + "sub_name": "", + "context": "other", + "detail_name": "", + "detail_context": "", + "field_name": "", + "field_value": "" + }, + { + "name": "Bot Client Detected", + "sub_name": "", + "context": "other", + "detail_name": "", + "detail_context": "", + "field_name": "", + "field_value": "" + } + ], + "threat_campaign_names": [], + "request": "GET /?param=%3Cscript%3Ealert%27xss%27%3C%2Fscript%3E HTTP/1.1\r\nHost: example.com\r\nUser-Agent: curl/7.68.0\r\nAccept: */*\r\n\r\n" + } + } + } + }, + "404": { + "$ref": "#/components/responses/NotFound" } } + } + }, + "/billing-usage/events": {} + }, + "components": { + "parameters": { + "Paginated": { + "name": "paginated", + "in": "query", + "schema": { + "type": "boolean", + "default": true + }, + "description": "A boolean indicating if the results should be presented as a paginated list. Defaults to `true`. \nWhen set to `false` a maximum of 3000 results are returned.\n", + "required": false }, - "FilterFieldConfigSyncGroups": { + "Limit": { + "name": "limit", + "in": "query", + "schema": { + "type": "integer", + "minimum": 0 + }, + "description": "An integer that specifies the maximum number of items to be returned. \nSetting this to `0` will result in no items being returned, but a total count will still be provided. \nThis parameter is not applicable if `paginated` is `false`.\n", + "required": false + }, + "Offset": { + "name": "offset", + "in": "query", + "schema": { + "type": "integer", + "minimum": 1 + }, + "description": "An integer that specifies the starting position of the results, starting at `1`.\nThis parameter is not applicable if `paginated` is `false`.\n" + }, + "FilterFieldDataPlaneKeys": { "name": "filter_fields", "in": "query", - "description": "An array of strings indicating which fields to filter by (for example, `name`, `config_status`). This parameter works in conjunction with `filter_values` and `filter_ops`.\n", + "description": "Filter options for data plane keys; used in conjunction with other filter parameters having the same array length.\n\nWhen filtering on `status`, only the following `filter_values` are supported:\n * revoked\n * expired\n * valid\n", "schema": { "type": "array", "items": { - "$ref": "#/components/schemas/FilterNameConfigSyncGroups" + "$ref": "#/components/schemas/FilterNameDataPlaneKeys" + } + } + }, + "FilterOperands": { + "name": "filter_ops", + "in": "query", + "description": "An array of strings defining the operands for filtering, to be used in conjunction with `filter_fields` and `filter_values`. \nAll filter parameters must have matching array lengths. Currently, the only supported operand is `\"IN\"`.\n", + "schema": { + "$ref": "#/components/schemas/FilterOperands" + } + }, + "FilterValues": { + "name": "filter_values", + "in": "query", + "description": "An array of strings containing the keywords for filtering. \nMultiple keywords can be chained using the `|` character. \nEnsure this parameter's array length matches those of `filter_fields` and `filter_ops` for effective filtering.\nThe total length of the filter string should not exceed 1024 characters.\n", + "schema": { + "type": "array", + "items": { + "type": "string", + "example": "value1|value2|value3", + "minLength": 1, + "maxLength": 1024 + } + } + }, + "DataPlaneKeyParamObjectID": { + "name": "data_plane_key_id", + "in": "path", + "schema": { + "$ref": "#/components/schemas/DataPlaneKeyObjectID" + }, + "description": "A globally unique identifier for the data plane key.\n", + "required": true + }, + "FilterFieldCertificates": { + "name": "filter_fields", + "in": "query", + "description": "Filter options for certificates; used in conjunction with other filter parameters having the same array length.\n", + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/FilterNameCertificates" + } + } + }, + "SortDirection": { + "name": "sort_dir", + "in": "query", + "description": "Sorting direction for the criteria and the resulting collection returned. Defaults to descending if not specified.\n", + "schema": { + "type": "string", + "enum": [ + "Ascending", + "Descending" + ], + "x-enum-varnames": [ + "ascending", + "descending" + ] + } + }, + "SortNameCertificatesDep": { + "name": "sort_certificates", + "in": "query", + "deprecated": true, + "description": "Sort certificates by enumerate value(s). Ordinal position determines primary, secondary, etc.\n", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "name", + "subject_name", + "not_before", + "not_after" + ], + "x-enum-varnames": [ + "sort_name_certificates_name", + "sort_name_certificates_subject_name", + "sort_name_certificates_not_before", + "sort_name_certificates_not_after" + ] + } + } + }, + "SortNameCertificates": { + "name": "sort_fields", + "in": "query", + "description": "Sort certificates by enumerate value(s). Ordinal position determines primary, secondary, etc.\n", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "name", + "subject_name", + "not_before", + "not_after" + ], + "x-enum-varnames": [ + "sort_name_certificates_name", + "sort_name_certificates_subject_name", + "sort_name_certificates_not_before", + "sort_name_certificates_not_after" + ] + } + } + }, + "CertificateParamObjectID": { + "name": "certificateObjectID", + "in": "path", + "schema": { + "$ref": "#/components/schemas/CertificateObjectID" + }, + "description": "A globally unique identifier for the certificate.\n", + "required": true + }, + "DeleteFromDataPlanesParamFlag": { + "name": "deleteFromDataPlanes", + "in": "query", + "schema": { + "type": "boolean" + }, + "description": "Flag indicating whether the certificate should be deleted from its associated data planes.\n" + }, + "FilterFieldCertificateDeployments": { + "name": "filter_fields", + "in": "query", + "description": "Filter options for certificate deployments; used in conjunction with other filter parameters having the same array length.\n", + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/FilterNameCertificateDeployments" + } + } + }, + "SortNameCertificateDeploymentsDep": { + "name": "sort_certificate_deployments", + "in": "query", + "deprecated": true, + "description": "Sort certificate deployments by enumerate value(s). Ordinal position determines primary, secondary, etc.\n", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "name" + ], + "x-enum-varnames": [ + "sort_name_certificate_deployments_name" + ] + } + } + }, + "SortNameCertificateDeployments": { + "name": "sort_fields", + "in": "query", + "description": "Sort certificate deployments by enumerate value(s). Ordinal position determines primary, secondary, etc.\n", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "name" + ], + "x-enum-varnames": [ + "sort_name_certificate_deployments_name" + ] + } + } + }, + "FilterFieldConfigSyncGroups": { + "name": "filter_fields", + "in": "query", + "description": "An array of strings indicating which fields to filter by (for example, `name`, `config_status`). This parameter works in conjunction with `filter_values` and `filter_ops`.\n", + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/FilterNameConfigSyncGroups" } } }, @@ -6702,7 +8303,7 @@ "description": "Optional flag to control how the request is processed.\n - When `false` or omitted (by default), the request creates a Staged Config directly. (`StagedConfigCreateResponse`)\n - When `true`, the request parses the import and returns metadata you can use to create a Staged Config through a POST. ( `StagedConfigCreateRequest`)\n", "required": false }, - "NapLogProfileCompileNapRelease": { + "NapCompileNapRelease": { "name": "nap_release", "in": "query", "schema": { @@ -6712,14 +8313,14 @@ "required": true, "example": "5.10.0" }, - "NapLogProfileCompileDownload": { + "NapCompileDownload": { "name": "download", "in": "query", "schema": { "type": "boolean", "default": false }, - "description": "Whether to download the NGINX App Protect log profile bundle. When `true`, the request blocks until the bundle is ready and returns the bundle content. The request may take longer depending on the bundle's compilation status.\n", + "description": "Whether to download the compiled bundle. When `true`, the request blocks until the bundle is ready and returns the bundle content. The request may take longer depending on the bundle's compilation status.\n", "required": false, "example": true }, @@ -7146,6 +8747,17 @@ "$ref": "#/components/schemas/FilterNameTemplates" } } + }, + "FilterFieldSecurityEvents": { + "name": "filter_fields", + "in": "query", + "description": "An array of field names to filter by. Works in conjunction with `filter_values` and `filter_ops`.\n", + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AnalyticsFilterField" + } + } } }, "schemas": { @@ -12087,664 +13699,2137 @@ { "$ref": "#/components/schemas/UsageMetrics" }, - { - "type": "object", - "properties": { - "requests": { - "type": "integer", - "description": "Total requests handled by an NGINX Instance", - "minimum": 0 - } - } + { + "type": "object", + "properties": { + "requests": { + "type": "integer", + "description": "Total requests handled by an NGINX Instance", + "minimum": 0 + } + } + } + ] + }, + "upstream": { + "$ref": "#/components/schemas/UsageMetrics" + } + } + }, + "StreamUsage": { + "type": "object", + "properties": { + "client": { + "$ref": "#/components/schemas/UsageMetrics" + }, + "upstream": { + "$ref": "#/components/schemas/UsageMetrics" + } + } + }, + "UsageMetrics": { + "type": "object", + "properties": { + "received": { + "type": "integer", + "description": "Total bytes received by an NGINX Instance from clients/upstreams", + "minimum": 0 + }, + "sent": { + "type": "integer", + "description": "Total bytes sent by the NGINX Instance to clients/upstreams", + "minimum": 0 + }, + "connections": { + "type": "integer", + "description": "Total connections of the NGINX Instance with clients/upstreams", + "minimum": 0 + } + } + }, + "NginxUsageHttp": { + "$ref": "#/components/schemas/HttpUsage" + }, + "NginxUsageStream": { + "$ref": "#/components/schemas/StreamUsage" + }, + "MetricStartTime": { + "description": "The start time of your metrics query.\n\nUsage:\n* `start_time` is required if `end_time` is specified.\n* If `start_time` and `end_time` isn't provided, the API returns metrics from the current time to the month before the current time.\n* The `start_time` cannot be older than 120 days before the current time.\n\nYou can set the `start_time` in these ways:\n* In ISO 8601 format. For example, \"2019-08-07T09:57:36.088757764Z\".\n* As an offset from the current time. For the offset, use `+` or `-`, followed by a number and unit [`y` (years), `M` (months), `w` (weeks), `d` (days), `h` (hours), `m` (minutes), or `s` (seconds)]. \n* Example of an offset: \"now-3h\" (3 hours before now).\n", + "type": "string", + "example": "2019-08-07T09:57:36.088757764Z" + }, + "MetricEndTime": { + "description": "The end time of your metrics query.\n\nUsage:\n* Must be greater than `start_time`.\n* The time difference between `start_time` and `end_time` should be greater than an hour.\n* The default `end_time` is the current time.\n* The `end_time` cannot be older than 120 days before the current time.\n\nYou can set the `end_time` in these ways:\n* In ISO 8601 format. For example, \"2019-08-07T09:57:36.088757764Z\".\n* As an offset from the current time. For the offset, use `+` or `-`, followed by a number and unit [`y` (years), `M` (months), `w` (weeks), `d` (days), `h` (hours), `m` (minutes), or `s` (seconds)]. \n* Example of an offset: \"now-3h\" (3 hours before now).\n", + "type": "string", + "example": "2019-08-07T09:57:36.088757764Z" + }, + "InventoryMetricAggregation": { + "type": "string", + "description": "Static list of aggregation functions that can be applied to a compatible metric.\n * count\n * sum\n * avg\n * min\n * max\n", + "enum": [ + "count", + "sum", + "avg", + "min", + "max" + ], + "x-enum-varnames": [ + "metric_aggregation_count", + "metric_aggregation_sum", + "metric_aggregation_avg", + "metric_aggregation_min", + "metric_aggregation_max" + ] + }, + "BaseInventoryQueryRequest": { + "type": "object", + "required": [ + "metrics" + ], + "properties": { + "metrics": { + "$ref": "#/components/schemas/InventoryMetricNames" + }, + "start_time": { + "$ref": "#/components/schemas/MetricStartTime" + }, + "end_time": { + "$ref": "#/components/schemas/MetricEndTime" + } + } + }, + "InventoryMetricQueryRequest": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/BaseInventoryQueryRequest" + } + ] + }, + "InventoryMetricNames": { + "type": "array", + "description": "Specify the metrics to collect.\n\nUsage: \n* List multiple metrics as JSON objects.\n* You can aggregate metrics with `count`, `sum`, `avg`, `min`, `max`.\n", + "items": { + "$ref": "#/components/schemas/InventoryMetricQuery" + }, + "example": [ + { + "name": "nginx.plus.instances", + "aggregate": [ + "count" + ] + } + ] + }, + "InventoryMetricQuery": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "$ref": "#/components/schemas/InventoryMetricName" + }, + "aggregate": { + "type": "array", + "items": { + "$ref": "#/components/schemas/InventoryMetricAggregation" + } + } + } + }, + "InventoryMetricName": { + "type": "string", + "description": "Metric names available for querying.\n", + "example": "nginx.plus.instances", + "oneOf": [ + { + "$ref": "#/components/schemas/MetricNginxInstancesPlus" + }, + { + "$ref": "#/components/schemas/MetricK8sClusterNodes" + } + ] + }, + "MetricNginxInstancesPlus": { + "type": "string", + "description": "Total number of nginx plus instances.\n\nAggregation(s) supported:\n * count\n * sum\n * avg\n * min\n * max\n", + "enum": [ + "nginx.plus.instances" + ] + }, + "MetricK8sClusterNodes": { + "type": "string", + "description": "Sum of the Kubernetes worker nodes where nginx plus instances are deployed in a Kubernetes cluster.\n\nAggregation(s) supported:\n * count\n * sum\n * avg\n * min\n * max\n", + "enum": [ + "k8s.cluster.nodes" + ] + }, + "FilterNameNapSignatures": { + "type": "string", + "description": "Keywords for NGINX App Protect signature filters.\nWhen filtering on `accuracy`, only the following `filter_values` are supported:\n * high\n * medium\n * low\nWhen filtering on `risk`, only the following `filter_values` are supported:\n * high\n * medium\n * low\nWhen filtering on `signature_type`, only the following `filter_values` are supported:\n * request\n * response\n", + "enum": [ + "accuracy", + "risk", + "signature_type" + ], + "x-enum-varnames": [ + "filter_name_nap_signature_accuracy", + "filter_name_nap_signature_risk", + "filter_name_nap_signature_signature_type" + ] + }, + "FilterNameNapSignatureSets": { + "type": "string", + "description": "Keywords for NGINX App Protect signature set filters.\nWhen filtering on `type`, only the following `filter_values` are supported:\n * filter-based\n * manual\n", + "enum": [ + "type", + "name" + ], + "x-enum-varnames": [ + "filter_name_nap_signature_set_type", + "filter_name_nap_signature_set_name" + ] + }, + "NapSignatureID": { + "description": "An unique identifier for the NGINX App Protect signature.", + "type": "integer", + "pattern": "^\\d{9}" + }, + "NapSignatureSetObjectID": { + "description": "A globally unique identifier for the NGINX App Protect signature set.", + "type": "string", + "format": "object_id", + "pattern": "^sigset_.*", + "x-go-type": "objects.ID", + "x-go-type-import": { + "name": "objects", + "path": "gitlab.com/f5/nginx/one/saas/control-plane/pkg/collections/objects" + } + }, + "NapCompileStatus": { + "description": "Provide the status of the NGINX App Protect compilation request.", + "required": [ + "status", + "nap_release", + "created_at", + "modified_at" + ], + "properties": { + "nap_release": { + "description": "The NGINX App Protect release version the NGINX App Protect log profile compilation was requested for.", + "type": "string" + }, + "status": { + "description": "Status of the NGINX App Protect compilation request. * `pending` - The compilation request has been accepted and is currently processing. * `failed` - The compilation attempt failed. * `succeeded` - The compilation was successful.", + "type": "string", + "enum": [ + "pending", + "failed", + "succeeded" + ], + "x-enum-varnames": [ + "nap_compile_status_pending", + "nap_compile_status_failed", + "nap_compile_status_succeeded" + ] + }, + "failure_reason": { + "type": "string", + "description": "The failure reason populated when status is 'failed'." + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time when the compile request was created." + }, + "modified_at": { + "type": "string", + "format": "date-time", + "description": "The date and time when the compile request was last modified." + }, + "size": { + "type": "integer", + "description": "The size of the compiled bundle, only set when status is `succeeded`." + }, + "hash": { + "type": "string", + "description": "The sha256 hash value of the compiled bundle, only set when status is `succeeded`." + } + }, + "example": { + "nap_release": "5.10.0", + "status": "succeeded", + "created_at": "2026-01-13T18:54:19.140336Z", + "modified_at": "2026-01-13T18:56:31.264956Z" + } + }, + "VersionsList": { + "type": "object", + "required": [ + "items" + ], + "properties": { + "items": { + "description": "An array of versions.", + "type": "array", + "items": { + "$ref": "#/components/schemas/NapSignatureVersion" + } + } + } + }, + "ThreatCampaignVersionsListResponse": { + "$ref": "#/components/schemas/VersionsList" + }, + "AttackSignatureVersionsListResponse": { + "$ref": "#/components/schemas/VersionsList" + }, + "BotSignatureVersionsListResponse": { + "$ref": "#/components/schemas/VersionsList" + }, + "NapPolicy": { + "description": "The base64-encoded contents of the NGINX App Protect policy.", + "type": "object", + "required": [ + "policy" + ], + "properties": { + "policy": { + "type": "string", + "format": "base64", + "maxLength": 3145728 + } + } + }, + "NapPolicyObject": { + "allOf": [ + { + "$ref": "#/components/schemas/NapPolicyMetadata" + }, + { + "$ref": "#/components/schemas/NapPolicyDeployments" + } + ] + }, + "NapPolicyMetadata": { + "description": "Summary information about NGINX App Protect policy.", + "type": "object", + "required": [ + "object_id", + "name", + "latest" + ], + "properties": { + "object_id": { + "$ref": "#/components/schemas/NapPolicyObjectID" + }, + "name": { + "description": "The name of the NGINX App Protect policy.", + "type": "string" + }, + "description": { + "type": "string", + "description": "Some detail on the NGINX App Protect policy." + }, + "latest": { + "$ref": "#/components/schemas/NapPolicyVersionMetadata" + } + } + }, + "NapPolicyListResponse": { + "description": "List of all NGINX App Protect policies.", + "allOf": [ + { + "$ref": "#/components/schemas/PaginationResponse" + }, + { + "description": "List of NGINX App Protect policies.", + "type": "object", + "required": [ + "items" + ], + "properties": { + "items": { + "description": "An array of NGINX App Protect policy objects.", + "type": "array", + "items": { + "$ref": "#/components/schemas/NapPolicyObject" + } + } + }, + "example": { + "items": [ + { + "object_id": "pol_-uvR3F2TQGm18jnl7bpaGw", + "name": "test-policy", + "description": "test policy", + "deployments": [ + { + "publication_object_id": "pub_-uvR3F2TQGm18jnl7bpaGw", + "associated_name": "test-instance", + "associated_type": "instance", + "associated_object_id": "inst_-uvR3F2TQGm18jnl7bpaGw", + "status": "deployed", + "enforcement_mode": "blocking", + "policy_version": "2023-12-06 22:37:24", + "policy_version_object_id": "pv_-abc3F2TQGm18jnl7bpaGw", + "deployed_on": "2023-12-06T22:37:24.120114Z" + } + ], + "latest": { + "object_id": "pv_-uvR3F2TQGm18jnl7bpaGw", + "version": "2023-12-06 22:37:24", + "created_at": "2023-12-06T22:37:24.120114Z", + "deployment_status": "deployed", + "enforcement_mode": "blocking" + } + } + ] + } + } + ] + }, + "NapPolicyVersionDeployments": { + "type": "object", + "properties": { + "deployments": { + "type": "array", + "items": { + "$ref": "#/components/schemas/NapPolicyVersionDeployment" + } + } + } + }, + "NapDeploymentAssociation": { + "type": "object", + "required": [ + "associated_type", + "associated_object_id", + "associated_name" + ], + "properties": { + "associated_type": { + "$ref": "#/components/schemas/DeploymentAssociatedType" + }, + "associated_object_id": { + "$ref": "#/components/schemas/ObjectID" + }, + "associated_name": { + "$ref": "#/components/schemas/DeploymentAssociatedName" + } + } + }, + "NapDeployment": { + "allOf": [ + { + "$ref": "#/components/schemas/NapDeploymentAssociation" + }, + { + "type": "object", + "description": "Information about a NGINX App Protect policy deployment.\n", + "required": [ + "publication_object_id", + "status", + "deployed_on" + ], + "properties": { + "publication_object_id": { + "$ref": "#/components/schemas/PublicationObjectID" + }, + "status": { + "$ref": "#/components/schemas/NapDeploymentStatus" + }, + "deployed_on": { + "description": "Date and time of the deployment.", + "type": "string", + "format": "date-time" + } + }, + "example": { + "publication_object_id": "pub_-uvR3F2TQGm18jnl7bpaGw", + "associated_name": "test-instance", + "associated_type": "instance", + "associated_object_id": "inst_-uvR3F2TQGm18jnl7bpaGw", + "status": "deployed", + "deployed_on": "2023-12-06T22:37:24.120114Z" + } + } + ] + }, + "NapPolicyVersionDeployment": { + "allOf": [ + { + "$ref": "#/components/schemas/NapDeploymentAssociation" + }, + { + "type": "object", + "description": "Information about a NGINX App Protect policy deployment.\n", + "required": [ + "publication_object_id", + "status", + "deployed_on" + ], + "properties": { + "publication_object_id": { + "$ref": "#/components/schemas/PublicationObjectID" + }, + "status": { + "$ref": "#/components/schemas/NapDeploymentStatus" + }, + "deployed_on": { + "description": "Date and time of the deployment.", + "type": "string", + "format": "date-time" + } + }, + "example": { + "publication_object_id": "pub_-uvR3F2TQGm18jnl7bpaGw", + "associated_name": "test-instance", + "associated_type": "instance", + "associated_object_id": "inst_-uvR3F2TQGm18jnl7bpaGw", + "status": "deployed", + "deployed_on": "2023-12-06T22:37:24.120114Z" + } + } + ] + }, + "NapPolicyDeployments": { + "type": "object", + "required": [ + "deployments" + ], + "properties": { + "deployments": { + "type": "array", + "items": { + "$ref": "#/components/schemas/NapPolicyDeployment" + } + } + } + }, + "NapLogProfileDeployments": { + "type": "object", + "properties": { + "deployments": { + "type": "array", + "items": { + "$ref": "#/components/schemas/NapLogProfileDeployment" + } + } + } + }, + "NapLogProfileDeployment": { + "description": "Detailed information about a NGINX App Protect log-profile deployment.", + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/NapDeployment" + }, + { + "type": "object", + "required": [ + "nap_release", + "publication_object_id", + "associated_name", + "associated_type", + "associated_object_id", + "status", + "deployed_on" + ], + "properties": { + "nap_release": { + "description": "The compiler version of NGINX App Protect the log profile was deployed with.", + "type": "string" + }, + "latest_deployed": { + "$ref": "#/components/schemas/NapLatestDeployed" + } + } + } + ], + "example": { + "nap_release": "5.10.0", + "publication_object_id": "pub_-uvR3F2TQGm18jnl7bpaGw", + "associated_name": "test-instance", + "associated_type": "instance", + "associated_object_id": "inst_-uvR3F2TQGm18jnl7bpaGw", + "status": "deployed", + "deployed_on": "2023-12-06T22:37:24.120114Z", + "latest_deployed": "yes" + } + }, + "NapPolicyDeployment": { + "description": "Detailed information about a NGINX App Protect policy deployment.", + "type": "object", + "required": [ + "publication_object_id", + "associated_object_id", + "associated_name", + "associated_type", + "enforcement_mode", + "status", + "policy_version", + "policy_version_object_id", + "deployed_on" + ], + "allOf": [ + { + "$ref": "#/components/schemas/NapPolicyVersionDeployment" + }, + { + "type": "object", + "required": [ + "enforcement_mode", + "policy_version", + "policy_version_object_id" + ], + "properties": { + "enforcement_mode": { + "$ref": "#/components/schemas/NapPolicyEnforcementMode" + }, + "policy_version": { + "description": "The version associated with the NGINX App Protect policy.", + "type": "string" + }, + "policy_version_object_id": { + "$ref": "#/components/schemas/NapPolicyVersionObjectID" + } + } + } + ], + "example": { + "publication_object_id": "pub_-uvR3F2TQGm18jnl7bpaGw", + "associated_name": "test-instance", + "associated_type": "instance", + "associated_object_id": "inst_-uvR3F2TQGm18jnl7bpaGw", + "status": "deployed", + "deployed_on": "2023-12-06T22:37:24.120114Z", + "enforcement_mode": "blocking", + "policy_version": "2023-12-06 22:37:24", + "policy_version_object_id": "pv_-abc3F2TQGm18jnl7bpaGw" + } + }, + "NapPolicyDeploymentDetails": { + "type": "object", + "required": [ + "publication_object_id", + "associated_object_id", + "associated_name", + "associated_type", + "enforcement_mode", + "status", + "policy_version", + "policy_version_object_id", + "deployed_on", + "threat_campaign_version", + "attack_signature_version", + "bot_signature_version" + ], + "allOf": [ + { + "$ref": "#/components/schemas/NapPolicyDeployment" + }, + { + "type": "object", + "properties": { + "threat_campaign_version": { + "$ref": "#/components/schemas/NapSignatureVersion" + }, + "attack_signature_version": { + "$ref": "#/components/schemas/NapSignatureVersion" + }, + "bot_signature_version": { + "$ref": "#/components/schemas/NapSignatureVersion" + } + } + } + ], + "example": { + "publication_object_id": "pub_-uvR3F2TQGm18jnl7bpaGw", + "associated_name": "test-instance", + "associated_type": "instance", + "associated_object_id": "inst_-uvR3F2TQGm18jnl7bpaGw", + "status": "deployed", + "policy_version": "2023-12-06 22:37:24", + "policy_version_object_id": "pv_-abc3F2TQGm18jnl7bpaGw", + "deployed_on": "2023-12-06T22:37:24.120114Z", + "enforcement_mode": "blocking", + "threat_campaign_version": "2023.12.06", + "attack_signature_version": "2023.12.06", + "bot_signature_version": "2023.12.06" + } + }, + "NapPolicyDeploymentsListResponse": { + "description": "List of all NGINX App Protect deployments.", + "allOf": [ + { + "$ref": "#/components/schemas/PaginationResponse" + }, + { + "type": "object", + "required": [ + "items" + ], + "properties": { + "items": { + "description": "An array of NGINX App Protect deployments.", + "type": "array", + "items": { + "$ref": "#/components/schemas/NapPolicyDeploymentDetails" + } + } + }, + "example": { + "items": [ + { + "publication_object_id": "pub_-uvR3F2TQGm18jnl7bpaGw", + "associated_name": "test-instance", + "associated_type": "instance", + "associated_object_id": "inst_-uvR3F2TQGm18jnl7bpaGw", + "status": "deployed", + "policy_version": "2023-12-06 22:37:24", + "policy_version_object_id": "pv_-abc3F2TQGm18jnl7bpaGw", + "deployed_on": "2023-12-06T22:37:24.120114Z", + "enforcement_mode": "blocking", + "threat_campaign_version": "2023.12.06", + "attack_signature_version": "2023.12.06", + "bot_signature_version": "2023.12.06" + } + ] + } + } + ] + }, + "NapLogProfileDeploymentsListResponse": { + "description": "List of all NGINX App Protect log profile deployments.", + "allOf": [ + { + "$ref": "#/components/schemas/PaginationResponse" + }, + { + "type": "object", + "required": [ + "items" + ], + "properties": { + "items": { + "description": "An array of NGINX App Protect log profile deployments.", + "type": "array", + "items": { + "$ref": "#/components/schemas/NapLogProfileDeployment" + } + } + }, + "example": { + "items": [ + { + "nap_release": "5.10.0", + "publication_object_id": "pub_-uvR3F2TQGm18jnl7bpaGw", + "associated_name": "test-instance", + "associated_type": "instance", + "associated_object_id": "inst_-uvR3F2TQGm18jnl7bpaGw", + "status": "deployed", + "deployed_on": "2023-12-06T22:37:24.120114Z", + "latest_deployed": "yes" + } + ] + } + } + ] + }, + "NapPolicyVersionMetadata": { + "type": "object", + "description": "Summary information about the specific NGINX App Protect policy version.", + "required": [ + "object_id", + "version", + "enforcement_mode", + "created_at" + ], + "properties": { + "object_id": { + "$ref": "#/components/schemas/NapPolicyVersionObjectID" + }, + "version": { + "$ref": "#/components/schemas/NapSignatureVersion" + }, + "enforcement_mode": { + "$ref": "#/components/schemas/NapPolicyEnforcementMode" + }, + "created_at": { + "description": "The date and time when the NGINX App Protect policy version was created.", + "type": "string", + "format": "date-time" + } + } + }, + "NapPolicyVersionDetails": { + "description": "Detailed information about NGINX App Protect policy version.", + "type": "object", + "required": [ + "policy", + "object_id", + "version", + "enforcement_mode", + "created_at" + ], + "allOf": [ + { + "$ref": "#/components/schemas/NapPolicyVersionMetadata" + }, + { + "$ref": "#/components/schemas/NapPolicy" + }, + { + "$ref": "#/components/schemas/NapPolicyVersionDeployments" + } + ] + }, + "NapPolicyVersionObject": { + "description": "Summary information about NGINX App Protect policy version.", + "allOf": [ + { + "$ref": "#/components/schemas/NapPolicyVersionMetadata" + }, + { + "$ref": "#/components/schemas/NapPolicyVersionDeployments" + }, + { + "type": "object", + "required": [ + "latest" + ], + "properties": { + "latest": { + "description": "Indicates whether the NGINX App Protect policy version is latest. Default (`false`) returns the current policy. \nWhen set to `true`, returns the latest policy.\n", + "type": "boolean", + "default": false + } + } + } + ] + }, + "NapPolicyVersionsListResponse": { + "description": "List of all NGINX App Protect versions.", + "allOf": [ + { + "$ref": "#/components/schemas/PaginationResponse" + }, + { + "type": "object", + "required": [ + "items" + ], + "properties": { + "items": { + "description": "An array of NGINX App Protect version objects.", + "type": "array", + "items": { + "$ref": "#/components/schemas/NapPolicyVersionObject" + } + } + }, + "example": { + "items": [ + { + "version": "2023-12-06 22:37:24", + "object_id": "pv_-uvR3F2TQGm18jnl7bpaGw", + "created_at": "2023-12-06T22:37:24.120114Z", + "enforcement_mode": "blocking", + "latest": false + } + ] + } + } + ] + }, + "NapLogProfileListResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/PaginationResponse" + }, + { + "type": "object", + "required": [ + "items" + ], + "properties": { + "items": { + "description": "An array of NGINX App Protect log profiles.", + "type": "array", + "items": { + "$ref": "#/components/schemas/NapLogProfileObject" + } + } + } + } + ] + }, + "NapLogProfileObjectDetails": { + "allOf": [ + { + "$ref": "#/components/schemas/NapLogProfileObject" + }, + { + "type": "object", + "required": [ + "config" + ], + "properties": { + "config": { + "description": "The NGINX App Protect log profile configuration.", + "type": "string" + } + } + }, + { + "type": "object", + "required": [ + "bundles" + ], + "properties": { + "bundles": { + "description": "Compiled NGINX APP Protect log profile bundles for this specific log profile. \nShows compilation status of the latest log profile contents across different NAP release versions.\n", + "type": "array", + "items": { + "$ref": "#/components/schemas/NapCompileStatus" + } + } + } + } + ], + "example": { + "created_at": "2026-01-16T21:12:51.843434Z", + "hash": "oxiWKPqR/soi4MQCgVnW8KHt8Jk68AqCeQcQ1sed4Dk=", + "modified_at": "2026-01-16T21:12:51.843434Z", + "name": "test-log-profiles", + "object_id": "lp_XYxnZgVYQFKire4M1KcVVQ", + "is_f5_default": false, + "config": "eyJsb2dfc3RyZWFtIjogIntmb3JtYXQgY29tYmluZWQgZXg=", + "deployments": [ + { + "nap_release": "5.10.0", + "publication_object_id": "pub_-uvR3F2TQGm18jnl7bpaGw", + "associated_name": "test-instance", + "associated_type": "instance", + "associated_object_id": "inst_-uvR3F2TQGm18jnl7bpaGw", + "status": "deployed", + "deployed_on": "2023-12-06T22:37:24.120114Z", + "latest_deployed": "yes" + } + ], + "bundles": [ + { + "nap_release": "5.10.0", + "status": "succeeded", + "created_at": "2026-01-13T18:54:19.140336Z", + "modified_at": "2026-01-13T18:56:31.264956Z" + }, + { + "nap_release": "5.9.0", + "status": "succeeded", + "created_at": "2026-01-13T18:54:19.140336Z", + "modified_at": "2026-01-13T18:56:31.264956Z" + } + ] + } + }, + "NapLogProfileObject": { + "allOf": [ + { + "$ref": "#/components/schemas/NapLogProfileDeployments" + }, + { + "$ref": "#/components/schemas/NapLogProfileMetadata" + } + ], + "example": { + "created_at": "2026-01-16T21:12:51.843434Z", + "hash": "oxiWKPqR/soi4MQCgVnW8KHt8Jk68AqCeQcQ1sed4Dk=", + "modified_at": "2026-01-16T21:12:51.843434Z", + "name": "test-log-profiles", + "object_id": "lp_XYxnZgVYQFKire4M1KcVVQ", + "is_f5_default": false, + "deployments": [ + { + "nap_release": "5.10.0", + "publication_object_id": "pub_-uvR3F2TQGm18jnl7bpaGw", + "associated_name": "test-instance", + "associated_type": "instance", + "associated_object_id": "inst_-uvR3F2TQGm18jnl7bpaGw", + "status": "deployed", + "deployed_on": "2023-12-06T22:37:24.120114Z", + "latest_deployed": "yes" + } + ] + } + }, + "NapLogProfileMetadata": { + "type": "object", + "required": [ + "name", + "object_id", + "hash", + "is_f5_default", + "modified_at", + "created_at" + ], + "properties": { + "name": { + "type": "string", + "description": "The name of the NGINX App Protect log profile." + }, + "object_id": { + "$ref": "#/components/schemas/NapLogProfileObjectID" + }, + "hash": { + "type": "string", + "description": "The hash value of the NGINX App Protect log profile configs." + }, + "is_f5_default": { + "$ref": "#/components/schemas/IsF5Default" + }, + "description": { + "description": "Optional field to describe the NGINX App Protect log profile.", + "type": "string", + "minLength": 5, + "maxLength": 256 + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time when the log profile was created." + }, + "modified_at": { + "type": "string", + "format": "date-time", + "description": "The date and time when the log profile was last modified." + } + } + }, + "NapGlobalSettingsListResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/PaginationResponse" + }, + { + "type": "object", + "required": [ + "items" + ], + "properties": { + "items": { + "description": "An array of NGINX App Protect global settings.", + "type": "array", + "items": { + "$ref": "#/components/schemas/NapGlobalSettingMetadata" + } + } + } + } + ] + }, + "NapGlobalSettingGetResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/NapGlobalSettingMetadata" + }, + { + "type": "object", + "required": [ + "config" + ], + "properties": { + "config": { + "description": "The NGINX App Protect global setting configuration.", + "type": "string" + } + } + } + ] + }, + "NapGlobalSettingMetadata": { + "type": "object", + "required": [ + "name", + "object_id" + ], + "properties": { + "name": { + "type": "string", + "description": "The name of the NGINX App Protect global setting object." + }, + "description": { + "description": "Optional field to describe the NGINX App Protect global setting object.", + "type": "string", + "minLength": 5, + "maxLength": 256 + }, + "object_id": { + "$ref": "#/components/schemas/NapGlobalSettingObjectID" + } + } + }, + "NapLogProfileCreateRequest": { + "description": "Create NGINX App Protect log profile.", + "type": "object", + "required": [ + "name", + "config" + ], + "properties": { + "name": { + "description": "The name of the NGINX App Protect log profile.", + "type": "string", + "minLength": 1, + "maxLength": 128 + }, + "description": { + "description": "Optional field to describe the NGINX App Protect log profile.", + "type": "string", + "minLength": 5, + "maxLength": 256 + }, + "config": { + "description": "The NGINX App Protect log profile configuration.", + "type": "string", + "format": "base64", + "maxLength": 3145728 + } + } + }, + "NapLogProfileUpdateRequest": { + "description": "Update NGINX App Protect log profile.", + "type": "object", + "required": [ + "config" + ], + "properties": { + "name": { + "description": "The name of the NGINX App Protect log profile.", + "type": "string", + "minLength": 1, + "maxLength": 128 + }, + "description": { + "description": "Optional field to describe describing the NGINX App Protect log profile.", + "type": "string", + "minLength": 5, + "maxLength": 256 + }, + "config": { + "description": "The NGINX App Protect log profile configuration.", + "type": "string", + "format": "base64", + "minLength": 5, + "maxLength": 3145728 + } + } + }, + "NapPolicyBulkRequest": { + "type": "array", + "items": { + "$ref": "#/components/schemas/NapPolicyBulkRequestData" + }, + "minItems": 1, + "maxItems": 50, + "example": [ + { + "object_id": "pol_-uvR3F2TQGm18jnl7bpaGw", + "action": "delete" + }, + { + "object_id": "pol_PL0c1XodRemmzVEjiXSsTg", + "action": "delete" + } + ] + }, + "NapPolicyBulkRequestData": { + "type": "object", + "description": "Part of bulk operation on a Nap policy, only `delete` is supported.", + "required": [ + "action", + "object_id" + ], + "properties": { + "object_id": { + "$ref": "#/components/schemas/NapPolicyObjectID" + }, + "action": { + "$ref": "#/components/schemas/BulkRequestAction" + } + }, + "example": { + "object_id": "pol_-uvR3F2TQGm18jnl7bpaGw", + "action": "delete" + } + }, + "NapBulkResponse": { + "description": "The Nap policy bulk outcome.", + "type": "array", + "items": { + "$ref": "#/components/schemas/BulkRequestObjectStatus" + } + }, + "NapSignatureMeta": { + "required": [ + "signature_id", + "name", + "attack_type" + ], + "properties": { + "name": { + "type": "string" + }, + "signature_id": { + "type": "integer" + }, + "attack_type": { + "type": "string" + } + } + }, + "NapSignature": { + "description": "Detail information for NGINX App Protect signatures. Note: `description` is omitted for list operation.\n", + "allOf": [ + { + "$ref": "#/components/schemas/NapSignatureMeta" + }, + { + "type": "object", + "required": [ + "signature_type", + "risk", + "accuracy", + "has_cve", + "modified_at", + "systems" + ], + "properties": { + "accuracy": { + "default": "low", + "enum": [ + "high", + "low", + "medium" + ], + "x-enum-varnames": [ + "nap_signature_accuracy_high", + "nap_signature_accuracy_low", + "nap_signature_accuracy_medium" + ], + "type": "string" + }, + "description": { + "type": "string" + }, + "has_cve": { + "default": false, + "type": "boolean" + }, + "modified_at": { + "type": "string", + "format": "date-time", + "description": "The date and time when the signature was last modified." + }, + "references": { + "items": { + "required": [ + "type", + "value" + ], + "properties": { + "type": { + "default": "nessus", + "enum": [ + "bugtraq", + "cve", + "nessus", + "url" + ], + "x-enum-varnames": [ + "nap_signature_references_type_bugtrag", + "nap_signature_references_type_cve", + "nap_signature_references_type_nessus", + "nap_signature_references_type_url" + ], + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "risk": { + "default": "low", + "enum": [ + "high", + "low", + "medium" + ], + "x-enum-varnames": [ + "nap_signature_risk_high", + "nap_signature_risk_low", + "nap_signature_risk_medium" + ], + "type": "string" + }, + "signature_type": { + "default": "request", + "enum": [ + "request", + "response" + ], + "type": "string", + "x-enum-varnames": [ + "nap_signature_signature_type_request", + "nap_signature_signature_type_response" + ] + }, + "systems": { + "items": { + "type": "string" + }, + "type": "array" + } + } + } + ], + "example": { + "signature_id": 123456789, + "name": "Example Signature", + "description": "This is an example signature.", + "signature_type": "request", + "attack_type": "SQL Injection", + "risk": "high", + "accuracy": "medium", + "has_cve": true, + "modified_at": "2023-10-01T12:00:00Z", + "references": [ + { + "type": "cve", + "value": "CVE-2023-12345" + } + ], + "systems": [ + "System A" + ] + } + }, + "NapSignatureSet": { + "type": "object", + "required": [ + "object_id", + "name", + "type", + "category", + "signature_count", + "accuracy", + "default_alarm", + "default_block", + "default_learn", + "systems", + "modified_at" + ], + "properties": { + "object_id": { + "$ref": "#/components/schemas/NapSignatureSetObjectID" + }, + "name": { + "type": "string" + }, + "accuracy": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "low", + "medium", + "high" + ], + "x-enum-varnames": [ + "nap_signature_set_accuracy_low", + "nap_signature_set_accuracy_medium", + "nap_signature_set_accuracy_high" + ] + } + }, + "signature_count": { + "type": "integer" + }, + "category": { + "enum": [ + "User-defined", + "Basic", + "Attack Type Specific" + ], + "x-enum-varnames": [ + "nap_signature_set_category_user_defined", + "nap_signature_set_category_basic", + "nap_signature_set_category_attack_type_specific" + ], + "type": "string" + }, + "default_alarm": { + "default": true, + "type": "boolean" + }, + "default_block": { + "default": true, + "type": "boolean" + }, + "default_learn": { + "default": true, + "type": "boolean" + }, + "filter": { + "properties": { + "accuracy_filter": { + "default": "ge", + "enum": [ + "all", + "eq", + "ge", + "le" + ], + "x-enum-varnames": [ + "nap_signature_set_filter_accuracy_filter_all", + "nap_signature_set_filter_accuracy_filter_eq", + "nap_signature_set_filter_accuracy_filter_ge", + "nap_signature_set_filter_accuracy_filter_le" + ], + "type": "string" + }, + "accuracy_value": { + "default": "all", + "enum": [ + "all", + "high", + "low", + "medium" + ], + "x-enum-varnames": [ + "nap_signature_set_filter_accuracy_value_all", + "nap_signature_set_filter_accuracy_value_high", + "nap_signature_set_filter_accuracy_value_low", + "nap_signature_set_filter_accuracy_value_medium" + ], + "type": "string" + }, + "attack_type": { + "properties": { + "name": { + "type": "string" + } + }, + "type": "object" + }, + "has_cve": { + "default": "all", + "enum": [ + "all", + "no", + "yes" + ], + "x-enum-varnames": [ + "nap_signature_set_filter_have_cve_all", + "nap_signature_set_filter_have_cve_no", + "nap_signature_set_filter_have_cve_yes" + ], + "type": "string" + }, + "modified_at_filter": { + "default": "all", + "enum": [ + "after", + "all", + "before" + ], + "x-enum-varnames": [ + "nap_signature_set_filter_modified_at_filter_after", + "nap_signature_set_filter_modified_at_filter_all", + "nap_signature_set_filter_modified_at_filter_before" + ], + "type": "string" + }, + "modified_at_value": { + "default": "1970-01-01", + "type": "string" + }, + "risk_filter": { + "default": "eq", + "enum": [ + "all", + "eq", + "ge", + "le" + ], + "x-enum-varnames": [ + "nap_signature_set_filter_risk_filter_all", + "nap_signature_set_filter_risk_filter_eq", + "nap_signature_set_filter_risk_filter_ge", + "nap_signature_set_filter_risk_filter_le" + ], + "type": "string" + }, + "risk_value": { + "default": "low", + "enum": [ + "all", + "high", + "low", + "medium" + ], + "x-enum-varnames": [ + "nap_signature_set_filter_risk_value_all", + "nap_signature_set_filter_risk_value_high", + "nap_signature_set_filter_risk_value_low", + "nap_signature_set_filter_risk_value_medium" + ], + "type": "string" + }, + "signature_type": { + "default": "request", + "enum": [ + "all", + "request", + "response" + ], + "x-enum-varnames": [ + "nap_signature_set_filter_signature_type_all", + "nap_signature_set_filter_signature_type_request", + "nap_signature_set_filter_signature_type_response" + ], + "type": "string" + }, + "user_defined_filter": { + "default": "all", + "enum": [ + "all", + "no", + "yes" + ], + "x-enum-varnames": [ + "nap_signature_set_filter_user_defined_filter_all", + "nap_signature_set_filter_user_defined_filter_no", + "nap_signature_set_filter_user_defined_filter_yes" + ], + "type": "string" } - ] - }, - "upstream": { - "$ref": "#/components/schemas/UsageMetrics" - } - } - }, - "StreamUsage": { - "type": "object", - "properties": { - "client": { - "$ref": "#/components/schemas/UsageMetrics" + }, + "type": "object" }, - "upstream": { - "$ref": "#/components/schemas/UsageMetrics" - } - } - }, - "UsageMetrics": { - "type": "object", - "properties": { - "received": { - "type": "integer", - "description": "Total bytes received by an NGINX Instance from clients/upstreams", - "minimum": 0 + "modified_at": { + "type": "string", + "format": "date-time", + "description": "The date and time when the signature-set was last modified." }, - "sent": { - "type": "integer", - "description": "Total bytes sent by the NGINX Instance to clients/upstreams", - "minimum": 0 + "systems": { + "items": { + "type": "string" + }, + "type": "array" }, - "connections": { - "type": "integer", - "description": "Total connections of the NGINX Instance with clients/upstreams", - "minimum": 0 + "type": { + "default": "filter-based", + "enum": [ + "filter-based", + "manual" + ], + "x-enum-varnames": [ + "nap_signature_set_type_filter_based", + "nap_signature_set_type_manual" + ], + "type": "string" } - } - }, - "NginxUsageHttp": { - "$ref": "#/components/schemas/HttpUsage" - }, - "NginxUsageStream": { - "$ref": "#/components/schemas/StreamUsage" - }, - "MetricStartTime": { - "description": "The start time of your metrics query.\n\nUsage:\n* `start_time` is required if `end_time` is specified.\n* If `start_time` and `end_time` isn't provided, the API returns metrics from the current time to the month before the current time.\n* The `start_time` cannot be older than 120 days before the current time.\n\nYou can set the `start_time` in these ways:\n* In ISO 8601 format. For example, \"2019-08-07T09:57:36.088757764Z\".\n* As an offset from the current time. For the offset, use `+` or `-`, followed by a number and unit [`y` (years), `M` (months), `w` (weeks), `d` (days), `h` (hours), `m` (minutes), or `s` (seconds)]. \n* Example of an offset: \"now-3h\" (3 hours before now).\n", - "type": "string", - "example": "2019-08-07T09:57:36.088757764Z" - }, - "MetricEndTime": { - "description": "The end time of your metrics query.\n\nUsage:\n* Must be greater than `start_time`.\n* The time difference between `start_time` and `end_time` should be greater than an hour.\n* The default `end_time` is the current time.\n* The `end_time` cannot be older than 120 days before the current time.\n\nYou can set the `end_time` in these ways:\n* In ISO 8601 format. For example, \"2019-08-07T09:57:36.088757764Z\".\n* As an offset from the current time. For the offset, use `+` or `-`, followed by a number and unit [`y` (years), `M` (months), `w` (weeks), `d` (days), `h` (hours), `m` (minutes), or `s` (seconds)]. \n* Example of an offset: \"now-3h\" (3 hours before now).\n", - "type": "string", - "example": "2019-08-07T09:57:36.088757764Z" - }, - "InventoryMetricAggregation": { - "type": "string", - "description": "Static list of aggregation functions that can be applied to a compatible metric.\n * count\n * sum\n * avg\n * min\n * max\n", - "enum": [ - "count", - "sum", - "avg", - "min", - "max" - ], - "x-enum-varnames": [ - "metric_aggregation_count", - "metric_aggregation_sum", - "metric_aggregation_avg", - "metric_aggregation_min", - "metric_aggregation_max" - ] - }, - "BaseInventoryQueryRequest": { - "type": "object", - "required": [ - "metrics" - ], - "properties": { - "metrics": { - "$ref": "#/components/schemas/InventoryMetricNames" - }, - "start_time": { - "$ref": "#/components/schemas/MetricStartTime" + }, + "example": { + "default_block": true, + "default_learn": true, + "signature_count": 0, + "filter": { + "accuracy_value": "all", + "accuracy_filter": "all", + "attack_type": { + "name": "XML External Entities (XXE)" + }, + "risk_filter": "all", + "has_cve": "all", + "user_defined_filter": "all", + "risk_value": "all", + "modified_at_filter": "all", + "signature_type": "request" }, - "end_time": { - "$ref": "#/components/schemas/MetricEndTime" - } + "assign_to_policy_by_default": false, + "default_alarm": true, + "accuracy": [], + "type": "filter-based", + "name": "XML External Entities (XXE) Signatures", + "object_id": "sigset_-ZMshmi83MBL97dr5d0a9w", + "category": "User-defined", + "modified_at": "2023-08-10T16:59:15Z", + "systems": [] } }, - "InventoryMetricQueryRequest": { - "type": "object", + "NapSignatureListResponse": { "allOf": [ { - "$ref": "#/components/schemas/BaseInventoryQueryRequest" - } - ] - }, - "InventoryMetricNames": { - "type": "array", - "description": "Specify the metrics to collect.\n\nUsage: \n* List multiple metrics as JSON objects.\n* You can aggregate metrics with `count`, `sum`, `avg`, `min`, `max`.\n", - "items": { - "$ref": "#/components/schemas/InventoryMetricQuery" - }, - "example": [ - { - "name": "nginx.plus.instances", - "aggregate": [ - "count" - ] - } - ] - }, - "InventoryMetricQuery": { - "type": "object", - "required": [ - "name" - ], - "properties": { - "name": { - "$ref": "#/components/schemas/InventoryMetricName" + "$ref": "#/components/schemas/PaginationResponse" }, - "aggregate": { - "type": "array", - "items": { - "$ref": "#/components/schemas/InventoryMetricAggregation" + { + "type": "object", + "required": [ + "items" + ], + "properties": { + "items": { + "description": "An array of NGINX App Protect signatures.", + "type": "array", + "items": { + "$ref": "#/components/schemas/NapSignature" + } + } } } - } + ] }, - "InventoryMetricName": { - "type": "string", - "description": "Metric names available for querying.\n", - "example": "nginx.plus.instances", - "oneOf": [ + "NapSignatureSetListResponse": { + "allOf": [ { - "$ref": "#/components/schemas/MetricNginxInstancesPlus" + "$ref": "#/components/schemas/PaginationResponse" }, { - "$ref": "#/components/schemas/MetricK8sClusterNodes" + "type": "object", + "required": [ + "items" + ], + "properties": { + "items": { + "description": "An array of NGINX App Protect signature sets.", + "type": "array", + "items": { + "$ref": "#/components/schemas/NapSignatureSet" + } + } + } } ] }, - "MetricNginxInstancesPlus": { + "FilterNameNapLogProfile": { "type": "string", - "description": "Total number of nginx plus instances.\n\nAggregation(s) supported:\n * count\n * sum\n * avg\n * min\n * max\n", + "description": "Keywords for NGINX App Protect log profile filters.\n", "enum": [ - "nginx.plus.instances" + "name", + "object_id", + "deployment_status" + ], + "x-enum-varnames": [ + "filter_name_nap_log_profile_name", + "filter_name_nap_log_profile_object_id", + "filter_name_nap_log_profile_deployment_status" ] }, - "MetricK8sClusterNodes": { + "IsF5Default": { + "type": "boolean", + "description": "Indicates whether this is an F5 default object (true) or a user-defined object (false)." + }, + "FilterNameNapLogProfileDeployment": { "type": "string", - "description": "Sum of the Kubernetes worker nodes where nginx plus instances are deployed in a Kubernetes cluster.\n\nAggregation(s) supported:\n * count\n * sum\n * avg\n * min\n * max\n", + "description": "Keywords for NGINX App Protect log profile deployment filters.\nWhen filtering on `type`, only the following `filter_values` are supported:\n * instance\n * config_sync_group\nWhen filtering on `status`, only the following `filter_values` are supported:\n * deployed\n * deploying\n * failed\n", "enum": [ - "k8s.cluster.nodes" + "name", + "type", + "status", + "object_id" + ], + "x-enum-varnames": [ + "filter_name_nap_deployment_name", + "filter_name_nap_deployment_type", + "filter_name_nap_deployment_status", + "filter_name_nap_deployment_object_id" ] }, - "FilterNameNapSignatures": { + "FilterNameNapPolicy": { "type": "string", - "description": "Keywords for NGINX App Protect signature filters.\nWhen filtering on `accuracy`, only the following `filter_values` are supported:\n * high\n * medium\n * low\nWhen filtering on `risk`, only the following `filter_values` are supported:\n * high\n * medium\n * low\nWhen filtering on `signature_type`, only the following `filter_values` are supported:\n * request\n * response\n", + "description": "Keywords for NGINX App Protect policy filters.\nWhen filtering on `enforcement_mode`, only the following `filter_values` are supported:\n * blocking\n * transparent\nWhen filtering on `object_id`, both NAP Policy and NAP Policy version object id prefixes are supported.\n", "enum": [ - "accuracy", - "risk", - "signature_type" + "name", + "enforcement_mode", + "object_id", + "deployment_enforcement_mode", + "deployment_status" ], "x-enum-varnames": [ - "filter_name_nap_signature_accuracy", - "filter_name_nap_signature_risk", - "filter_name_nap_signature_signature_type" + "filter_name_nap_policy_name", + "filter_name_nap_policy_enforcement_mode", + "filter_name_nap_policy_object_id", + "filter_name_nap_policy_deployment_enforcement_mode", + "filter_name_nap_policy_deployment_status" ] }, - "FilterNameNapSignatureSets": { + "FilterNameNapPolicyDeployment": { "type": "string", - "description": "Keywords for NGINX App Protect signature set filters.\nWhen filtering on `type`, only the following `filter_values` are supported:\n * filter-based\n * manual\n", + "description": "Keywords for NGINX App Protect deployment filters.\nWhen filtering on `type`, only the following `filter_values` are supported:\n * instance\n * config_sync_group\nWhen filtering on `status`, only the following `filter_values` are supported:\n * deployed\n * deploying\n * failed\n", "enum": [ + "name", "type", - "name" + "policy_version", + "status", + "object_id" ], "x-enum-varnames": [ - "filter_name_nap_signature_set_type", - "filter_name_nap_signature_set_name" + "filter_name_nap_deployment_name", + "filter_name_nap_deployment_type", + "filter_name_nap_deployment_policy_version", + "filter_name_nap_deployment_status", + "filter_name_nap_deployment_object_id" ] }, - "NapSignatureID": { - "description": "An unique identifier for the NGINX App Protect signature.", - "type": "integer", - "pattern": "^\\d{9}" + "FilterNameNapPolicyVersion": { + "type": "string", + "description": "Keywords for NGINX App Protect policy version filters.\nWhen filtering on `deployment_status`, only the following `filter_values` are supported:\n * deployed\n * not_deployed\n * deploying\n * failed\nWhen filtering on `enforcement_mode`, only the following `filter_values` are supported:\n * blocking\n * transparent\n", + "enum": [ + "deployment_status", + "enforcement_mode", + "object_id" + ], + "x-enum-varnames": [ + "filter_name_nap_policy_version_deployment_status", + "filter_name_nap_policy_version_enforcement_mode", + "filter_name_nap_policy_version_object_id" + ] }, - "NapSignatureSetObjectID": { - "description": "A globally unique identifier for the NGINX App Protect signature set.", + "NapGlobalSettingObjectID": { + "description": "A globally unique identifier for the App Protect global settings object.", "type": "string", "format": "object_id", - "pattern": "^sigset_.*", + "pattern": "^gs_.*", "x-go-type": "objects.ID", "x-go-type-import": { "name": "objects", "path": "gitlab.com/f5/nginx/one/saas/control-plane/pkg/collections/objects" } }, - "NapCompileStatus": { - "description": "Provide the status of the NGINX App Protect compilation request.", - "required": [ - "status", - "nap_release", - "created_at", - "modified_at" - ], - "properties": { - "nap_release": { - "description": "The NGINX App Protect release version the NGINX App Protect log profile compilation was requested for.", - "type": "string" - }, - "status": { - "description": "Status of the NGINX App Protect compilation request. * `pending` - The compilation request has been accepted and is currently processing. * `failed` - The compilation attempt failed. * `succeeded` - The compilation was successful.", - "type": "string", - "enum": [ - "pending", - "failed", - "succeeded" - ], - "x-enum-varnames": [ - "nap_compile_status_pending", - "nap_compile_status_failed", - "nap_compile_status_succeeded" - ] - }, - "failure_reason": { - "type": "string", - "description": "The failure reason populated when status is 'failed'." - }, - "created_at": { - "type": "string", - "format": "date-time", - "description": "The date and time when the compile request was created." - }, - "modified_at": { - "type": "string", - "format": "date-time", - "description": "The date and time when the compile request was last modified." - } - }, - "example": { - "nap_release": "5.10.0", - "status": "succeeded", - "created_at": "2026-01-13T18:54:19.140336Z", - "modified_at": "2026-01-13T18:56:31.264956Z" - } - }, - "VersionsList": { - "type": "object", - "required": [ - "items" - ], - "properties": { - "items": { - "description": "An array of versions.", - "type": "array", - "items": { - "$ref": "#/components/schemas/NapSignatureVersion" - } - } - } + "TemplateName": { + "type": "string", + "description": "The name of the template.\nMust be suitable for use as a file name and as an NGINX configuration include.\nOnly alphanumeric characters, underscores, dashes, and dots are allowed.\nNo spaces, slashes, or special characters.\n", + "minLength": 1, + "maxLength": 255, + "pattern": "^[a-zA-Z0-9][a-zA-Z0-9_.-]*$", + "example": "reverse-proxy" }, - "ThreatCampaignVersionsListResponse": { - "$ref": "#/components/schemas/VersionsList" + "TemplateDescription": { + "type": "string", + "description": "A human-readable description of the template.", + "example": "A base template for setting up a reverse proxy" }, - "AttackSignatureVersionsListResponse": { - "$ref": "#/components/schemas/VersionsList" + "TemplateObjectID": { + "description": "A globally unique identifier for template.", + "type": "string", + "format": "object_id", + "pattern": "^tmpl_.*", + "x-go-type": "objects.ID", + "x-go-type-import": { + "name": "objects", + "path": "gitlab.com/f5/nginx/one/saas/control-plane/pkg/collections/objects" + }, + "example": "tmpl_-uvR3F2TQGm18jnl7bpaGw" }, - "BotSignatureVersionsListResponse": { - "$ref": "#/components/schemas/VersionsList" + "TemplateVersionObjectID": { + "description": "A globally unique identifier for the template version.", + "type": "string", + "format": "object_id", + "pattern": "^tmplv_.*", + "x-go-type": "objects.ID", + "x-go-type-import": { + "name": "objects", + "path": "gitlab.com/f5/nginx/one/saas/control-plane/pkg/collections/objects" + }, + "example": "tmplv_-ayR3F2TQGm18jnl7bpaGw" }, - "NapPolicy": { - "description": "The base64-encoded contents of the NGINX App Protect policy.", - "type": "object", - "required": [ - "policy" + "TemplateType": { + "type": "string", + "description": "The type of the template.\n- `base`: A base template that defines the structure of an NGINX configuration.\n- `augment`: An augment template that extends or modifies an existing NGINX configuration defined by a base template.\n", + "enum": [ + "base", + "augment" ], - "properties": { - "policy": { - "type": "string", - "format": "base64", - "maxLength": 3145728 - } - } + "x-enum-varnames": [ + "template_type_base", + "template_type_augment" + ], + "example": "base" }, - "NapPolicyObject": { - "allOf": [ - { - "$ref": "#/components/schemas/NapPolicyMetadata" - }, - { - "$ref": "#/components/schemas/NapPolicyDeployments" - } - ] + "TemplateContextPath": { + "type": "string", + "description": "Specifies the full hierarchical context path within the NGINX configuration, using '/' as a separator.\n* \"main\": Refers to the top-level context of the NGINX configuration.\n* \"http\": Indicates the `http` block within the main context.\n* \"http/server\": Indicates the `server` block within the `http` context.\n* \"http/server/location\": Indicates the `location` block within the `server` context of the `http` block.\n* \"http/upstream\": Indicates the `upstream` block within the `http` context.\n* \"stream\": Indicates the `stream` block within the main context.\n* \"stream/server\": Indicates the `server` block within the `stream` context.\n* \"stream/upstream\": Indicates the `upstream` block within the `stream` context.\n", + "enum": [ + "main", + "http", + "http/server", + "http/server/location", + "http/upstream", + "stream", + "stream/server", + "stream/upstream" + ], + "x-enum-varnames": [ + "template_context_path_main", + "template_context_path_http", + "template_context_path_http_server", + "template_context_path_http_server_location", + "template_context_path_http_upstream", + "template_context_path_stream", + "template_context_path_stream_server", + "template_context_path_stream_upstream" + ], + "example": "http/server/location" }, - "NapPolicyMetadata": { - "description": "Summary information about NGINX App Protect policy.", + "TemplateImportRequest": { "type": "object", + "description": "A request to import a template into the system. This can be either a *base template* or an *augment template*,\nas determined by the `type` field in the request body.\n\nBase templates define the structure of an NGINX configuration and may include hook points\nfor augment templates using custom Go template functions.\n\nAugment templates are reusable configuration snippets that can be applied to specific NGINX contexts\nwithin a base template, such as `http`, `http/server`, `stream` or `stream/server`.\n\nNginx One supports custom Go template functions for advanced configuration generation.\nSee [Template Functions](https://yourdocs.com/templates/functions) for a complete list of supported functions.\n", "required": [ - "object_id", "name", - "latest" + "file", + "type" ], "properties": { - "object_id": { - "$ref": "#/components/schemas/NapPolicyObjectID" - }, "name": { - "description": "The name of the NGINX App Protect policy.", - "type": "string" + "$ref": "#/components/schemas/TemplateName" }, - "description": { + "file": { "type": "string", - "description": "Some detail on the NGINX App Protect policy." + "description": "A .tar.gz archive containing a template and any necessary supporting files for generating an NGINX configuration.\n\nThe archive must include the following at its root:\n- A template file (e.g., reverse_proxy_base.tmpl) written in valid Go template syntax for NGINX.\n- If the template uses input variables, a schema file is also required. This file defines and validates the expected input data.\n- The schema file could be a JSON schema or YAML (e.g., schema.json, schema.yaml).\n\nFile structure:\n├── reverse_proxy_base.tmpl # Required Go template file\n├── schema.json or schema.yaml # Required only if input variables are used\n", + "format": "binary", + "maxLength": 1000000, + "example": "template.tar.gz" }, - "latest": { - "$ref": "#/components/schemas/NapPolicyVersionMetadata" + "type": { + "$ref": "#/components/schemas/TemplateType" + }, + "description": { + "$ref": "#/components/schemas/TemplateDescription" + }, + "allowed_in_contexts": { + "type": "array", + "description": "Required when type is `augment`. Specifies the full hierarchical context path(s) within the NGINX configuration where the augment template output can be placed.\n", + "items": { + "$ref": "#/components/schemas/TemplateContextPath" + } } } }, - "NapPolicyListResponse": { - "description": "List of all NGINX App Protect policies.", + "TemplatesListResponse": { + "description": "List of all templates.", "allOf": [ { "$ref": "#/components/schemas/PaginationResponse" }, { - "description": "List of NGINX App Protect policies.", + "description": "List of config templates.", "type": "object", "required": [ "items" ], "properties": { "items": { - "description": "An array of NGINX App Protect policy objects.", + "description": "An array of templates.", "type": "array", "items": { - "$ref": "#/components/schemas/NapPolicyObject" + "$ref": "#/components/schemas/TemplateSummary" } } }, "example": { + "total": 101, + "count": 4, + "start_index": 1, + "items_per_page": 100, "items": [ { - "object_id": "pol_-uvR3F2TQGm18jnl7bpaGw", - "name": "test-policy", - "description": "test policy", - "deployments": [ - { - "publication_object_id": "pub_-uvR3F2TQGm18jnl7bpaGw", - "associated_name": "test-instance", - "associated_type": "instance", - "associated_object_id": "inst_-uvR3F2TQGm18jnl7bpaGw", - "status": "deployed", - "enforcement_mode": "blocking", - "policy_version": "2023-12-06 22:37:24", - "policy_version_object_id": "pv_-abc3F2TQGm18jnl7bpaGw", - "deployed_on": "2023-12-06T22:37:24.120114Z" - } + "object_id": "tmpl_-uvR3F2TQGm18jnl7bpaGw", + "latest_template_version_object_id": "tmplv_-uvR3F2TQGm18jnl7bpaGw", + "version": 1, + "latest_version": 1, + "state": "final", + "name": "reverse-proxy", + "description": "A base template for setting up a reverse proxy", + "type": "base", + "allowed_in_contexts": [], + "augment_includes": [ + "http", + "http/server", + "http/upstream", + "http/server/location", + "stream", + "stream/upstream", + "stream/server" ], - "latest": { - "object_id": "pv_-uvR3F2TQGm18jnl7bpaGw", - "version": "2023-12-06 22:37:24", - "created_at": "2023-12-06T22:37:24.120114Z", - "deployment_status": "deployed", - "enforcement_mode": "blocking" - } + "created_at": "2026-09-01T12:00:00Z", + "modified_at": "2026-09-15T14:30:00Z" + }, + { + "object_id": "tmpl_-xeR3F2TQGm18jnl7bpaAw", + "latest_template_version_object_id": "tmplv_-xeR3F2TQGm18jnl7bpaAw", + "version": 1, + "latest_version": 1, + "state": "final", + "name": "gzip", + "description": "Augment template for enabling gzip compression", + "type": "augment", + "allowed_in_contexts": [ + "http", + "http/server" + ], + "augment_includes": [], + "created_at": "2026-09-01T12:00:00Z", + "modified_at": "2026-09-15T14:30:00Z" + }, + { + "object_id": "tmpl_-abR3F2TQGm18jnl7bpaXw", + "latest_template_version_object_id": "tmplv_-abR3F2TQGm18jnl7bpaXw", + "version": 1, + "latest_version": 1, + "state": "final", + "name": "rate-limiting-http", + "description": "Add rate limiting to HTTP requests", + "type": "augment", + "allowed_in_contexts": [ + "http", + "http/server" + ], + "augment_includes": [], + "created_at": "2026-09-01T12:00:00Z", + "modified_at": "2026-09-15T14:30:00Z" + }, + { + "object_id": "tmpl_-cdR3F2TQGm18jnl7bpaZw", + "latest_template_version_object_id": "tmplv_-cdR3F2TQGm18jnl7bpaZw", + "version": 1, + "latest_version": 1, + "state": "final", + "name": "limit-request", + "description": "Limit requests per second for a location", + "type": "augment", + "allowed_in_contexts": [ + "http/server/location" + ], + "augment_includes": [], + "created_at": "2026-09-01T12:00:00Z", + "modified_at": "2026-09-15T14:30:00Z" } ] } } ] }, - "NapPolicyVersionDeployments": { - "type": "object", - "properties": { - "deployments": { - "type": "array", - "items": { - "$ref": "#/components/schemas/NapPolicyVersionDeployment" - } - } - } + "TemplateVersionState": { + "type": "string", + "description": "The state of a template version.\n- `draft`: Version is editable and not yet finalized.\n- `final`: Version is immutable and finalized. Version can't be transitioned back to draft.\n", + "enum": [ + "draft", + "final" + ], + "x-enum-varnames": [ + "template_version_state_draft", + "template_version_state_final" + ], + "example": "final" }, - "NapDeploymentAssociation": { + "TemplateVersionMetadata": { "type": "object", "required": [ - "associated_type", - "associated_object_id", - "associated_name" + "created_at", + "modified_at", + "object_id", + "latest_template_version_object_id", + "latest_version", + "version", + "state" ], "properties": { - "associated_type": { - "$ref": "#/components/schemas/DeploymentAssociatedType" - }, - "associated_object_id": { - "$ref": "#/components/schemas/ObjectID" - }, - "associated_name": { - "$ref": "#/components/schemas/DeploymentAssociatedName" - } - } - }, - "NapDeployment": { - "allOf": [ - { - "$ref": "#/components/schemas/NapDeploymentAssociation" - }, - { - "type": "object", - "description": "Information about a NGINX App Protect policy deployment.\n", - "required": [ - "publication_object_id", - "status", - "deployed_on" - ], - "properties": { - "publication_object_id": { - "$ref": "#/components/schemas/PublicationObjectID" - }, - "status": { - "$ref": "#/components/schemas/NapDeploymentStatus" - }, - "deployed_on": { - "description": "Date and time of the deployment.", - "type": "string", - "format": "date-time" - } - }, - "example": { - "publication_object_id": "pub_-uvR3F2TQGm18jnl7bpaGw", - "associated_name": "test-instance", - "associated_type": "instance", - "associated_object_id": "inst_-uvR3F2TQGm18jnl7bpaGw", - "status": "deployed", - "deployed_on": "2023-12-06T22:37:24.120114Z" - } - } - ] - }, - "NapPolicyVersionDeployment": { - "allOf": [ - { - "$ref": "#/components/schemas/NapDeploymentAssociation" + "created_at": { + "type": "string", + "format": "date-time", + "description": "The creation timestamp of the template." }, - { - "type": "object", - "description": "Information about a NGINX App Protect policy deployment.\n", - "required": [ - "publication_object_id", - "status", - "deployed_on" - ], - "properties": { - "publication_object_id": { - "$ref": "#/components/schemas/PublicationObjectID" - }, - "status": { - "$ref": "#/components/schemas/NapDeploymentStatus" - }, - "deployed_on": { - "description": "Date and time of the deployment.", - "type": "string", - "format": "date-time" - } - }, - "example": { - "publication_object_id": "pub_-uvR3F2TQGm18jnl7bpaGw", - "associated_name": "test-instance", - "associated_type": "instance", - "associated_object_id": "inst_-uvR3F2TQGm18jnl7bpaGw", - "status": "deployed", - "deployed_on": "2023-12-06T22:37:24.120114Z" - } + "modified_at": { + "type": "string", + "format": "date-time", + "description": "The last modification timestamp of the template." + }, + "object_id": { + "$ref": "#/components/schemas/TemplateObjectID" + }, + "latest_template_version_object_id": { + "$ref": "#/components/schemas/TemplateVersionObjectID" + }, + "latest_version": { + "type": "integer", + "description": "The latest version available for the template." + }, + "version": { + "type": "integer", + "description": "The version number of this template." + }, + "state": { + "$ref": "#/components/schemas/TemplateVersionState" } - ] + } }, - "NapPolicyDeployments": { + "TemplateSummaryBase": { + "description": "Base summary of a template object, including its metadata, allowed contexts and augment includes.\n", "type": "object", "required": [ - "deployments" + "name", + "type", + "augment_includes" ], "properties": { - "deployments": { + "name": { + "$ref": "#/components/schemas/TemplateName" + }, + "type": { + "$ref": "#/components/schemas/TemplateType" + }, + "description": { + "$ref": "#/components/schemas/TemplateDescription" + }, + "allowed_in_contexts": { "type": "array", + "description": "Specifies the full hierarchical context path(s) within the NGINX configuration where this template output can be placed.\n\nFor base templates, this list is empty. Instead, refer to `augment_includes` to see where augment output can be injected within the base template.\n", "items": { - "$ref": "#/components/schemas/NapPolicyDeployment" + "$ref": "#/components/schemas/TemplateContextPath" } - } - } - }, - "NapLogProfileDeployments": { - "type": "object", - "properties": { - "deployments": { + }, + "augment_includes": { "type": "array", + "description": "Lists the explicit hierarchical context paths within the NGINX configuration where augment template output can be injected.\n\nEach entry corresponds to a location in the template where an `augment_includes` function is used, indicating a supported point for augment insertion (e.g., \"http/server\", \"stream/server\").\n", "items": { - "$ref": "#/components/schemas/NapLogProfileDeployment" + "$ref": "#/components/schemas/TemplateContextPath" } } } }, - "NapLogProfileDeployment": { - "description": "Detailed information about a NGINX App Protect log-profile deployment.", - "type": "object", + "TemplateSummary": { + "description": "A summary of a template object, including its metadata, allowed contexts and augment includes.\n", "allOf": [ { - "$ref": "#/components/schemas/NapDeployment" + "$ref": "#/components/schemas/TemplateVersionMetadata" }, { - "type": "object", - "required": [ - "nap_release", - "publication_object_id", - "associated_name", - "associated_type", - "associated_object_id", - "status", - "deployed_on" - ], - "properties": { - "nap_release": { - "description": "The compiler version of NGINX App Protect the log profile was deployed with.", - "type": "string" - }, - "latest_deployed": { - "$ref": "#/components/schemas/NapLatestDeployed" - } - } + "$ref": "#/components/schemas/TemplateSummaryBase" } ], "example": { - "nap_release": "5.10.0", - "publication_object_id": "pub_-uvR3F2TQGm18jnl7bpaGw", - "associated_name": "test-instance", - "associated_type": "instance", - "associated_object_id": "inst_-uvR3F2TQGm18jnl7bpaGw", - "status": "deployed", - "deployed_on": "2023-12-06T22:37:24.120114Z", - "latest_deployed": "yes" + "object_id": "tmpl_-uvR3F2TQGm18jnl7bpaGw", + "latest_template_version_object_id": "tmplv_-uvR3F2TQGm18jnl7bpaGw", + "latest_version": 1, + "version": 1, + "state": "final", + "name": "reverse-proxy", + "description": "A base template for setting up a reverse proxy", + "type": "base", + "allowed_in_contexts": [], + "augment_includes": [ + "http", + "http/server", + "http/upstream", + "http/server/location" + ], + "created_at": "2023-09-01T12:00:00Z", + "modified_at": "2023-09-15T14:30:00Z" } }, - "NapPolicyDeployment": { - "description": "Detailed information about a NGINX App Protect policy deployment.", + "TemplateFileData": { "type": "object", + "description": "Details about the file in the template.\n", "required": [ - "publication_object_id", - "associated_object_id", - "associated_name", - "associated_type", - "enforcement_mode", - "status", - "policy_version", - "policy_version_object_id", - "deployed_on" + "name", + "contents", + "file_type", + "file_format", + "mime_type", + "size", + "ctime" ], - "allOf": [ - { - "$ref": "#/components/schemas/NapPolicyVersionDeployment" + "properties": { + "name": { + "type": "string", + "description": "The name of a file inside a template archive (.tar.gz). File names must not be absolute paths or contain directory traversal components. For safety, leading slashes or \"..\" are not allowed.\n", + "minLength": 1, + "maxLength": 255, + "pattern": "^[a-zA-Z0-9_.\\-\\/]+$", + "example": "gzip-http.tmpl" }, - { - "type": "object", - "required": [ - "enforcement_mode", - "policy_version", - "policy_version_object_id" + "contents": { + "type": "string", + "description": "The contents of the file.\n- If `file_format` is \"plain\", this is a UTF-8 encoded string.\n- If `file_format` is \"bytes\", this is a Base64-encoded string.\n", + "maxLength": 1000000 + }, + "file_type": { + "type": "string", + "description": "The contents type of the file.\n* template: The file contains a Go template.\n* schema: The file contains a JSON or YAML schema for validating input data for the template. Optional if the template does not require input variables.\n", + "enum": [ + "template", + "schema" ], - "properties": { - "enforcement_mode": { - "$ref": "#/components/schemas/NapPolicyEnforcementMode" - }, - "policy_version": { - "description": "The version associated with the NGINX App Protect policy.", - "type": "string" - }, - "policy_version_object_id": { - "$ref": "#/components/schemas/NapPolicyVersionObjectID" - } - } - } - ], - "example": { - "publication_object_id": "pub_-uvR3F2TQGm18jnl7bpaGw", - "associated_name": "test-instance", - "associated_type": "instance", - "associated_object_id": "inst_-uvR3F2TQGm18jnl7bpaGw", - "status": "deployed", - "deployed_on": "2023-12-06T22:37:24.120114Z", - "enforcement_mode": "blocking", - "policy_version": "2023-12-06 22:37:24", - "policy_version_object_id": "pv_-abc3F2TQGm18jnl7bpaGw" - } - }, - "NapPolicyDeploymentDetails": { - "type": "object", - "required": [ - "publication_object_id", - "associated_object_id", - "associated_name", - "associated_type", - "enforcement_mode", - "status", - "policy_version", - "policy_version_object_id", - "deployed_on", - "threat_campaign_version", - "attack_signature_version", - "bot_signature_version" - ], - "allOf": [ - { - "$ref": "#/components/schemas/NapPolicyDeployment" + "x-enum-varnames": [ + "template_file_type_template", + "template_file_type_schema" + ] }, - { - "type": "object", - "properties": { - "threat_campaign_version": { - "$ref": "#/components/schemas/NapSignatureVersion" - }, - "attack_signature_version": { - "$ref": "#/components/schemas/NapSignatureVersion" - }, - "bot_signature_version": { - "$ref": "#/components/schemas/NapSignatureVersion" - } - } - } - ], - "example": { - "publication_object_id": "pub_-uvR3F2TQGm18jnl7bpaGw", - "associated_name": "test-instance", - "associated_type": "instance", - "associated_object_id": "inst_-uvR3F2TQGm18jnl7bpaGw", - "status": "deployed", - "policy_version": "2023-12-06 22:37:24", - "policy_version_object_id": "pv_-abc3F2TQGm18jnl7bpaGw", - "deployed_on": "2023-12-06T22:37:24.120114Z", - "enforcement_mode": "blocking", - "threat_campaign_version": "2023.12.06", - "attack_signature_version": "2023.12.06", - "bot_signature_version": "2023.12.06" + "file_format": { + "type": "string", + "description": "The encoding format of the contents in the file for transport.\n\n- `plain`: Human-readable content (plain UTF-8 string).\n- `bytes`: Base64-encoded binary content.\n", + "enum": [ + "plain", + "bytes" + ], + "x-enum-varnames": [ + "template_file_format_plain", + "template_file_format_bytes" + ] + }, + "mime_type": { + "type": "string", + "description": "The MIME type of the file, indicating its content type.\nFor example, `text/plain`, `application/json`, `application/gzip`.\n", + "enum": [ + "text/plain", + "application/json", + "application/yaml" + ] + }, + "size": { + "type": "integer", + "description": "The size of the file, in bytes." + }, + "ctime": { + "type": "string", + "format": "date-time", + "description": "Timestamp when the file was created." + } + }, + "example": { + "name": "nginx.tmpl", + "file_type": "template", + "file_format": "plain", + "mime_type": "text/plain", + "contents": "http {\n {{ augment_includes \"http\" . }}\n\n upstream backend {\n {{- range .upstream_servers }}\n server {{ . }};\n {{- end }}\n }\n\n server {\n listen 80;\n server_name {{ .server_name }};\n\n location / {\n proxy_pass {{ default \"http://backend\" .proxy_pass }};\n }\n }\n}", + "size": 345, + "ctime": "2026-09-01T12:00:00Z" } }, - "NapPolicyDeploymentsListResponse": { - "description": "List of all NGINX App Protect deployments.", + "TemplateCreationRequest": { + "description": "A request payload used to create a new template, including its metadata and associated file contents.", + "type": "object", "allOf": [ { - "$ref": "#/components/schemas/PaginationResponse" + "$ref": "#/components/schemas/TemplateSummaryBase" }, { "type": "object", @@ -12753,39 +15838,53 @@ ], "properties": { "items": { - "description": "An array of NGINX App Protect deployments.", + "description": "A list of files in the template.", "type": "array", "items": { - "$ref": "#/components/schemas/NapPolicyDeploymentDetails" + "$ref": "#/components/schemas/TemplateFileData" } } - }, - "example": { - "items": [ - { - "publication_object_id": "pub_-uvR3F2TQGm18jnl7bpaGw", - "associated_name": "test-instance", - "associated_type": "instance", - "associated_object_id": "inst_-uvR3F2TQGm18jnl7bpaGw", - "status": "deployed", - "policy_version": "2023-12-06 22:37:24", - "policy_version_object_id": "pv_-abc3F2TQGm18jnl7bpaGw", - "deployed_on": "2023-12-06T22:37:24.120114Z", - "enforcement_mode": "blocking", - "threat_campaign_version": "2023.12.06", - "attack_signature_version": "2023.12.06", - "bot_signature_version": "2023.12.06" - } - ] } } - ] + ], + "example": { + "name": "reverse-proxy", + "type": "base", + "allowed_in_contexts": [], + "augment_includes": [ + "http" + ], + "items": [ + { + "name": "nginx.tmpl", + "file_type": "template", + "file_format": "bytes", + "mime_type": "text/plain", + "contents": "aHR0cCB7XG4gIHt7IGF1Z21lbnRfaW5jbHVkZXMgXCJodHRwXCIgLiB9fVxuXG4gdXBzdHJlYW0gYmFja2VuZCB7XG4gIC17LSByYW5nZSAudXBzdHJlYW1fc2VydmVycyB9XG4gICAgc2VydmVyIHsgLiB9O1xuICB7LSBlbmQgfVxuIH1cblxuIHNlcnZlciB7XG4gIGxpc3RlbiA4MDtcbiAgc2VydmVyX25hbWUge3sgLnNlcnZlcl9uYW1lIH19O1xuXG4gIGxvY2F0aW9uIC8ge1xuICAgIHByb3h5X3Bhc3Mge3sgZGVmYXVsdCBcImh0dHA6Ly9iYWNrZW5kXCIgLnByb3h5X3Bhc3MgfX07XG4gIH1cbn1cbiIs", + "size": 1234, + "ctime": "2026-09-01T12:00:00Z" + }, + { + "name": "schema.json", + "file_type": "schema", + "file_format": "bytes", + "mime_type": "application/json", + "contents": "ewogICIkc2NoZW1hIjogImh0dHA6Ly9qc29uLXNjaGVtYS5vcmcvZHJhZnQtMDcvc2NoZW1hIyIsCiAgInR5cGUiOiAib2JqZWN0IiwKICAicHJvcGVydGllcyI6IHsKICAgICJ1cHN0cmVhbV9zZXJ2ZXJzIjogewogICAgICAidHlwZSI6ICJhcnJheSIsCiAgICAgICJpdGVtcyI6IHsKICAgICAgICAidHlwZSI6ICJzdHJpbmciLAogICAgICAgICJmb3JtYXQiOiAiaG9zdG5hbWUiLAogICAgICAgICJwYXR0ZXJuIjogIl5bYS1aQS1aMC05Li1dKyg6WzAtOV0rKT8kIgogICAgICB9LAogICAgICAibWluSXRlbXMiOiAxCiAgICB9LAogICAgInNlcnZlcl9uYW1lIjogewogICAgICAidHlwZSI6ICJzdHJpbmciLAogICAgICAicGF0dGVybiI6ICJeW2EtWkEtWjAtOS4tXSskIgogICAgfSwKICAgICJwcm94eV9wYXNzIjogewogICAgICAidHlwZSI6ICJzdHJpbmciLAogICAgICAiZm9ybWF0IjogInVyaSIKICAgIH0KICB9LAogICJyZXF1aXJlZCI6IFsidXBzdHJlYW1fc2VydmVycyIsICJzZXJ2ZXJfbmFtZSJdLAogICJhZGRpdGlvbmFsUHJvcGVydGllcyI6IGZhbHNlCn0=", + "size": 456, + "ctime": "2026-09-01T12:00:00Z" + } + ] + } }, - "NapLogProfileDeploymentsListResponse": { - "description": "List of all NGINX App Protect log profile deployments.", + "TemplateDetailsResponse": { + "description": "Full detailed response about an existing template object including summary and file contents.", + "type": "object", "allOf": [ { - "$ref": "#/components/schemas/PaginationResponse" + "$ref": "#/components/schemas/TemplateVersionMetadata" + }, + { + "$ref": "#/components/schemas/TemplateSummaryBase" }, { "type": "object", @@ -12794,2604 +15893,2639 @@ ], "properties": { "items": { - "description": "An array of NGINX App Protect log profile deployments.", + "description": "A list of files in the template.", "type": "array", "items": { - "$ref": "#/components/schemas/NapLogProfileDeployment" + "$ref": "#/components/schemas/TemplateFileData" } } - }, - "example": { - "items": [ - { - "nap_release": "5.10.0", - "publication_object_id": "pub_-uvR3F2TQGm18jnl7bpaGw", - "associated_name": "test-instance", - "associated_type": "instance", - "associated_object_id": "inst_-uvR3F2TQGm18jnl7bpaGw", - "status": "deployed", - "deployed_on": "2023-12-06T22:37:24.120114Z", - "latest_deployed": "yes" - } - ] } } - ] - }, - "NapPolicyVersionMetadata": { - "type": "object", - "description": "Summary information about the specific NGINX App Protect policy version.", - "required": [ - "object_id", - "version", - "enforcement_mode", - "created_at" ], - "properties": { - "object_id": { - "$ref": "#/components/schemas/NapPolicyVersionObjectID" - }, - "version": { - "$ref": "#/components/schemas/NapSignatureVersion" - }, - "enforcement_mode": { - "$ref": "#/components/schemas/NapPolicyEnforcementMode" - }, - "created_at": { - "description": "The date and time when the NGINX App Protect policy version was created.", - "type": "string", - "format": "date-time" - } + "example": { + "object_id": "tmpl_-uvR3F2TQGm18jnl7bpaGw", + "created_at": "2026-09-01T12:00:00Z", + "modified_at": "2026-09-15T14:30:00Z", + "latest_template_version_object_id": "tmplv_-uvR3F2TQGm18jnl7bpaGw", + "version": 1, + "latest_version": 1, + "state": "final", + "name": "reverse-proxy", + "type": "base", + "allowed_in_contexts": [], + "augment_includes": [ + "http" + ], + "items": [ + { + "name": "nginx.tmpl", + "file_type": "template", + "file_format": "bytes", + "mime_type": "text/plain", + "contents": "aHR0cCB7XG4gIHt7IGF1Z21lbnRfaW5jbHVkZXMgXCJodHRwXCIgLiB9fVxuXG4gdXBzdHJlYW0gYmFja2VuZCB7XG4gIC17LSByYW5nZSAudXBzdHJlYW1fc2VydmVycyB9XG4gICAgc2VydmVyIHsgLiB9O1xuICB7LSBlbmQgfVxuIH1cblxuIHNlcnZlciB7XG4gIGxpc3RlbiA4MDtcbiAgc2VydmVyX25hbWUge3sgLnNlcnZlcl9uYW1lIH19O1xuXG4gIGxvY2F0aW9uIC8ge1xuICAgIHByb3h5X3Bhc3Mge3sgZGVmYXVsdCBcImh0dHA6Ly9iYWNrZW5kXCIgLnByb3h5X3Bhc3MgfX07XG4gIH1cbn1cbiIs", + "size": 1234, + "ctime": "2026-09-01T12:00:00Z" + }, + { + "name": "schema.json", + "file_type": "schema", + "file_format": "bytes", + "mime_type": "application/json", + "contents": "ewogICIkc2NoZW1hIjogImh0dHA6Ly9qc29uLXNjaGVtYS5vcmcvZHJhZnQtMDcvc2NoZW1hIyIsCiAgInR5cGUiOiAib2JqZWN0IiwKICAicHJvcGVydGllcyI6IHsKICAgICJ1cHN0cmVhbV9zZXJ2ZXJzIjogewogICAgICAidHlwZSI6ICJhcnJheSIsCiAgICAgICJpdGVtcyI6IHsKICAgICAgICAidHlwZSI6ICJzdHJpbmciLAogICAgICAgICJmb3JtYXQiOiAiaG9zdG5hbWUiLAogICAgICAgICJwYXR0ZXJuIjogIl5bYS1aQS1aMC05Li1dKyg6WzAtOV0rKT8kIgogICAgICB9LAogICAgICAibWluSXRlbXMiOiAxCiAgICB9LAogICAgInNlcnZlcl9uYW1lIjogewogICAgICAidHlwZSI6ICJzdHJpbmciLAogICAgICAicGF0dGVybiI6ICJeW2EtWkEtWjAtOS4tXSskIgogICAgfSwKICAgICJwcm94eV9wYXNzIjogewogICAgICAidHlwZSI6ICJzdHJpbmciLAogICAgICAiZm9ybWF0IjogInVyaSIKICAgIH0KICB9LAogICJyZXF1aXJlZCI6IFsidXBzdHJlYW1fc2VydmVycyIsICJzZXJ2ZXJfbmFtZSJdLAogICJhZGRpdGlvbmFsUHJvcGVydGllcyI6IGZhbHNlCn0=", + "size": 456, + "ctime": "2026-09-01T12:00:00Z" + } + ] } }, - "NapPolicyVersionDetails": { - "description": "Detailed information about NGINX App Protect policy version.", + "TemplateValuesRequest": { + "type": "object", + "description": "Key-value pairs for template rendering.", + "additionalProperties": true + }, + "TemplateSubmissionRequest": { "type": "object", + "description": "Defines a request to render an NGINX configuration by combining a single base template \nwith zero or more augment templates.\n\n### Validations and Constraints:\n- All templates referenced by Object ID must be available in the system before submission.\n- Only one base template can be submitted.\n- The base template must explicitly use custom Go function `augment_includes (\"\", .)` to apply `augments`.\n- Its not required to include all augments in the request that base template supports.\n- The order of augments in the list determines the order in which they are rendered and applied.\n- Each augment must specify its `target_context`, indicating where it should be applied in \n the base template.\n- Input values for each template are passed independently via the `values` \n object, and validated against each template’s Schema.\n\n### Processing:\n- The `base_template` defines the starting point of the NGINX configuration rendering.\n- `conf_path` determines where the rendered configuration from base and augments should be placed within the NGINX directory structure.\n- Each `augment` template is applied in the order provided, inserted at the appropriate target context\n using the `augment_includes (\"\", .)` function declared in the base template.\n- The system validates that each augment is compatible with the specified target context.\n- The final composed configuration is validated to ensure correctness and prevent conflicts or misconfigurations.\n\n### External Template Documentation:\nFor more information on template functions and best practices, refer to:\n - [Template Function Reference](https://yourdocs.com/templates/functions)\n - [Template Authoring Guide](https://yourdocs.com/templates/guide)\n", "required": [ - "policy", - "object_id", - "version", - "enforcement_mode", - "created_at" + "conf_path", + "base_template", + "augments" ], - "allOf": [ - { - "$ref": "#/components/schemas/NapPolicyVersionMetadata" + "properties": { + "description": { + "type": "string", + "description": "Description of the submission, required when not rendering as preview only." }, - { - "$ref": "#/components/schemas/NapPolicy" + "target_object_ids": { + "type": "array", + "description": "The target object ID(s) for submitting the rendered configuration.\n", + "items": { + "$ref": "#/components/schemas/ObjectID" + } }, - { - "$ref": "#/components/schemas/NapPolicyVersionDeployments" - } - ] - }, - "NapPolicyVersionObject": { - "description": "Summary information about NGINX App Protect policy version.", - "allOf": [ - { - "$ref": "#/components/schemas/NapPolicyVersionMetadata" + "conf_path": { + "$ref": "#/components/schemas/ConfigPath" }, - { - "$ref": "#/components/schemas/NapPolicyVersionDeployments" + "base_template": { + "$ref": "#/components/schemas/BaseTemplateSubmissionRequest" }, - { - "type": "object", - "required": [ - "latest" - ], - "properties": { - "latest": { - "description": "Indicates whether the NGINX App Protect policy version is latest. Default (`false`) returns the current policy. \nWhen set to `true`, returns the latest policy.\n", - "type": "boolean", - "default": false - } + "augments": { + "type": "array", + "description": "Ordered list of augment templates to apply to the base template.\nAugments are rendered in the order provided.\n", + "items": { + "$ref": "#/components/schemas/AugmentTemplateSubmissionRequest" } + }, + "payloads": { + "$ref": "#/components/schemas/NginxConfigPayloads" } - ] - }, - "NapPolicyVersionsListResponse": { - "description": "List of all NGINX App Protect versions.", - "allOf": [ - { - "$ref": "#/components/schemas/PaginationResponse" + }, + "example": { + "conf_path": "/etc/nginx/nginx.conf", + "base_template": { + "object_id": "tmplv_-uvR3F2TQGm18jnl7bpaGw", + "values": { + "upstream_servers": [ + "10.0.0.1:8080", + "10.0.0.2:8080" + ], + "server_name": "example.com" + } }, - { - "type": "object", - "required": [ - "items" - ], - "properties": { - "items": { - "description": "An array of NGINX App Protect version objects.", - "type": "array", - "items": { - "$ref": "#/components/schemas/NapPolicyVersionObject" - } + "augments": [ + { + "object_id": "tmplv_-uvR3F2TQGm18jnl7bpaGw", + "target_context": "http/upstream", + "values": { + "upstream_servers": [ + "10.0.0.1:8080", + "10.0.0.2:8080" + ], + "server_name": "example.com" } }, - "example": { - "items": [ + { + "object_id": "tmplv_-xeR3F2TQGm18jnl7bpaAw", + "target_context": "http", + "values": { + "enabled": "on", + "types": "text/plain application/json" + } + }, + { + "object_id": "tmplv_-abR3F2TQGm18jnl7bpaXw", + "target_context": "http", + "values": { + "zone_name": "req_limit", + "memory": "10m", + "rate": "10r/s" + } + }, + { + "object_id": "tmplv_-cdR3F2TQGm18jnl7bpaZw", + "target_context": "http/server", + "values": { + "zone_name": "req_limit", + "burst": 5 + }, + "child_augments": [ { - "version": "2023-12-06 22:37:24", - "object_id": "pv_-uvR3F2TQGm18jnl7bpaGw", - "created_at": "2023-12-06T22:37:24.120114Z", - "enforcement_mode": "blocking", - "latest": false + "object_id": "tmplv_-cdR3F2TQGm18jnl7bpaZw", + "target_context": "http/server/location", + "values": { + "zone_name": "req_limit", + "burst": 5 + } } ] } - } - ] + ] + } }, - "NapLogProfileListResponse": { - "allOf": [ - { - "$ref": "#/components/schemas/PaginationResponse" + "BaseTemplateSubmissionRequest": { + "type": "object", + "required": [ + "object_id" + ], + "properties": { + "object_id": { + "$ref": "#/components/schemas/TemplateVersionObjectID" }, - { - "type": "object", - "required": [ - "items" + "values": { + "$ref": "#/components/schemas/TemplateValuesRequest" + } + }, + "example": { + "object_id": "tmplv_-uvR3F2TQGm18jnl7bpaGw", + "values": { + "upstream_servers": [ + "10.0.0.1:8080", + "10.0.0.2:8080" ], - "properties": { - "items": { - "description": "An array of NGINX App Protect log profiles.", - "type": "array", - "items": { - "$ref": "#/components/schemas/NapLogProfileObject" - } - } - } + "server_name": "example.com" } - ] + } }, - "NapLogProfileObjectDetails": { - "allOf": [ - { - "$ref": "#/components/schemas/NapLogProfileObject" + "AugmentTemplateSubmissionRequest": { + "type": "object", + "description": "Defines a request to apply an augment template to a specific target context within the base template.\n\nThis extends the `BaseTemplateSubmissionRequest`. Additionally adding,\n- `target_context`: Specifies the context within the base template where this augment should be applied.\n- `child_augments`: Optionally, an ordered list of nested augment templates to apply as children of this template.\n", + "required": [ + "object_id", + "target_context" + ], + "properties": { + "object_id": { + "$ref": "#/components/schemas/TemplateVersionObjectID" }, - { - "type": "object", - "required": [ - "config" - ], - "properties": { - "config": { - "description": "The NGINX App Protect log profile configuration.", - "type": "string" - } - } + "values": { + "$ref": "#/components/schemas/TemplateValuesRequest" }, - { - "type": "object", - "required": [ - "bundles" - ], - "properties": { - "bundles": { - "description": "Compiled NGINX APP Protect log profile bundles for this specific log profile. \nShows compilation status of the latest log profile contents across different NAP release versions.\n", - "type": "array", - "items": { - "$ref": "#/components/schemas/NapCompileStatus" - } - } + "target_context": { + "$ref": "#/components/schemas/TemplateContextPath" + }, + "child_augments": { + "type": "array", + "description": "Ordered list of nested augment templates to apply as children of this template.\n", + "items": { + "$ref": "#/components/schemas/AugmentTemplateSubmissionRequest" } } - ], + }, "example": { - "created_at": "2026-01-16T21:12:51.843434Z", - "hash": "oxiWKPqR/soi4MQCgVnW8KHt8Jk68AqCeQcQ1sed4Dk=", - "modified_at": "2026-01-16T21:12:51.843434Z", - "name": "test-log-profiles", - "object_id": "lp_XYxnZgVYQFKire4M1KcVVQ", - "config": "eyJsb2dfc3RyZWFtIjogIntmb3JtYXQgY29tYmluZWQgZXg=", - "deployments": [ - { - "nap_release": "5.10.0", - "publication_object_id": "pub_-uvR3F2TQGm18jnl7bpaGw", - "associated_name": "test-instance", - "associated_type": "instance", - "associated_object_id": "inst_-uvR3F2TQGm18jnl7bpaGw", - "status": "deployed", - "deployed_on": "2023-12-06T22:37:24.120114Z", - "latest_deployed": "yes" - } - ], - "bundles": [ - { - "nap_release": "5.10.0", - "status": "succeeded", - "created_at": "2026-01-13T18:54:19.140336Z", - "modified_at": "2026-01-13T18:56:31.264956Z" - }, + "object_id": "tmplv_-xeR3F2TQGm18jnl7bpaAw", + "target_context": "http/server", + "values": { + "enabled": "on", + "types": "text/plain application/json" + }, + "child_augments": [ { - "nap_release": "5.9.0", - "status": "succeeded", - "created_at": "2026-01-13T18:54:19.140336Z", - "modified_at": "2026-01-13T18:56:31.264956Z" + "object_id": "tmplv_-cdR3F2TQGm18jnl7bpaZw", + "target_context": "http/server/location", + "values": { + "zone_name": "req_limit", + "burst": 5 + } } ] } }, - "NapLogProfileObject": { - "allOf": [ - { - "$ref": "#/components/schemas/NapLogProfileDeployments" + "PreviewNginxConfig": { + "type": "object", + "description": "The rendered NGINX configuration preview, along with any errors encountered during rendering.\n", + "required": [ + "config" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/NginxConfigObject" }, - { - "$ref": "#/components/schemas/NapLogProfileMetadata" + "errors": { + "type": "array", + "description": "List of NGINX config parse errors encountered during rendering.", + "items": { + "$ref": "#/components/schemas/NginxConfigParseError" + } } + } + }, + "TemplateSubmissionResponse": { + "description": "Details of a template submission and all target(s) status results.", + "required": [ + "object_id", + "target_results" ], - "example": { - "created_at": "2026-01-16T21:12:51.843434Z", - "hash": "oxiWKPqR/soi4MQCgVnW8KHt8Jk68AqCeQcQ1sed4Dk=", - "modified_at": "2026-01-16T21:12:51.843434Z", - "name": "test-log-profiles", - "object_id": "lp_XYxnZgVYQFKire4M1KcVVQ", - "deployments": [ - { - "nap_release": "5.10.0", - "publication_object_id": "pub_-uvR3F2TQGm18jnl7bpaGw", - "associated_name": "test-instance", - "associated_type": "instance", - "associated_object_id": "inst_-uvR3F2TQGm18jnl7bpaGw", - "status": "deployed", - "deployed_on": "2023-12-06T22:37:24.120114Z", - "latest_deployed": "yes" + "properties": { + "object_id": { + "$ref": "#/components/schemas/ObjectID" + }, + "target_results": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TemplateSubmissionTargetResult" } - ] + } } }, - "NapLogProfileMetadata": { + "TemplateSubmissionTargetResult": { "type": "object", "required": [ - "name", - "object_id", - "hash", - "modified_at", - "created_at" + "target_object_id" ], "properties": { - "name": { - "type": "string", - "description": "The name of the NGINX App Protect log profile." + "target_object_id": { + "$ref": "#/components/schemas/ObjectID" }, - "object_id": { - "$ref": "#/components/schemas/NapLogProfileObjectID" + "staged_config_status": { + "$ref": "#/components/schemas/StagedConfigCreation" }, - "hash": { - "type": "string", - "description": "The hash value of the NGINX App Protect log profile configs." + "csg_publication_status": { + "$ref": "#/components/schemas/ConfigSyncGroupPublication" }, - "description": { - "description": "Optional field to describe the NGINX App Protect log profile.", + "instance_publication_status": { + "$ref": "#/components/schemas/PublicationInstance" + } + } + }, + "NginxConfigParseError": { + "type": "object", + "description": "Details about an error encountered during NGINX configuration rendering.", + "required": [ + "file", + "error" + ], + "properties": { + "file": { "type": "string", - "minLength": 5, - "maxLength": 256 + "description": "The name of the file where the error occurred." }, - "created_at": { - "type": "string", - "format": "date-time", - "description": "The date and time when the log profile was created." + "line": { + "type": "integer", + "description": "The line number in the file where the error occurred." }, - "modified_at": { + "error": { "type": "string", - "format": "date-time", - "description": "The date and time when the log profile was last modified." + "description": "A human-readable error message describing the issue." } + }, + "example": { + "file": "nginx.conf", + "line": 1, + "error": "\"upstream\" directive is not allowed here in /etc/nginx/nginx.conf:1" } }, - "NapGlobalSettingsListResponse": { + "TemplateSubmissionObjectID": { + "description": "A globally unique identifier for a template submission.", + "type": "string", + "format": "object_id", + "pattern": "^tmplsm_.*", + "x-go-type": "objects.ID", + "x-go-type-import": { + "name": "objects", + "path": "gitlab.com/f5/nginx/one/saas/control-plane/pkg/collections/objects" + }, + "example": "tmplsm_frBobKIAQ_21grAwV83VYz" + }, + "TemplateSubmissionListResponse": { + "description": "List of template submissions.", "allOf": [ { "$ref": "#/components/schemas/PaginationResponse" }, { + "description": "List of template submissions.", "type": "object", "required": [ "items" ], "properties": { "items": { - "description": "An array of NGINX App Protect global settings.", + "description": "An array of template submissions.", "type": "array", "items": { - "$ref": "#/components/schemas/NapGlobalSettingMetadata" + "$ref": "#/components/schemas/TemplateSubmissionSummary" } } } } ] }, - "NapGlobalSettingGetResponse": { - "allOf": [ - { - "$ref": "#/components/schemas/NapGlobalSettingMetadata" - }, - { - "type": "object", - "required": [ - "config" - ], - "properties": { - "config": { - "description": "The NGINX App Protect global setting configuration.", - "type": "string" - } - } - } - ] - }, - "NapGlobalSettingMetadata": { + "TemplateSubmissionSummary": { + "description": "Summary of a template submission.", "type": "object", "required": [ - "name", - "object_id" + "object_id", + "target_object_ids", + "created_at", + "modified_at", + "templates" ], "properties": { - "name": { - "type": "string", - "description": "The name of the NGINX App Protect global setting object." + "object_id": { + "$ref": "#/components/schemas/TemplateSubmissionObjectID" }, "description": { - "description": "Optional field to describe the NGINX App Protect global setting object.", "type": "string", - "minLength": 5, - "maxLength": 256 + "description": "Description of the submission." }, - "object_id": { - "$ref": "#/components/schemas/NapGlobalSettingObjectID" + "target_object_ids": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ObjectID" + } + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The creation timestamp of the submission." + }, + "modified_at": { + "type": "string", + "format": "date-time", + "description": "The last modification timestamp of the submission." + }, + "templates": { + "type": "array", + "description": "The templates associated with this submission (base + augments).", + "items": { + "$ref": "#/components/schemas/TemplateSubmissionTemplateSummary" + } } + }, + "example": { + "object_id": "tmplsm_frBobKIAQ_21grAwV83VYz", + "description": "Production reverse-proxy rollout", + "target_object_ids": [ + "sc_2CjPVkxoTcubUMOG9jD6yg" + ], + "created_at": "2023-09-01T12:00:00Z", + "modified_at": "2023-09-15T14:30:00Z", + "templates": [ + { + "template_object_id": "tmpl_-uvR3F2TQGm18jnl7bpaGw", + "template_version_object_id": "tmplv_kX9mR4pLSNqZwT1y6vHdJA", + "name": "reverse-proxy", + "type": "base", + "state": "final", + "version": 1, + "latest_version": 2, + "latest_template_version_object_id": "tmplv_Qm7nP8wKR2eYbA3x5cFgVw", + "allowed_in_contexts": [], + "augment_includes": [ + "http", + "http/server" + ], + "created_at": "2023-09-01T12:00:00Z", + "modified_at": "2023-09-15T14:30:00Z" + } + ] } }, - "NapLogProfileCreateRequest": { - "description": "Create NGINX App Protect log profile.", + "TemplateSubmissionTemplateSummary": { + "description": "A template entry within a submission, including the specific version used.", "type": "object", "required": [ + "template_object_id", + "template_version_object_id", "name", - "config" + "type", + "state", + "version", + "latest_version", + "latest_template_version_object_id", + "created_at", + "modified_at" ], "properties": { + "template_object_id": { + "$ref": "#/components/schemas/TemplateObjectID" + }, + "template_version_object_id": { + "$ref": "#/components/schemas/TemplateVersionObjectID", + "description": "The specific template version used in this submission." + }, "name": { - "description": "The name of the NGINX App Protect log profile.", "type": "string", - "minLength": 1, - "maxLength": 128 + "description": "The name of the template." }, "description": { - "description": "Optional field to describe the NGINX App Protect log profile.", "type": "string", - "minLength": 5, - "maxLength": 256 + "description": "The description of the template." }, - "config": { - "description": "The NGINX App Protect log profile configuration.", + "type": { + "$ref": "#/components/schemas/TemplateType" + }, + "state": { + "$ref": "#/components/schemas/TemplateVersionState" + }, + "version": { + "type": "integer", + "description": "The version number of the template version used in this submission." + }, + "latest_version": { + "type": "integer", + "description": "The latest version number generated for this template." + }, + "latest_template_version_object_id": { + "$ref": "#/components/schemas/TemplateVersionObjectID" + }, + "allowed_in_contexts": { + "type": "array", + "description": "The contexts this template is allowed in (augment templates only).", + "items": { + "$ref": "#/components/schemas/TemplateContextPath" + } + }, + "augment_includes": { + "type": "array", + "description": "The augment context paths this template includes.", + "items": { + "$ref": "#/components/schemas/TemplateContextPath" + } + }, + "created_at": { "type": "string", - "format": "base64", - "maxLength": 3145728 + "format": "date-time", + "description": "The creation timestamp of the template." + }, + "modified_at": { + "type": "string", + "format": "date-time", + "description": "The last modification timestamp of the template." } + }, + "example": { + "template_object_id": "tmpl_-uvR3F2TQGm18jnl7bpaGw", + "template_version_object_id": "tmplv_kX9mR4pLSNqZwT1y6vHdJA", + "name": "reverse-proxy", + "description": "A base template for setting up a reverse proxy", + "type": "base", + "state": "final", + "version": 1, + "latest_version": 2, + "latest_template_version_object_id": "tmplv_Qm7nP8wKR2eYbA3x5cFgVw", + "allowed_in_contexts": [], + "augment_includes": [ + "http", + "http/server", + "http/upstream" + ], + "created_at": "2023-09-01T12:00:00Z", + "modified_at": "2023-09-15T14:30:00Z" } }, - "NapLogProfileUpdateRequest": { - "description": "Update NGINX App Protect log profile.", + "FilterNameTemplates": { + "type": "string", + "description": "Keywords for config templates filters.\n", + "enum": [ + "name", + "type", + "object_id", + "allowed_in_contexts" + ], + "x-enum-varnames": [ + "filter_name_templates_name", + "filter_name_templates_type", + "filter_name_templates_object_id", + "filter_name_templates_allowed_in_contexts" + ] + }, + "StagedConfigCreation": { "type": "object", "required": [ - "config" + "status" + ], + "properties": { + "object_id": { + "$ref": "#/components/schemas/StagedConfigObjectID" + }, + "name": { + "type": "string" + }, + "status": { + "description": "Creation status for the staged config:\n* `failed` - The creation failed.\n* `succeeded` - The creation was successful.\n", + "type": "string", + "enum": [ + "failed", + "succeeded" + ], + "x-enum-varnames": [ + "staged_config_status_failed", + "staged_config_status_succeeded" + ] + } + } + }, + "EventRequestOutcome": { + "type": "string", + "description": "Binary outcome of WAF processing for the request.", + "enum": [ + "passed", + "rejected" + ], + "x-enum-varnames": [ + "request_outcome_passed", + "request_outcome_rejected" + ] + }, + "SignatureAccuracy": { + "type": "string", + "description": "Confidence level that the signature accurately identifies the attack.", + "enum": [ + "low", + "medium", + "high" + ], + "x-enum-varnames": [ + "signature_accuracy_low", + "signature_accuracy_medium", + "signature_accuracy_high" + ] + }, + "SignatureRisk": { + "type": "string", + "description": "Risk level of the attack identified by the signature.", + "enum": [ + "low", + "medium", + "high", + "critical" + ], + "x-enum-varnames": [ + "signature_risk_low", + "signature_risk_medium", + "signature_risk_high", + "signature_risk_critical" + ] + }, + "RequestStatus": { + "type": "string", + "description": "WAF enforcement decision for the request.", + "enum": [ + "blocked", + "alerted", + "passed" + ], + "x-enum-varnames": [ + "request_status_blocked", + "request_status_alerted", + "request_status_passed" + ] + }, + "AttacksDimensionField": { + "type": "string", + "description": "Available dimensions for grouping and filtering attack analytics.\n", + "enum": [ + "request_status", + "request_outcome_reason", + "request_method", + "ip", + "country", + "policy", + "url", + "response_code", + "hostname", + "threat_campaign" ], - "properties": { - "name": { - "description": "The name of the NGINX App Protect log profile.", - "type": "string", - "minLength": 1, - "maxLength": 128 - }, - "description": { - "description": "Optional field to describe describing the NGINX App Protect log profile.", - "type": "string", - "minLength": 5, - "maxLength": 256 - }, - "config": { - "description": "The NGINX App Protect log profile configuration.", - "type": "string", - "format": "base64", - "minLength": 5, - "maxLength": 3145728 - } - } + "x-enum-varnames": [ + "attacks_dimension_request_status", + "attacks_dimension_request_outcome_reason", + "attacks_dimension_request_method", + "attacks_dimension_ip", + "attacks_dimension_country", + "attacks_dimension_policy", + "attacks_dimension_url", + "attacks_dimension_response_code", + "attacks_dimension_hostname", + "attacks_dimension_threat_campaign" + ] }, - "NapPolicyBulkRequest": { - "type": "array", - "items": { - "$ref": "#/components/schemas/NapPolicyBulkRequestData" - }, - "minItems": 1, - "maxItems": 50, - "example": [ - { - "object_id": "pol_-uvR3F2TQGm18jnl7bpaGw", - "action": "delete" - }, - { - "object_id": "pol_PL0c1XodRemmzVEjiXSsTg", - "action": "delete" - } + "AttacksTimeSeriesDimensionField": { + "type": "string", + "description": "Dimensions available for time-series grouping.\nLimited to fixed enum dimensions that can be efficiently aggregated per time bucket.\n", + "enum": [ + "request_status", + "request_outcome_reason" + ], + "x-enum-varnames": [ + "attacks_ts_dimension_request_status", + "attacks_ts_dimension_request_outcome_reason" ] }, - "NapPolicyBulkRequestData": { - "type": "object", - "description": "Part of bulk operation on a Nap policy, only `delete` is supported.", - "required": [ - "action", - "object_id" + "Resolution": { + "type": "string", + "description": "Time bucket size for aggregation. If not specified, auto-selected based on time range:\n* < 1 hour: 1m\n* 1-6 hours: 5m\n* 6-24 hours: 15m\n* 1-7 days: 1h\n* > 7 days: 1d\n", + "enum": [ + "1m", + "5m", + "15m", + "1h", + "1d" ], - "properties": { - "object_id": { - "$ref": "#/components/schemas/NapPolicyObjectID" - }, - "action": { - "$ref": "#/components/schemas/BulkRequestAction" - } - }, - "example": { - "object_id": "pol_-uvR3F2TQGm18jnl7bpaGw", - "action": "delete" - } + "x-enum-varnames": [ + "resolution_1m", + "resolution_5m", + "resolution_15m", + "resolution_1h", + "resolution_1d" + ], + "example": "15m" }, - "NapBulkResponse": { - "description": "The Nap policy bulk outcome.", - "type": "array", - "items": { - "$ref": "#/components/schemas/BulkRequestObjectStatus" - } + "FilterOperator": { + "type": "string", + "description": "Filter operators that can be applied to a given list of dimension values.\n* `=` - Equals (uses first value only)\n* `!=` - Not equals (uses first value only)\n* `in` - Value is in the list (uses all values)\n* `not` - Value is not in the list (uses all values)\n", + "enum": [ + "=", + "!=", + "in", + "not" + ], + "x-enum-varnames": [ + "filter_operator_equal", + "filter_operator_not_equal", + "filter_operator_in", + "filter_operator_not" + ] }, - "NapSignatureMeta": { - "required": [ - "signature_id", - "name", - "attack_type" + "SortOrderDirection": { + "type": "string", + "description": "Sort direction for query results.", + "enum": [ + "asc", + "desc" ], - "properties": { - "name": { - "type": "string" - }, - "signature_id": { - "type": "integer" - }, - "attack_type": { - "type": "string" - } - } + "default": "desc", + "x-enum-varnames": [ + "order_direction_asc", + "order_direction_desc" + ] }, - "NapSignature": { - "description": "Detail information for NGINX App Protect signatures. Note: `description` is omitted for list operation.\n", - "allOf": [ - { - "$ref": "#/components/schemas/NapSignatureMeta" - }, - { - "type": "object", - "required": [ - "signature_type", - "risk", - "accuracy", - "has_cve", - "modified_at", - "systems" - ], - "properties": { - "accuracy": { - "default": "low", - "enum": [ - "high", - "low", - "medium" - ], - "x-enum-varnames": [ - "nap_signature_accuracy_high", - "nap_signature_accuracy_low", - "nap_signature_accuracy_medium" - ], - "type": "string" - }, - "description": { - "type": "string" - }, - "has_cve": { - "default": false, - "type": "boolean" - }, - "modified_at": { - "type": "string", - "format": "date-time", - "description": "The date and time when the signature was last modified." - }, - "references": { - "items": { - "required": [ - "type", - "value" - ], - "properties": { - "type": { - "default": "nessus", - "enum": [ - "bugtraq", - "cve", - "nessus", - "url" - ], - "x-enum-varnames": [ - "nap_signature_references_type_bugtrag", - "nap_signature_references_type_cve", - "nap_signature_references_type_nessus", - "nap_signature_references_type_url" - ], - "type": "string" - }, - "value": { - "type": "string" - } - }, - "type": "object" - }, - "type": "array" - }, - "risk": { - "default": "low", - "enum": [ - "high", - "low", - "medium" - ], - "x-enum-varnames": [ - "nap_signature_risk_high", - "nap_signature_risk_low", - "nap_signature_risk_medium" - ], - "type": "string" - }, - "signature_type": { - "default": "request", - "enum": [ - "request", - "response" - ], - "type": "string", - "x-enum-varnames": [ - "nap_signature_signature_type_request", - "nap_signature_signature_type_response" - ] - }, - "systems": { - "items": { - "type": "string" - }, - "type": "array" - } - } - } + "AnalyticsFilterField": { + "type": "string", + "description": "Field names available for filtering analytics queries.\nThis is a superset of all group_by dimensions. You can filter by any field,\neven when not grouping by it.\n", + "enum": [ + "request_outcome", + "request_outcome_reason", + "request_method", + "response_code", + "ip", + "country", + "url", + "policy", + "instance_object_id", + "csg_object_id", + "threat_campaign", + "hostname", + "request_host", + "support_id", + "violation_rating", + "request_status", + "accuracy", + "risk", + "signature_id", + "signature_name", + "cve", + "violation", + "sub_violation", + "context", + "context_key", + "context_value" ], - "example": { - "signature_id": 123456789, - "name": "Example Signature", - "description": "This is an example signature.", - "signature_type": "request", - "attack_type": "SQL Injection", - "risk": "high", - "accuracy": "medium", - "has_cve": true, - "modified_at": "2023-10-01T12:00:00Z", - "references": [ - { - "type": "cve", - "value": "CVE-2023-12345" - } - ], - "systems": [ - "System A" - ] - } + "x-enum-varnames": [ + "analytics_filter_field_request_outcome", + "analytics_filter_field_request_outcome_reason", + "analytics_filter_field_request_method", + "analytics_filter_field_response_code", + "analytics_filter_field_ip", + "analytics_filter_field_country", + "analytics_filter_field_url", + "analytics_filter_field_policy", + "analytics_filter_field_instance_object_id", + "analytics_filter_field_csg_object_id", + "analytics_filter_field_threat_campaign", + "analytics_filter_field_hostname", + "analytics_filter_field_request_host", + "analytics_filter_field_support_id", + "analytics_filter_field_violation_rating", + "analytics_filter_field_request_status", + "analytics_filter_field_accuracy", + "analytics_filter_field_risk", + "analytics_filter_field_signature_id", + "analytics_filter_field_signature_name", + "analytics_filter_field_cve", + "analytics_filter_field_violation", + "analytics_filter_field_sub_violation", + "analytics_filter_field_context", + "analytics_filter_field_context_key", + "analytics_filter_field_context_value" + ] }, - "NapSignatureSet": { + "AnalyticsFilter": { "type": "object", + "description": "A single filter condition.\nGeneric schema supporting both attacks and signature analytics filtering.\n", "required": [ - "object_id", - "name", - "type", - "category", - "signature_count", - "accuracy", - "default_alarm", - "default_block", - "default_learn", - "systems", - "modified_at" + "field", + "operator", + "values" ], "properties": { - "object_id": { - "$ref": "#/components/schemas/NapSignatureSetObjectID" + "field": { + "$ref": "#/components/schemas/AnalyticsFilterField" }, - "name": { - "type": "string" + "operator": { + "$ref": "#/components/schemas/FilterOperator" }, - "accuracy": { + "values": { "type": "array", - "items": { - "type": "string", - "enum": [ - "low", - "medium", - "high" - ], - "x-enum-varnames": [ - "nap_signature_set_accuracy_low", - "nap_signature_set_accuracy_medium", - "nap_signature_set_accuracy_high" - ] - } - }, - "signature_count": { - "type": "integer" - }, - "category": { - "enum": [ - "User-defined", - "Basic", - "Attack Type Specific" - ], - "x-enum-varnames": [ - "nap_signature_set_category_user_defined", - "nap_signature_set_category_basic", - "nap_signature_set_category_attack_type_specific" - ], - "type": "string" - }, - "default_alarm": { - "default": true, - "type": "boolean" - }, - "default_block": { - "default": true, - "type": "boolean" - }, - "default_learn": { - "default": true, - "type": "boolean" - }, - "filter": { - "properties": { - "accuracy_filter": { - "default": "ge", - "enum": [ - "all", - "eq", - "ge", - "le" - ], - "x-enum-varnames": [ - "nap_signature_set_filter_accuracy_filter_all", - "nap_signature_set_filter_accuracy_filter_eq", - "nap_signature_set_filter_accuracy_filter_ge", - "nap_signature_set_filter_accuracy_filter_le" - ], - "type": "string" - }, - "accuracy_value": { - "default": "all", - "enum": [ - "all", - "high", - "low", - "medium" - ], - "x-enum-varnames": [ - "nap_signature_set_filter_accuracy_value_all", - "nap_signature_set_filter_accuracy_value_high", - "nap_signature_set_filter_accuracy_value_low", - "nap_signature_set_filter_accuracy_value_medium" - ], - "type": "string" - }, - "attack_type": { - "properties": { - "name": { - "type": "string" - } - }, - "type": "object" - }, - "has_cve": { - "default": "all", - "enum": [ - "all", - "no", - "yes" - ], - "x-enum-varnames": [ - "nap_signature_set_filter_have_cve_all", - "nap_signature_set_filter_have_cve_no", - "nap_signature_set_filter_have_cve_yes" - ], - "type": "string" - }, - "modified_at_filter": { - "default": "all", - "enum": [ - "after", - "all", - "before" - ], - "x-enum-varnames": [ - "nap_signature_set_filter_modified_at_filter_after", - "nap_signature_set_filter_modified_at_filter_all", - "nap_signature_set_filter_modified_at_filter_before" - ], - "type": "string" - }, - "modified_at_value": { - "default": "1970-01-01", - "type": "string" - }, - "risk_filter": { - "default": "eq", - "enum": [ - "all", - "eq", - "ge", - "le" - ], - "x-enum-varnames": [ - "nap_signature_set_filter_risk_filter_all", - "nap_signature_set_filter_risk_filter_eq", - "nap_signature_set_filter_risk_filter_ge", - "nap_signature_set_filter_risk_filter_le" - ], - "type": "string" - }, - "risk_value": { - "default": "low", - "enum": [ - "all", - "high", - "low", - "medium" - ], - "x-enum-varnames": [ - "nap_signature_set_filter_risk_value_all", - "nap_signature_set_filter_risk_value_high", - "nap_signature_set_filter_risk_value_low", - "nap_signature_set_filter_risk_value_medium" - ], - "type": "string" - }, - "signature_type": { - "default": "request", - "enum": [ - "all", - "request", - "response" - ], - "x-enum-varnames": [ - "nap_signature_set_filter_signature_type_all", - "nap_signature_set_filter_signature_type_request", - "nap_signature_set_filter_signature_type_response" - ], - "type": "string" - }, - "user_defined_filter": { - "default": "all", - "enum": [ - "all", - "no", - "yes" - ], - "x-enum-varnames": [ - "nap_signature_set_filter_user_defined_filter_all", - "nap_signature_set_filter_user_defined_filter_no", - "nap_signature_set_filter_user_defined_filter_yes" - ], - "type": "string" - } - }, - "type": "object" - }, - "modified_at": { - "type": "string", - "format": "date-time", - "description": "The date and time when the signature-set was last modified." - }, - "systems": { + "description": "Values to filter by.\n- For `=` and `!=`: only the first value is used\n- For `in` and `not`: all values are used\n", "items": { "type": "string" }, - "type": "array" - }, - "type": { - "default": "filter-based", + "minItems": 1, + "example": [ + "blocked" + ] + } + } + }, + "AnalyticsOrderBy": { + "type": "object", + "description": "Specifies the sort order for dynamic dimension results.\n", + "properties": { + "field": { + "type": "string", + "description": "Field to sort by.\n- `count`: Sort by count (default)\n- `value`: Sort alphabetically by field value\n", "enum": [ - "filter-based", - "manual" - ], - "x-enum-varnames": [ - "nap_signature_set_type_filter_based", - "nap_signature_set_type_manual" + "count", + "value" ], - "type": "string" + "default": "count" + }, + "direction": { + "$ref": "#/components/schemas/SortOrderDirection" } }, "example": { - "default_block": true, - "default_learn": true, - "signature_count": 0, - "filter": { - "accuracy_value": "all", - "accuracy_filter": "all", - "attack_type": { - "name": "XML External Entities (XXE)" - }, - "risk_filter": "all", - "has_cve": "all", - "user_defined_filter": "all", - "risk_value": "all", - "modified_at_filter": "all", - "signature_type": "request" + "field": "count", + "direction": "desc" + } + }, + "BaseQueryRequest": { + "type": "object", + "description": "Base query request with common fields for both attacks and signature analytics.\nShared properties for all analytical query types.\n", + "required": [ + "start_time" + ], + "properties": { + "start_time": { + "type": "string", + "description": "Beginning of the time range (inclusive).\nAccepts ISO 8601 format (`2024-01-15T00:00:00Z`) or relative offset (`now-24h`, `now-1d`).\n", + "example": "now-24h" }, - "assign_to_policy_by_default": false, - "default_alarm": true, - "accuracy": [], - "type": "filter-based", - "name": "XML External Entities (XXE) Signatures", - "object_id": "sigset_-ZMshmi83MBL97dr5d0a9w", - "category": "User-defined", - "modified_at": "2023-08-10T16:59:15Z", - "systems": [] + "end_time": { + "type": "string", + "description": "End of the time range (exclusive).\nAccepts ISO 8601 format (`2024-01-15T00:00:00Z`) or relative offset (`now-24h`, `now-1d`).\n", + "default": "now", + "example": "now" + }, + "limit": { + "type": "integer", + "description": "Maximum items per dynamic dimension array (1-1000).\nDoes not apply to fixed enum dimensions.\n", + "minimum": 1, + "maximum": 1000, + "default": 100, + "example": 10 + } } }, - "NapSignatureListResponse": { + "AttacksQueryRequest": { "allOf": [ { - "$ref": "#/components/schemas/PaginationResponse" + "$ref": "#/components/schemas/BaseQueryRequest" }, { "type": "object", - "required": [ - "items" - ], + "description": "Request body for querying attack analytics.\n", "properties": { - "items": { - "description": "An array of NGINX App Protect signatures.", + "group_by": { + "allOf": [ + { + "$ref": "#/components/schemas/AttacksDimensionField" + }, + { + "description": "Dimension to aggregate results by.\n\n**Fixed enum dimensions** (returned as objects with known keys):\n* `request_status` - blocked, alerted, passed\n* `request_method` - GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH\n\n**Simple array dimensions** (returned as arrays with code/count):\n* `response_code` - HTTP response codes\n\n**Dynamic dimensions** (returned as arrays with cross-dimension context):\n* `ip`, `country`, `policy`, `url`, `hostname`\n\n**Response behavior:**\n- If omitted: Returns `total` count only\n- If specified: Returns dimensional breakdown, `total` is omitted\n", + "example": "request_status" + } + ] + }, + "filter": { "type": "array", + "description": "Pre-aggregation filter conditions.\nAll filters are combined with AND logic.\nUse the `in` operator to achieve `OR` within a single dimension.\n", "items": { - "$ref": "#/components/schemas/NapSignature" - } + "$ref": "#/components/schemas/AnalyticsFilter" + }, + "default": [] + }, + "order_by": { + "$ref": "#/components/schemas/AnalyticsOrderBy" } } } ] }, - "NapSignatureSetListResponse": { + "AttacksTimeSeriesQueryRequest": { "allOf": [ { - "$ref": "#/components/schemas/PaginationResponse" + "$ref": "#/components/schemas/BaseQueryRequest" }, { "type": "object", - "required": [ - "items" - ], + "description": "Request body for querying attack analytics time series.\n", "properties": { - "items": { - "description": "An array of NGINX App Protect signature sets.", + "resolution": { + "$ref": "#/components/schemas/Resolution" + }, + "group_by": { + "allOf": [ + { + "$ref": "#/components/schemas/AttacksTimeSeriesDimensionField" + }, + { + "description": "Dimension to break down time-series by.\nLimited to fixed enum dimensions for performance.\n\n* `request_status` - Returns `blocked`, `alerted`, `passed` series\n* `request_outcome_reason` - Returns the underlying reason for the outcome.\n\n**Common `request_outcome_reason` values:**\n- `SECURITY_WAF_OK`: Legitimate request, no violations.\n- `SECURITY_WAF_VIOLATION`: Request blocked due to signature or protocol violation.\n- `SECURITY_WAF_FLAGGED`: Violation detected, but request allowed (Transparent/Alert-only mode).\n- `SECURITY_WAF_VIOLATION_TRANSPARENT`: Request would have been blocked, but the policy/signature is in staging/transparent mode.\n- `SECURITY_NGINX_VIOLATION`: Request rejected due to NGINX-level constraints (e.g., malformed headers).\n- `SECURITY_WAF_BYPASS`: Request was explicitly allowed due to an allow-list or bypass rule.\n\n**Response behavior:**\n- If omitted: Returns `total` series only\n- If specified: Returns dimensional breakdown, `total` is omitted\n", + "example": "request_status" + } + ] + }, + "filter": { "type": "array", + "description": "Pre-aggregation filter conditions.\nAll filters are combined with AND logic.\nUse the `in` operator to achieve `OR` within a single dimension.\n", "items": { - "$ref": "#/components/schemas/NapSignatureSet" - } + "$ref": "#/components/schemas/AnalyticsFilter" + }, + "default": [] } } } ] }, - "FilterNameNapLogProfile": { - "type": "string", - "description": "Keywords for NGINX App Protect log profile filters.\n", - "enum": [ - "name", - "object_id", - "deployment_status" - ], - "x-enum-varnames": [ - "filter_name_nap_log_profile_name", - "filter_name_nap_log_profile_object_id", - "filter_name_nap_log_profile_deployment_status" - ] - }, - "FilterNameNapLogProfileDeployment": { - "type": "string", - "description": "Keywords for NGINX App Protect log profile deployment filters.\nWhen filtering on `type`, only the following `filter_values` are supported:\n * instance\n * config_sync_group\nWhen filtering on `status`, only the following `filter_values` are supported:\n * deployed\n * deploying\n * failed\n", - "enum": [ - "name", - "type", - "status", - "object_id" - ], - "x-enum-varnames": [ - "filter_name_nap_deployment_name", - "filter_name_nap_deployment_type", - "filter_name_nap_deployment_status", - "filter_name_nap_deployment_object_id" - ] - }, - "FilterNameNapPolicy": { - "type": "string", - "description": "Keywords for NGINX App Protect policy filters.\nWhen filtering on `enforcement_mode`, only the following `filter_values` are supported:\n * blocking\n * transparent\nWhen filtering on `object_id`, both NAP Policy and NAP Policy version object id prefixes are supported.\n", - "enum": [ - "name", - "enforcement_mode", - "object_id", - "deployment_enforcement_mode", - "deployment_status" - ], - "x-enum-varnames": [ - "filter_name_nap_policy_name", - "filter_name_nap_policy_enforcement_mode", - "filter_name_nap_policy_object_id", - "filter_name_nap_policy_deployment_enforcement_mode", - "filter_name_nap_policy_deployment_status" - ] - }, - "FilterNameNapPolicyDeployment": { - "type": "string", - "description": "Keywords for NGINX App Protect deployment filters.\nWhen filtering on `type`, only the following `filter_values` are supported:\n * instance\n * config_sync_group\nWhen filtering on `status`, only the following `filter_values` are supported:\n * deployed\n * deploying\n * failed\n", - "enum": [ - "name", - "type", - "policy_version", - "status", - "object_id" - ], - "x-enum-varnames": [ - "filter_name_nap_deployment_name", - "filter_name_nap_deployment_type", - "filter_name_nap_deployment_policy_version", - "filter_name_nap_deployment_status", - "filter_name_nap_deployment_object_id" - ] - }, - "FilterNameNapPolicyVersion": { - "type": "string", - "description": "Keywords for NGINX App Protect policy version filters.\nWhen filtering on `deployment_status`, only the following `filter_values` are supported:\n * deployed\n * not_deployed\n * deploying\n * failed\nWhen filtering on `enforcement_mode`, only the following `filter_values` are supported:\n * blocking\n * transparent\n", - "enum": [ - "deployment_status", - "enforcement_mode", - "object_id" - ], - "x-enum-varnames": [ - "filter_name_nap_policy_version_deployment_status", - "filter_name_nap_policy_version_enforcement_mode", - "filter_name_nap_policy_version_object_id" - ] - }, - "NapGlobalSettingObjectID": { - "description": "A globally unique identifier for the App Protect global settings object.", - "type": "string", - "format": "object_id", - "pattern": "^gs_.*", - "x-go-type": "objects.ID", - "x-go-type-import": { - "name": "objects", - "path": "gitlab.com/f5/nginx/one/saas/control-plane/pkg/collections/objects" - } - }, - "TemplateName": { - "type": "string", - "description": "The name of the template.\nMust be suitable for use as a file name and as an NGINX configuration include.\nOnly alphanumeric characters, underscores, dashes, and dots are allowed.\nNo spaces, slashes, or special characters.\n", - "minLength": 1, - "maxLength": 255, - "pattern": "^[a-zA-Z0-9][a-zA-Z0-9_.-]*$", - "example": "reverse-proxy" - }, - "TemplateDescription": { - "type": "string", - "description": "A human-readable description of the template.", - "example": "A base template for setting up a reverse proxy" - }, - "TemplateObjectID": { - "description": "A globally unique identifier for template.", - "type": "string", - "format": "object_id", - "pattern": "^tmpl_.*", - "x-go-type": "objects.ID", - "x-go-type-import": { - "name": "objects", - "path": "gitlab.com/f5/nginx/one/saas/control-plane/pkg/collections/objects" + "QueryMetadata": { + "type": "object", + "description": "Query metadata returned with analytics responses.\nReflects the actual time range and resolution used for the query.\n", + "properties": { + "start_time": { + "type": "string", + "format": "date-time", + "description": "The start of the query time range (inclusive)." + }, + "end_time": { + "type": "string", + "format": "date-time", + "description": "The end of the query time range (exclusive)." + }, + "resolution": { + "allOf": [ + { + "$ref": "#/components/schemas/Resolution" + }, + { + "description": "The time bucket size used for time-series queries.\nOnly present in time-series responses.\n" + } + ] + } }, - "example": "tmpl_-uvR3F2TQGm18jnl7bpaGw" + "example": { + "start_time": "2024-01-15T00:00:00Z", + "end_time": "2024-01-15T23:59:59Z", + "resolution": "1h" + } }, - "TemplateVersionObjectID": { - "description": "A globally unique identifier for the template version.", - "type": "string", - "format": "object_id", - "pattern": "^tmplv_.*", - "x-go-type": "objects.ID", - "x-go-type-import": { - "name": "objects", - "path": "gitlab.com/f5/nginx/one/saas/control-plane/pkg/collections/objects" + "RequestStatusCountsResponse": { + "type": "object", + "description": "Attack counts grouped by WAF enforcement status.\nEach property represents a distinct status with its count.\n", + "properties": { + "blocked": { + "type": "integer", + "description": "Count of attacks that were blocked by the WAF." + }, + "alerted": { + "type": "integer", + "description": "Count of attacks that were alerted but not blocked (transparent mode)." + }, + "passed": { + "type": "integer", + "description": "Count of attacks that passed through with no violations." + } }, - "example": "tmplv_-ayR3F2TQGm18jnl7bpaGw" - }, - "TemplateType": { - "type": "string", - "description": "The type of the template.\n- `base`: A base template that defines the structure of an NGINX configuration.\n- `augment`: An augment template that extends or modifies an existing NGINX configuration defined by a base template.\n", - "enum": [ - "base", - "augment" - ], - "x-enum-varnames": [ - "template_type_base", - "template_type_augment" - ], - "example": "base" + "example": { + "blocked": 1200, + "alerted": 200, + "passed": 100 + } }, - "TemplateContextPath": { - "type": "string", - "description": "Specifies the full hierarchical context path within the NGINX configuration, using '/' as a separator.\n* \"main\": Refers to the top-level context of the NGINX configuration.\n* \"http\": Indicates the `http` block within the main context.\n* \"http/server\": Indicates the `server` block within the `http` context.\n* \"http/server/location\": Indicates the `location` block within the `server` context of the `http` block.\n* \"http/upstream\": Indicates the `upstream` block within the `http` context.\n* \"stream\": Indicates the `stream` block within the main context.\n* \"stream/server\": Indicates the `server` block within the `stream` context.\n* \"stream/upstream\": Indicates the `upstream` block within the `stream` context.\n", - "enum": [ - "main", - "http", - "http/server", - "http/server/location", - "http/upstream", - "stream", - "stream/server", - "stream/upstream" - ], - "x-enum-varnames": [ - "template_context_path_main", - "template_context_path_http", - "template_context_path_http_server", - "template_context_path_http_server_location", - "template_context_path_http_upstream", - "template_context_path_stream", - "template_context_path_stream_server", - "template_context_path_stream_upstream" - ], - "example": "http/server/location" + "RequestOutcomeReasonCountsResponse": { + "type": "object", + "description": "Total counts grouped by the underlying request outcome reason for the enforcement decision.\n", + "properties": { + "SECURITY_WAF_OK": { + "type": "integer", + "description": "Total requests passed with no security violations.", + "example": 1024 + }, + "SECURITY_WAF_VIOLATION": { + "type": "integer", + "description": "Total requests blocked due to a policy or signature violation.", + "example": 88 + }, + "SECURITY_WAF_FLAGGED": { + "type": "integer", + "description": "Total violations detected but allowed (Policy in Transparent/Alert mode).", + "example": 11 + }, + "SECURITY_WAF_VIOLATION_TRANSPARENT": { + "type": "integer", + "description": "Total violations detected but allowed (Individual signature in Staging).", + "example": 2 + }, + "SECURITY_NGINX_VIOLATION": { + "type": "integer", + "description": "Total requests rejected due to NGINX-level parsing errors.", + "example": 5 + }, + "SECURITY_WAF_BYPASS": { + "type": "integer", + "description": "Total requests explicitly allowed via allow-lists or bypass rules.", + "example": 0 + } + } }, - "TemplateImportRequest": { + "RequestMethodCountsResponse": { "type": "object", - "description": "A request to import a template into the system. This can be either a *base template* or an *augment template*,\nas determined by the `type` field in the request body.\n\nBase templates define the structure of an NGINX configuration and may include hook points\nfor augment templates using custom Go template functions.\n\nAugment templates are reusable configuration snippets that can be applied to specific NGINX contexts\nwithin a base template, such as `http`, `http/server`, `stream` or `stream/server`.\n\nNginx One supports custom Go template functions for advanced configuration generation.\nSee [Template Functions](https://yourdocs.com/templates/functions) for a complete list of supported functions.\n", - "required": [ - "name", - "file", - "type" - ], + "description": "Attack counts grouped by HTTP request method.\nEach property represents an HTTP method with its count.\n", "properties": { - "name": { - "$ref": "#/components/schemas/TemplateName" + "get": { + "type": "integer", + "description": "Count of attacks using GET method." }, - "file": { - "type": "string", - "description": "A .tar.gz archive containing a template and any necessary supporting files for generating an NGINX configuration.\n\nThe archive must include the following at its root:\n- A template file (e.g., reverse_proxy_base.tmpl) written in valid Go template syntax for NGINX.\n- If the template uses input variables, a schema file is also required. This file defines and validates the expected input data.\n- The schema file could be a JSON schema or YAML (e.g., schema.json, schema.yaml).\n\nFile structure:\n├── reverse_proxy_base.tmpl # Required Go template file\n├── schema.json or schema.yaml # Required only if input variables are used\n", - "format": "binary", - "maxLength": 1000000, - "example": "template.tar.gz" + "post": { + "type": "integer", + "description": "Count of attacks using POST method." }, - "type": { - "$ref": "#/components/schemas/TemplateType" + "put": { + "type": "integer", + "description": "Count of attacks using PUT method." }, - "description": { - "$ref": "#/components/schemas/TemplateDescription" + "delete": { + "type": "integer", + "description": "Count of attacks using DELETE method." }, - "allowed_in_contexts": { - "type": "array", - "description": "Required when type is `augment`. Specifies the full hierarchical context path(s) within the NGINX configuration where the augment template output can be placed.\n", - "items": { - "$ref": "#/components/schemas/TemplateContextPath" - } + "patch": { + "type": "integer", + "description": "Count of attacks using PATCH method." + }, + "connect": { + "type": "integer", + "description": "Count of attacks using CONNECT method." + }, + "head": { + "type": "integer", + "description": "Count of attacks using HEAD method." + }, + "options": { + "type": "integer", + "description": "Count of attacks using OPTIONS method." + }, + "trace": { + "type": "integer", + "description": "Count of attacks using TRACE method." } + }, + "example": { + "get": 800, + "post": 500, + "put": 50 } }, - "TemplatesListResponse": { - "description": "List of all templates.", - "allOf": [ - { - "$ref": "#/components/schemas/PaginationResponse" + "AccuracyCountsResponse": { + "type": "object", + "description": "Signature hit counts grouped by accuracy level.\nEach property represents an accuracy level with its count.\n", + "properties": { + "low": { + "type": "integer", + "description": "Count of signature hits with low accuracy." }, - { - "description": "List of config templates.", - "type": "object", - "required": [ - "items" - ], - "properties": { - "items": { - "description": "An array of templates.", - "type": "array", - "items": { - "$ref": "#/components/schemas/TemplateSummary" - } - } - }, - "example": { - "total": 101, - "count": 4, - "start_index": 1, - "items_per_page": 100, - "items": [ - { - "object_id": "tmpl_-uvR3F2TQGm18jnl7bpaGw", - "latest_template_version_object_id": "tmplv_-uvR3F2TQGm18jnl7bpaGw", - "version": 1, - "latest_version": 1, - "state": "final", - "name": "reverse-proxy", - "description": "A base template for setting up a reverse proxy", - "type": "base", - "allowed_in_contexts": [], - "augment_includes": [ - "http", - "http/server", - "http/upstream", - "http/server/location", - "stream", - "stream/upstream", - "stream/server" - ], - "created_at": "2026-09-01T12:00:00Z", - "modified_at": "2026-09-15T14:30:00Z" - }, - { - "object_id": "tmpl_-xeR3F2TQGm18jnl7bpaAw", - "latest_template_version_object_id": "tmplv_-xeR3F2TQGm18jnl7bpaAw", - "version": 1, - "latest_version": 1, - "state": "final", - "name": "gzip", - "description": "Augment template for enabling gzip compression", - "type": "augment", - "allowed_in_contexts": [ - "http", - "http/server" - ], - "augment_includes": [], - "created_at": "2026-09-01T12:00:00Z", - "modified_at": "2026-09-15T14:30:00Z" - }, - { - "object_id": "tmpl_-abR3F2TQGm18jnl7bpaXw", - "latest_template_version_object_id": "tmplv_-abR3F2TQGm18jnl7bpaXw", - "version": 1, - "latest_version": 1, - "state": "final", - "name": "rate-limiting-http", - "description": "Add rate limiting to HTTP requests", - "type": "augment", - "allowed_in_contexts": [ - "http", - "http/server" - ], - "augment_includes": [], - "created_at": "2026-09-01T12:00:00Z", - "modified_at": "2026-09-15T14:30:00Z" - }, - { - "object_id": "tmpl_-cdR3F2TQGm18jnl7bpaZw", - "latest_template_version_object_id": "tmplv_-cdR3F2TQGm18jnl7bpaZw", - "version": 1, - "latest_version": 1, - "state": "final", - "name": "limit-request", - "description": "Limit requests per second for a location", - "type": "augment", - "allowed_in_contexts": [ - "http/server/location" - ], - "augment_includes": [], - "created_at": "2026-09-01T12:00:00Z", - "modified_at": "2026-09-15T14:30:00Z" - } - ] - } + "medium": { + "type": "integer", + "description": "Count of signature hits with medium accuracy." + }, + "high": { + "type": "integer", + "description": "Count of signature hits with high accuracy." } - ] + }, + "example": { + "low": 150, + "medium": 420, + "high": 700 + } }, - "TemplateVersionState": { - "type": "string", - "description": "The state of a template version.\n- `draft`: Version is editable and not yet finalized.\n- `final`: Version is immutable and finalized. Version can't be transitioned back to draft.\n", - "enum": [ - "draft", - "final" - ], - "x-enum-varnames": [ - "template_version_state_draft", - "template_version_state_final" + "RiskCountsResponse": { + "type": "object", + "description": "Signature hit counts grouped by risk level.\nEach property represents a risk level with its count.\n", + "properties": { + "low": { + "type": "integer", + "description": "Count of signature hits with low risk." + }, + "medium": { + "type": "integer", + "description": "Count of signature hits with medium risk." + }, + "high": { + "type": "integer", + "description": "Count of signature hits with high risk." + }, + "critical": { + "type": "integer", + "description": "Count of signature hits with critical risk." + } + }, + "example": { + "low": 200, + "medium": 350, + "high": 520, + "critical": 200 + } + }, + "ResponseCodeItem": { + "type": "object", + "description": "Attack counts for a specific HTTP response code.\n", + "required": [ + "code", + "count" ], - "example": "final" + "properties": { + "code": { + "type": "string", + "description": "HTTP response code (e.g., \"403\", \"200\", \"500\").", + "example": "403" + }, + "count": { + "type": "integer", + "description": "Number of attacks resulting in this response code." + } + }, + "example": { + "code": "403", + "count": 450 + } }, - "TemplateVersionMetadata": { + "DistinctCounts": { "type": "object", + "description": "Cross-dimension counts providing context about the attacks for a given dimension value.\nEach field represents a COUNT(DISTINCT ...) aggregation.\n\nFor example, when grouping by IP address:\n- `ips` will be 1 (the IP itself)\n- `urls` shows how many different URLs were targeted from this IP\n- `violations` shows how many different violation types were triggered\n- `policies` shows how many different WAF policies were matched\n", "required": [ - "created_at", - "modified_at", - "object_id", - "latest_template_version_object_id", - "latest_version", - "version", - "state" + "ips", + "urls", + "violations", + "policies" ], "properties": { - "created_at": { - "type": "string", - "format": "date-time", - "description": "The creation timestamp of the template." - }, - "modified_at": { - "type": "string", - "format": "date-time", - "description": "The last modification timestamp of the template." + "ips": { + "type": "integer", + "description": "Count of distinct source IP addresses associated with this dimension value." }, - "object_id": { - "$ref": "#/components/schemas/TemplateObjectID" + "urls": { + "type": "integer", + "description": "Count of distinct URLs targeted." }, - "latest_template_version_object_id": { - "$ref": "#/components/schemas/TemplateVersionObjectID" + "violations": { + "type": "integer", + "description": "Count of distinct violation types detected." }, - "latest_version": { + "policies": { "type": "integer", - "description": "The latest version available for the template." + "description": "Count of distinct WAF policies that were triggered." + } + }, + "example": { + "ips": 15, + "urls": 8, + "violations": 12, + "policies": 3 + } + }, + "DimensionItem": { + "type": "object", + "description": "A single item in a dimensional breakdown for dynamic dimensions.\n", + "required": [ + "value", + "count", + "distinct" + ], + "properties": { + "value": { + "type": "string", + "description": "The dimension value being grouped. Content depends on the `group_by` dimension:\n- `ip`: Client IP address (e.g., \"203.0.113.42\")\n- `country`: ISO 3166-1 alpha-2 country code (e.g., \"US\")\n- `url`: Request URL path (e.g., \"/api/login\")\n- `policy`: WAF policy name (e.g., \"strict-policy\")\n" }, - "version": { + "count": { "type": "integer", - "description": "The version number of this template." + "description": "Total number of attacks for this dimension value within the queried time range.\n" }, - "state": { - "$ref": "#/components/schemas/TemplateVersionState" + "distinct": { + "$ref": "#/components/schemas/DistinctCounts" + }, + "country": { + "type": "string", + "maxLength": 2, + "description": "ISO 3166-1 alpha-2 country code for the IP address.\nOnly present when `group_by` is `ip`.\n" } + }, + "example": { + "value": "203.0.113.42", + "count": 450, + "distinct": { + "ips": 1, + "urls": 3, + "violations": 5, + "policies": 1 + }, + "country": "US" } }, - "TemplateSummaryBase": { - "description": "Base summary of a template object, including its metadata, allowed contexts and augment includes.\n", + "AttacksQueryResponse": { "type": "object", + "description": "Response for attack analytics query.\n\n**Response behavior:**\n- Without `group_by`: Returns `total` count and `threat_campaigns` (distinct count)\n- With `group_by`: Returns dimensional breakdown only (e.g., `request_status`), `total` and `threat_campaigns` are omitted\n\nThe `total`/`threat_campaigns` and dimensional breakdowns are mutually exclusive.\n", "required": [ - "name", - "type", - "augment_includes" + "query_metadata" ], "properties": { - "name": { - "$ref": "#/components/schemas/TemplateName" + "query_metadata": { + "$ref": "#/components/schemas/QueryMetadata" }, - "type": { - "$ref": "#/components/schemas/TemplateType" + "total": { + "type": "integer", + "description": "Total attack count for the query. Only present when no `group_by` is specified.\n" }, - "description": { - "$ref": "#/components/schemas/TemplateDescription" + "threat_campaigns": { + "type": "integer", + "description": "Count of distinct threat campaigns in the queried time range.\nOnly present when no `group_by` is specified.\n" }, - "allowed_in_contexts": { + "request_status": { + "$ref": "#/components/schemas/RequestStatusCountsResponse" + }, + "request_outcome_reason": { + "$ref": "#/components/schemas/RequestOutcomeReasonCountsResponse" + }, + "request_method": { + "$ref": "#/components/schemas/RequestMethodCountsResponse" + }, + "ip": { "type": "array", - "description": "Specifies the full hierarchical context path(s) within the NGINX configuration where this template output can be placed.\n\nFor base templates, this list is empty. Instead, refer to `augment_includes` to see where augment output can be injected within the base template.\n", + "description": "Attack counts grouped by client IP address. Sorted by count descending.", "items": { - "$ref": "#/components/schemas/TemplateContextPath" + "$ref": "#/components/schemas/DimensionItem" } }, - "augment_includes": { + "country": { "type": "array", - "description": "Lists the explicit hierarchical context paths within the NGINX configuration where augment template output can be injected.\n\nEach entry corresponds to a location in the template where an `augment_includes` function is used, indicating a supported point for augment insertion (e.g., \"http/server\", \"stream/server\").\n", + "description": "Attack counts grouped by source country. Sorted by count descending.", "items": { - "$ref": "#/components/schemas/TemplateContextPath" + "$ref": "#/components/schemas/DimensionItem" + } + }, + "policy": { + "type": "array", + "description": "Attack counts grouped by WAF policy name. Sorted by count descending.", + "items": { + "$ref": "#/components/schemas/DimensionItem" + } + }, + "url": { + "type": "array", + "description": "Attack counts grouped by request URL. Sorted by count descending.", + "items": { + "$ref": "#/components/schemas/DimensionItem" + } + }, + "response_code": { + "type": "array", + "description": "Attack counts grouped by HTTP response code. Sorted by count descending.", + "items": { + "$ref": "#/components/schemas/ResponseCodeItem" + } + }, + "hostname": { + "type": "array", + "description": "Attack counts grouped by NGINX instance hostname. Sorted by count descending.", + "items": { + "$ref": "#/components/schemas/DimensionItem" + } + }, + "threat_campaign": { + "type": "array", + "description": "Attack counts grouped by threat campaign name. Sorted by count descending.", + "items": { + "$ref": "#/components/schemas/DimensionItem" } } } }, - "TemplateSummary": { - "description": "A summary of a template object, including its metadata, allowed contexts and augment includes.\n", - "allOf": [ - { - "$ref": "#/components/schemas/TemplateVersionMetadata" + "TimeSeriesDataPoint": { + "type": "object", + "description": "A single data point in a time series for a given dimension.\n", + "required": [ + "timestamp", + "count" + ], + "properties": { + "timestamp": { + "type": "string", + "format": "date-time", + "description": "The start time of this bucket." }, - { - "$ref": "#/components/schemas/TemplateSummaryBase" + "count": { + "type": "integer", + "description": "The count for this time bucket.\nRepresents the pivot entity type:\n- **For attacks endpoint**: Count of attack events\n- **For signatures endpoint**: Count of signature hits (pattern occurrences)\n" } - ], + }, "example": { - "object_id": "tmpl_-uvR3F2TQGm18jnl7bpaGw", - "latest_template_version_object_id": "tmplv_-uvR3F2TQGm18jnl7bpaGw", - "latest_version": 1, - "version": 1, - "state": "final", - "name": "reverse-proxy", - "description": "A base template for setting up a reverse proxy", - "type": "base", - "allowed_in_contexts": [], - "augment_includes": [ - "http", - "http/server", - "http/upstream", - "http/server/location" - ], - "created_at": "2023-09-01T12:00:00Z", - "modified_at": "2023-09-15T14:30:00Z" + "timestamp": "2024-01-15T00:00:00Z", + "count": 120 } }, - "TemplateFileData": { + "RequestStatusTimeSeries": { "type": "object", - "description": "Details about the file in the template.\n", - "required": [ - "name", - "contents", - "file_type", - "file_format", - "mime_type", - "size", - "ctime" - ], + "description": "Time-series data grouped by WAF enforcement status.\nEach property contains an array of data points for that status.\n", "properties": { - "name": { - "type": "string", - "description": "The name of a file inside a template archive (.tar.gz). File names must not be absolute paths or contain directory traversal components. For safety, leading slashes or \"..\" are not allowed.\n", - "minLength": 1, - "maxLength": 255, - "pattern": "^[a-zA-Z0-9_.\\-\\/]+$", - "example": "gzip-http.tmpl" + "blocked": { + "type": "array", + "description": "Time series of blocked attack counts.", + "items": { + "$ref": "#/components/schemas/TimeSeriesDataPoint" + } }, - "contents": { - "type": "string", - "description": "The contents of the file.\n- If `file_format` is \"plain\", this is a UTF-8 encoded string.\n- If `file_format` is \"bytes\", this is a Base64-encoded string.\n", - "maxLength": 1000000 + "alerted": { + "type": "array", + "description": "Time series of alerted attack counts (transparent mode).", + "items": { + "$ref": "#/components/schemas/TimeSeriesDataPoint" + } }, - "file_type": { - "type": "string", - "description": "The contents type of the file.\n* template: The file contains a Go template.\n* schema: The file contains a JSON or YAML schema for validating input data for the template. Optional if the template does not require input variables.\n", - "enum": [ - "template", - "schema" - ], - "x-enum-varnames": [ - "template_file_type_template", - "template_file_type_schema" - ] + "passed": { + "type": "array", + "description": "Time series of passed attack counts (no violations).", + "items": { + "$ref": "#/components/schemas/TimeSeriesDataPoint" + } + } + } + }, + "RequestOutcomeReasonTimeSeries": { + "type": "object", + "description": "Time-series data grouped by the specific outcome reason for the enforcement decision.\nEach property contains an array of data points representing that specific reason's count over time.\n", + "properties": { + "SECURITY_WAF_OK": { + "type": "array", + "description": "Request passed with no security violations detected.", + "items": { + "$ref": "#/components/schemas/TimeSeriesDataPoint" + } }, - "file_format": { - "type": "string", - "description": "The encoding format of the contents in the file for transport.\n\n- `plain`: Human-readable content (plain UTF-8 string).\n- `bytes`: Base64-encoded binary content.\n", - "enum": [ - "plain", - "bytes" - ], - "x-enum-varnames": [ - "template_file_format_plain", - "template_file_format_bytes" - ] + "SECURITY_WAF_VIOLATION": { + "type": "array", + "description": "Request blocked due to a confirmed signature or protocol violation.", + "items": { + "$ref": "#/components/schemas/TimeSeriesDataPoint" + } }, - "mime_type": { - "type": "string", - "description": "The MIME type of the file, indicating its content type.\nFor example, `text/plain`, `application/json`, `application/gzip`.\n", - "enum": [ - "text/plain", - "application/json", - "application/yaml" - ] + "SECURITY_WAF_FLAGGED": { + "type": "array", + "description": "Violation detected, but allowed due to policy-level transparent mode.", + "items": { + "$ref": "#/components/schemas/TimeSeriesDataPoint" + } }, - "size": { - "type": "integer", - "description": "The size of the file, in bytes." + "SECURITY_WAF_VIOLATION_TRANSPARENT": { + "type": "array", + "description": "Individual signature or violation was in staging/transparent mode and did not block.", + "items": { + "$ref": "#/components/schemas/TimeSeriesDataPoint" + } }, - "ctime": { - "type": "string", - "format": "date-time", - "description": "Timestamp when the file was created." + "SECURITY_NGINX_VIOLATION": { + "type": "array", + "description": "Request rejected due to NGINX-level constraints (e.g., malformed headers).", + "items": { + "$ref": "#/components/schemas/TimeSeriesDataPoint" + } + }, + "SECURITY_WAF_BYPASS": { + "type": "array", + "description": "Request was explicitly allowed due to an allow-list or bypass rule.", + "items": { + "$ref": "#/components/schemas/TimeSeriesDataPoint" + } + } + } + }, + "AttacksTimeSeriesQueryResponse": { + "type": "object", + "description": "Response for attack analytics time-series query.\n\n**Response behavior:**\n- Without `group_by`: Returns `total` series only (array of data points)\n- With `group_by`: Returns dimensional breakdown only (e.g., `request_status`), `total` is omitted\n\nThe `total` and dimensional breakdowns are mutually exclusive.\n\n**Time alignment:** All series arrays contain the same timestamps, aligned to the\nresolution boundary. Buckets with no events are zero-filled to ensure consistent\ndata points across all series for chart rendering.\n", + "required": [ + "query_metadata" + ], + "properties": { + "query_metadata": { + "$ref": "#/components/schemas/QueryMetadata" + }, + "total": { + "type": "array", + "description": "Total attack counts over time. Only present when no `group_by` is specified.\n", + "items": { + "$ref": "#/components/schemas/TimeSeriesDataPoint" + } + }, + "request_status": { + "$ref": "#/components/schemas/RequestStatusTimeSeries" + }, + "request_outcome_reason": { + "$ref": "#/components/schemas/RequestOutcomeReasonTimeSeries" } - }, - "example": { - "name": "nginx.tmpl", - "file_type": "template", - "file_format": "plain", - "mime_type": "text/plain", - "contents": "http {\n {{ augment_includes \"http\" . }}\n\n upstream backend {\n {{- range .upstream_servers }}\n server {{ . }};\n {{- end }}\n }\n\n server {\n listen 80;\n server_name {{ .server_name }};\n\n location / {\n proxy_pass {{ default \"http://backend\" .proxy_pass }};\n }\n }\n}", - "size": 345, - "ctime": "2026-09-01T12:00:00Z" } }, - "TemplateCreationRequest": { - "description": "A request payload used to create a new template, including its metadata and associated file contents.", - "type": "object", + "SignaturesDimensionField": { + "type": "string", + "description": "Available dimensions for grouping and filtering signature analytics.\n", + "enum": [ + "request_status", + "accuracy", + "risk", + "signature", + "cve" + ], + "x-enum-varnames": [ + "signatures_dimension_request_status", + "signatures_dimension_accuracy", + "signatures_dimension_risk", + "signatures_dimension_signature", + "signatures_dimension_cve" + ] + }, + "SignaturesTimeSeriesDimensionField": { + "type": "string", + "description": "Dimensions available for time-series grouping of signature data.\nLimited to fixed enum dimensions that can be efficiently aggregated per time bucket.\n", + "enum": [ + "request_status", + "accuracy", + "risk" + ], + "x-enum-varnames": [ + "signatures_ts_dimension_request_status", + "signatures_ts_dimension_accuracy", + "signatures_ts_dimension_risk" + ] + }, + "SignaturesQueryRequest": { "allOf": [ { - "$ref": "#/components/schemas/TemplateSummaryBase" + "$ref": "#/components/schemas/BaseQueryRequest" }, { "type": "object", - "required": [ - "items" - ], + "description": "Request body for querying signature analytics.\n", "properties": { - "items": { - "description": "A list of files in the template.", + "group_by": { + "allOf": [ + { + "$ref": "#/components/schemas/SignaturesDimensionField" + }, + { + "description": "Dimension to aggregate results by.\n\n**Fixed enum dimensions** (returned as objects with known keys):\n* `request_status` - blocked, alerted, passed\n* `accuracy` - low, medium, high\n* `risk` - low, medium, high, critical\n\n**Dynamic dimensions** (returned as arrays sorted by count descending):\n* `signature` - Individual signatures with id, name, accuracy, risk\n* `cve` - CVE identifiers\n\n**Response behavior:**\n- If omitted: Returns `total` (signature hits) and `unique` (distinct signatures)\n- If specified: Returns dimensional breakdown, `total` and `unique` are omitted\n", + "example": "signature" + } + ] + }, + "filter": { "type": "array", + "description": "Pre-aggregation filter conditions.\nAll filters are combined with AND logic.\nUse the `in` operator to achieve `OR` within a single dimension.\n", "items": { - "$ref": "#/components/schemas/TemplateFileData" - } + "$ref": "#/components/schemas/AnalyticsFilter" + }, + "default": [] + }, + "order_by": { + "$ref": "#/components/schemas/AnalyticsOrderBy" } } } - ], - "example": { - "name": "reverse-proxy", - "type": "base", - "allowed_in_contexts": [], - "augment_includes": [ - "http" - ], - "items": [ - { - "name": "nginx.tmpl", - "file_type": "template", - "file_format": "bytes", - "mime_type": "text/plain", - "contents": "aHR0cCB7XG4gIHt7IGF1Z21lbnRfaW5jbHVkZXMgXCJodHRwXCIgLiB9fVxuXG4gdXBzdHJlYW0gYmFja2VuZCB7XG4gIC17LSByYW5nZSAudXBzdHJlYW1fc2VydmVycyB9XG4gICAgc2VydmVyIHsgLiB9O1xuICB7LSBlbmQgfVxuIH1cblxuIHNlcnZlciB7XG4gIGxpc3RlbiA4MDtcbiAgc2VydmVyX25hbWUge3sgLnNlcnZlcl9uYW1lIH19O1xuXG4gIGxvY2F0aW9uIC8ge1xuICAgIHByb3h5X3Bhc3Mge3sgZGVmYXVsdCBcImh0dHA6Ly9iYWNrZW5kXCIgLnByb3h5X3Bhc3MgfX07XG4gIH1cbn1cbiIs", - "size": 1234, - "ctime": "2026-09-01T12:00:00Z" - }, - { - "name": "schema.json", - "file_type": "schema", - "file_format": "bytes", - "mime_type": "application/json", - "contents": "ewogICIkc2NoZW1hIjogImh0dHA6Ly9qc29uLXNjaGVtYS5vcmcvZHJhZnQtMDcvc2NoZW1hIyIsCiAgInR5cGUiOiAib2JqZWN0IiwKICAicHJvcGVydGllcyI6IHsKICAgICJ1cHN0cmVhbV9zZXJ2ZXJzIjogewogICAgICAidHlwZSI6ICJhcnJheSIsCiAgICAgICJpdGVtcyI6IHsKICAgICAgICAidHlwZSI6ICJzdHJpbmciLAogICAgICAgICJmb3JtYXQiOiAiaG9zdG5hbWUiLAogICAgICAgICJwYXR0ZXJuIjogIl5bYS1aQS1aMC05Li1dKyg6WzAtOV0rKT8kIgogICAgICB9LAogICAgICAibWluSXRlbXMiOiAxCiAgICB9LAogICAgInNlcnZlcl9uYW1lIjogewogICAgICAidHlwZSI6ICJzdHJpbmciLAogICAgICAicGF0dGVybiI6ICJeW2EtWkEtWjAtOS4tXSskIgogICAgfSwKICAgICJwcm94eV9wYXNzIjogewogICAgICAidHlwZSI6ICJzdHJpbmciLAogICAgICAiZm9ybWF0IjogInVyaSIKICAgIH0KICB9LAogICJyZXF1aXJlZCI6IFsidXBzdHJlYW1fc2VydmVycyIsICJzZXJ2ZXJfbmFtZSJdLAogICJhZGRpdGlvbmFsUHJvcGVydGllcyI6IGZhbHNlCn0=", - "size": 456, - "ctime": "2026-09-01T12:00:00Z" - } - ] - } + ] }, - "TemplateDetailsResponse": { - "description": "Full detailed response about an existing template object including summary and file contents.", - "type": "object", + "SignaturesTimeSeriesQueryRequest": { "allOf": [ { - "$ref": "#/components/schemas/TemplateVersionMetadata" - }, - { - "$ref": "#/components/schemas/TemplateSummaryBase" + "$ref": "#/components/schemas/BaseQueryRequest" }, { "type": "object", - "required": [ - "items" - ], + "description": "Request body for querying signature analytics time series.\n", "properties": { - "items": { - "description": "A list of files in the template.", + "resolution": { + "$ref": "#/components/schemas/Resolution" + }, + "group_by": { + "allOf": [ + { + "$ref": "#/components/schemas/SignaturesTimeSeriesDimensionField" + }, + { + "description": "Dimension to break down time-series by.\nLimited to fixed enum dimensions for performance.\n\n* `request_status` - Returns `blocked`, `alerted`, `passed` series\n* `accuracy` - Returns `low`, `medium`, `high` series\n* `risk` - Returns `low`, `medium`, `high`, `critical` series\n\n**Response behavior:**\n- If omitted: Returns `total` series only\n- If specified: Returns dimensional breakdown, `total` is omitted\n", + "example": "request_status" + } + ] + }, + "filter": { "type": "array", + "description": "Pre-aggregation filter conditions.\nAll filters are combined with AND logic.\nUse the `in` operator to achieve `OR` within a single dimension.\n", "items": { - "$ref": "#/components/schemas/TemplateFileData" - } + "$ref": "#/components/schemas/AnalyticsFilter" + }, + "default": [] } } } - ], - "example": { - "object_id": "tmpl_-uvR3F2TQGm18jnl7bpaGw", - "created_at": "2026-09-01T12:00:00Z", - "modified_at": "2026-09-15T14:30:00Z", - "latest_template_version_object_id": "tmplv_-uvR3F2TQGm18jnl7bpaGw", - "version": 1, - "latest_version": 1, - "state": "final", - "name": "reverse-proxy", - "type": "base", - "allowed_in_contexts": [], - "augment_includes": [ - "http" - ], - "items": [ - { - "name": "nginx.tmpl", - "file_type": "template", - "file_format": "bytes", - "mime_type": "text/plain", - "contents": "aHR0cCB7XG4gIHt7IGF1Z21lbnRfaW5jbHVkZXMgXCJodHRwXCIgLiB9fVxuXG4gdXBzdHJlYW0gYmFja2VuZCB7XG4gIC17LSByYW5nZSAudXBzdHJlYW1fc2VydmVycyB9XG4gICAgc2VydmVyIHsgLiB9O1xuICB7LSBlbmQgfVxuIH1cblxuIHNlcnZlciB7XG4gIGxpc3RlbiA4MDtcbiAgc2VydmVyX25hbWUge3sgLnNlcnZlcl9uYW1lIH19O1xuXG4gIGxvY2F0aW9uIC8ge1xuICAgIHByb3h5X3Bhc3Mge3sgZGVmYXVsdCBcImh0dHA6Ly9iYWNrZW5kXCIgLnByb3h5X3Bhc3MgfX07XG4gIH1cbn1cbiIs", - "size": 1234, - "ctime": "2026-09-01T12:00:00Z" - }, - { - "name": "schema.json", - "file_type": "schema", - "file_format": "bytes", - "mime_type": "application/json", - "contents": "ewogICIkc2NoZW1hIjogImh0dHA6Ly9qc29uLXNjaGVtYS5vcmcvZHJhZnQtMDcvc2NoZW1hIyIsCiAgInR5cGUiOiAib2JqZWN0IiwKICAicHJvcGVydGllcyI6IHsKICAgICJ1cHN0cmVhbV9zZXJ2ZXJzIjogewogICAgICAidHlwZSI6ICJhcnJheSIsCiAgICAgICJpdGVtcyI6IHsKICAgICAgICAidHlwZSI6ICJzdHJpbmciLAogICAgICAgICJmb3JtYXQiOiAiaG9zdG5hbWUiLAogICAgICAgICJwYXR0ZXJuIjogIl5bYS1aQS1aMC05Li1dKyg6WzAtOV0rKT8kIgogICAgICB9LAogICAgICAibWluSXRlbXMiOiAxCiAgICB9LAogICAgInNlcnZlcl9uYW1lIjogewogICAgICAidHlwZSI6ICJzdHJpbmciLAogICAgICAicGF0dGVybiI6ICJeW2EtWkEtWjAtOS4tXSskIgogICAgfSwKICAgICJwcm94eV9wYXNzIjogewogICAgICAidHlwZSI6ICJzdHJpbmciLAogICAgICAiZm9ybWF0IjogInVyaSIKICAgIH0KICB9LAogICJyZXF1aXJlZCI6IFsidXBzdHJlYW1fc2VydmVycyIsICJzZXJ2ZXJfbmFtZSJdLAogICJhZGRpdGlvbmFsUHJvcGVydGllcyI6IGZhbHNlCn0=", - "size": 456, - "ctime": "2026-09-01T12:00:00Z" - } - ] - } - }, - "TemplateValuesRequest": { - "type": "object", - "description": "Key-value pairs for template rendering.", - "additionalProperties": true - }, - "TemplateSubmissionRequest": { - "type": "object", - "description": "Defines a request to render an NGINX configuration by combining a single base template \nwith zero or more augment templates.\n\n### Validations and Constraints:\n- All templates referenced by Object ID must be available in the system before submission.\n- Only one base template can be submitted.\n- The base template must explicitly use custom Go function `augment_includes (\"\", .)` to apply `augments`.\n- Its not required to include all augments in the request that base template supports.\n- The order of augments in the list determines the order in which they are rendered and applied.\n- Each augment must specify its `target_context`, indicating where it should be applied in \n the base template.\n- Input values for each template are passed independently via the `values` \n object, and validated against each template’s Schema.\n\n### Processing:\n- The `base_template` defines the starting point of the NGINX configuration rendering.\n- `conf_path` determines where the rendered configuration from base and augments should be placed within the NGINX directory structure.\n- Each `augment` template is applied in the order provided, inserted at the appropriate target context\n using the `augment_includes (\"\", .)` function declared in the base template.\n- The system validates that each augment is compatible with the specified target context.\n- The final composed configuration is validated to ensure correctness and prevent conflicts or misconfigurations.\n\n### External Template Documentation:\nFor more information on template functions and best practices, refer to:\n - [Template Function Reference](https://yourdocs.com/templates/functions)\n - [Template Authoring Guide](https://yourdocs.com/templates/guide)\n", - "required": [ - "conf_path", - "base_template", - "augments" - ], - "properties": { - "conf_path": { - "$ref": "#/components/schemas/ConfigPath" - }, - "base_template": { - "$ref": "#/components/schemas/BaseTemplateSubmissionRequest" - }, - "augments": { - "type": "array", - "description": "Ordered list of augment templates to apply to the base template.\nAugments are rendered in the order provided.\n", - "items": { - "$ref": "#/components/schemas/AugmentTemplateSubmissionRequest" - } - } - }, - "example": { - "conf_path": "/etc/nginx/nginx.conf", - "base_template": { - "object_id": "tmplv_-uvR3F2TQGm18jnl7bpaGw", - "values": { - "upstream_servers": [ - "10.0.0.1:8080", - "10.0.0.2:8080" - ], - "server_name": "example.com" - } - }, - "augments": [ - { - "object_id": "tmplv_-uvR3F2TQGm18jnl7bpaGw", - "target_context": "http/upstream", - "values": { - "upstream_servers": [ - "10.0.0.1:8080", - "10.0.0.2:8080" - ], - "server_name": "example.com" - } - }, - { - "object_id": "tmplv_-xeR3F2TQGm18jnl7bpaAw", - "target_context": "http", - "values": { - "enabled": "on", - "types": "text/plain application/json" - } - }, - { - "object_id": "tmplv_-abR3F2TQGm18jnl7bpaXw", - "target_context": "http", - "values": { - "zone_name": "req_limit", - "memory": "10m", - "rate": "10r/s" - } - }, - { - "object_id": "tmplv_-cdR3F2TQGm18jnl7bpaZw", - "target_context": "http/server", - "values": { - "zone_name": "req_limit", - "burst": 5 - }, - "child_augments": [ - { - "object_id": "tmplv_-cdR3F2TQGm18jnl7bpaZw", - "target_context": "http/server/location", - "values": { - "zone_name": "req_limit", - "burst": 5 - } - } - ] - } - ] - } + ] }, - "BaseTemplateSubmissionRequest": { + "SignatureDimensionItem": { "type": "object", + "description": "A single item in the signature dimensional breakdown.\nIncludes signature metadata (id, name, accuracy, risk) along with hit count.\n", "required": [ - "object_id" + "signature_id", + "name", + "count", + "accuracy", + "risk" ], "properties": { - "object_id": { - "$ref": "#/components/schemas/TemplateVersionObjectID" + "signature_id": { + "type": "string", + "description": "The unique identifier for the signature.\n", + "example": "200001834" }, - "values": { - "$ref": "#/components/schemas/TemplateValuesRequest" + "name": { + "type": "string", + "description": "The human-readable name of the signature.\n", + "example": "Unix hidden (dot-file)" + }, + "count": { + "type": "integer", + "description": "Number of times this signature was triggered within the queried time range.\n" + }, + "accuracy": { + "allOf": [ + { + "$ref": "#/components/schemas/SignatureAccuracy" + }, + { + "description": "The accuracy level of the signature.", + "example": "high" + } + ] + }, + "risk": { + "allOf": [ + { + "$ref": "#/components/schemas/SignatureRisk" + }, + { + "description": "The risk level of the signature.", + "example": "medium" + } + ] + }, + "distinct": { + "$ref": "#/components/schemas/DistinctCounts" } }, "example": { - "object_id": "tmplv_-uvR3F2TQGm18jnl7bpaGw", - "values": { - "upstream_servers": [ - "10.0.0.1:8080", - "10.0.0.2:8080" - ], - "server_name": "example.com" + "signature_id": "200001834", + "name": "Unix hidden (dot-file)", + "count": 141, + "accuracy": "high", + "risk": "medium", + "distinct": { + "ips": 12, + "urls": 5, + "violations": 3, + "policies": 2 } } }, - "AugmentTemplateSubmissionRequest": { + "CveDimensionItem": { "type": "object", - "description": "Defines a request to apply an augment template to a specific target context within the base template.\n\nThis extends the `BaseTemplateSubmissionRequest`. Additionally adding,\n- `target_context`: Specifies the context within the base template where this augment should be applied.\n- `child_augments`: Optionally, an ordered list of nested augment templates to apply as children of this template.\n", + "description": "A single item in the CVE dimensional breakdown.\n", "required": [ - "object_id", - "target_context" + "value", + "count" ], "properties": { - "object_id": { - "$ref": "#/components/schemas/TemplateVersionObjectID" - }, - "values": { - "$ref": "#/components/schemas/TemplateValuesRequest" + "value": { + "type": "string", + "description": "The CVE identifier (e.g., \"CVE-2021-44228\").\n", + "example": "CVE-2021-44228" }, - "target_context": { - "$ref": "#/components/schemas/TemplateContextPath" + "count": { + "type": "integer", + "description": "Number of signature hits associated with this CVE.\n" }, - "child_augments": { - "type": "array", - "description": "Ordered list of nested augment templates to apply as children of this template.\n", - "items": { - "$ref": "#/components/schemas/AugmentTemplateSubmissionRequest" - } + "distinct": { + "$ref": "#/components/schemas/DistinctCounts" } }, "example": { - "object_id": "tmplv_-xeR3F2TQGm18jnl7bpaAw", - "target_context": "http/server", - "values": { - "enabled": "on", - "types": "text/plain application/json" - }, - "child_augments": [ - { - "object_id": "tmplv_-cdR3F2TQGm18jnl7bpaZw", - "target_context": "http/server/location", - "values": { - "zone_name": "req_limit", - "burst": 5 - } - } - ] + "value": "CVE-2021-44228", + "count": 450, + "distinct": { + "ips": 8, + "urls": 3, + "violations": 2, + "policies": 1 + } } }, - "PreviewNginxConfig": { + "SignaturesQueryResponse": { "type": "object", - "description": "The rendered NGINX configuration preview, along with any errors encountered during rendering.\n", + "description": "Response for signature analytics query.\n\n**Response behavior:**\n- Without `group_by`: Returns `total` (signature hits) and `unique` (distinct signatures)\n- With `group_by`: Returns dimensional breakdown only, `total` and `unique` are omitted\n\nThe `total`/`unique` and dimensional breakdowns are mutually exclusive.\n", "required": [ - "config" + "query_metadata" ], "properties": { - "config": { - "$ref": "#/components/schemas/NginxConfigObject" + "query_metadata": { + "$ref": "#/components/schemas/QueryMetadata" }, - "errors": { + "total": { + "type": "integer", + "description": "Total signature hit count for the query.\nOnly present when no `group_by` is specified.\n" + }, + "unique": { + "type": "integer", + "description": "Count of distinct signatures triggered.\nOnly present when no `group_by` is specified.\n" + }, + "request_status": { + "$ref": "#/components/schemas/RequestStatusCountsResponse" + }, + "accuracy": { + "$ref": "#/components/schemas/AccuracyCountsResponse" + }, + "risk": { + "$ref": "#/components/schemas/RiskCountsResponse" + }, + "signature": { "type": "array", - "description": "List of NGINX config parse errors encountered during rendering.", + "description": "Signature hit counts grouped by individual signature. Sorted by count descending.", "items": { - "$ref": "#/components/schemas/NginxConfigParseError" + "$ref": "#/components/schemas/SignatureDimensionItem" + } + }, + "cve": { + "type": "array", + "description": "Signature hit counts grouped by CVE. Sorted by count descending.", + "items": { + "$ref": "#/components/schemas/CveDimensionItem" } } } }, - "NginxConfigParseError": { + "AccuracyTimeSeries": { "type": "object", - "description": "Details about an error encountered during NGINX configuration rendering.", - "required": [ - "file", - "error" - ], + "description": "Time-series data grouped by signature accuracy level.\nEach property contains an array of data points for that accuracy.\n", "properties": { - "file": { - "type": "string", - "description": "The name of the file where the error occurred." - }, - "line": { - "type": "integer", - "description": "The line number in the file where the error occurred." + "low": { + "type": "array", + "description": "Time series of low-accuracy signature hit counts.", + "items": { + "$ref": "#/components/schemas/TimeSeriesDataPoint" + } }, - "error": { - "type": "string", - "description": "A human-readable error message describing the issue." - } - }, - "example": { - "file": "nginx.conf", - "line": 1, - "error": "\"upstream\" directive is not allowed here in /etc/nginx/nginx.conf:1" - } - }, - "FilterNameTemplates": { - "type": "string", - "description": "Keywords for config templates filters.\n", - "enum": [ - "name", - "type", - "object_id", - "allowed_in_contexts" - ], - "x-enum-varnames": [ - "filter_name_templates_name", - "filter_name_templates_type", - "filter_name_templates_object_id", - "filter_name_templates_allowed_in_contexts" - ] - }, - "EventRequestOutcome": { - "type": "string", - "description": "WAF enforcement decision for the request.", - "enum": [ - "blocked", - "passed", - "alerted" - ], - "x-enum-varnames": [ - "request_outcome_blocked", - "request_outcome_passed", - "request_outcome_alerted" - ] - }, - "EventLevel": { - "type": "string", - "description": "Log level classification for the security event.\nFollows standard logging convention for severity.\n", - "enum": [ - "DEBUG", - "INFO", - "WARNING", - "ERROR", - "CRITICAL" - ], - "x-enum-varnames": [ - "event_level_debug", - "event_level_info", - "event_level_warning", - "event_level_error", - "event_level_critical" - ] - }, - "SignatureAccuracy": { - "type": "string", - "description": "Confidence level that the signature accurately identifies the attack.", - "enum": [ - "low", - "medium", - "high" - ], - "x-enum-varnames": [ - "signature_accuracy_low", - "signature_accuracy_medium", - "signature_accuracy_high" - ] - }, - "SignatureRisk": { - "type": "string", - "description": "Risk level of the attack identified by the signature.", - "enum": [ - "low", - "medium", - "high", - "critical" - ], - "x-enum-varnames": [ - "signature_risk_low", - "signature_risk_medium", - "signature_risk_high", - "signature_risk_critical" - ] - }, - "RequestStatus": { - "type": "string", - "description": "Status of request processing by the WAF.", - "enum": [ - "complete", - "truncated", - "malformed", - "skipped", - "aborted" - ], - "x-enum-varnames": [ - "request_status_complete", - "request_status_truncated", - "request_status_malformed", - "request_status_skipped", - "request_status_aborted" - ] - }, - "AttacksDimensionField": { - "type": "string", - "description": "Available dimensions for grouping and filtering attack analytics.\n", - "enum": [ - "request_outcome", - "request_outcome_reason", - "request_method", - "ip", - "country", - "policy", - "url", - "response_code", - "instance_object_id", - "csg_object_id" - ], - "x-enum-varnames": [ - "attacks_dimension_request_outcome", - "attacks_dimension_request_outcome_reason", - "attacks_dimension_request_method", - "attacks_dimension_ip", - "attacks_dimension_country", - "attacks_dimension_policy", - "attacks_dimension_url", - "attacks_dimension_response_code", - "attacks_dimension_instance_object_id", - "attacks_dimension_csg_object_id" - ] - }, - "AttacksTimeSeriesDimensionField": { - "type": "string", - "description": "Dimensions available for time-series grouping.\nLimited to fixed enum dimensions that can be efficiently aggregated per time bucket.\n", - "enum": [ - "request_outcome", - "request_outcome_reason" - ], - "x-enum-varnames": [ - "attacks_ts_dimension_request_outcome", - "attacks_ts_dimension_request_outcome_reason" - ] - }, - "Resolution": { - "type": "string", - "description": "Time bucket size for aggregation. If not specified, auto-selected based on time range:\n* < 1 hour: 1m\n* 1-6 hours: 5m\n* 6-24 hours: 15m\n* 1-7 days: 1h\n* > 7 days: 1d\n", - "enum": [ - "1m", - "5m", - "15m", - "1h", - "1d" - ], - "x-enum-varnames": [ - "resolution_1m", - "resolution_5m", - "resolution_15m", - "resolution_1h", - "resolution_1d" - ], - "example": "15m" + "medium": { + "type": "array", + "description": "Time series of medium-accuracy signature hit counts.", + "items": { + "$ref": "#/components/schemas/TimeSeriesDataPoint" + } + }, + "high": { + "type": "array", + "description": "Time series of high-accuracy signature hit counts.", + "items": { + "$ref": "#/components/schemas/TimeSeriesDataPoint" + } + } + } }, - "FilterOperator": { - "type": "string", - "description": "Filter operators that can be applied to a given list of dimension values.\n* `=` - Equals (uses first value only)\n* `!=` - Not equals (uses first value only)\n* `in` - Value is in the list (uses all values)\n* `not` - Value is not in the list (uses all values)\n", - "enum": [ - "=", - "!=", - "in", - "not" - ], - "x-enum-varnames": [ - "filter_operator_equal", - "filter_operator_not_equal", - "filter_operator_in", - "filter_operator_not" - ] + "RiskTimeSeries": { + "type": "object", + "description": "Time-series data grouped by signature risk level.\nEach property contains an array of data points for that risk level.\n", + "properties": { + "low": { + "type": "array", + "description": "Time series of low-risk signature hit counts.", + "items": { + "$ref": "#/components/schemas/TimeSeriesDataPoint" + } + }, + "medium": { + "type": "array", + "description": "Time series of medium-risk signature hit counts.", + "items": { + "$ref": "#/components/schemas/TimeSeriesDataPoint" + } + }, + "high": { + "type": "array", + "description": "Time series of high-risk signature hit counts.", + "items": { + "$ref": "#/components/schemas/TimeSeriesDataPoint" + } + }, + "critical": { + "type": "array", + "description": "Time series of critical-risk signature hit counts.", + "items": { + "$ref": "#/components/schemas/TimeSeriesDataPoint" + } + } + } }, - "SortOrderDirection": { - "type": "string", - "description": "Sort direction for query results.", - "enum": [ - "asc", - "desc" + "SignaturesTimeSeriesQueryResponse": { + "type": "object", + "description": "Response for signature analytics time-series query.\n\n**Response behavior:**\n- Without `group_by`: Returns `total` series only (array of data points)\n- With `group_by`: Returns dimensional breakdown only (e.g., `request_status`), `total` is omitted\n\nThe `total` and dimensional breakdowns are mutually exclusive.\n\n**Time alignment:** All series arrays contain the same timestamps, aligned to the\nresolution boundary. Buckets with no events are zero-filled to ensure consistent\ndata points across all series for chart rendering.\n", + "required": [ + "query_metadata" ], - "default": "desc", - "x-enum-varnames": [ - "order_direction_asc", - "order_direction_desc" - ] + "properties": { + "query_metadata": { + "$ref": "#/components/schemas/QueryMetadata" + }, + "total": { + "type": "array", + "description": "Total signature hit counts over time. Only present when no `group_by` is specified.\n", + "items": { + "$ref": "#/components/schemas/TimeSeriesDataPoint" + } + }, + "request_status": { + "$ref": "#/components/schemas/RequestStatusTimeSeries" + }, + "accuracy": { + "$ref": "#/components/schemas/AccuracyTimeSeries" + }, + "risk": { + "$ref": "#/components/schemas/RiskTimeSeries" + } + } }, - "AnalyticsFilter": { + "HttpMetadata": { + "type": "object", + "description": "HTTP request and response metadata from the security event.\n", + "properties": { + "hostname": { + "type": "string", + "description": "The HTTP Host header value.", + "example": "example.com" + }, + "remote_addr": { + "type": "string", + "description": "Client IP address.", + "example": "192.168.1.100" + }, + "remote_port": { + "type": "integer", + "description": "Client source port.", + "example": 54321 + }, + "server_addr": { + "type": "string", + "description": "Server IP address that received the request.", + "example": "10.0.0.1" + }, + "server_port": { + "type": "integer", + "description": "Server port that received the request.", + "example": 443 + }, + "uri": { + "type": "string", + "description": "Request URI path including query string.", + "example": "/api/login?user=admin" + }, + "request_method": { + "type": "string", + "description": "HTTP request method.", + "example": "GET" + }, + "response_code": { + "type": "integer", + "description": "HTTP response status code.", + "example": 403 + } + } + }, + "SignatureDetail": { "type": "object", - "description": "A single filter condition on a dimension.\nGeneric schema supporting both attacks and signature analytics filtering.\n", + "description": "Details of a signature that was triggered by the security event.\nA single event can trigger multiple signatures.\n", "required": [ - "dimension", - "operator", - "values" + "id", + "name" ], "properties": { - "dimension": { + "id": { + "type": "integer", + "description": "Unique identifier of the signature.", + "example": 200001834 + }, + "name": { "type": "string", - "description": "The dimension to filter by. Accepts any dimension from either\nAttacksDimensionField or SignaturesDimensionField enums.\n" + "description": "Human-readable name of the signature.", + "example": "XSS script tag end (Parameter)" }, - "operator": { - "$ref": "#/components/schemas/FilterOperator" + "accuracy": { + "allOf": [ + { + "$ref": "#/components/schemas/SignatureAccuracy" + }, + { + "description": "Confidence level that this signature accurately identifies the attack.", + "example": "high" + } + ] }, - "values": { - "type": "array", - "description": "Values to filter by.\n- For `=` and `!=`: only the first value is used\n- For `in` and `not`: all values are used\n", - "items": { - "type": "string" - }, - "minItems": 1, - "example": [ - "blocked" + "risk": { + "allOf": [ + { + "$ref": "#/components/schemas/SignatureRisk" + }, + { + "description": "Severity/risk level of the attack identified by this signature.", + "example": "high" + } ] + }, + "cve": { + "type": "string", + "description": "CVE identifier if this signature is associated with a known vulnerability.", + "example": "CVE-2021-44228" + }, + "blocking_mask": { + "type": "string", + "description": "Bitmask indicating blocking behavior configuration.", + "example": "0x0" + }, + "buffer": { + "type": "string", + "description": "The buffer/location where the signature matched (e.g., parameter name, header).", + "example": "param" + }, + "offset": { + "type": "integer", + "description": "Byte offset within the payload where the signature match begins.", + "example": 0 + }, + "length": { + "type": "integer", + "description": "Length of the matched string in bytes.", + "example": 42 } } }, - "AnalyticsOrderBy": { + "ViolationDetail": { "type": "object", - "description": "Specifies the sort order for dynamic dimension results.\n", + "description": "Details of a violation detected in the security event.\nA single event can trigger multiple violations.\n", + "required": [ + "name" + ], "properties": { - "dimension": { + "name": { "type": "string", - "description": "Field to sort by.\n- `count`: Sort by count (default)\n- `value`: Sort alphabetically by dimension value\n", - "enum": [ - "count", - "value" - ], - "default": "count" + "description": "Primary violation name/type.", + "example": "Illegal meta character in value" }, - "direction": { - "$ref": "#/components/schemas/SortOrderDirection" + "sub_name": { + "type": "string", + "description": "Sub-category or additional violation classification.", + "example": "" + }, + "context": { + "type": "string", + "description": "The context where the violation was detected (e.g., parameter, header, uri).", + "example": "parameter" + }, + "detail_name": { + "type": "string", + "description": "Technical violation identifier (e.g., VIOL_PARAMETER_VALUE_METACHAR).", + "example": "VIOL_PARAMETER_VALUE_METACHAR" + }, + "detail_context": { + "type": "string", + "description": "Additional context for the violation detail.", + "example": "parameter" + }, + "field_name": { + "type": "string", + "description": "Name of the field that triggered the violation.", + "example": "param" + }, + "field_value": { + "type": "string", + "description": "The value that triggered the violation.", + "example": "" } - }, - "example": { - "dimension": "count", - "direction": "desc" } }, - "BaseQueryRequest": { + "SecurityEventBase": { "type": "object", - "description": "Base query request with common fields for both attacks and signature analytics.\nShared properties for all analytical query types.\n", + "description": "Base security event with common fields across all event types.\nSeverity is determined by violation_rating (0-5), not a separate field.\n", "required": [ - "start_time" + "timestamp", + "support_id" ], "properties": { - "start_time": { + "timestamp": { + "type": "string", + "format": "date-time", + "description": "When the security event occurred.", + "example": "2024-01-22T12:13:25Z" + }, + "support_id": { + "type": "string", + "description": "WAF support identifier for correlating with support cases.", + "example": "1844305495056427365" + }, + "policy_name": { "type": "string", - "description": "Beginning of the time range (inclusive).\nAccepts ISO 8601 format (`2024-01-15T00:00:00Z`) or relative offset (`now-24h`, `now-1d`).\n", - "example": "now-24h" + "description": "Name of the WAF policy that processed the request.", + "example": "app_protect_default_policy" }, - "end_time": { + "country_code": { "type": "string", - "description": "End of the time range (exclusive).\nAccepts ISO 8601 format (`2024-01-15T00:00:00Z`) or relative offset (`now-24h`, `now-1d`).\n", - "default": "now", - "example": "now" + "maxLength": 2, + "description": "ISO 3166-1 alpha-2 country code of the client IP.", + "example": "US" }, - "limit": { + "violation_rating": { "type": "integer", - "description": "Maximum items per dynamic dimension array (1-1000).\nDoes not apply to fixed enum dimensions.\n", - "minimum": 1, - "maximum": 1000, - "default": 100, - "example": 10 + "minimum": 0, + "maximum": 5, + "description": "Numeric violation severity rating (0-5).", + "example": 5 + }, + "instance_object_id": { + "type": "string", + "description": "NGINX One Console instance object identifier.", + "example": "inst_8Iwn7dT7RF-PRLxkSt5EYQ" + }, + "csg_object_id": { + "type": "string", + "description": "NGINX One Console Config Sync Group object identifier.", + "example": "csg_-uvR3F2TQGm18jnl7bpaGw" } } }, - "AttacksQueryRequest": { + "SecurityEvent": { "allOf": [ { - "$ref": "#/components/schemas/BaseQueryRequest" + "$ref": "#/components/schemas/SecurityEventBase" }, { "type": "object", - "description": "Request body for querying attack analytics.\n", + "description": "Full security event details including all metadata, violations, and signatures.\nUsed for the single event retrieval endpoint.\n", + "required": [ + "signatures", + "violations" + ], "properties": { - "group_by": { + "version": { + "type": "string", + "description": "Event schema version.", + "example": "v1.0" + }, + "system_id": { + "type": "string", + "description": "System identifier of the NGINX instance.", + "example": "31ed9d05-9cb0-48c3-9f97-d63b1b6dd342" + }, + "parent_hostname": { + "type": "string", + "description": "Hostname of the machine running NGINX.", + "example": "nginx-host-01" + }, + "http": { + "$ref": "#/components/schemas/HttpMetadata" + }, + "x_forwarded_for_header_value": { + "type": "string", + "description": "Value of the X-Forwarded-For header if present.", + "example": "203.0.113.42" + }, + "request_status": { "allOf": [ { - "$ref": "#/components/schemas/AttacksDimensionField" + "$ref": "#/components/schemas/RequestStatus" }, { - "description": "Dimension to aggregate results by.\n\n**Fixed enum dimensions** (returned as objects with known keys):\n* `request_outcome` - blocked, passed, alerted\n* `request_method` - GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH\n\n**Simple array dimensions** (returned as arrays with code/count):\n* `response_code` - HTTP response codes\n\n**Dynamic dimensions** (returned as arrays with cross-dimension context):\n* `ip`, `country`, `policy`, `url`, `instance_object_id`, `csg_object_id`\n\n**Response behavior:**\n- If omitted: Returns `total` count only\n- If specified: Returns dimensional breakdown, `total` is omitted\n", - "example": "request_outcome" + "description": "WAF enforcement decision for the request.", + "example": "blocked" } ] }, - "filter": { + "request_outcome": { + "allOf": [ + { + "$ref": "#/components/schemas/EventRequestOutcome" + }, + { + "description": "Binary outcome of WAF processing for the request.", + "example": "rejected" + } + ] + }, + "request_outcome_reason": { + "type": "string", + "description": "Reason code for the enforcement decision.", + "example": "SECURITY_WAF_VIOLATION" + }, + "blocking_exception_reason": { + "type": "string", + "description": "Reason if blocking was bypassed due to an exception.", + "example": "" + }, + "is_truncated": { + "type": "boolean", + "description": "Whether the request was truncated during processing.", + "example": false + }, + "signatures": { "type": "array", - "description": "Pre-aggregation filter conditions.\nAll filters are combined with AND logic.\nUse the `in` operator to achieve `OR` within a single dimension.\n", + "description": "List of signatures triggered by this event.", "items": { - "$ref": "#/components/schemas/AnalyticsFilter" + "$ref": "#/components/schemas/SignatureDetail" + } + }, + "violations": { + "type": "array", + "description": "List of violations detected in this event.", + "items": { + "$ref": "#/components/schemas/ViolationDetail" + } + }, + "threat_campaign_names": { + "type": "array", + "description": "Names of threat campaigns associated with this event.", + "items": { + "type": "string" }, - "default": [] + "example": [] }, - "order_by": { - "$ref": "#/components/schemas/AnalyticsOrderBy" + "request": { + "type": "string", + "description": "Raw HTTP request (if available and not truncated).\nContains headers and body as received by the WAF.\n", + "example": "GET /?param=%3Cscript%3Ealert%27xss%27%3C%2Fscript%3E HTTP/1.1\r\nHost: example.com\r\nUser-Agent: curl/7.68.0\r\nAccept: */*\r\n\r\n" } } } ] }, - "AttacksTimeSeriesQueryRequest": { + "SecurityEventListItem": { "allOf": [ { - "$ref": "#/components/schemas/BaseQueryRequest" + "$ref": "#/components/schemas/SecurityEventBase" }, { "type": "object", - "description": "Request body for querying attack analytics time series.\n", + "description": "Summary of a security event for list display.\nContains key fields for quick scanning and filtering in the events list.\nThis is a subset of SecurityEvent optimized for the list view.\n", "properties": { - "resolution": { - "$ref": "#/components/schemas/Resolution" + "client_ip": { + "type": "string", + "description": "Client IP address that sent the request.", + "example": "192.168.1.100" }, - "group_by": { + "url": { + "type": "string", + "description": "Request URI path.", + "example": "/" + }, + "request_method": { + "type": "string", + "description": "HTTP request method.", + "example": "GET" + }, + "response_code": { + "type": "integer", + "description": "HTTP response status code.", + "example": 403 + }, + "request_status": { "allOf": [ { - "$ref": "#/components/schemas/AttacksTimeSeriesDimensionField" + "$ref": "#/components/schemas/RequestStatus" }, { - "description": "Dimension to break down time-series by.\nLimited to fixed enum dimensions for performance.\n\n* `request_outcome` - Returns `blocked`, `passed`, `alerted` series\n* `request_outcome_reason` - Returns the underlying reason for the outcome.\n\n**Common `request_outcome_reason` values:**\n- `SECURITY_WAF_OK`: Legitimate request, no violations.\n- `SECURITY_WAF_VIOLATION`: Request blocked due to signature or protocol violation.\n- `SECURITY_WAF_FLAGGED`: Violation detected, but request allowed (Transparent/Alert-only mode).\n- `SECURITY_WAF_VIOLATION_TRANSPARENT`: Request would have been blocked, but the policy/signature is in staging/transparent mode.\n- `SECURITY_NGINX_VIOLATION`: Request rejected due to NGINX-level constraints (e.g., malformed headers).\n- `SECURITY_WAF_BYPASS`: Request was explicitly allowed due to an allow-list or bypass rule.\n\n**Response behavior:**\n- If omitted: Returns `total` series only\n- If specified: Returns dimensional breakdown, `total` is omitted\n", - "example": "request_outcome" + "description": "WAF enforcement decision for the request.", + "example": "blocked" } ] - }, - "filter": { + } + } + } + ] + }, + "SecurityEventListResponse": { + "allOf": [ + { + "$ref": "#/components/schemas/PaginationResponse" + }, + { + "type": "object", + "description": "Paginated list of security events.\n", + "required": [ + "items" + ], + "properties": { + "items": { "type": "array", - "description": "Pre-aggregation filter conditions.\nAll filters are combined with AND logic.\nUse the `in` operator to achieve `OR` within a single dimension.\n", + "description": "List of security events for the current page.", "items": { - "$ref": "#/components/schemas/AnalyticsFilter" - }, - "default": [] + "$ref": "#/components/schemas/SecurityEventListItem" + } } } } ] }, - "SignaturesDimensionField": { + "ViolationsMetricField": { "type": "string", - "description": "Available dimensions for grouping and filtering signature analytics.\n", + "description": "Count metric for violation context group_by queries.\n\n* hits: Total occurrence count (default)\n* unique: Distinct violation types per context\n", "enum": [ - "request_outcome", - "accuracy", - "risk", - "signature", - "cve" + "hits", + "unique" ], "x-enum-varnames": [ - "signatures_dimension_request_outcome", - "signatures_dimension_accuracy", - "signatures_dimension_risk", - "signatures_dimension_signature", - "signatures_dimension_cve" + "violations_metric_hits", + "violations_metric_unique" ] }, - "SignaturesTimeSeriesDimensionField": { + "ViolationsDimensionField": { "type": "string", - "description": "Dimensions available for time-series grouping of signature data.\nLimited to fixed enum dimensions that can be efficiently aggregated per time bucket.\n", + "description": "Available dimensions for grouping and filtering violation analytics.\n\n* violation: Primary violation type (e.g., \"Attack signature detected\", \"Illegal meta character in value\")\n* sub_violation: Sub-category or additional violation classification providing more granular detail. A value of \"N/A\" indicates no additional information.\n* context: Location where violation was detected (header, cookie, parameter, uri, request, other)\n* context_key: Field name within the detection context (cookie name, header name, parameter name)\n* context_value: Field value that triggered the violation\n", "enum": [ - "request_outcome", - "accuracy", - "risk" + "violation", + "sub_violation", + "context", + "context_key", + "context_value" ], "x-enum-varnames": [ - "signatures_ts_dimension_request_outcome", - "signatures_ts_dimension_accuracy", - "signatures_ts_dimension_risk" + "violations_dimension_violation", + "violations_dimension_sub_violation", + "violations_dimension_context", + "violations_dimension_context_key", + "violations_dimension_context_value" ] }, - "SignaturesQueryRequest": { + "ViolationsQueryRequest": { "allOf": [ { "$ref": "#/components/schemas/BaseQueryRequest" }, { "type": "object", - "description": "Request body for querying signature analytics.\n", + "description": "Request body for querying violation analytics.\n", "properties": { "group_by": { "allOf": [ { - "$ref": "#/components/schemas/SignaturesDimensionField" + "$ref": "#/components/schemas/ViolationsDimensionField" }, { - "description": "Dimension to aggregate results by.\n\n**Fixed enum dimensions** (returned as objects with known keys):\n* `request_outcome` - blocked, passed, alerted\n* `accuracy` - low, medium, high\n* `risk` - low, medium, high, critical\n\n**Dynamic dimensions** (returned as arrays sorted by count descending):\n* `signature` - Individual signatures with id, name, accuracy, risk\n* `cve` - CVE identifiers\n\n**Response behavior:**\n- If omitted: Returns `total` (signature hits) and `unique` (distinct signatures)\n- If specified: Returns dimensional breakdown, `total` and `unique` are omitted\n", - "example": "signature" + "description": "Dimension to aggregate results by.\n\n**Fixed enum dimensions** (returned as objects with known keys):\n* `context` - cookie, header, parameter, request, uri, other\n\n**Dynamic dimensions** (returned as arrays with cross-dimension context):\n* `violation` - WAF policy violation types (e.g., \"Attack signature detected\")\n* `sub_violation` - Specific subtypes providing granular detail (e.g., \"SQL-Injection\" or \"Missing Mandatory Host Header\"). Returns \"N/A\" if not applicable.\n\n**Response behavior:**\n- If omitted: Returns `total` (violation occurrences) and `unique` (distinct violation types)\n- If specified: Returns dimensional breakdown, `total` and `unique` are omitted\n", + "example": "violation" } ] }, - "filter": { - "type": "array", - "description": "Pre-aggregation filter conditions.\nAll filters are combined with AND logic.\nUse the `in` operator to achieve `OR` within a single dimension.\n", - "items": { - "$ref": "#/components/schemas/AnalyticsFilter" - }, - "default": [] - }, - "order_by": { - "$ref": "#/components/schemas/AnalyticsOrderBy" - } - } - } - ] - }, - "SignaturesTimeSeriesQueryRequest": { - "allOf": [ - { - "$ref": "#/components/schemas/BaseQueryRequest" - }, - { - "type": "object", - "description": "Request body for querying signature analytics time series.\n", - "properties": { - "resolution": { - "$ref": "#/components/schemas/Resolution" - }, - "group_by": { + "metric": { "allOf": [ { - "$ref": "#/components/schemas/SignaturesTimeSeriesDimensionField" + "$ref": "#/components/schemas/ViolationsMetricField" }, { - "description": "Dimension to break down time-series by.\nLimited to fixed enum dimensions for performance.\n\n* `request_outcome` - Returns `blocked`, `passed`, `alerted` series\n* `accuracy` - Returns `low`, `medium`, `high` series\n* `risk` - Returns `low`, `medium`, `high`, `critical` series\n\n**Response behavior:**\n- If omitted: Returns `total` series only\n- If specified: Returns dimensional breakdown, `total` is omitted\n", - "example": "request_outcome" + "description": "Count metric when `group_by=context`. Omit for default (`hits`).\n\n* `hits`: Total violation occurrence count per context\n* `unique`: Distinct violation types per context\n", + "example": "unique" } ] }, "filter": { "type": "array", - "description": "Pre-aggregation filter conditions.\nAll filters are combined with AND logic.\nUse the `in` operator to achieve `OR` within a single dimension.\n", + "description": "Pre-aggregation filter conditions.\nAll filters are combined with AND logic.\nUse the `in` operator to achieve `OR` within a single dimension.\n\nSupported filter dimensions include attack-level dimensions (policy, ip, url, etc.)\nin addition to violation-specific dimensions.\n", "items": { "$ref": "#/components/schemas/AnalyticsFilter" }, "default": [] + }, + "order_by": { + "$ref": "#/components/schemas/AnalyticsOrderBy" } } } - ] + ] + }, + "ViolationDistinctCounts": { + "type": "object", + "description": "Cross-dimension counts providing context about violations for a given dimension value.\nEach field represents a distinct count aggregation.\n", + "required": [ + "ips", + "urls", + "policies" + ], + "properties": { + "ips": { + "type": "integer", + "description": "Count of distinct source IP addresses associated with this violation type." + }, + "urls": { + "type": "integer", + "description": "Count of distinct URLs where this violation was triggered." + }, + "policies": { + "type": "integer", + "description": "Count of distinct WAF policies that triggered this violation." + } + }, + "example": { + "ips": 15, + "urls": 8, + "policies": 3 + } }, - "HttpMetadata": { + "ViolationDimensionItem": { "type": "object", - "description": "HTTP request and response metadata from the security event.\n", + "description": "A single item in a violation dimensional breakdown.\n", + "required": [ + "value", + "count", + "distinct" + ], "properties": { - "hostname": { - "type": "string", - "description": "The HTTP Host header value.", - "example": "example.com" - }, - "remote_addr": { + "value": { "type": "string", - "description": "Client IP address.", - "example": "192.168.1.100" + "description": "The violation or sub-violation name.\nExamples: \"Attack signature detected\", \"Illegal meta character in value\"\n" }, - "remote_port": { + "count": { "type": "integer", - "description": "Client source port.", - "example": 54321 + "description": "Total number of times this violation occurred within the queried time range.\n" }, - "server_addr": { - "type": "string", - "description": "Server IP address that received the request.", - "example": "10.0.0.1" + "distinct": { + "$ref": "#/components/schemas/ViolationDistinctCounts" + } + }, + "example": { + "value": "Illegal meta character in value", + "count": 1080, + "distinct": { + "ips": 1, + "urls": 1, + "policies": 1 + } + } + }, + "ViolationContextCountsResponse": { + "type": "object", + "description": "Violation counts grouped by context type.\nIndicates where in the HTTP request the violation was detected.\n", + "properties": { + "cookie": { + "type": "integer", + "description": "Count of violations detected in cookie values." }, - "server_port": { + "header": { "type": "integer", - "description": "Server port that received the request.", - "example": 443 + "description": "Count of violations detected in HTTP headers." }, - "uri": { - "type": "string", - "description": "Request URI path including query string.", - "example": "/api/login?user=admin" + "parameter": { + "type": "integer", + "description": "Count of violations detected in request parameters (query string or body)." }, - "request_method": { - "type": "string", - "description": "HTTP request method.", - "example": "GET" + "request": { + "type": "integer", + "description": "Count of violations detected in the request body or general request context." }, - "response_code": { + "uri": { "type": "integer", - "description": "HTTP response status code.", - "example": 403 + "description": "Count of violations detected in the URI/URL path." } + }, + "example": { + "cookie": 0, + "header": 130, + "parameter": 1426, + "request": 302, + "uri": 0 } }, - "SignatureDetail": { + "ViolationsQueryResponse": { "type": "object", - "description": "Details of a signature that was triggered by the security event.\nA single event can trigger multiple signatures.\n", + "description": "Response for violation analytics query.\n\n**Response behavior:**\n- Without `group_by`: Returns `total` (total violation occurrences) and `unique` (distinct violation types)\n- With `group_by`: Returns dimensional breakdown only (e.g., `violation`, `context`), `total` and `unique` are omitted\n\nThe aggregate fields (`total`, `unique`) and dimensional breakdowns are mutually exclusive.\n", "required": [ - "id", - "name" + "query_metadata" ], "properties": { - "id": { - "type": "integer", - "description": "Unique identifier of the signature.", - "example": 200001834 - }, - "name": { - "type": "string", - "description": "Human-readable name of the signature.", - "example": "XSS script tag end (Parameter)" + "query_metadata": { + "$ref": "#/components/schemas/QueryMetadata" }, - "accuracy": { - "allOf": [ - { - "$ref": "#/components/schemas/SignatureAccuracy" - }, - { - "description": "Confidence level that this signature accurately identifies the attack.", - "example": "high" - } - ] + "total": { + "type": "integer", + "description": "Total violation occurrence count for the query.\nOnly present when no `group_by` is specified.\n" }, - "risk": { - "allOf": [ - { - "$ref": "#/components/schemas/SignatureRisk" - }, - { - "description": "Severity/risk level of the attack identified by this signature.", - "example": "high" - } - ] + "unique": { + "type": "integer", + "description": "Count of distinct violation types triggered.\nOnly present when no `group_by` is specified.\n" }, - "cve": { - "type": "string", - "description": "CVE identifier if this signature is associated with a known vulnerability.", - "example": "CVE-2021-44228" + "violation": { + "type": "array", + "description": "Violation counts grouped by violation type.\nSorted by count descending.\n", + "items": { + "$ref": "#/components/schemas/ViolationDimensionItem" + } }, - "blocking_mask": { - "type": "string", - "description": "Bitmask indicating blocking behavior configuration.", - "example": "0x0" + "sub_violation": { + "type": "array", + "description": "Violation counts grouped by sub-violation type.\nSorted by count descending.\n", + "items": { + "$ref": "#/components/schemas/ViolationDimensionItem" + } }, - "buffer": { - "type": "string", - "description": "The buffer/location where the signature matched (e.g., parameter name, header).", - "example": "param" + "context": { + "$ref": "#/components/schemas/ViolationContextCountsResponse" }, - "offset": { - "type": "integer", - "description": "Byte offset within the payload where the signature match begins.", - "example": 0 + "context_key": { + "type": "array", + "description": "Violation counts grouped by detection context and field name.\nSorted by count descending. Only present when `group_by=context_key`.\n", + "items": { + "$ref": "#/components/schemas/ViolationContextKeyItem" + } }, - "length": { - "type": "integer", - "description": "Length of the matched string in bytes.", - "example": 42 + "context_value": { + "type": "array", + "description": "Violation counts grouped by detection context and field value.\nSorted by count descending. Only present when `group_by=context_value`.\n", + "items": { + "$ref": "#/components/schemas/ViolationContextValueItem" + } } } }, - "ViolationDetail": { + "ViolationContextKeyItem": { "type": "object", - "description": "Details of a violation detected in the security event.\nA single event can trigger multiple violations.\n", - "required": [ - "name" - ], + "description": "A single entry from a context_key dimension query.", "properties": { - "name": { - "type": "string", - "description": "Primary violation name/type.", - "example": "Illegal meta character in value" - }, - "sub_name": { - "type": "string", - "description": "Sub-category or additional violation classification.", - "example": "" - }, "context": { "type": "string", - "description": "The context where the violation was detected (e.g., parameter, header, uri).", + "description": "Detection context (cookie, header, parameter, uri, request, other).", "example": "parameter" }, - "detail_name": { + "context_key": { "type": "string", - "description": "Technical violation identifier (e.g., VIOL_PARAMETER_VALUE_METACHAR).", - "example": "VIOL_PARAMETER_VALUE_METACHAR" + "description": "Field name within the context (e.g. cookie name, header name, parameter name).", + "example": "search" }, - "detail_context": { + "context_value": { "type": "string", - "description": "Additional context for the violation detail.", - "example": "parameter" + "description": "Most representative field value for this key.", + "example": "" }, - "field_name": { + "count": { + "type": "integer", + "description": "Number of times this key was involved in a violation.", + "example": 228 + } + } + }, + "ViolationContextValueItem": { + "type": "object", + "description": "A single entry from a context_value dimension query.", + "properties": { + "context": { "type": "string", - "description": "Name of the field that triggered the violation.", - "example": "param" + "description": "Detection context (cookie, header, parameter, uri, request, other).", + "example": "parameter" }, - "field_value": { + "context_value": { "type": "string", - "description": "The value that triggered the violation.", + "description": "Field value that triggered the violation.", "example": "" + }, + "count": { + "type": "integer", + "description": "Number of times this value was involved in a violation.", + "example": 228 } } }, - "SecurityEventBase": { + "BillingUsageEventsResponse": { "type": "object", - "description": "Base security event with common fields across all event types.\nSeverity is determined by violation_rating (0-5), not a separate field.\n", + "allOf": [ + { + "$ref": "#/components/schemas/PaginationResponse" + } + ], + "description": "Paginated response for billing usage events query.\n", "required": [ - "timestamp", - "support_id" + "items" ], "properties": { - "timestamp": { + "items": { + "type": "array", + "description": "List of billing usage events matching the query.", + "items": { + "$ref": "#/components/schemas/BillingUsageEvent" + } + } + } + }, + "BillingUsageEvent": { + "type": "object", + "description": "A single billing usage event containing NGINX information, usage metrics, NGINX metrics,\nNGINX deployment details, JWT token information, and event metadata.\n", + "required": [ + "event_id", + "jti", + "nginx_uid" + ], + "properties": { + "nginx_uid": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the NGINX instance.", + "example": "b84b6b2a-721b-46ce-87a4-449fcbc62bae" + }, + "nginx_version": { + "type": "string", + "description": "Version of the NGINX instance.", + "example": "1.29.3" + }, + "nap_status": { + "$ref": "#/components/schemas/NAPStatus" + }, + "start_time": { "type": "string", "format": "date-time", - "description": "When the security event occurred.", - "example": "2024-01-22T12:13:25Z" + "description": "Start time of the event.", + "example": "2026-03-20T23:53:51.000Z" + }, + "end_time": { + "type": "string", + "format": "date-time", + "description": "End time of the event.", + "example": "2026-03-23T19:33:19.000Z" + }, + "http_client_received": { + "type": "integer", + "minimum": 0, + "description": "Bytes received from HTTP clients.", + "example": 11 + }, + "http_client_sent": { + "type": "integer", + "minimum": 0, + "description": "Bytes sent to HTTP clients.", + "example": 12 + }, + "http_client_connections": { + "type": "integer", + "minimum": 0, + "description": "Number of HTTP client connections.", + "example": 13 + }, + "http_client_requests": { + "type": "integer", + "minimum": 0, + "description": "Number of HTTP client requests.", + "example": 14 + }, + "http_upstream_received": { + "type": "integer", + "minimum": 0, + "description": "Bytes received from HTTP upstreams.", + "example": 21 + }, + "http_upstream_sent": { + "type": "integer", + "minimum": 0, + "description": "Bytes sent to HTTP upstreams.", + "example": 22 + }, + "http_upstream_connections": { + "type": "integer", + "minimum": 0, + "description": "Number of HTTP upstream connections.", + "example": 23 + }, + "stream_client_received": { + "type": "integer", + "minimum": 0, + "description": "Bytes received from Stream clients.", + "example": 31 + }, + "stream_client_sent": { + "type": "integer", + "minimum": 0, + "description": "Bytes sent to Stream clients.", + "example": 32 + }, + "stream_client_connections": { + "type": "integer", + "minimum": 0, + "description": "Number of Stream client connections.", + "example": 33 + }, + "stream_upstream_received": { + "type": "integer", + "minimum": 0, + "description": "Bytes received from Stream upstreams.", + "example": 41 + }, + "stream_upstream_sent": { + "type": "integer", + "minimum": 0, + "description": "Bytes sent to Stream upstreams.", + "example": 42 + }, + "stream_upstream_connections": { + "type": "integer", + "minimum": 0, + "description": "Number of Stream upstream connections.", + "example": 43 + }, + "stream_connections": { + "type": "integer", + "minimum": 0, + "description": "Total number of stream connections.", + "example": 0 + }, + "user_agent": { + "type": "string", + "description": "User agent string.", + "example": "nginx/r36" + }, + "workers": { + "type": "integer", + "minimum": 0, + "description": "Number of NGINX workers.", + "example": 51 + }, + "uptime": { + "type": "integer", + "minimum": 0, + "description": "NGINX uptime.", + "example": 52 + }, + "reloads": { + "type": "integer", + "minimum": 0, + "description": "Number of NGINX reloads.", + "example": 53 + }, + "deployment_cluster_id": { + "type": "string", + "format": "uuid", + "description": "Deployment cluster identifier.", + "example": "d24cdb86-9788-4bb5-8d3d-b95d914a618c" + }, + "deployment_cluster_node_count": { + "type": "integer", + "minimum": 0, + "description": "Number of nodes in the deployment cluster.", + "example": 5 }, - "support_id": { + "deployment_installation_id": { "type": "string", - "description": "WAF support identifier for correlating with support cases.", - "example": "1844305495056427365" + "format": "uuid", + "description": "Deployment installation identifier.", + "example": "c548592a-5afb-4e23-84f0-8a5b197dcf96" }, - "request_outcome": { - "allOf": [ - { - "$ref": "#/components/schemas/EventRequestOutcome" - }, - { - "description": "WAF enforcement decision for the request.", - "example": "blocked" - } - ] + "deployment_product_type": { + "$ref": "#/components/schemas/ProductType" }, - "policy_name": { + "sub": { "type": "string", - "description": "Name of the WAF policy that processed the request.", - "example": "app_protect_default_policy" + "description": "JWT subject claim identifying the subscription associated with this usage event.", + "example": "TST-ff13edf7-f912-42c0-ba2e-39c513bb3882" }, - "country_code": { + "jti": { "type": "string", - "maxLength": 2, - "description": "ISO 3166-1 alpha-2 country code of the client IP.", - "example": "US" + "format": "uuid", + "description": "JWT Token ID.", + "example": "18a10260-0ec4-11f1-bbca-5d8e192a1888" }, - "violation_rating": { + "f5_sat": { "type": "integer", + "format": "int64", "minimum": 0, - "maximum": 5, - "description": "Numeric violation severity rating (0-5).", - "example": 5 + "description": "F5 service activation time expiry time, as a Unix epoch timestamp.", + "example": 1772323200 }, - "instance_object_id": { + "f5_order_type": { "type": "string", - "description": "NGINX One Console instance object identifier.", - "example": "inst_8Iwn7dT7RF-PRLxkSt5EYQ" + "description": "F5 order type.", + "example": "paid" }, - "csg_object_id": { + "aud": { "type": "string", - "description": "NGINX One Console Config Sync Group object identifier.", - "example": "csg_-uvR3F2TQGm18jnl7bpaGw" - } - } - }, - "SecurityEvent": { - "allOf": [ - { - "$ref": "#/components/schemas/SecurityEventBase" + "description": "JWT audience claim identifying the intended recipient of the token.", + "example": "urn:f5:teem" }, - { - "type": "object", - "description": "Full security event details including all metadata, violations, and signatures.\nUsed for the single event retrieval endpoint.\n", - "required": [ - "signatures", - "violations" - ], - "properties": { - "type": { - "type": "string", - "description": "Event type classification.", - "example": "Security Event" - }, - "version": { - "type": "string", - "description": "Event schema version.", - "example": "v1.0" - }, - "level": { - "allOf": [ - { - "$ref": "#/components/schemas/EventLevel" - }, - { - "description": "Log level classification for the security event.\n", - "example": "WARNING" - } - ] - }, - "service_id": { - "type": "string", - "description": "Service identifier that generated the event.", - "example": "2b63403b-b8fc-4dd5-a0e9-0ee7d2d252fb" - }, - "correlation_id": { - "type": "string", - "description": "Identifier for correlating related events.", - "example": "6707cc37-d416-4077-bd12-777491027011" - }, - "description": { - "type": "string", - "description": "Human-readable event description.", - "example": "Attack detected" - }, - "system_id": { - "type": "string", - "description": "System identifier of the NGINX instance.", - "example": "31ed9d05-9cb0-48c3-9f97-d63b1b6dd342" - }, - "parent_hostname": { - "type": "string", - "description": "Hostname of the machine running NGINX.", - "example": "nginx-host-01" - }, - "http": { - "$ref": "#/components/schemas/HttpMetadata" - }, - "x_forwarded_for_header_value": { - "type": "string", - "description": "Value of the X-Forwarded-For header if present.", - "example": "203.0.113.42" - }, - "request_status": { - "allOf": [ - { - "$ref": "#/components/schemas/RequestStatus" - }, - { - "description": "Status of request processing.", - "example": "complete" - } - ] - }, - "request_outcome_reason": { - "type": "string", - "description": "Reason code for the enforcement decision.", - "example": "SECURITY_WAF_VIOLATION" - }, - "blocking_exception_reason": { - "type": "string", - "description": "Reason if blocking was bypassed due to an exception.", - "example": "" - }, - "is_truncated": { - "type": "boolean", - "description": "Whether the request was truncated during processing.", - "example": false - }, - "signatures": { - "type": "array", - "description": "List of signatures triggered by this event.", - "items": { - "$ref": "#/components/schemas/SignatureDetail" - } - }, - "violations": { - "type": "array", - "description": "List of violations detected in this event.", - "items": { - "$ref": "#/components/schemas/ViolationDetail" - } - }, - "threat_campaign_names": { - "type": "array", - "description": "Names of threat campaigns associated with this event.", - "items": { - "type": "string" - }, - "example": [] - }, - "request": { - "type": "string", - "description": "Raw HTTP request (if available and not truncated).\nContains headers and body as received by the WAF.\n", - "example": "GET /?param=%3Cscript%3Ealert%27xss%27%3C%2Fscript%3E HTTP/1.1\r\nHost: example.com\r\nUser-Agent: curl/7.68.0\r\nAccept: */*\r\n\r\n" - } - } - } - ] - }, - "SecurityEventListItem": { - "allOf": [ - { - "$ref": "#/components/schemas/SecurityEventBase" + "iss": { + "type": "string", + "description": "JWT issuer claim identifying the entity that issued the token.", + "example": "F5 Inc." }, - { - "type": "object", - "description": "Summary of a security event for list display.\nContains key fields for quick scanning and filtering in the events list.\nThis is a subset of SecurityEvent optimized for the list view.\n", - "properties": { - "client_ip": { - "type": "string", - "description": "Client IP address that sent the request.", - "example": "192.168.1.100" - }, - "url": { - "type": "string", - "description": "Request URI path.", - "example": "/" - }, - "method": { - "type": "string", - "description": "HTTP request method.", - "example": "GET" - }, - "response_code": { - "type": "integer", - "description": "HTTP response status code.", - "example": 403 - } - } - } - ] - }, - "SecurityEventListResponse": { - "allOf": [ - { - "$ref": "#/components/schemas/PaginationResponse" + "iat": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "JWT issued-at time as a Unix epoch timestamp.", + "example": 1771637081 }, - { - "type": "object", - "description": "Paginated list of security events.\n", - "required": [ - "items" - ], - "properties": { - "items": { - "type": "array", - "description": "List of security events for the current page.", - "items": { - "$ref": "#/components/schemas/SecurityEventListItem" - } - } - } + "source_type": { + "$ref": "#/components/schemas/SourceType" + }, + "dedup_version": { + "type": "string", + "format": "date-time", + "description": "Deduplication version timestamp assigned for storage-level upsert/deduplication.", + "example": "2026-03-23T19:33:32.284Z" + }, + "event_id": { + "type": "string", + "description": "Unique event identifier.", + "example": "4nNhnUFf23Zf4PExDYtcYZUkfHlyW48JouApQkxFqzo=" } - ] + } }, - "ViolationsDimensionField": { + "SourceType": { "type": "string", - "description": "Available dimensions for grouping and filtering violation analytics.\n\n* violation: Primary violation type (e.g., \"Attack signature detected\", \"Illegal meta character in value\")\n* sub_violation: Sub-category or additional violation classification providing more granular detail. A value of \"N/A\" indicates no additional information.\n* context: Location where violation was detected (header, cookie, parameter, uri, request, other)\n", + "description": "Source type of the billing usage event.\n* `SOURCE_TYPE_NGINX_ONE` - NGINX One\n* `SOURCE_TYPE_NIM` - NGINX Instance Manager\n", "enum": [ - "violation", - "sub_violation", - "context" + "SOURCE_TYPE_NGINX_ONE", + "SOURCE_TYPE_NIM" ], "x-enum-varnames": [ - "violations_dimension_violation", - "violations_dimension_sub_violation", - "violations_dimension_context" - ] + "source_type_nginx_one", + "source_type_nim" + ], + "example": "SOURCE_TYPE_NGINX_ONE" }, - "ViolationsQueryRequest": { - "allOf": [ - { - "$ref": "#/components/schemas/BaseQueryRequest" - }, - { - "type": "object", - "description": "Request body for querying violation analytics.\n", - "properties": { - "group_by": { - "allOf": [ - { - "$ref": "#/components/schemas/ViolationsDimensionField" - }, - { - "description": "Dimension to aggregate results by.\n\n**Fixed enum dimensions** (returned as objects with known keys):\n* `context` - cookie, header, parameter, request, uri, other\n\n**Dynamic dimensions** (returned as arrays with cross-dimension context):\n* `violation` - WAF policy violation types (e.g., \"Attack signature detected\")\n* `sub_violation` - Specific subtypes providing granular detail (e.g., \"SQL-Injection\" or \"Missing Mandatory Host Header\"). Returns \"N/A\" if not applicable.\n\n**Response behavior:**\n- If omitted: Returns `total` (violation occurrences) and `unique` (distinct violation types)\n- If specified: Returns dimensional breakdown, `total` and `unique` are omitted\n", - "example": "violation" - } - ] - }, - "filter": { - "type": "array", - "description": "Pre-aggregation filter conditions.\nAll filters are combined with AND logic.\nUse the `in` operator to achieve `OR` within a single dimension.\n\nSupported filter dimensions include attack-level dimensions (policy, ip, url, etc.)\nin addition to violation-specific dimensions.\n", - "items": { - "$ref": "#/components/schemas/AnalyticsFilter" - }, - "default": [] - }, - "order_by": { - "$ref": "#/components/schemas/AnalyticsOrderBy" - } - } - } - ] + "NAPStatus": { + "type": "string", + "description": "NGINX App Protect status of the instance.\n* `NAP_STATUS_INACTIVE_OR_UNSPECIFIED` - Not specified or inactive\n* `NAP_STATUS_ACTIVE` - Active\n", + "enum": [ + "NAP_STATUS_INACTIVE_OR_UNSPECIFIED", + "NAP_STATUS_ACTIVE" + ], + "x-enum-varnames": [ + "nap_status_inactive_or_unspecified", + "nap_status_active" + ], + "example": "NAP_STATUS_ACTIVE" + }, + "ProductType": { + "type": "string", + "description": "Deployment product type.\n* `PRODUCT_TYPE_UNSPECIFIED` - Not specified is treated as being NGINX+\n* `PRODUCT_TYPE_NIC` - NGINX Ingress Controller\n* `PRODUCT_TYPE_NGF` - NGINX Gateway Fabric\n", + "enum": [ + "PRODUCT_TYPE_UNSPECIFIED", + "PRODUCT_TYPE_NIC", + "PRODUCT_TYPE_NGF" + ], + "x-enum-varnames": [ + "product_type_unspecified", + "product_type_nic", + "product_type_ngf" + ], + "example": "PRODUCT_TYPE_NIC" } }, "examples": { @@ -15608,6 +18742,12 @@ "tags": [ "Templates" ] + }, + { + "name": "NGINX One App Protect Analytics", + "tags": [ + "NGINX One App Protect" + ] } ] } \ No newline at end of file From dd939d8de868edc0ed34d0b7bb8275b006946f46 Mon Sep 17 00:00:00 2001 From: Venkat Reddy Marepally <102700175+vrmare@users.noreply.github.com> Date: Tue, 7 Apr 2026 22:11:38 -0700 Subject: [PATCH 07/13] fix call-out note --- .../waf-security-dashboard/dashboard-metrics-reference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/dashboard-metrics-reference.md b/content/nginx-one-console/waf-integration/waf-security-dashboard/dashboard-metrics-reference.md index 1f9f6a965..cc8c163d9 100644 --- a/content/nginx-one-console/waf-integration/waf-security-dashboard/dashboard-metrics-reference.md +++ b/content/nginx-one-console/waf-integration/waf-security-dashboard/dashboard-metrics-reference.md @@ -50,7 +50,7 @@ Time-series widgets bucket their data based on the selected window — shorter w | Last 2–7 days | 1 hour | | Last 14 days | 6 hours | -{{< note >}}Security events are retained for **90 days**, but the dashboard time window picker is currently limited to the **last 14 days**. To query the full retention window, use the [analytics API]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md" >}}), which accepts any time range up to 90 days.{{< /note >}} +{{< call-out "note" >}}Security events are retained for **90 days**, but the dashboard time window picker is currently limited to the **last 14 days**. To query the full retention window, use the [analytics API]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md" >}}), which accepts any time range up to 90 days.{{< /call-out >}} ### Add Filter From 7c557d19b2fde7adf23c774a8e5ef92e1032ae6f Mon Sep 17 00:00:00 2001 From: Venkat Reddy Marepally <102700175+vrmare@users.noreply.github.com> Date: Wed, 8 Apr 2026 12:21:17 -0700 Subject: [PATCH 08/13] renamed for clarity --- .../waf-integration/_index.md | 2 +- .../waf-security-dashboard/_index.md | 2 +- .../dashboard-metrics-reference.md | 18 +++------- .../default-log-profile.md | 34 +++++++++---------- .../find-event-by-support-id.md | 5 +-- .../security-monitoring-overview.md | 6 ++-- .../set-up-security-monitoring.md | 14 ++++---- 7 files changed, 37 insertions(+), 44 deletions(-) diff --git a/content/nginx-one-console/waf-integration/_index.md b/content/nginx-one-console/waf-integration/_index.md index 2e4a1e9b7..1a4b0b85f 100644 --- a/content/nginx-one-console/waf-integration/_index.md +++ b/content/nginx-one-console/waf-integration/_index.md @@ -1,5 +1,5 @@ --- -title: Secure with F5 WAF for NGINX +title: Secure your fleet with F5 WAF for NGINX description: weight: 400 url: /nginx-one-console/waf-integration diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/_index.md b/content/nginx-one-console/waf-integration/waf-security-dashboard/_index.md index 761758604..2b54e1883 100644 --- a/content/nginx-one-console/waf-integration/waf-security-dashboard/_index.md +++ b/content/nginx-one-console/waf-integration/waf-security-dashboard/_index.md @@ -10,7 +10,7 @@ Use the security monitoring module in NGINX One Console to collect, visualize, a This section covers: - [Security monitoring overview]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/security-monitoring-overview.md" >}}) — what the security dashboard is, the data pipeline behind it, and what you can do with it. -- [Default log profile]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md" >}}) — the immutable, pre-compiled log profile the dashboard depends on. +- [secops_dashboard log profile]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md" >}}) — the immutable, pre-compiled log profile the dashboard depends on. - [Set up security monitoring]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md" >}}) — install F5 WAF for NGINX, configure the log profile, and forward events through NGINX Agent. - [Security dashboard reference]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/dashboard-metrics-reference.md" >}}) — dashboard tabs, global controls, and how each widget maps to an underlying dimension. - [Find a security event by Support ID]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/find-event-by-support-id.md" >}}) — look up a single security event by its Support ID for quick triage. diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/dashboard-metrics-reference.md b/content/nginx-one-console/waf-integration/waf-security-dashboard/dashboard-metrics-reference.md index cc8c163d9..7d5474705 100644 --- a/content/nginx-one-console/waf-integration/waf-security-dashboard/dashboard-metrics-reference.md +++ b/content/nginx-one-console/waf-integration/waf-security-dashboard/dashboard-metrics-reference.md @@ -38,19 +38,11 @@ Two controls at the top of the page apply to every widget on every tab. ### Time window -Selects the query window for all widgets. The picker offers preset windows from **Last 5 minutes** to **Last 14 days**. You can also select a custom range by highlighting an area of interest on any time-series chart. +Selects the query window for all widgets. The picker offers preset windows from **Last 5 minutes** to **Last 60 days**. You can also select a custom range by highlighting an area of interest on any time-series chart. -Time-series widgets bucket their data based on the selected window — shorter windows produce finer buckets. +Time-series widgets bucket their data automatically based on the selected window — shorter windows produce finer buckets. -| Selected window | Default bucket size for time-series widgets | -|:--- |:--- | -| Last 5–30 minutes | 1 minute | -| Last 1–6 hours | 1 minute | -| Last 12–24 hours | 1 hour | -| Last 2–7 days | 1 hour | -| Last 14 days | 6 hours | - -{{< call-out "note" >}}Security events are retained for **90 days**, but the dashboard time window picker is currently limited to the **last 14 days**. To query the full retention window, use the [analytics API]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md" >}}), which accepts any time range up to 90 days.{{< /call-out >}} +{{< call-out "note" >}}Security events are retained for **90 days**, but the dashboard time window picker tops out at the **last 60 days**. To query the full retention window, use the [analytics API]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md" >}}), which accepts any time range up to 90 days.{{< /call-out >}} ### Add Filter @@ -73,7 +65,7 @@ Applies one or more filter expressions to every widget on every tab. The dashboa | **Signature ID** | The numeric F5 WAF for NGINX signature ID. | | **Signature Name** | The name of a triggered signature. | | **Signature Risk** | The risk level of a triggered signature: `low`, `medium`, or `high`. | -| **Status** | The final WAF decision: `blocked` or `alerted`. | +| **Status** | The final WAF decision: `blocked`, `alerted`, or `passed`. | | **Subviolation** | The sub-violation name within a violation. | | **Support ID** | The unique identifier F5 WAF for NGINX assigns to each event. | | **Threat Campaign** | The name of a matched threat campaign. | @@ -143,7 +135,7 @@ The Event Logs tab lists individual security events matching the global filters | Column | Description | |:--- |:--- | -| **Status** | The final WAF decision: `blocked` or `alerted`. | +| **Status** | The final WAF decision: `blocked`, `alerted`, or `passed`. | | **URI** | The request URI that triggered the event. | | **Policy** | The F5 WAF for NGINX policy that produced the event. | | **Time** | When F5 WAF for NGINX produced the event. | diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md b/content/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md index 618e6d843..a2e385f37 100644 --- a/content/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md +++ b/content/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md @@ -2,37 +2,37 @@ nd-content-type: concept nd-docs: DOCS-000 nd-product: NONECO -title: Default log profile +title: secops_dashboard log profile description: "An immutable, pre-compiled F5 WAF for NGINX log profile that captures the security telemetry the security dashboard needs." weight: 200 toc: true nd-keywords: "default log profile, security dashboard, F5 WAF for NGINX, log profile, security telemetry, NAP log profile" nd-summary: > - The default log profile is a pre-configured F5 WAF for NGINX log profile that captures security violations in a standardized format for the security monitoring dashboard. + The `secops_dashboard` log profile is a pre-configured F5 WAF for NGINX log profile that captures security violations in a standardized format for the security monitoring dashboard. It is the default log profile used by the security dashboard. Use it to send security telemetry from your NGINX Plus data planes to NGINX One Console without authoring or compiling a custom log profile. - This document covers what the default log profile is, when to use it, and how it differs from custom log profiles. + This document covers what the `secops_dashboard` log profile is, when to use it, and how it differs from custom log profiles. nd-audience: operator --- -The security monitoring dashboard depends on a consistent set of fields being present on every security event. The default log profile is the contract that guarantees that consistency across every data plane forwarding events to NGINX One Console. +The security monitoring dashboard depends on a consistent set of fields being present on every security event. The `secops_dashboard` log profile is the contract that guarantees that consistency across every data plane forwarding events to NGINX One Console. -## What is the default log profile? +## What is the `secops_dashboard` log profile? -The default log profile is a pre-configured, system-managed F5 WAF for NGINX log profile that captures the security telemetry fields the NGINX One Console security monitoring dashboard expects. NGINX One Console ships and maintains it; you cannot edit or delete it. +The `secops_dashboard` log profile is a pre-configured, system-managed F5 WAF for NGINX log profile that captures the security telemetry fields the NGINX One Console security monitoring dashboard expects. It is the default log profile used by the security dashboard. NGINX One Console ships and maintains it; you cannot edit or delete it. -It is similar in structure and function to other [log profiles]({{< ref "/nginx-one-console/waf-integration/log-profiles/_index.md" >}}), but it is treated as a system asset rather than a user-managed resource. The default log profile is the only log profile guaranteed to produce data the security dashboard can render correctly. Custom log profiles can coexist with it and continue to serve other logging destinations (SIEMs, file logs, custom syslog endpoints), but they are not interpreted by the security dashboard. +It is similar in structure and function to other [log profiles]({{< ref "/nginx-one-console/waf-integration/log-profiles/_index.md" >}}), but it is treated as a system asset rather than a user-managed resource. The `secops_dashboard` log profile is the only log profile guaranteed to produce data the security dashboard can render correctly. Custom log profiles can coexist with it and continue to serve other logging destinations (SIEMs, file logs, custom syslog endpoints), but they are not interpreted by the security dashboard. -This document covers what the default log profile is and when to use it. For the steps to deploy it as part of setting up an instance, see [Set up security monitoring]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md" >}}). +This document covers what the `secops_dashboard` log profile is and when to use it. For the steps to deploy it as part of setting up an instance, see [Set up security monitoring]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md" >}}). --- ## How to identify it in the console -In NGINX One Console, go to **WAF** > **Log Profiles**. The default log profile appears in the list as **`secops_dashboard`** with an **F5** badge next to its name. The badge marks it as a system-managed profile created and maintained by F5. +In NGINX One Console, go to **WAF** > **Log Profiles**. The `secops_dashboard` log profile appears in the list with an **F5** badge next to its name. The badge marks it as a system-managed profile created and maintained by F5. -The available **Actions** on the default log profile are limited compared to a user-created log profile. You can **Deploy**, **Download JSON**, **Manage Bundle**, and **Make a copy**, but **Edit** and **Delete** are not exposed — the profile is system-managed and cannot be modified or removed. +The available **Actions** on the `secops_dashboard` log profile are limited compared to a user-created log profile. You can **Deploy**, **Download JSON**, **Manage Bundle**, and **Make a copy**, but **Edit** and **Delete** are not exposed — the profile is system-managed and cannot be modified or removed. -To see the compiled bundles for the default log profile, open the profile and select **Actions** > **Manage Bundle**. The **Bundles** tab lists every available WAF compiler version with its compilation status (`Compiled` or `Compiling`) and a **Download** action for each compiled bundle. NGINX One Console keeps these bundles up to date automatically — you do not need to compile them yourself. +To see the compiled bundles for the `secops_dashboard` log profile, open the profile and select **Actions** > **Manage Bundle**. The **Bundles** tab lists every available WAF compiler version with its compilation status (`Compiled` or `Compiling`) and a **Download** action for each compiled bundle. NGINX One Console keeps these bundles up to date automatically — you do not need to compile them yourself. If you need a log profile with a different field set or filter rules, use **Make a copy** to create an editable, user-owned log profile based on `secops_dashboard`. The copy is a regular custom log profile and is not used by the security dashboard. @@ -40,10 +40,10 @@ If you need a log profile with a different field set or filter rules, use **Make ## Key characteristics -The default log profile has three properties that distinguish it from user-created log profiles. +The `secops_dashboard` log profile has three properties that distinguish it from user-created log profiles. -- **Immutable**: You cannot edit or delete the default log profile. NGINX One Console manages it as a system resource so the security monitoring data format remains consistent across every instance and tenant. -- **Pre-compiled**: NGINX One Console automatically compiles the default log profile for every available WAF compiler version. Deployment completes immediately without an on-demand compilation step. +- **Immutable**: You cannot edit or delete the `secops_dashboard` log profile. NGINX One Console manages it as a system resource so the security monitoring data format remains consistent across every instance and tenant. +- **Pre-compiled**: NGINX One Console automatically compiles the `secops_dashboard` log profile for every available WAF compiler version. Deployment completes immediately without an on-demand compilation step. - **Standardized field set**: It captures every field the security dashboard reads, including the support ID, violation details, signature information, threat campaign matches, request context, and client geolocation. Filters and analytics in the dashboard assume these fields are present. --- @@ -52,15 +52,15 @@ The default log profile has three properties that distinguish it from user-creat ### Operator: enable security monitoring for an NGINX Plus fleet -A platform operator wants central visibility into F5 WAF for NGINX events across a fleet of NGINX Plus instances. They deploy the default log profile to every instance, knowing that every event will land in NGINX One Console with the same field set, so dashboard widgets, filters, and analytics behave the same regardless of which instance produced the event. They do not need to author, compile, or version-control a log profile to get the dashboard working. +A platform operator wants central visibility into F5 WAF for NGINX events across a fleet of NGINX Plus instances. They deploy the `secops_dashboard` log profile to every instance, knowing that every event will land in NGINX One Console with the same field set, so dashboard widgets, filters, and analytics behave the same regardless of which instance produced the event. They do not need to author, compile, or version-control a log profile to get the dashboard working. ### Security engineer: keep dashboard data consistent during a policy change -A security engineer is rolling out a new WAF policy to a subset of instances and wants the security dashboard to continue showing comparable metrics across the migration. Because the default log profile is immutable and shared, the data format does not change with the policy, and the engineer can compare attack counts and signature trends before and after the rollout without normalizing fields. +A security engineer is rolling out a new WAF policy to a subset of instances and wants the security dashboard to continue showing comparable metrics across the migration. Because the `secops_dashboard` log profile is immutable and shared, the data format does not change with the policy, and the engineer can compare attack counts and signature trends before and after the rollout without normalizing fields. ### Operator: combine dashboard monitoring with a custom SIEM pipeline -An operator already forwards security logs to an external SIEM with a custom log profile that uses a different field layout. They deploy the default log profile alongside the existing custom profile so that NGINX One Console gets the standardized format the dashboard requires, while the SIEM continues to receive the custom format unchanged. +An operator already forwards security logs to an external SIEM with a custom log profile that uses a different field layout. They deploy the `secops_dashboard` log profile alongside the existing custom profile so that NGINX One Console gets the standardized format the dashboard requires, while the SIEM continues to receive the custom format unchanged. --- diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/find-event-by-support-id.md b/content/nginx-one-console/waf-integration/waf-security-dashboard/find-event-by-support-id.md index 9c279fdaf..c223d0c58 100644 --- a/content/nginx-one-console/waf-integration/waf-security-dashboard/find-event-by-support-id.md +++ b/content/nginx-one-console/waf-integration/waf-security-dashboard/find-event-by-support-id.md @@ -51,7 +51,7 @@ The Security Event detail panel surfaces every field stored on the event: - **Time of Request** — when F5 WAF for NGINX produced the event. - **Triggered violations and signatures** — every violation and signature that fired on the event, with their full attributes (name, accuracy, risk, CVE, context). - **Threat campaigns** — any threat campaigns matched by the event. -- **Policy and outcome** — the F5 WAF for NGINX policy that produced the event, the request status (`blocked` or `alerted`), and the outcome reason. +- **Policy and outcome** — the F5 WAF for NGINX policy that produced the event, the request status (`blocked`, `alerted`, or `passed`), and the outcome reason. --- @@ -59,7 +59,8 @@ The Security Event detail panel surfaces every field stored on the event: A Support ID can come from any system that observed the request: -- **F5 WAF for NGINX security logs on the data plane** — the Support ID is the first field in every log line emitted by the [default log profile]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md" >}}). +- **NGINX One Console Event Logs tab** — every row in the Event Logs table on the [security dashboard]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/dashboard-metrics-reference.md#event-logs-tab" >}}) includes the Support ID. Copy a Support ID from there to share in a ticket, support case, or follow-up message. +- **F5 WAF for NGINX security logs on the data plane** — the Support ID is the first field in every log line emitted by the [`secops_dashboard` log profile]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md" >}}). - **F5 WAF for NGINX rejection page** — when F5 WAF for NGINX blocks a request, the response page typically includes the Support ID so the user can quote it back to support. - **Customer support cases** — end users who hit a Request Rejected page can be asked to provide the Support ID from that page. diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/security-monitoring-overview.md b/content/nginx-one-console/waf-integration/waf-security-dashboard/security-monitoring-overview.md index 56b068c31..30de25d01 100644 --- a/content/nginx-one-console/waf-integration/waf-security-dashboard/security-monitoring-overview.md +++ b/content/nginx-one-console/waf-integration/waf-security-dashboard/security-monitoring-overview.md @@ -29,7 +29,7 @@ This document covers what the module is and how data flows through it. For deplo The data pipeline has four stages: 1. **Detection.** F5 WAF for NGINX inspects requests on the data plane and produces a security log entry whenever a request matches a violation, signature, or threat campaign. -2. **Forwarding.** F5 WAF for NGINX writes the entry over syslog (port `1514` on localhost) using the [default log profile]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md" >}}). NGINX Agent's OpenTelemetry collector receives it through the `tcplog/nginx_app_protect` receiver. +2. **Forwarding.** F5 WAF for NGINX writes the entry over syslog (port `1514` on localhost) using the [`secops_dashboard` log profile]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md" >}}). NGINX Agent's OpenTelemetry collector receives it through the `tcplog/nginx_app_protect` receiver. 3. **Transport.** The collector batches events and exports them to NGINX One Console through the `otlp/default` exporter. Batching keeps the upstream call rate low while keeping per-event delivery latency under a minute. 4. **Storage and query.** NGINX One Console parses, indexes, and stores the events. The security dashboard and the analytics API both read from the same store. @@ -50,7 +50,7 @@ Security events inherit the scope of the instance that produced them. ## Retention -Security events are retained for **90 days**. Queries that reach further back than 90 days return no results. If you need long-term retention, forward events to an external SIEM with a [custom log profile]({{< ref "/nginx-one-console/waf-integration/log-profiles/_index.md" >}}) in addition to the default log profile. +Security events are retained for **90 days**. Queries that reach further back than 90 days return no results. If you need long-term retention, forward events to an external SIEM with a [custom log profile]({{< ref "/nginx-one-console/waf-integration/log-profiles/_index.md" >}}) in addition to the `secops_dashboard` log profile. --- @@ -83,7 +83,7 @@ A platform team needs a weekly summary of WAF activity across hundreds of instan For more information, see: - [Set up security monitoring]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md" >}}) -- [Default log profile]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md" >}}) +- [secops_dashboard log profile]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md" >}}) - [Dashboard metrics reference]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/dashboard-metrics-reference.md" >}}) - [Find a security event by Support ID]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/find-event-by-support-id.md" >}}) - [Query security events through the API]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md" >}}) diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md b/content/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md index b1676e80c..2b844cfa1 100644 --- a/content/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md +++ b/content/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md @@ -9,7 +9,7 @@ toc: true nd-keywords: "F5 WAF for NGINX, security monitoring, security dashboard, default log profile, security events" nd-summary: > Forward F5 WAF for NGINX security events from an NGINX Plus instance to the NGINX One Console security monitoring dashboard. - You deploy the default log profile through the console, add the WAF directives to your NGINX configuration, and verify events flow into the dashboard. + You deploy the `secops_dashboard` log profile through the console, add the WAF directives to your NGINX configuration, and verify events flow into the dashboard. Repeat these steps for each data plane you want to monitor. nd-audience: operator --- @@ -18,7 +18,7 @@ nd-audience: operator This guide walks you through enabling F5 WAF for NGINX security monitoring on an NGINX Plus instance that is already connected to NGINX One Console. After you complete the steps, security events appear in the [security monitoring dashboard]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/_index.md" >}}), where you can review attacks, violations, and triggered signatures. -The flow uses the NGINX One Console UI end to end. You deploy the [default log profile]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md" >}}) to the instance, add the F5 WAF for NGINX directives to the NGINX configuration through the console's config editor, and verify the pipeline by triggering test violations. NGINX Agent automatically configures its OpenTelemetry collector to forward security events to NGINX One Console once it sees the correct directives in the NGINX configuration — you do not need to edit the agent configuration by hand. +The flow uses the NGINX One Console UI end to end. You deploy the [`secops_dashboard` log profile]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md" >}}) to the instance, add the F5 WAF for NGINX directives to the NGINX configuration through the console's config editor, and verify the pipeline by triggering test violations. NGINX Agent automatically configures its OpenTelemetry collector to forward security events to NGINX One Console once it sees the correct directives in the NGINX configuration — you do not need to edit the agent configuration by hand. --- @@ -33,9 +33,9 @@ Before you begin, ensure you have: --- -## Deploy the default log profile +## Deploy the `secops_dashboard` log profile -The security dashboard relies on the default log profile (`secops_dashboard`) to capture security violations in a standardized format. The default log profile is created and maintained by F5, immutable, and pre-compiled for every available WAF compiler version. It deploys exactly the same way as a custom log profile, and because it is pre-compiled, deployment completes immediately without an on-demand compile. For background, see [Default log profile]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md" >}}). +The security dashboard relies on the `secops_dashboard` log profile to capture security violations in a standardized format. It is created and maintained by F5, immutable, and pre-compiled for every available WAF compiler version, so it deploys exactly the same way as a custom log profile but completes immediately without an on-demand compile. For background, see [secops_dashboard log profile]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md" >}}). 1. In NGINX One Console, go to **WAF** > **Log Profiles** and select **`secops_dashboard`**. @@ -66,7 +66,7 @@ For more on the deployment wizard and the alternative **Add File** > **Existing ## Verify the setup -When you select **Publish** in the previous step, NGINX One Console pushes the configuration change to the instance and displays a confirmation toast indicating the publish succeeded. At that point both the F5 WAF for NGINX policy and the default log profile are in place on the data plane, and the security log directive is wired up to NGINX Agent. +When you select **Publish** in the previous step, NGINX One Console pushes the configuration change to the instance and displays a confirmation toast indicating the publish succeeded. At that point both the F5 WAF for NGINX policy and the `secops_dashboard` log profile are in place on the data plane, and the security log directive is wired up to NGINX Agent. From this point on, any request that F5 WAF for NGINX inspects on the instance produces a security event that flows to NGINX One Console. To see those events: @@ -97,7 +97,7 @@ Re-run the deployment wizard after fixing the configuration. **Symptom**: The publish toast confirmed success, the instance is online in NGINX One Console, but the **WAF > Security Dashboard** shows no events for your instance. -**Cause**: The most common causes are that the default log profile is not deployed to that instance, the `app_protect_security_log` directive is in a context that does not handle traffic, or the instance has not yet processed any requests F5 WAF for NGINX would inspect. +**Cause**: The most common causes are that the `secops_dashboard` log profile is not deployed to that instance, the `app_protect_security_log` directive is in a context that does not handle traffic, or the instance has not yet processed any requests F5 WAF for NGINX would inspect. **Fix**: @@ -115,7 +115,7 @@ If events still do not appear after a request is processed, contact F5 support w For more information, see: - [Security monitoring overview]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/security-monitoring-overview.md" >}}) -- [Default log profile]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md" >}}) +- [secops_dashboard log profile]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md" >}}) - [Deploy log profiles]({{< ref "/nginx-one-console/waf-integration/log-profiles/deploy-log-profiles.md" >}}) - [Add an instance]({{< ref "/nginx-one-console/connect-instances/add-instance.md" >}}) - [Dashboard metrics reference]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/dashboard-metrics-reference.md" >}}) From 23766af3cc6ff6e5c549f9a33fa6e9393f64b758 Mon Sep 17 00:00:00 2001 From: Venkat Reddy Marepally <102700175+vrmare@users.noreply.github.com> Date: Wed, 8 Apr 2026 14:02:39 -0700 Subject: [PATCH 09/13] Apply review feedback from the WAF security monitoring docs walkthrough --- .../waf-integration/waf-security-dashboard/_index.md | 2 +- .../waf-security-dashboard/default-log-profile.md | 4 ++-- .../waf-security-dashboard/query-events-api.md | 2 +- .../security-monitoring-overview.md | 11 +++++------ .../set-up-security-monitoring.md | 12 +++++++----- 5 files changed, 16 insertions(+), 15 deletions(-) diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/_index.md b/content/nginx-one-console/waf-integration/waf-security-dashboard/_index.md index 2b54e1883..0dba8d861 100644 --- a/content/nginx-one-console/waf-integration/waf-security-dashboard/_index.md +++ b/content/nginx-one-console/waf-integration/waf-security-dashboard/_index.md @@ -5,7 +5,7 @@ weight: 425 url: /nginx-one-console/waf-integration/waf-security-dashboard --- -Use the security monitoring module in NGINX One Console to collect, visualize, and query security events from F5 WAF for NGINX instances. Review attacks, violations, and triggered signatures to assess threats and fine-tune your policies. +Use the security monitoring module in NGINX One Console to collect, visualize, and query security events from F5 WAF for NGINX running on NGINX Plus instances. Review attacks, violations, and triggered signatures to assess threats and fine-tune your policies. This section covers: diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md b/content/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md index a2e385f37..80235f5c6 100644 --- a/content/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md +++ b/content/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md @@ -18,9 +18,9 @@ The security monitoring dashboard depends on a consistent set of fields being pr ## What is the `secops_dashboard` log profile? -The `secops_dashboard` log profile is a pre-configured, system-managed F5 WAF for NGINX log profile that captures the security telemetry fields the NGINX One Console security monitoring dashboard expects. It is the default log profile used by the security dashboard. NGINX One Console ships and maintains it; you cannot edit or delete it. +The `secops_dashboard` log profile is a pre-configured, system-managed F5 WAF for NGINX log profile that captures the security telemetry fields the NGINX One Console security monitoring dashboard expects. It is the default log profile used by the security dashboard. NGINX One Console maintains it as a system asset; you cannot edit or delete it. -It is similar in structure and function to other [log profiles]({{< ref "/nginx-one-console/waf-integration/log-profiles/_index.md" >}}), but it is treated as a system asset rather than a user-managed resource. The `secops_dashboard` log profile is the only log profile guaranteed to produce data the security dashboard can render correctly. Custom log profiles can coexist with it and continue to serve other logging destinations (SIEMs, file logs, custom syslog endpoints), but they are not interpreted by the security dashboard. +It is similar in structure and function to other [log profiles]({{< ref "/nginx-one-console/waf-integration/log-profiles/_index.md" >}}), but it is treated as a system asset rather than a user-managed resource. The `secops_dashboard` log profile is the only log profile guaranteed to produce data the security dashboard can render correctly. Custom log profiles can coexist with it and continue to serve other logging destinations such as Security Information and Event Management (SIEM) systems, file logs, or custom syslog endpoints, but they are not interpreted by the security dashboard. This document covers what the `secops_dashboard` log profile is and when to use it. For the steps to deploy it as part of setting up an instance, see [Set up security monitoring]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md" >}}). diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md b/content/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md index f6b215514..8aec93b06 100644 --- a/content/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md +++ b/content/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md @@ -16,7 +16,7 @@ nd-audience: developer ## Overview -You can use the NGINX One Console API to query F5 WAF for NGINX security events programmatically. The API exposes the same security event store the security monitoring dashboard reads from, so any view you can build in the dashboard can also be reproduced through the API. Use the API to integrate WAF activity into your own dashboards, automated reports, SIEM enrichment pipelines, or alerting workflows. +You can use the NGINX One Console API to query F5 WAF for NGINX security events programmatically. The API exposes the same security event store the security monitoring dashboard reads from, so any view you can build in the dashboard can also be reproduced through the API. Use the API to integrate WAF activity into your own dashboards, automated reports, Security Information and Event Management (SIEM) enrichment pipelines, or alerting workflows. For the full request and response schema of each operation, including the supported filter fields and group-by dimensions, see the [API reference guide]({{< ref "/nginx-one-console/api/api-reference-guide.md" >}}). diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/security-monitoring-overview.md b/content/nginx-one-console/waf-integration/waf-security-dashboard/security-monitoring-overview.md index 30de25d01..60cf611fe 100644 --- a/content/nginx-one-console/waf-integration/waf-security-dashboard/security-monitoring-overview.md +++ b/content/nginx-one-console/waf-integration/waf-security-dashboard/security-monitoring-overview.md @@ -39,18 +39,17 @@ Every event carries the support ID, the policy that matched it, the violation an ## How data is scoped -Security events inherit the scope of the instance that produced them. +Every security event carries enough context to attribute it to a specific data plane, a specific policy, and the application it targeted. -- **Tenant**: Events belong to the NGINX One Console tenant the data plane is registered to. Tenants do not see each other's data. -- **Namespace**: Within a tenant, events are partitioned by the namespace the instance lives in. Filters and queries are scoped to the active namespace by default. -- **Instance and policy**: Each event records the instance hostname and the F5 WAF for NGINX policy name that produced it, so you can attribute activity to a specific data plane and a specific policy version. -- **Hostname vs. request host**: The dashboard exposes both the NGINX instance hostname and the HTTP `Host` header from the request as separate filterable fields. Use the instance hostname to scope by data plane; use the request host to scope by the application being attacked. +- **Instance**: Each event records the NGINX instance hostname that produced it. Use this to scope by data plane. +- **Policy**: Each event records the F5 WAF for NGINX policy that produced it, so you can compare activity across policy versions or rollouts. +- **Destination hostname**: Each event records the HTTP `Host` header sent by the client. Use this to scope by the application being attacked, which is often distinct from the instance hostname when the same data plane fronts multiple applications. --- ## Retention -Security events are retained for **90 days**. Queries that reach further back than 90 days return no results. If you need long-term retention, forward events to an external SIEM with a [custom log profile]({{< ref "/nginx-one-console/waf-integration/log-profiles/_index.md" >}}) in addition to the `secops_dashboard` log profile. +Security events are retained for **90 days**. Queries that reach further back than 90 days return no results. If you need long-term retention, forward events to an external Security Information and Event Management (SIEM) system with a [custom log profile]({{< ref "/nginx-one-console/waf-integration/log-profiles/_index.md" >}}) in addition to the `secops_dashboard` log profile. --- diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md b/content/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md index 2b844cfa1..d4f5c6539 100644 --- a/content/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md +++ b/content/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md @@ -30,6 +30,7 @@ Before you begin, ensure you have: - **F5 WAF for NGINX installed and loaded**: F5 WAF for NGINX installed on the same host as NGINX Plus, with the `load_module` directive added to `nginx.conf` and `app_protect_enable on;` set in the contexts you want WAF to inspect. See [Install F5 WAF for NGINX]({{< ref "/waf/install/virtual-environment.md" >}}) and [Update configuration files]({{< ref "/waf/install/virtual-environment.md#update-configuration-files" >}}). - **A WAF policy deployed to the instance**: An F5 WAF for NGINX policy referenced by an `app_protect_policy_file` directive in the same context where you enable WAF. See [WAF policies]({{< ref "/nginx-one-console/waf-integration/policy/_index.md" >}}) for how to create and deploy a policy through NGINX One Console. - **Instance connected to NGINX One Console**: The data plane is registered with NGINX One Console and NGINX Agent is running on it. See [Add an instance]({{< ref "/nginx-one-console/connect-instances/add-instance.md" >}}). +- **NGINX Agent 3.9.0 or later**: Security event forwarding to NGINX One Console requires NGINX Agent 3.9.0 or later. See the [NGINX Agent install and upgrade guide]({{< ref "/nginx-one-console/agent/install-upgrade/_index.md" >}}) to upgrade an existing agent. --- @@ -97,14 +98,15 @@ Re-run the deployment wizard after fixing the configuration. **Symptom**: The publish toast confirmed success, the instance is online in NGINX One Console, but the **WAF > Security Dashboard** shows no events for your instance. -**Cause**: The most common causes are that the `secops_dashboard` log profile is not deployed to that instance, the `app_protect_security_log` directive is in a context that does not handle traffic, or the instance has not yet processed any requests F5 WAF for NGINX would inspect. +**Cause**: The most common causes are that NGINX Agent on the instance is older than 3.9.0 and does not include the auto-configured security event pipeline, the `secops_dashboard` log profile is not deployed to that instance, the `app_protect_security_log` directive is in a context that does not handle traffic, or the instance has not yet processed any requests F5 WAF for NGINX would inspect. **Fix**: -1. Go to **WAF** > **Log Profiles** and confirm `secops_dashboard` is listed as deployed to the target instance under **Deployed To**. -2. Open the instance configuration and confirm the `app_protect_security_log` directive sits in a `server` or `location` block that actually handles request traffic — not in a context the data plane never enters. -3. Confirm the instance is receiving traffic. Until F5 WAF for NGINX inspects a request, the dashboard has nothing to display. -4. Apply a global filter on the dashboard to scope to your instance hostname or policy, in case events are present but hidden by an existing filter. +1. Confirm NGINX Agent on the instance is **3.9.0 or later**. Earlier 3.x releases publish the configuration successfully but do not forward security events to NGINX One Console. See the [NGINX Agent install and upgrade guide]({{< ref "/nginx-one-console/agent/install-upgrade/_index.md" >}}) to upgrade. +2. Go to **WAF** > **Log Profiles** and confirm `secops_dashboard` is listed as deployed to the target instance under **Deployed To**. +3. Open the instance configuration and confirm the `app_protect_security_log` directive sits in a `server` or `location` block that actually handles request traffic — not in a context the data plane never enters. +4. Confirm the instance is receiving traffic. Until F5 WAF for NGINX inspects a request, the dashboard has nothing to display. +5. Apply a global filter on the dashboard to scope to your instance hostname or policy, in case events are present but hidden by an existing filter. If events still do not appear after a request is processed, contact F5 support with the instance hostname and the time window you tested. From e51026a4cda82885dbf34d2caad478be908c698b Mon Sep 17 00:00:00 2001 From: Venkat Reddy Marepally <102700175+vrmare@users.noreply.github.com> Date: Thu, 9 Apr 2026 11:47:42 -0700 Subject: [PATCH 10/13] addressed more reeview comments --- .../default-log-profile.md | 6 +-- .../find-event-by-support-id.md | 15 ++++-- .../query-events-api.md | 52 +++++-------------- .../security-monitoring-overview.md | 12 ++--- .../set-up-security-monitoring.md | 22 +++++--- 5 files changed, 46 insertions(+), 61 deletions(-) diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md b/content/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md index 80235f5c6..4137375cd 100644 --- a/content/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md +++ b/content/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md @@ -6,7 +6,7 @@ title: secops_dashboard log profile description: "An immutable, pre-compiled F5 WAF for NGINX log profile that captures the security telemetry the security dashboard needs." weight: 200 toc: true -nd-keywords: "default log profile, security dashboard, F5 WAF for NGINX, log profile, security telemetry, NAP log profile" +nd-keywords: "secops_dashboard, default log profile, security dashboard, F5 WAF for NGINX, log profile, security telemetry, NAP log profile, system-managed profile, pre-compiled, immutable log profile, NGINX One Console, WAF log profile" nd-summary: > The `secops_dashboard` log profile is a pre-configured F5 WAF for NGINX log profile that captures security violations in a standardized format for the security monitoring dashboard. It is the default log profile used by the security dashboard. Use it to send security telemetry from your NGINX Plus data planes to NGINX One Console without authoring or compiling a custom log profile. @@ -14,7 +14,7 @@ nd-summary: > nd-audience: operator --- -The security monitoring dashboard depends on a consistent set of fields being present on every security event. The `secops_dashboard` log profile is the contract that guarantees that consistency across every data plane forwarding events to NGINX One Console. +The security monitoring dashboard depends on a consistent set of fields being present on every security event. The `secops_dashboard` log profile is the guarantee of that consistency: it ensures every data plane forwards the same set of fields, so the dashboard can render every event correctly. ## What is the `secops_dashboard` log profile? @@ -54,7 +54,7 @@ The `secops_dashboard` log profile has three properties that distinguish it from A platform operator wants central visibility into F5 WAF for NGINX events across a fleet of NGINX Plus instances. They deploy the `secops_dashboard` log profile to every instance, knowing that every event will land in NGINX One Console with the same field set, so dashboard widgets, filters, and analytics behave the same regardless of which instance produced the event. They do not need to author, compile, or version-control a log profile to get the dashboard working. -### Security engineer: keep dashboard data consistent during a policy change +### Security engineer: rolling out a policy change without touching telemetry A security engineer is rolling out a new WAF policy to a subset of instances and wants the security dashboard to continue showing comparable metrics across the migration. Because the `secops_dashboard` log profile is immutable and shared, the data format does not change with the policy, and the engineer can compare attack counts and signature trends before and after the rollout without normalizing fields. diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/find-event-by-support-id.md b/content/nginx-one-console/waf-integration/waf-security-dashboard/find-event-by-support-id.md index c223d0c58..9be5a22aa 100644 --- a/content/nginx-one-console/waf-integration/waf-security-dashboard/find-event-by-support-id.md +++ b/content/nginx-one-console/waf-integration/waf-security-dashboard/find-event-by-support-id.md @@ -6,7 +6,7 @@ title: Find a security event by Support ID description: "Look up an F5 WAF for NGINX security event in NGINX One Console using its Support ID." weight: 500 toc: true -nd-keywords: "support ID, security event, F5 WAF for NGINX, security dashboard, troubleshooting, event lookup" +nd-keywords: "support ID, security event, F5 WAF for NGINX, security dashboard, event lookup, Support ID Details, getSecurityEvent, listSecurityEvents, WAF block, rejection page, triage, 90-day retention" nd-summary: > Use the Support ID Details page in NGINX One Console to look up a single F5 WAF for NGINX security event by its Support ID. This is the fastest way to drill from a customer report, an upstream log line, or an alert into the full WAF event record. @@ -16,7 +16,7 @@ nd-audience: operator ## Overview -Every request that F5 WAF for NGINX inspects is assigned a unique **Support ID**. The Support ID stays with the request through every system that touches it — F5 WAF for NGINX security logs, NGINX access logs (when configured), upstream application logs, and the security monitoring dashboard. NGINX One Console exposes a dedicated **Support ID Details** page so you can paste a Support ID and immediately see the full WAF event record without filtering through the dashboard. +Use the Support ID Details page in NGINX One Console to look up a single F5 WAF for NGINX security event by its Support ID. F5 WAF for NGINX assigns a unique Support ID to every inspected request, and that ID travels through every system that touches the request: security logs, NGINX access logs, upstream application logs, and the security monitoring dashboard. Use this page when you already know the ID of the event you want to inspect — for example, from a customer support case, a raw F5 WAF for NGINX log line, an alert payload, or an upstream application that captured the ID from a request header. To explore events without a known ID, use the Event Logs tab on the [security monitoring dashboard]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/dashboard-metrics-reference.md#event-logs-tab" >}}) instead. @@ -28,7 +28,6 @@ Before you begin, ensure you have: - **A Support ID**: A numeric Support ID for the event you want to inspect. See [Where to find a Support ID](#where-to-find-a-support-id) below. - **Security monitoring set up**: F5 WAF for NGINX security events must already be flowing into NGINX One Console for the event to be available. See [Set up security monitoring]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md" >}}). -- **Within the retention window**: Security events are retained for 90 days. Events older than 90 days are no longer available. --- @@ -38,7 +37,15 @@ Before you begin, ensure you have: 2. Paste the Support ID into the **Enter a Support ID** field. 3. The page displays the **Security Event** detail panel for the matching event, including the request, source, and raw request data. -If no event is found, the most likely causes are that the Support ID does not belong to a WAF-inspected request, the event is older than the 90-day retention window, or the Support ID was mistyped. + {{< call-out "note" >}}Security events are retained for 90 days. Events older than 90 days are no longer available.{{< /call-out >}} + +### Troubleshooting + +If no event is found, the most likely causes are: + +- The Support ID does not belong to a WAF-inspected request +- The event is older than the 90-day retention window +- The Support ID was mistyped --- diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md b/content/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md index 8aec93b06..f332d7e5a 100644 --- a/content/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md +++ b/content/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md @@ -16,49 +16,21 @@ nd-audience: developer ## Overview -You can use the NGINX One Console API to query F5 WAF for NGINX security events programmatically. The API exposes the same security event store the security monitoring dashboard reads from, so any view you can build in the dashboard can also be reproduced through the API. Use the API to integrate WAF activity into your own dashboards, automated reports, Security Information and Event Management (SIEM) enrichment pipelines, or alerting workflows. +Use the NGINX One Console API to query F5 WAF for NGINX security events programmatically. The API exposes the same security event store the security monitoring dashboard reads from, so any view you can build in the dashboard can also be reproduced through the API. Use the API to integrate WAF activity into your own dashboards, automated reports, Security Information and Event Management (SIEM) enrichment pipelines, or alerting workflows. For the full request and response schema of each operation, including the supported filter fields and group-by dimensions, see the [API reference guide]({{< ref "/nginx-one-console/api/api-reference-guide.md" >}}). -## Events - -Use these operations to list security events and retrieve a single event by ID. - -- [List security events]({{< ref "/nginx-one-console/api/api-reference-guide/#operation/listSecurityEvents" >}}) - - Returns a paginated list of F5 WAF for NGINX security events. Accepts `filter_fields` to narrow results by any of the documented filter fields, a time range for the query window, and standard pagination parameters. -- [Get security event details]({{< ref "/nginx-one-console/api/api-reference-guide/#operation/getSecurityEvent" >}}) - - Returns the full detail for a single security event by ID, including all triggered violations, all triggered signatures, threat campaign matches, and the raw matched request when available. - ---- - -## Attack analytics - -Use these operations to count security events grouped by event-level dimensions. - -- [Query attack analytics]({{< ref "/nginx-one-console/api/api-reference-guide/#operation/queryAttackAnalytics" >}}) - - Returns event counts grouped by an event-level dimension (`request_status`, `ip`, `country`, `policy`, `url`, `hostname`, and others). Supports filter fields, time range, group-by, and limit. -- [Query attack analytics time series]({{< ref "/nginx-one-console/api/api-reference-guide/#operation/queryAttackAnalyticsTimeSeries" >}}) - - Returns the same counts bucketed over time. Use this to drive time-series widgets and trend reports. - ---- - -## Signature analytics - -Use these operations to count security events grouped by attributes of the signatures that fired on them. - -- [Query signature analytics]({{< ref "/nginx-one-console/api/api-reference-guide/#operation/querySignatureAnalytics" >}}) - - Returns event counts grouped by a signature-level dimension (`signature`, `accuracy`, `risk`, `cve`, `request_status`). Filtering on signature-level fields narrows results to events whose matching signatures pass the filter. -- [Query signature analytics time series]({{< ref "/nginx-one-console/api/api-reference-guide/#operation/querySignatureAnalyticsTimeSeries" >}}) - - Returns the same counts bucketed over time. - ---- - -## Violation analytics - -Use this operation to count security events grouped by attributes of the violations they triggered. - -- [Query violation analytics]({{< ref "/nginx-one-console/api/api-reference-guide/#operation/queryViolationAnalytics" >}}) - - Returns event counts grouped by a violation-level dimension (`violation`, `sub_violation`, `context`, `context_key`, `context_value`). +## Operations + +| Category | Operation | Purpose | +|---|---|---| +| Events | [List security events]({{< ref "/nginx-one-console/api/api-reference-guide/#operation/listSecurityEvents" >}}) | Returns a paginated list of F5 WAF for NGINX security events. Accepts `filter_fields`, a time range, and standard pagination parameters. | +| Events | [Get security event details]({{< ref "/nginx-one-console/api/api-reference-guide/#operation/getSecurityEvent" >}}) | Returns the full detail for a single security event by ID, including all triggered violations, signatures, threat campaign matches, and the raw matched request when available. | +| Attack analytics | [Query attack analytics]({{< ref "/nginx-one-console/api/api-reference-guide/#operation/queryAttackAnalytics" >}}) | Returns event counts grouped by an event-level dimension (`request_status`, `ip`, `country`, `policy`, `url`, `hostname`, and others). Supports filter fields, time range, group-by, and limit. | +| Attack analytics | [Query attack analytics time series]({{< ref "/nginx-one-console/api/api-reference-guide/#operation/queryAttackAnalyticsTimeSeries" >}}) | Returns the same counts bucketed over time. Use this to drive time-series widgets and trend reports. | +| Signature analytics | [Query signature analytics]({{< ref "/nginx-one-console/api/api-reference-guide/#operation/querySignatureAnalytics" >}}) | Returns event counts grouped by a signature-level dimension (`signature`, `accuracy`, `risk`, `cve`, `request_status`). Filtering on signature-level fields narrows results to events whose matching signatures pass the filter. | +| Signature analytics | [Query signature analytics time series]({{< ref "/nginx-one-console/api/api-reference-guide/#operation/querySignatureAnalyticsTimeSeries" >}}) | Returns the same counts bucketed over time. | +| Violation analytics | [Query violation analytics]({{< ref "/nginx-one-console/api/api-reference-guide/#operation/queryViolationAnalytics" >}}) | Returns event counts grouped by a violation-level dimension (`violation`, `sub_violation`, `context`, `context_key`, `context_value`). | --- diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/security-monitoring-overview.md b/content/nginx-one-console/waf-integration/waf-security-dashboard/security-monitoring-overview.md index 60cf611fe..431b1ca76 100644 --- a/content/nginx-one-console/waf-integration/waf-security-dashboard/security-monitoring-overview.md +++ b/content/nginx-one-console/waf-integration/waf-security-dashboard/security-monitoring-overview.md @@ -14,7 +14,7 @@ nd-summary: > nd-audience: operator --- -Security monitoring brings F5 WAF for NGINX events from every connected instance into a single place in NGINX One Console. Before you set it up, it helps to understand what data the system collects, how it gets there, and how it is organized. +Security monitoring brings F5 WAF for NGINX events from every connected instance into a single place in NGINX One Console. This page explains what data the system collects, how it flows, and how it is organized. ## What is security monitoring? @@ -37,13 +37,13 @@ Every event carries the support ID, the policy that matched it, the violation an --- -## How data is scoped +## Data scoping Every security event carries enough context to attribute it to a specific data plane, a specific policy, and the application it targeted. - **Instance**: Each event records the NGINX instance hostname that produced it. Use this to scope by data plane. -- **Policy**: Each event records the F5 WAF for NGINX policy that produced it, so you can compare activity across policy versions or rollouts. -- **Destination hostname**: Each event records the HTTP `Host` header sent by the client. Use this to scope by the application being attacked, which is often distinct from the instance hostname when the same data plane fronts multiple applications. +- **Policy**: Each event records the F5 WAF for NGINX policy that produced it, so you can compare activity across policy versions or rollouts — useful for measuring the impact of a policy change before promoting it. +- **Destination hostname**: Each event records the HTTP `Host` header sent by the client — the *application* being attacked, not the instance hostname (which identifies the data plane). Use this when one data plane fronts multiple applications and you need to scope by app rather than by infrastructure. --- @@ -57,11 +57,11 @@ Security events are retained for **90 days**. Queries that reach further back th ### Operator: triage an active attack -An operator notices a spike in attack volume on the security dashboard. They use the global filters to narrow down to the affected policy and time window, then drill into the top signatures and attacked endpoints to identify which signatures fired and which URLs were targeted. From a single event, they pull the Support ID, the X-Forwarded-For chain, and the raw request to confirm the source and decide whether to tighten the policy. +An operator notices a spike in attack volume on the security dashboard. The operator uses the global filters to narrow down to the affected policy and time window, then drills into the top signatures and attacked endpoints to identify which signatures fired and which URLs were targeted. From a single event, the operator pulls the Support ID, the X-Forwarded-For chain, and the raw request to confirm the source and decide whether to tighten the policy. ### Security engineer: tune a noisy policy -A security engineer suspects a policy is producing false positives. They open the security dashboard, filter by policy and blocked requests, and review the breakdown of triggered signatures. The high-volume signatures with low risk and accuracy stand out as candidates for tuning. They cross-check a few events against the raw requests to confirm the signature is firing on legitimate traffic before adjusting the policy. +A security engineer suspects a policy is producing false positives. The engineer opens the security dashboard, filters by policy and blocked requests, and reviews the breakdown of triggered signatures. The high-volume signatures with low risk and accuracy stand out as candidates for tuning. The engineer cross-checks a few events against the raw requests to confirm the signature is firing on legitimate traffic before adjusting the policy. ### Platform team: report on WAF activity across the fleet diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md b/content/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md index d4f5c6539..76b32225c 100644 --- a/content/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md +++ b/content/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md @@ -16,9 +16,9 @@ nd-audience: operator ## Overview -This guide walks you through enabling F5 WAF for NGINX security monitoring on an NGINX Plus instance that is already connected to NGINX One Console. After you complete the steps, security events appear in the [security monitoring dashboard]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/_index.md" >}}), where you can review attacks, violations, and triggered signatures. +Use this guide to enable F5 WAF for NGINX security monitoring on an NGINX Plus instance that is already connected to NGINX One Console. After completing the steps, security events appear in the [security monitoring dashboard]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/_index.md" >}}), where you can review attacks, violations, and triggered signatures. -The flow uses the NGINX One Console UI end to end. You deploy the [`secops_dashboard` log profile]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md" >}}) to the instance, add the F5 WAF for NGINX directives to the NGINX configuration through the console's config editor, and verify the pipeline by triggering test violations. NGINX Agent automatically configures its OpenTelemetry collector to forward security events to NGINX One Console once it sees the correct directives in the NGINX configuration — you do not need to edit the agent configuration by hand. +You deploy the [`secops_dashboard` log profile]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md" >}}) to the instance through NGINX One Console. You then add the F5 WAF for NGINX directives to the NGINX configuration using the console's config editor, and verify the pipeline by triggering test violations. NGINX Agent automatically configures its OpenTelemetry collector to forward security events to NGINX One Console when it detects the correct directives in the NGINX configuration. You do not need to edit the NGINX Agent configuration by hand. --- @@ -48,7 +48,7 @@ The security dashboard relies on the `secops_dashboard` log profile to capture s - Under **Target**, choose **Instance** or **Config Sync Group** and select your target. - In **Log Profile File Path**, specify the path where the compiled bundle should be deployed on the data plane (for example, `/etc/nginx/secops_dashboard.tgz`). -4. Select **Next**. The wizard displays the F5 WAF for NGINX directive snippet to paste into your NGINX configuration, along with the config editor for the target instance. +4. Select **Next**. The wizard displays the F5 WAF for NGINX directive snippet to paste into your NGINX configuration. The wizard also opens the config editor for the target instance. 5. Open the server block where you want to enable F5 WAF for NGINX (for example, `/etc/nginx/conf.d/default.conf`) and paste the snippet into the `server`, `http`, or `location` context. The snippet looks like this: @@ -57,7 +57,7 @@ The security dashboard relies on the `secops_dashboard` log profile to capture s app_protect_security_log /etc/nginx/secops_dashboard.tgz syslog:server=127.0.0.1:1514; ``` - Make sure `app_protect_enable on;` and `app_protect_policy_file` are already present in the same context (covered by the prerequisites above). + `app_protect_enable on;` and `app_protect_policy_file` must be present in the same context. These are covered in [Before you begin](#before-you-begin). 6. Review the configuration diff the console shows for the affected files, then select **Publish**. NGINX One Console pushes the updated configuration to the instance and reloads NGINX. @@ -67,9 +67,9 @@ For more on the deployment wizard and the alternative **Add File** > **Existing ## Verify the setup -When you select **Publish** in the previous step, NGINX One Console pushes the configuration change to the instance and displays a confirmation toast indicating the publish succeeded. At that point both the F5 WAF for NGINX policy and the `secops_dashboard` log profile are in place on the data plane, and the security log directive is wired up to NGINX Agent. +When you select **Publish** in the previous step, NGINX One Console pushes the configuration change to the instance and displays a confirmation message. At that point, the F5 WAF for NGINX policy and the `secops_dashboard` log profile are in place on the data plane, and the security log directive is wired to NGINX Agent. -From this point on, any request that F5 WAF for NGINX inspects on the instance produces a security event that flows to NGINX One Console. To see those events: +Any request that F5 WAF for NGINX inspects on the instance produces a security event that flows to NGINX One Console. To see security events in the dashboard: 1. In NGINX One Console, go to **WAF** > **Security Dashboard**. 2. As your instance handles traffic, attacks, violations, and triggered signatures appear on the dashboard within about a minute of the request being processed. @@ -114,12 +114,18 @@ If events still do not appear after a request is processed, contact F5 support w ## References -For more information, see: +**Conceptual background** - [Security monitoring overview]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/security-monitoring-overview.md" >}}) + +**Reference** + - [secops_dashboard log profile]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md" >}}) +- [Dashboard metrics reference]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/dashboard-metrics-reference.md" >}}) + +**Related how-to guides** + - [Deploy log profiles]({{< ref "/nginx-one-console/waf-integration/log-profiles/deploy-log-profiles.md" >}}) - [Add an instance]({{< ref "/nginx-one-console/connect-instances/add-instance.md" >}}) -- [Dashboard metrics reference]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/dashboard-metrics-reference.md" >}}) - [Find a security event by Support ID]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/find-event-by-support-id.md" >}}) - [Query security events through the API]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md" >}}) From af39012769fcc592dac77e6970057c1e139f864c Mon Sep 17 00:00:00 2001 From: Venkat Reddy Marepally <102700175+vrmare@users.noreply.github.com> Date: Thu, 9 Apr 2026 11:51:03 -0700 Subject: [PATCH 11/13] addressed more reeview comments --- .../waf-security-dashboard/security-monitoring-overview.md | 2 +- .../waf-security-dashboard/set-up-security-monitoring.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/security-monitoring-overview.md b/content/nginx-one-console/waf-integration/waf-security-dashboard/security-monitoring-overview.md index 431b1ca76..360bc5419 100644 --- a/content/nginx-one-console/waf-integration/waf-security-dashboard/security-monitoring-overview.md +++ b/content/nginx-one-console/waf-integration/waf-security-dashboard/security-monitoring-overview.md @@ -65,7 +65,7 @@ A security engineer suspects a policy is producing false positives. The engineer ### Platform team: report on WAF activity across the fleet -A platform team needs a weekly summary of WAF activity across hundreds of instances. They use the analytics API to pull attack counts, top signatures, and top violations grouped by instance, then render the result in their own reporting tool. The dashboard remains the interactive surface for ad-hoc investigation; the API is the integration point for automation. +A platform team needs a weekly summary of WAF activity across hundreds of instances. The team uses the analytics API to pull attack counts, top signatures, and top violations grouped by instance, then renders the result in their own reporting tool. The dashboard remains the interactive surface for ad-hoc investigation; the API is the integration point for automation. --- diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md b/content/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md index 76b32225c..8b142d40f 100644 --- a/content/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md +++ b/content/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md @@ -46,7 +46,7 @@ The security dashboard relies on the `secops_dashboard` log profile to capture s - Confirm `secops_dashboard` is selected under **Log Profile**. - Under **Target**, choose **Instance** or **Config Sync Group** and select your target. - - In **Log Profile File Path**, specify the path where the compiled bundle should be deployed on the data plane (for example, `/etc/nginx/secops_dashboard.tgz`). + - In **Log Profile File Path**, specify the path where NGINX One Console should deploy the compiled bundle on the data plane (for example, `/etc/nginx/secops_dashboard.tgz`). 4. Select **Next**. The wizard displays the F5 WAF for NGINX directive snippet to paste into your NGINX configuration. The wizard also opens the config editor for the target instance. From f77bf1788a81d9f913d2af09388d5f8e1e744093 Mon Sep 17 00:00:00 2001 From: Venkat Reddy Marepally <102700175+vrmare@users.noreply.github.com> Date: Thu, 9 Apr 2026 12:58:58 -0700 Subject: [PATCH 12/13] moved waf api to automation docs --- .../query-events-api.md | 2 +- .../waf-integration/waf-security-dashboard/_index.md | 2 +- .../dashboard-metrics-reference.md | 12 ++++++------ .../find-event-by-support-id.md | 4 ++-- .../security-monitoring-overview.md | 2 +- .../set-up-security-monitoring.md | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) rename content/nginx-one-console/{waf-integration/waf-security-dashboard => api}/query-events-api.md (99%) diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md b/content/nginx-one-console/api/query-events-api.md similarity index 99% rename from content/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md rename to content/nginx-one-console/api/query-events-api.md index f332d7e5a..1a2f6ad9c 100644 --- a/content/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md +++ b/content/nginx-one-console/api/query-events-api.md @@ -4,7 +4,7 @@ nd-docs: DOCS-000 nd-product: NONECO title: Query security events through the API description: "List F5 WAF for NGINX security events and run analytics queries through the NGINX One Console API." -weight: 600 +weight: 200 toc: true nd-keywords: "security events API, analytics API, F5 WAF for NGINX, app-protect, NGINX One Console API" nd-summary: > diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/_index.md b/content/nginx-one-console/waf-integration/waf-security-dashboard/_index.md index 0dba8d861..09958ef21 100644 --- a/content/nginx-one-console/waf-integration/waf-security-dashboard/_index.md +++ b/content/nginx-one-console/waf-integration/waf-security-dashboard/_index.md @@ -14,4 +14,4 @@ This section covers: - [Set up security monitoring]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md" >}}) — install F5 WAF for NGINX, configure the log profile, and forward events through NGINX Agent. - [Security dashboard reference]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/dashboard-metrics-reference.md" >}}) — dashboard tabs, global controls, and how each widget maps to an underlying dimension. - [Find a security event by Support ID]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/find-event-by-support-id.md" >}}) — look up a single security event by its Support ID for quick triage. -- [Query security events through the API]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md" >}}) — list events and run analytics queries programmatically. +- [Query security events through the API]({{< ref "/nginx-one-console/api/query-events-api.md" >}}) — list events and run analytics queries programmatically. diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/dashboard-metrics-reference.md b/content/nginx-one-console/waf-integration/waf-security-dashboard/dashboard-metrics-reference.md index 7d5474705..2bcf7cc48 100644 --- a/content/nginx-one-console/waf-integration/waf-security-dashboard/dashboard-metrics-reference.md +++ b/content/nginx-one-console/waf-integration/waf-security-dashboard/dashboard-metrics-reference.md @@ -16,7 +16,7 @@ nd-audience: operator ## Overview -Use this reference to look up how the F5 WAF for NGINX security monitoring dashboard is organized and which underlying dimension each widget reads from. Every widget in the dashboard has an in-product tooltip that explains what the displayed values mean. This article mainly covers the dashboard structure, the global controls that affect every widget, and the mapping you need when you want to reproduce a widget's view through the [analytics API]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md" >}}). +Use this reference to look up how the F5 WAF for NGINX security monitoring dashboard is organized and which underlying dimension each widget reads from. Every widget in the dashboard has an in-product tooltip that explains what the displayed values mean. This article mainly covers the dashboard structure, the global controls that affect every widget, and the mapping you need when you want to reproduce a widget's view through the [analytics API]({{< ref "/nginx-one-console/api/query-events-api.md" >}}). --- @@ -42,7 +42,7 @@ Selects the query window for all widgets. The picker offers preset windows from Time-series widgets bucket their data automatically based on the selected window — shorter windows produce finer buckets. -{{< call-out "note" >}}Security events are retained for **90 days**, but the dashboard time window picker tops out at the **last 60 days**. To query the full retention window, use the [analytics API]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md" >}}), which accepts any time range up to 90 days.{{< /call-out >}} +{{< call-out "note" >}}Security events are retained for **90 days**, but the dashboard time window picker tops out at the **last 60 days**. To query the full retention window, use the [analytics API]({{< ref "/nginx-one-console/api/query-events-api.md" >}}), which accepts any time range up to 90 days.{{< /call-out >}} ### Add Filter @@ -101,7 +101,7 @@ Each widget on the Main tab has a tooltip describing what it displays. The table | **Request Methods** | Donut chart showing the share of events for each HTTP method observed in the window. | | **Response Codes** | Donut chart showing the share of events for each response code observed in the window. | -To reproduce these widgets through the analytics API, see [Query security events through the API]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md" >}}). +To reproduce these widgets through the analytics API, see [Query security events through the API]({{< ref "/nginx-one-console/api/query-events-api.md" >}}). --- @@ -120,7 +120,7 @@ The Advanced tab exposes signature- and violation-level analytics for tuning and | **Top Threat Campaigns** | Each row shows hits, distinct URIs, IPs, violations, and policies for the threat campaign. | | **Top Attacked Instances** | Each row shows hits, distinct URIs, IPs, violations, and policies, scoped to the NGINX instance hostname (not the HTTP `Host` header). | -To reproduce these widgets through the analytics API, see [Query security events through the API]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md" >}}). +To reproduce these widgets through the analytics API, see [Query security events through the API]({{< ref "/nginx-one-console/api/query-events-api.md" >}}). --- @@ -144,7 +144,7 @@ The Event Logs tab lists individual security events matching the global filters | **Violation Rating** | Numeric severity rating (0–5) assigned by F5 WAF for NGINX. | | **Support ID** | The unique identifier F5 WAF for NGINX assigns to the event. Use this to correlate with raw F5 WAF for NGINX logs on the data plane. | -To list events with the same columns through the analytics API, see [Query security events through the API]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md" >}}). +To list events with the same columns through the analytics API, see [Query security events through the API]({{< ref "/nginx-one-console/api/query-events-api.md" >}}). ### Pagination @@ -173,4 +173,4 @@ For more information, see: - [Security monitoring overview]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/security-monitoring-overview.md" >}}) - [Set up security monitoring]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md" >}}) - [Find a security event by Support ID]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/find-event-by-support-id.md" >}}) -- [Query security events through the API]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md" >}}) +- [Query security events through the API]({{< ref "/nginx-one-console/api/query-events-api.md" >}}) diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/find-event-by-support-id.md b/content/nginx-one-console/waf-integration/waf-security-dashboard/find-event-by-support-id.md index 9be5a22aa..b1751e1a9 100644 --- a/content/nginx-one-console/waf-integration/waf-security-dashboard/find-event-by-support-id.md +++ b/content/nginx-one-console/waf-integration/waf-security-dashboard/find-event-by-support-id.md @@ -89,7 +89,7 @@ An upstream service surfaces an incident referencing a Support ID extracted from The same lookup is available through the analytics API. Use the [`getSecurityEvent`]({{< ref "/nginx-one-console/api/api-reference-guide/#operation/getSecurityEvent" >}}) operation to fetch a single event, or [`listSecurityEvents`]({{< ref "/nginx-one-console/api/api-reference-guide/#operation/listSecurityEvents" >}}) with `support_id` in `filter_fields` to look up by Support ID programmatically. -For more on querying events through the API, see [Query security events through the API]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md" >}}). +For more on querying events through the API, see [Query security events through the API]({{< ref "/nginx-one-console/api/query-events-api.md" >}}). --- @@ -98,5 +98,5 @@ For more on querying events through the API, see [Query security events through For more information, see: - [Security dashboard reference]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/dashboard-metrics-reference.md" >}}) -- [Query security events through the API]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md" >}}) +- [Query security events through the API]({{< ref "/nginx-one-console/api/query-events-api.md" >}}) - [Set up security monitoring]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md" >}}) diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/security-monitoring-overview.md b/content/nginx-one-console/waf-integration/waf-security-dashboard/security-monitoring-overview.md index 360bc5419..fd6639e2d 100644 --- a/content/nginx-one-console/waf-integration/waf-security-dashboard/security-monitoring-overview.md +++ b/content/nginx-one-console/waf-integration/waf-security-dashboard/security-monitoring-overview.md @@ -85,4 +85,4 @@ For more information, see: - [secops_dashboard log profile]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/default-log-profile.md" >}}) - [Dashboard metrics reference]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/dashboard-metrics-reference.md" >}}) - [Find a security event by Support ID]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/find-event-by-support-id.md" >}}) -- [Query security events through the API]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md" >}}) +- [Query security events through the API]({{< ref "/nginx-one-console/api/query-events-api.md" >}}) diff --git a/content/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md b/content/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md index 8b142d40f..62ad89a3a 100644 --- a/content/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md +++ b/content/nginx-one-console/waf-integration/waf-security-dashboard/set-up-security-monitoring.md @@ -128,4 +128,4 @@ If events still do not appear after a request is processed, contact F5 support w - [Deploy log profiles]({{< ref "/nginx-one-console/waf-integration/log-profiles/deploy-log-profiles.md" >}}) - [Add an instance]({{< ref "/nginx-one-console/connect-instances/add-instance.md" >}}) - [Find a security event by Support ID]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/find-event-by-support-id.md" >}}) -- [Query security events through the API]({{< ref "/nginx-one-console/waf-integration/waf-security-dashboard/query-events-api.md" >}}) +- [Query security events through the API]({{< ref "/nginx-one-console/api/query-events-api.md" >}}) From 363e107b95646a2b0fa83b269d4160103519aefe Mon Sep 17 00:00:00 2001 From: Venkat Reddy Marepally <102700175+vrmare@users.noreply.github.com> Date: Thu, 9 Apr 2026 13:14:30 -0700 Subject: [PATCH 13/13] final one.json --- static/nginx-one-console/api/one.json | 193 +++++++++++++++++++++++++- 1 file changed, 186 insertions(+), 7 deletions(-) diff --git a/static/nginx-one-console/api/one.json b/static/nginx-one-console/api/one.json index eb6b71ef2..9b77dfb08 100644 --- a/static/nginx-one-console/api/one.json +++ b/static/nginx-one-console/api/one.json @@ -6084,7 +6084,7 @@ "Templates" ], "summary": "Submit templates for previewing NGINX configuration.", - "description": "Submits a set of templates for rendering NGINX configuration.\n\nThe `preview_only` query parameter controls how the request is processed:\n - When `preview_only` is `true`, the API validates template parameters and renders the full NGINX configuration for preview **without creating a template submission object**. (**Currently, only this mode is supported.**)\n - When `preview_only` is `false` or omitted, the API is intended to render and create a submission. This feature is **not supported yet**.\n\n**Note:** Currently, only preview mode is implemented. Submission creation will be supported in a future release.\n", + "description": "Submits a set of templates for rendering NGINX configuration.\n\nThe `preview_only` query parameter controls how the request is processed:\n - When `preview_only` is `true`, the API validates template parameters and renders the full NGINX configuration for preview **without creating a template submission object**. (**Currently, only this mode is supported.**)\n - When `preview_only` is `false` or omitted, the API is intended to render and create a submission. \n - If no target object ID is provided, a new staged config will be created.\n", "parameters": [ { "$ref": "#/components/parameters/TemplateSubmissionPreviewOnly" @@ -6097,6 +6097,17 @@ "application/json": { "schema": { "$ref": "#/components/schemas/TemplateSubmissionRequest" + }, + "examples": { + "SubmissionWithPreviewOnly": { + "$ref": "#/components/examples/SubmissionWithPreviewOnly" + }, + "SubmissionForCreateNewStagedConfig": { + "$ref": "#/components/examples/SubmissionForCreateNewStagedConfig" + }, + "SubmissionForUpdateExistingStagedConfigTarget": { + "$ref": "#/components/examples/SubmissionForUpdateExistingStagedConfigTarget" + } } } } @@ -15425,6 +15436,7 @@ "TemplateDescription": { "type": "string", "description": "A human-readable description of the template.", + "maxLength": 2048, "example": "A base template for setting up a reverse proxy" }, "TemplateObjectID": { @@ -15945,7 +15957,7 @@ }, "TemplateSubmissionRequest": { "type": "object", - "description": "Defines a request to render an NGINX configuration by combining a single base template \nwith zero or more augment templates.\n\n### Validations and Constraints:\n- All templates referenced by Object ID must be available in the system before submission.\n- Only one base template can be submitted.\n- The base template must explicitly use custom Go function `augment_includes (\"\", .)` to apply `augments`.\n- Its not required to include all augments in the request that base template supports.\n- The order of augments in the list determines the order in which they are rendered and applied.\n- Each augment must specify its `target_context`, indicating where it should be applied in \n the base template.\n- Input values for each template are passed independently via the `values` \n object, and validated against each template’s Schema.\n\n### Processing:\n- The `base_template` defines the starting point of the NGINX configuration rendering.\n- `conf_path` determines where the rendered configuration from base and augments should be placed within the NGINX directory structure.\n- Each `augment` template is applied in the order provided, inserted at the appropriate target context\n using the `augment_includes (\"\", .)` function declared in the base template.\n- The system validates that each augment is compatible with the specified target context.\n- The final composed configuration is validated to ensure correctness and prevent conflicts or misconfigurations.\n\n### External Template Documentation:\nFor more information on template functions and best practices, refer to:\n - [Template Function Reference](https://yourdocs.com/templates/functions)\n - [Template Authoring Guide](https://yourdocs.com/templates/guide)\n", + "description": "Defines a request to render an NGINX configuration by combining a single base template \nwith zero or more augment templates.\n\n### Validations and Constraints:\n- All templates referenced by Object ID must be available in the system before submission.\n- Only one base template can be submitted.\n- The base template must explicitly use custom Go function `augment_includes (\"\", .)` to apply `augments`.\n- Its not required to include all augments in the request that base template supports.\n- The order of augments in the list determines the order in which they are rendered and applied.\n- Each augment must specify its `target_context`, indicating where it should be applied in \n the base template.\n- Input values for each template are passed independently via the `values` \n object, and validated against each template’s Schema.\n- The `payloads` for auxiliary files only accepts types of `managed_certificate` and `managed_key`.\n\n### Processing:\n- The `base_template` defines the starting point of the NGINX configuration rendering.\n- `conf_path` determines where the rendered configuration from base and augments should be placed within the NGINX directory structure.\n- Each `augment` template is applied in the order provided, inserted at the appropriate target context\n using the `augment_includes (\"\", .)` function declared in the base template.\n- The system validates that each augment is compatible with the specified target context.\n- The final composed configuration is validated to ensure correctness and prevent conflicts or misconfigurations.\n\n### External Template Documentation:\nFor more information on template functions and best practices, refer to:\n - [Template Function Reference](https://yourdocs.com/templates/functions)\n - [Template Authoring Guide](https://yourdocs.com/templates/guide)\n", "required": [ "conf_path", "base_template", @@ -15954,7 +15966,8 @@ "properties": { "description": { "type": "string", - "description": "Description of the submission, required when not rendering as preview only." + "description": "Description of the submission, required when not rendering as preview only.", + "maxLength": 1024 }, "target_object_ids": { "type": "array", @@ -16157,7 +16170,7 @@ "$ref": "#/components/schemas/ObjectID" }, "staged_config_status": { - "$ref": "#/components/schemas/StagedConfigCreation" + "$ref": "#/components/schemas/StagedConfigSubmission" }, "csg_publication_status": { "$ref": "#/components/schemas/ConfigSyncGroupPublication" @@ -16410,7 +16423,7 @@ "filter_name_templates_allowed_in_contexts" ] }, - "StagedConfigCreation": { + "StagedConfigSubmission": { "type": "object", "required": [ "status" @@ -16423,7 +16436,7 @@ "type": "string" }, "status": { - "description": "Creation status for the staged config:\n* `failed` - The creation failed.\n* `succeeded` - The creation was successful.\n", + "description": "Submission status for the staged config:\n* `failed` - The submission failed.\n* `succeeded` - The submission was successful.\n", "type": "string", "enum": [ "failed", @@ -16433,6 +16446,10 @@ "staged_config_status_failed", "staged_config_status_succeeded" ] + }, + "status_cause": { + "type": "string", + "example": "staged config does not exist" } } }, @@ -16534,19 +16551,29 @@ }, "Resolution": { "type": "string", - "description": "Time bucket size for aggregation. If not specified, auto-selected based on time range:\n* < 1 hour: 1m\n* 1-6 hours: 5m\n* 6-24 hours: 15m\n* 1-7 days: 1h\n* > 7 days: 1d\n", + "description": "Time bucket size for aggregation. Defaults to `1h` when not specified.\nPick a value that yields a reasonable number of buckets for the\nrequested time range (e.g. `30m` for 24h, `2h` for 7d, `12h` for 30d).\n", "enum": [ "1m", "5m", "15m", + "30m", "1h", + "2h", + "4h", + "6h", + "12h", "1d" ], "x-enum-varnames": [ "resolution_1m", "resolution_5m", "resolution_15m", + "resolution_30m", "resolution_1h", + "resolution_2h", + "resolution_4h", + "resolution_6h", + "resolution_12h", "resolution_1d" ], "example": "15m" @@ -18629,6 +18656,158 @@ ] } }, + "SubmissionWithPreviewOnly": { + "value": { + "conf_path": "/etc/nginx/nginx.conf", + "base_template": { + "object_id": "tmplv_-uvR3F2TQGm18jnl7bpaGw", + "values": { + "upstream_servers": [ + "10.0.0.1:8080", + "10.0.0.2:8080" + ], + "server_name": "example.com" + } + }, + "augments": [ + { + "object_id": "tmplv_-uvR3F2TQGm18jnl7bpaGw", + "target_context": "http/upstream", + "values": { + "upstream_servers": [ + "10.0.0.1:8080", + "10.0.0.2:8080" + ], + "server_name": "example.com" + } + }, + { + "object_id": "tmplv_-xeR3F2TQGm18jnl7bpaAw", + "target_context": "http", + "values": { + "enabled": "on", + "types": "text/plain application/json" + } + }, + { + "object_id": "tmplv_-abR3F2TQGm18jnl7bpaXw", + "target_context": "http", + "values": { + "zone_name": "req_limit", + "memory": "10m", + "rate": "10r/s" + } + }, + { + "object_id": "tmplv_-cdR3F2TQGm18jnl7bpaZw", + "target_context": "http/server", + "values": { + "zone_name": "req_limit", + "burst": 5 + }, + "child_augments": [ + { + "object_id": "tmplv_-cdR3F2TQGm18jnl7bpaZw", + "target_context": "http/server/location", + "values": { + "zone_name": "req_limit", + "burst": 5 + } + } + ] + } + ] + } + }, + "SubmissionForCreateNewStagedConfig": { + "value": { + "conf_path": "/etc/nginx/nginx.conf", + "base_template": { + "object_id": "tmplv_-uvR3F2TQGm18jnl7bpaGw", + "values": { + "upstream_servers": [ + "10.0.0.1:8080", + "10.0.0.2:8080" + ], + "server_name": "example.com" + } + }, + "augments": [ + { + "object_id": "tmplv_-abR3F2TQGm18jnl7bpaXw", + "target_context": "http", + "values": { + "zone_name": "req_limit", + "memory": "10m", + "rate": "10r/s" + } + } + ], + "payloads": [ + { + "type": "managed_certificate", + "object_id": "cert_rto8NYiCQputrIasNx2NOA", + "paths": [ + "/etc/nginx/cert.pem" + ] + }, + { + "type": "managed_key", + "object_id": "cert_rto8NYiCQputrIasNx2NOA", + "paths": [ + "/etc/nginx/key.pem" + ] + } + ], + "description": "Create a new staged config for reverse proxy with rate limiting" + } + }, + "SubmissionForUpdateExistingStagedConfigTarget": { + "value": { + "conf_path": "/etc/nginx/nginx.conf", + "base_template": { + "object_id": "tmplv_-uvR3F2TQGm18jnl7bpaGw", + "values": { + "upstream_servers": [ + "10.0.0.1:8080", + "10.0.0.2:8080" + ], + "server_name": "example.com" + } + }, + "augments": [ + { + "object_id": "tmplv_-abR3F2TQGm18jnl7bpaXw", + "target_context": "http", + "values": { + "zone_name": "req_limit", + "memory": "10m", + "rate": "10r/s" + } + } + ], + "payloads": [ + { + "type": "managed_certificate", + "object_id": "cert_rto8NYiCQputrIasNx2NOA", + "paths": [ + "/etc/nginx/cert.pem" + ] + }, + { + "type": "managed_key", + "object_id": "cert_rto8NYiCQputrIasNx2NOA", + "paths": [ + "/etc/nginx/key.pem" + ] + } + ], + "description": "Update existing staged config for reverse proxy with rate limiting", + "target_object_ids": [ + "sc_cEoiYCVJRuekVpYOvV1raA" + ] + } + }, "TemplateBaseSummary": { "value": { "name": "reverse_proxy",