From 4ba01bfd48e3ccb8d3c6128ae33452161d625012 Mon Sep 17 00:00:00 2001 From: Seth Malaki Date: Thu, 22 Oct 2026 13:53:11 +0100 Subject: [PATCH 1/2] docs(manager): add optional Kibana WAF exception to gateway access steps Kibana Discover returns 403 when a Gateway WAF policy with the Core Rule Set covers the web console gateway. Add one optional step with the smallest GlobalWAFPlugin that fixes it, and point the WAF troubleshooting 403 section at it. EV-7238 --- .../operations/cnx/access-the-manager.mdx | 18 ++++++++++++++++++ .../threat/gateway-waf/troubleshooting.mdx | 2 ++ 2 files changed, 20 insertions(+) diff --git a/calico-enterprise/operations/cnx/access-the-manager.mdx b/calico-enterprise/operations/cnx/access-the-manager.mdx index 7cd4d16133..533e0843d8 100644 --- a/calico-enterprise/operations/cnx/access-the-manager.mdx +++ b/calico-enterprise/operations/cnx/access-the-manager.mdx @@ -217,6 +217,24 @@ Instead of creating an ingress or load balancer yourself, you can let the operat 1. Point your hostname at that address in DNS. +1. Optional: if you protect the web console with a [Gateway WAF](../../threat/gateway-waf/overview.mdx) policy that uses the Core Rule Set, Kibana Discover fails with HTTP `403`. The Core Rule Set reads Kibana's search requests as attacks. To allow them, create this `GlobalWAFPlugin`. Replace `manager.example.com` with your hostname in both rules: + + ```yaml + apiVersion: applicationlayer.projectcalico.org/v3 + kind: GlobalWAFPlugin + metadata: + name: kibana-exceptions + spec: + before: | + SecRule SERVER_NAME "@streq manager.example.com" "id:100000001,phase:1,pass,nolog,t:none,t:lowercase,chain" + SecRule REQUEST_METHOD "@streq POST" "t:none,chain" + SecRule REQUEST_FILENAME "@streq /tigera-kibana/internal/bsearch" "t:none,t:urlDecodeUni,t:normalizePath,ctl:requestBodyAccess=Off" + SecRule SERVER_NAME "@streq manager.example.com" "id:100000002,phase:1,pass,nolog,t:none,t:lowercase,chain" + SecRule REQUEST_FILENAME "@beginsWith /tigera-kibana/" "t:none,t:urlDecodeUni,t:normalizePath,ctl:ruleRemoveTargetById=931100;ARGS:url,ctl:ruleRemoveTargetById=934110;ARGS:url" + ``` + + Then add `{kind: GlobalWAFPlugin, name: kibana-exceptions}` to `spec.plugins` in the `default` `GlobalWAFPolicy`. Edit the list in place, because re-applying a whole `default` drops fields it leaves out. The WAF then skips only the body of Kibana search requests on your web console host. It still inspects everything else. For more on plugins, see [Write custom rules with plugins](../../threat/gateway-waf/write-custom-rules.mdx). + :::note If your cluster uses OIDC, set the `Authentication` resource's `managerDomain` to `https://` plus that hostname (as in the example below). The host must match `spec.ingressGateway.hostname`, or the operator reports the $[prodname] web console as degraded: diff --git a/calico-enterprise/threat/gateway-waf/troubleshooting.mdx b/calico-enterprise/threat/gateway-waf/troubleshooting.mdx index 93661f150c..3ab9635061 100644 --- a/calico-enterprise/threat/gateway-waf/troubleshooting.mdx +++ b/calico-enterprise/threat/gateway-waf/troubleshooting.mdx @@ -175,6 +175,8 @@ kubectl logs -n \ For how to write exception rules within your namespace's ID range, see [Write custom rules with plugins](./write-custom-rules.mdx). +If Kibana Discover in the web console returns `403`, see the optional WAF step in [Configure access to the web console](../../operations/cnx/access-the-manager.mdx). + :::caution `SecRuleRemoveById` can only target rule IDs within your namespace's allocated range. You cannot remove Core Rule Set baseline rules (IDs `900000`–`999999`) or Tigera-managed rules — the admission webhook will reject the plugin with `ProtectedIDRemoval`. From 3a44df4a6090f59c8cf6aceb5049117ff9bda8fb Mon Sep 17 00:00:00 2001 From: Seth Malaki Date: Thu, 22 Oct 2026 17:08:07 +0100 Subject: [PATCH 2/2] docs(manager): use a hostname placeholder and a plugins snippet in the Kibana WAF step Per review: name the hostname placeholder and define it after the YAML, show only the spec.plugins entry to add to the existing default GlobalWAFPolicy, and say that the url argument exception covers every Kibana request, not just search. EV-7238 --- .../operations/cnx/access-the-manager.mdx | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/calico-enterprise/operations/cnx/access-the-manager.mdx b/calico-enterprise/operations/cnx/access-the-manager.mdx index 533e0843d8..8794069373 100644 --- a/calico-enterprise/operations/cnx/access-the-manager.mdx +++ b/calico-enterprise/operations/cnx/access-the-manager.mdx @@ -217,7 +217,7 @@ Instead of creating an ingress or load balancer yourself, you can let the operat 1. Point your hostname at that address in DNS. -1. Optional: if you protect the web console with a [Gateway WAF](../../threat/gateway-waf/overview.mdx) policy that uses the Core Rule Set, Kibana Discover fails with HTTP `403`. The Core Rule Set reads Kibana's search requests as attacks. To allow them, create this `GlobalWAFPlugin`. Replace `manager.example.com` with your hostname in both rules: +1. Optional: if you protect the web console with a [Gateway WAF](../../threat/gateway-waf/overview.mdx) policy that uses the Core Rule Set, Kibana Discover fails with HTTP `403`. The Core Rule Set reads Kibana's search requests as attacks. To allow them, create this `GlobalWAFPlugin`: ```yaml apiVersion: applicationlayer.projectcalico.org/v3 @@ -226,14 +226,26 @@ Instead of creating an ingress or load balancer yourself, you can let the operat name: kibana-exceptions spec: before: | - SecRule SERVER_NAME "@streq manager.example.com" "id:100000001,phase:1,pass,nolog,t:none,t:lowercase,chain" + SecRule SERVER_NAME "@streq " "id:100000001,phase:1,pass,nolog,t:none,t:lowercase,chain" SecRule REQUEST_METHOD "@streq POST" "t:none,chain" SecRule REQUEST_FILENAME "@streq /tigera-kibana/internal/bsearch" "t:none,t:urlDecodeUni,t:normalizePath,ctl:requestBodyAccess=Off" - SecRule SERVER_NAME "@streq manager.example.com" "id:100000002,phase:1,pass,nolog,t:none,t:lowercase,chain" + SecRule SERVER_NAME "@streq " "id:100000002,phase:1,pass,nolog,t:none,t:lowercase,chain" SecRule REQUEST_FILENAME "@beginsWith /tigera-kibana/" "t:none,t:urlDecodeUni,t:normalizePath,ctl:ruleRemoveTargetById=931100;ARGS:url,ctl:ruleRemoveTargetById=934110;ARGS:url" ``` - Then add `{kind: GlobalWAFPlugin, name: kibana-exceptions}` to `spec.plugins` in the `default` `GlobalWAFPolicy`. Edit the list in place, because re-applying a whole `default` drops fields it leaves out. The WAF then skips only the body of Kibana search requests on your web console host. It still inspects everything else. For more on plugins, see [Write custom rules with plugins](../../threat/gateway-waf/write-custom-rules.mdx). + Replace the following: + * ``: The hostname you set in `spec.ingressGateway.hostname`, in lowercase. For example, `manager.example.com`. + + Then add `kibana-exceptions` to the `spec.plugins` list in your existing `default` `GlobalWAFPolicy`. Keep any plugins that are already in the list. If `spec.plugins` doesn't exist yet, add it: + + ```yaml + spec: + plugins: + - kind: GlobalWAFPlugin + name: kibana-exceptions + ``` + + On your web console host, the WAF stops inspecting the body of Kibana search requests. For every Kibana request, rules `931100` and `934110` no longer check the `url` argument. The WAF still inspects all other traffic. For more about plugins, see [Write custom rules with plugins](../../threat/gateway-waf/write-custom-rules.mdx). :::note