diff --git a/content/nic/configuration/policy-resource.md b/content/nic/configuration/policy-resource.md index e6c2bd31c0..095b2aeda6 100644 --- a/content/nic/configuration/policy-resource.md +++ b/content/nic/configuration/policy-resource.md @@ -1293,7 +1293,8 @@ waf: | ---| ---| ---| --- | |``enable`` | Enables F5 WAF for NGINX. | ``bool`` | Yes | |``apPolicy`` | The [F5 WAF for NGINX policy]({{< ref "/nic/integrations/app-protect-waf/configuration.md#waf-policies" >}}) of the WAF. Accepts an optional namespace. Mutually exclusive with ``apBundle``. | ``string`` | No | -|``apBundle`` | The [F5 WAF for NGINX policy bundle]({{< ref "/nic/integrations/app-protect-waf/configuration.md#waf-bundles" >}}). Mutually exclusive with ``apPolicy``. | ``string`` | No | +|``apBundle`` | The [F5 WAF for NGINX policy bundle]({{< ref "/nic/integrations/app-protect-waf/configuration.md#waf-bundles" >}}). Mutually exclusive with ``apPolicy`` and ``apBundleSource``. | ``string`` | No | +|``apBundleSource`` | [Remote source]({{< ref "/nic/integrations/app-protect-waf-v5/bundle-sources.md" >}}) for fetching the WAF policy bundle. Mutually exclusive with ``apBundle`` and ``apPolicy``. | [waf.apBundleSource](#wafapbundlesource) | No | |``securityLog.enable`` | **Deprecated:** Enables security log. | ``bool`` | No | |``securityLog.apLogConf`` | **Deprecated:** The [F5 WAF for NGINX log conf]({{< ref "/nic/integrations/app-protect-waf/configuration.md#waf-logs" >}}) resource. Accepts an optional namespace. Only works with ``apPolicy``. | ``string`` | No | |``securityLog.apLogBundle`` | **Deprecated:** The [F5 WAF for NGINX log bundle]({{< ref "/nic/integrations/app-protect-waf/configuration.md#waf-bundles" >}}) resource. Only works with ``apBundle``. | ``string`` | No | @@ -1310,11 +1311,41 @@ waf: | ---| ---| ---| --- | |``enable`` | Enables security log. | ``bool`` | No | |``apLogConf`` | The [App Protect WAF log conf]({{< ref "/nic/integrations/app-protect-waf/configuration.md#waf-logs" >}}) resource. Accepts an optional namespace. Only works with ``apPolicy``. | ``string`` | No | -|``apLogBundle`` | The [App Protect WAF log bundle]({{< ref "/nic/integrations/app-protect-waf/configuration.md#waf-bundles" >}}) resource. Only works with ``apBundle``. | ``string`` | No | +|``apLogBundle`` | The [App Protect WAF log bundle]({{< ref "/nic/integrations/app-protect-waf/configuration.md#waf-bundles" >}}) resource. Only works with ``apBundle``. Mutually exclusive with ``apLogBundleSource``. | ``string`` | No | +|``apLogBundleSource`` | [Remote source]({{< ref "/nic/integrations/app-protect-waf-v5/bundle-sources.md" >}}) for fetching the log profile bundle. Mutually exclusive with ``apLogBundle``. | [waf.apBundleSource](#wafapbundlesource) | No | |``logDest`` | The log destination for the security log. Only accepted variables are ``syslog:server=; localhost; :``, ``stderr``, ````. | ``string`` | No | {{% /table %}} +#### WAF.ApBundleSource + +The `apBundleSource` object configures how NGINX Ingress Controller fetches a pre-compiled WAF bundle from a remote source. The same fields are also used by `waf.securityLogs[].apLogBundleSource`. Three source types are supported: + +- **N1C (NGINX One Console)** — fetch policies compiled and managed through NGINX One Console. See [policy docs]({{< ref "/nginx-one-console/waf-integration/policy/_index.md" >}}). +- **NIM (NGINX Instance Manager)** — fetch policies compiled and managed through NGINX Instance Manager. See [bundle docs]({{< ref "/nim/waf-integration/policies-and-logs/bundles/create-bundle.md" >}}). +- **HTTPS** — fetch compiled `.tgz` bundles from any HTTPS server or endpoint. + +For details and examples, see [Connect F5 WAF for NGINX to bundle sources]({{< ref "/nic/integrations/app-protect-waf-v5/bundle-sources.md" >}}). + +{{% table %}} + +|Field | Description | Type | Required | +| ---| ---| ---| --- | +|``type`` | Source backend: ``N1C`` (NGINX One Console), ``NIM`` (NGINX Instance Manager), or ``HTTPS``. Defaults to ``HTTPS``. | ``string`` | No | +|``url`` | Tenant URL for ``N1C``/``NIM``, or full ``.tgz`` bundle URL for ``HTTPS``. Must use ``https://``. | ``string`` | Yes | +|``policyName`` | Management-plane policy name for ``N1C``/``NIM``. For ``apLogBundleSource``, set this to the log profile name. Ignored for ``HTTPS``. | ``string`` | No | +|``policyNamespace`` | Management-plane namespace or tenant. Required for ``N1C``. Not used for ``NIM`` or ``HTTPS``. | ``string`` | No | +|``enablePolling`` | Must be explicitly set. When ``true``, NIC re-fetches the bundle at ``pollInterval``. When ``false``, the bundle is fetched once at policy creation or update. | ``bool`` | Yes | +|``pollInterval`` | How often to re-fetch when ``enablePolling`` is ``true``. Minimum ``1m``, default ``5m``. | ``string`` | No | +|``secret`` | Secret in the same namespace as the Policy. For ``N1C``/``NIM``, use ``nginx.com/waf-bundle`` (token or username/password). For ``HTTPS``, use ``kubernetes.io/tls`` for client mTLS (``tls.crt`` and ``tls.key``). | ``string`` | No | +|``trustedCertSecret`` | Name of an ``nginx.org/ca`` Secret containing a custom CA certificate (``ca.crt``) for verifying the server TLS certificate. Must be in the same namespace as the Policy. | ``string`` | No | +|``insecureSkipVerify`` | Disables TLS certificate verification. Not recommended for production. | ``bool`` | No | +|``verifyChecksum`` | Enables SHA-256 verification of the downloaded bundle. HTTPS only. | ``bool`` | No | +|``timeout`` | Time limit for a single bundle fetch request. Default ``60s``. | ``string`` | No | +|``retryAttempts`` | Number of additional fetch attempts after a temporary fetch error (eg. timeout or HTTP 5xx). Valid range is ``1``–``10``. | ``int`` | No | + +{{% /table %}} + #### WAF Merging Behavior A VirtualServer/VirtualServerRoute can reference multiple WAF policies. However, only one can be applied. Every subsequent reference will be ignored. For example, here we reference two policies: diff --git a/content/nic/integrations/app-protect-waf-v5/bundle-sources.md b/content/nic/integrations/app-protect-waf-v5/bundle-sources.md new file mode 100644 index 0000000000..6afd7dbd3a --- /dev/null +++ b/content/nic/integrations/app-protect-waf-v5/bundle-sources.md @@ -0,0 +1,576 @@ +--- +title: Configure remote F5 WAF for NGINX bundle sources +description: "Configure NGINX Ingress Controller to fetch F5 WAF for NGINX policy bundles from NGINX One Console, NGINX Instance Manager, or an HTTPS server." +f5-keywords: "F5 WAF for NGINX, WAF policy bundle, apBundleSource, apLogBundleSource, NGINX One Console, NGINX Instance Manager, HTTPS bundle source, waf-bundle Secret, NGINX Ingress Controller, VirtualServer, Policy resource, bundle polling" +f5-summary: > + Use this guide to configure NGINX Ingress Controller to automatically fetch compiled F5 WAF for NGINX + policy bundles from NGINX One Console, NGINX Instance Manager, or any HTTPS server, instead of + manually copying bundle files onto the cluster. + Remote bundle sources let WAF protection stay current through polling, so security teams can publish + policy changes without redeploying Kubernetes resources. + This guide covers source-specific setup, verification, and polling for VirtualServer resources; it + does not cover compiling WAF policies or NGINX One Console/NGINX Instance Manager setup themselves. +f5-audience: operator +toc: true +weight: 1800 +f5-content-type: how-to +f5-product: NGINX Ingress Controller +--- + +## Overview + +This guide explains how to configure NGINX Ingress Controller to fetch pre-compiled F5 WAF for NGINX policy bundles from a remote source for VirtualServer resources, instead of manually copying bundles on to the cluster. + +This guide focuses on source-specific configuration details and validation steps. + +You can fetch bundles from: + +- **[NGINX One Console]({{< ref "/nginx-one-console/" >}})** — for policies compiled and managed through NGINX One Console +- **[NGINX Instance Manager]({{< ref "/nim/" >}})** — for policies compiled and managed through NGINX Instance Manager +- **[HTTPS](#https)** — for compiled `.tgz` bundles hosted on any HTTPS server + +Complete end-to-end NGINX Ingress Controller with F5 WAF for NGINX bundle source examples are available on GitHub: [N1C and NIM examples](https://github.com/nginx/kubernetes-ingress/tree/v{{< nic-version >}}/examples/custom-resources/waf-management-plane) and [HTTPS bundle server files](https://github.com/nginx/kubernetes-ingress/tree/v{{< nic-version >}}/examples/shared-examples/waf-bundle-server). + +## NGINX One Console + +### Step 1: Before you begin + +- NGINX Ingress Controller deployed with [F5 WAF for NGINX v5]({{< ref "/nic/integrations/app-protect-waf-v5/installation.md" >}}). You can also [install with Helm]({{< ref "/nic/install/waf-helm.md" >}}). +- An [NGINX One Console]({{< ref "/nginx-one-console/" >}}) account with a published WAF policy. See [Manage policies]({{< ref "/nginx-one-console/waf-integration/policy/_index.md" >}}). +- A VirtualServer resource to attach the WAF policy to. + +{{< call-out class="important" >}} NGINX Ingress Controller does not trigger compilation. Compilation happens when a policy is published in NGINX One Console. Ensure the policy has been published and a compiled bundle is available before continuing. {{< /call-out >}} + +### Step 2: Create a credentials Secret + +Create a Secret of type `nginx.com/waf-bundle` in the same namespace as the Policy. The Secret must contain a `token` key with your NGINX One Console API token: + +To create an API token, see [Authentication]({{< ref "/nginx-one-console/api/authentication.md" >}}). + +```shell +kubectl create secret generic n1c-credentials \ + --type=nginx.com/waf-bundle \ + --from-literal=token= +``` + +### Step 3: Create a WAF Policy + +Create a Policy resource using `apBundleSource` with `type: N1C`: + +```yaml +apiVersion: k8s.nginx.org/v1 +kind: Policy +metadata: + name: waf-policy +spec: + waf: + enable: true + apBundleSource: + type: N1C + url: "https://.console.ves.volterra.io" + policyName: "my-blocking-policy" + policyNamespace: "default" + secret: "n1c-credentials" + enablePolling: true + pollInterval: "5m" +``` + +Replace `` with your NGINX One Console tenant hostname, `policyName` with the name of your published policy, and `policyNamespace` with the NGINX One Console namespace where the policy resides. + +{{< call-out class="note" >}} The field name is `policyName` for both `apBundleSource` and `apLogBundleSource`. In `apBundleSource`, set it to the published WAF policy name. In `apLogBundleSource`, set it to the log profile name (for example, `secops_dashboard`). {{< /call-out >}} + +{{< call-out class="caution" >}} To skip TLS verification for testing, add `insecureSkipVerify: true` to the bundle source. Do not use this in production. {{< /call-out >}} + +### Step 4: Apply the policy to a VirtualServer + +After `waf-policy` is created, apply a VirtualServer that references it in `spec.policies`. + +```yaml +apiVersion: k8s.nginx.org/v1 +kind: VirtualServer +metadata: + name: webapp +spec: + host: webapp.example.com + policies: + - name: waf-policy + upstreams: + - name: webapp + service: webapp-svc + port: 80 + routes: + - path: / + action: + pass: webapp +``` + +For complete HTTPS setup manifests, see the [bundle server files](https://github.com/nginx/kubernetes-ingress/tree/v{{< nic-version >}}/examples/shared-examples/waf-bundle-server). + +### Step 5: Verify the bundle was fetched + +1. Check the Policy events for a successful fetch: + + ```shell + kubectl describe policy waf-policy + ``` + + Look for a `Normal` event confirming the bundle was fetched. If you see a `Warning` event, check the message for the cause — common issues include an incorrect `policyName`, an invalid token, or a policy that has not been published yet. + +1. Send a legitimate request to confirm traffic flows normally: + + ```shell + curl --resolve webapp.example.com:$IC_HTTP_PORT:$IC_IP \ + http://webapp.example.com:$IC_HTTP_PORT/ + ``` + +1. Send a malicious request to confirm WAF is blocking: + + ```shell + curl --resolve webapp.example.com:$IC_HTTP_PORT:$IC_IP \ + "http://webapp.example.com:$IC_HTTP_PORT/