diff --git a/content/nic/configuration/policy-resource.md b/content/nic/configuration/policy-resource.md index e6c2bd31c0..40c679491a 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/tutorials/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/tutorials/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/tutorials/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/compile-waf-policies.md b/content/nic/integrations/app-protect-waf-v5/compile-waf-policies.md index fedbca1379..434ef5a737 100644 --- a/content/nic/integrations/app-protect-waf-v5/compile-waf-policies.md +++ b/content/nic/integrations/app-protect-waf-v5/compile-waf-policies.md @@ -15,6 +15,8 @@ F5 WAF for NGINX uses policies to configure which security features are set. Whe By using NGINX Instance Manager to compile WAF policies, the policy bundle can also be used immediately by NGINX Ingress Controller without reloading. +{{< call-out class="tip" >}} NGINX Ingress Controller can fetch compiled bundles directly from NGINX Instance Manager or NGINX One Console without the manual download and upload steps described on this page. See [Connect F5 WAF for NGINX to bundle sources]({{< ref "/nic/tutorials/bundle-sources.md" >}}) for details on automated bundle fetching with optional polling for updates. {{< /call-out >}} + The following steps describe how to use the NGINX Instance Manager API to create a new security policy, compile a bundle, then add it to NGINX Ingress Controller. ## Before you begin diff --git a/content/nic/integrations/app-protect-waf-v5/configuration.md b/content/nic/integrations/app-protect-waf-v5/configuration.md index 536c59fcfc..e67cbfc794 100644 --- a/content/nic/integrations/app-protect-waf-v5/configuration.md +++ b/content/nic/integrations/app-protect-waf-v5/configuration.md @@ -19,7 +19,7 @@ NGINX Ingress Controller has global configuration parameters that match those in ## Enable F5 WAF for NGINX v5 -F5 WAF for NGINX v5 can be enabled and configured for custom resources only(VirtualServer, VirtualServerRoute). You need to create a Policy Custom Resource referencing a policy bundle, then add it to the VirtualServer/VirtualServerRoute definition. Additional detail can be found in the [Policy Resource documentation]({{< ref "/nic/configuration/policy-resource.md#waf" >}}). +F5 WAF for NGINX v5 can be enabled for VirtualServer, VirtualServerRoute, and Ingress resources through a Policy resource that references a WAF bundle or bundle source. Additional detail can be found in the [Policy Resource documentation]({{< ref "/nic/configuration/policy-resource.md#waf" >}}). --- @@ -29,6 +29,8 @@ F5 WAF for NGINX bundles for VirtualServer custom resources are defined by creat Before applying a policy, a WAF policy bundle must be created, then copied to a volume mounted to `/etc/app_protect/bundles`. +{{< call-out class="tip" >}} Instead of manually placing bundles on a mounted volume, you can configure NGINX Ingress Controller to fetch bundles from a remote source automatically. See [Connect F5 WAF for NGINX to bundle sources]({{< ref "/nic/tutorials/bundle-sources.md" >}}) for details on NGINX One Console, NGINX Instance Manager, and HTTPS source types. {{< /call-out >}} + {{< call-out class="note" >}} NGINX Ingress Controller supports `securityLogs` for policy bundles. Log bundles must also be copied to a volume mounted to `/etc/app_protect/bundles`. {{< /call-out >}} This example shows how a policy is configured by referencing a generated WAF Policy Bundle: diff --git a/content/nic/integrations/app-protect-waf-v5/troubleshoot-app-protect-waf.md b/content/nic/integrations/app-protect-waf-v5/troubleshoot-app-protect-waf.md index b5847094e1..d43ca4e07f 100644 --- a/content/nic/integrations/app-protect-waf-v5/troubleshoot-app-protect-waf.md +++ b/content/nic/integrations/app-protect-waf-v5/troubleshoot-app-protect-waf.md @@ -23,6 +23,9 @@ The table below categorizes some potential problems with NGINX Ingress Controlle |Start | The configuration is not applied. | Check if a policy bundle is compiled using version of the compiler running in NGINX Ingress Controller. | Policy bundle is invalid. | |Start | The configuration is not applied. | Check if bundle is present in a volume. | Policy bundle is not present in the mounted volume. | |APLogConf, Policy or Ingress Resource. | The configuration is not applied. | Check the events of the APLogConf, Policy and Ingress Resource, check the logs, replace the policy bundle. | Policy bundle is invalid. | +|[Bundle source]({{< ref "/nic/tutorials/bundle-sources.md" >}}). | Bundle not fetched, Warning event on Policy. | Check Policy events and status. Verify the bundle source URL and credentials are correct. | Invalid URL, authentication failure, or bundle not yet compiled on the management plane. | +|[Bundle source]({{< ref "/nic/tutorials/bundle-sources.md" >}}). | VirtualServer or Ingress returns HTTP 500. | Check Policy status for bundle source errors. | Bundle source is unreachable or the bundle is not yet available. | +|[Bundle source]({{< ref "/nic/tutorials/bundle-sources.md" >}}). | Policy not updating after bundle recompilation. | Verify ``enablePolling`` is ``true`` and ``pollInterval`` is at least ``1m``. | Polling is not enabled, or the poll interval is below the minimum. | {{< /table >}} diff --git a/content/nic/tutorials/bundle-sources.md b/content/nic/tutorials/bundle-sources.md new file mode 100644 index 0000000000..a37f90ba5d --- /dev/null +++ b/content/nic/tutorials/bundle-sources.md @@ -0,0 +1,563 @@ +--- +title: Connect F5 WAF for NGINX to NGINX One Console, NGINX Instance Manager, or HTTPS bundle sources +toc: true +weight: 1800 +f5-content-type: how-to +f5-product: INGRESS +--- + +This document 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 + +### 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 >}} + +### 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= +``` + +### 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 >}} + +### 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). + +### 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/