diff --git a/src/pages/en/dashboard_snapshots.md b/src/pages/en/dashboard_snapshots.md index b411aad..ea80447 100644 --- a/src/pages/en/dashboard_snapshots.md +++ b/src/pages/en/dashboard_snapshots.md @@ -17,10 +17,15 @@ To create a new snapshot: 1. **Name** — Enter a descriptive name (e.g., `incident-2024-02-01`, `checkout-debug`) 2. **Nodes** — Select all nodes or specific worker nodes to include 3. **Time Window** — Select any start and end time within the available raw capture data using the date/time picker -4. Click **Create** +4. **Workload Filter** (optional) — Scope the snapshot to specific workloads: + - **Namespaces** — Include only traffic involving pods in the selected namespaces + - **Pod name regex** — Include only traffic involving pods whose names match the regex pattern +5. Click **Create** The snapshot is extracted from [Raw Capture](/en/v2/raw_capture) buffers and moved to dedicated storage on the Hub. The time window can span from minutes to days — limited only by how much raw capture data is available. +When a workload filter is applied, the resulting PCAP contains only packets where at least one peer (source or destination) matches the filter criteria. This is useful in multi-tenant clusters where most captured traffic is irrelevant to the investigation. + --- ## PCAP Export diff --git a/src/pages/en/dns.md b/src/pages/en/dns.md index 85958d5..e7ecbb9 100644 --- a/src/pages/en/dns.md +++ b/src/pages/en/dns.md @@ -6,6 +6,10 @@ layout: ../../layouts/MainLayout.astro **Kubeshark** provides UDP layer visibility into [Kubernetes’ DNS traffic](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/) by capturing all UDP streams that include DNS traffic. Once captured, DNS traffic is dissected and become available as any other protocol supported by **Kubeshark**. +### Self-Traffic Filtering + +When `tap.capture.captureSelf` is disabled (the default), Kubeshark automatically filters out its own DNS queries to the configured cloud API endpoint from the traffic stream. This prevents Kubeshark's internal housekeeping DNS lookups from appearing alongside your application traffic. Other DNS queries made by Kubeshark pods (e.g., resolving in-cluster services) are still visible. + ### DNS Log Use **Kubeshark** to view a DNS log and export into a PCAP file. To view only DNS entries, use: `dns` in the [filter](/en/v2/kfl2) input. Use the [export to PCAP button](/en/pcap#manual-pcap-export) to export the DNS traffic to a PCAP file. diff --git a/src/pages/en/mcp/raw_capture_tools.md b/src/pages/en/mcp/raw_capture_tools.md index 5ade6b6..f442d7f 100644 --- a/src/pages/en/mcp/raw_capture_tools.md +++ b/src/pages/en/mcp/raw_capture_tools.md @@ -107,7 +107,11 @@ Create a new snapshot. ```json { "name": "incident-001", - "duration": "1h" + "duration": "1h", + "workload_filter": { + "namespaces": ["production", "payments"], + "pod_regex": "checkout-.*" + } } ``` @@ -115,6 +119,11 @@ Create a new snapshot. |-------|------|-------------| | `name` | string | Unique snapshot identifier | | `duration` | string | Time duration to capture (e.g., `30m`, `1h`, `2h`) | +| `workload_filter` | object | (Optional) Scope the snapshot to specific workloads | +| `workload_filter.namespaces` | []string | Include only traffic involving pods in these namespaces | +| `workload_filter.pod_regex` | string | Include only traffic involving pods matching this regex | + +When `workload_filter` is provided, the resulting PCAP contains only packets where at least one peer matches the filter. Both fields are optional within the filter object — omit either to not filter on that dimension. **Response:** ```json diff --git a/src/pages/en/oidc.md b/src/pages/en/oidc.md index 61a00b8..5c622f3 100644 --- a/src/pages/en/oidc.md +++ b/src/pages/en/oidc.md @@ -100,6 +100,10 @@ After configuring the values file, install Kubeshark: helm install kubeshark kubeshark/kubeshark -f ./values.yaml ``` +### Login Behavior + +Kubeshark sends `prompt=login` on every OIDC authorize request, forcing the IdP to re-prompt for credentials on each login. After logging out of Kubeshark, the IdP will not silently re-authenticate the user from a leftover SSO session cookie — operators can pick a different user without clearing browser state. This does not affect the IdP session for other applications in the same org. + ### Try Your OIDC-Enabled Kubeshark Once OIDC is enabled you'll be redirected to your IdP's login page. The screenshots below show Dex; Okta / Auth0 / Keycloak follow the same flow. diff --git a/src/pages/en/saml.md b/src/pages/en/saml.md index 3ba5930..93f4569 100644 --- a/src/pages/en/saml.md +++ b/src/pages/en/saml.md @@ -56,6 +56,10 @@ auth: > - Per-role `filter` (raw KFL string) was replaced with `namespaces` (comma list, see below). Configs carrying `filter:` are ignored at unmarshal — migrate to `namespaces:`. > - `auth.defaultFilter` is removed. The deny-default semantic moves into per-role `namespaces: ""`; opt out for admin roles with `namespaces: "*"`. +### Login Behavior + +Kubeshark sends `ForceAuthn=true` on every SAML AuthnRequest, forcing the IdP to re-prompt for credentials on each login. After logging out of Kubeshark, the IdP will not silently re-authenticate the user from a leftover SSO session cookie — operators can pick a different user without clearing browser state. This does not affect the IdP session for other applications in the same org. + ### X.509 Certificate & Key ```shell diff --git a/src/pages/en/v2/kfl2.md b/src/pages/en/v2/kfl2.md index 316585f..cac0ef7 100644 --- a/src/pages/en/v2/kfl2.md +++ b/src/pages/en/v2/kfl2.md @@ -167,6 +167,8 @@ Boolean variables that indicate which protocol was detected. Use these as the fi | `grpc` | gRPC over HTTP/2 | `conn` / `flow` | L4 connection/flow tracking | | `radius` | RADIUS | `tcp_conn` / `udp_conn` | Transport-specific connections | | `diameter` | Diameter | `tcp_flow` / `udp_flow` | Transport-specific flows | +| `tlsx` | TLS handshake (ClientHello/ServerHello) | `mongodb` | MongoDB | +| `mysql` | MySQL | `postgresql` | PostgreSQL | ### Identity and Metadata Variables @@ -249,6 +251,20 @@ gRPC traffic is detected as a sub-protocol of HTTP/2. When `grpc` is true, all H | `tls_response_size` | int | TLS response size in bytes | | `tls_total_size` | int | Sum of request + response sizes | +### TLS Handshake Variables (TLSX) + +These variables are available when `tlsx` is true (TLS ClientHello or ServerHello entries). See [TLS Handshake Inspection](/en/tls_handshake_inspection) for details. + +| Variable | Type | Description | +|----------|------|-------------| +| `tls_sni` | string | Server Name Indication hostname (from ClientHello) | +| `tls_cipher_suite` | int | Negotiated cipher suite ID (from ServerHello) | +| `tls_cipher_suites` | []string | Offered cipher suite names (from ClientHello) | +| `tls_alpn` | string | Negotiated ALPN protocol | +| `tls_version` | int | Negotiated TLS version (from ServerHello) | + +> **Note:** `tlsx` is different from `tls`. The `tls` flag indicates traffic captured via eBPF TLS interception (decrypted HTTPS). The `tlsx` flag indicates TLS handshake entries (ClientHello/ServerHello) parsed from unencrypted handshake bytes. + ### TCP Variables | Variable | Type | Description | @@ -648,6 +664,37 @@ KFL is statically typed. Common gotchas: - Map access on missing keys errors — use `key in map` or `map_get()` first - List membership uses `value in list` — not `list.contains(value)` +## Protocol Scoping + +Protocol-specific variables are automatically scoped to their owning protocol. A filter like `status_code == 200` only matches HTTP entries — it will never match DNS, Kafka, or other protocol entries, even when their default value would satisfy the comparison. + +This applies to all comparison operators (`==`, `!=`, `<`, `<=`, `>`, `>=`), membership (`in`), string functions (`contains`, `startsWith`, `endsWith`, `matches`), and CEL list macros (`.exists`, `.all`, `.filter`, `.map`). + +You can still prefix with the protocol flag for readability (`http && status_code == 200`), but it is no longer required for correctness. + +### Field Existence and Absence + +Use a protocol-specific variable as a bareword to test whether entries of that protocol exist: + +```cel +# Every HTTP entry (field existence) +status_code + +# Every non-HTTP entry (field absence) +!status_code + +# Every DNS entry +dns_questions + +# Every Kafka entry +kafka_api_key + +# Every TLS handshake entry +tls_sni +``` + +This works for all non-boolean protocol variables. Boolean protocol variables (`dns_request`, `kafka_request`, `ws_request`, etc.) retain their original value semantics when used as barewords. + ## Default Values When a variable is not present in an entry, KFL uses these defaults: @@ -661,6 +708,8 @@ When a variable is not present in an entry, KFL uses these defaults: | map | `{}` | | bytes | `[]` | +> **Note:** Default values only apply within the owning protocol's scope. A filter like `status_code == 0` matches only HTTP entries where the status is actually zero — it does not match non-HTTP entries. + ## Performance Tips 1. **Protocol flags first** — `http && ...` is faster than `... && http` diff --git a/src/pages/en/v2/traffic_snapshots.md b/src/pages/en/v2/traffic_snapshots.md index a64c336..f1b428b 100644 --- a/src/pages/en/v2/traffic_snapshots.md +++ b/src/pages/en/v2/traffic_snapshots.md @@ -8,6 +8,7 @@ Traffic Snapshots extract any time window from the available [Raw Capture](/en/v **Key value:** - **Download cluster-wide PCAPs** — filtered by time, nodes, workloads, and IPs. Get exactly what matters, ready for Wireshark or any PCAP-compatible tool. +- **Workload-scoped snapshots** — scope a snapshot to specific Kubernetes namespaces and/or a pod-name regex, so the resulting PCAP contains only traffic involving the matching pods. - **Long-term retention** — store snapshots and PCAPs in cloud storage (S3, Azure Blob) for compliance, audits, and future investigation. ---