Skip to content

Show what a NetworkPolicy actually does on its detail page and list column - #1745

Merged
nadaverell merged 2 commits into
mainfrom
fix/network-policy-detail-semantics
Sep 13, 2026
Merged

nadaverell merged 2 commits into
mainfrom
fix/network-policy-detail-semantics

Conversation

@nadaverell

@nadaverell nadaverell commented Sep 13, 2026 •

Copy link
Copy Markdown
Contributor

Why

The NetworkPolicy detail page and list column mis-described policies in ways that read as more permissive than reality:

  • A peer with both podSelector and namespaceSelector (an AND — "these pods, in these namespaces") showed only the pod selector, so a narrow cross-namespace grant read as a broad same-namespace one.
  • A selector made of matchExpressions rendered as "all pods" / "All pods" in the flow diagram.
  • endPort ranges were dropped from the rule list (TCP/9000 for a 9000–9100 range).
  • A spec that omits policyTypes showed as isolating nothing (list: -; detail: no rules at all), when Kubernetes' defaulting makes it isolate ingress — the classic default-deny shape.

What

One shared helper, packages/k8s-ui/src/utils/network-policy.ts, now backs the list column (getNetworkPolicyTypes), the detail renderer and the flow diagram, so the three surfaces cannot disagree:

  • effectivePolicyTypes(spec) applies Kubernetes' defaulting exactly (omitted ⇒ Ingress, plus Egress iff egress rules exist) and reports whether the type was declared. The detail page says "by default — policyTypes not set" when it wasn't.
  • formatNetworkPolicyPort renders PROTO/port, PROTO/start-end for numeric ranges, PROTO/* for protocol-only entries; a range off a named port is not a range and isn't shown as one.
  • The renderer shows both selectors of a peer, labelled as an AND ("podSelector: … / in namespaceSelector: …"), matching what the diagram already drew.
  • The diagram formats selectors through the existing formatKubernetesLabelSelector, so matchExpressions read as tier In (web,api) rather than "all".

Scope note on policyTypes. The API server defaults policyTypes on admission, so objects read from a cluster always carry it explicitly and the list/detail were already right for them. The defaulting fix matters for specs that haven't been admitted — the YAML preview/editor, GitOps desired-state views, snapshots — and it keeps the UI consistent with pkg/netpol, which applies the same rule server-side.

Additive only: no @skyhook-io/k8s-ui export or prop removed or renamed.

Testing

  • vitest: utils/network-policy.test.ts (defaulting, type naming, port formatting incl. invalid-range cases) and NetworkPolicyRenderer.test.tsx (each of the four shapes, the explicit-types negative, and diagram-specific assertions so a break in one surface can't hide behind the other). Full k8s-ui suite green; make tsc clean.
  • Visual test on a kind cluster with four labelled policies: the list column shows Ingress for the default-deny; detail pages render the denied flow, the AND'ed peer (app=radar in kubernetes.io/metadata.name=radar), role Exists → tier In (web,api) in the diagram, and TCP/9000-9100 + UDP/53 with the 10.0.0.0/8 except 10.0.1.0/24 egress block. No console errors.

Follow-ups (separate PRs)

  • pkg/netpol: a per-policy explanation primitive (enables the next item without duplicating semantics).
  • Rebase /api/network-policies/evaluate (the Traffic view's dropped-flow panel) on pkg/netpol; its own evaluator still ignores ports, mishandles namespaceSelector and ipBlock.
  • Reachability view: a label overlap after the in-cluster probe runs.

Note

Low Risk
Presentation-only changes in k8s-ui with unit tests; no enforcement or API behavior changes, and the diff corrects previously misleading policy UI.

Overview
Introduces shared network-policy helpers so the list column, detail renderer, and flow diagram agree on Kubernetes semantics instead of each interpreting the spec differently.

effectivePolicyTypes / effectivePolicyTypeNames apply API defaulting when policyTypes is omitted (ingress-only unless egress rules exist); the detail view always shows policy types and notes "by default — policyTypes not set" when defaulted. formatNetworkPolicyPort standardizes port badges and diagram labels, including numeric endPort ranges.

The renderer now shows both podSelector and namespaceSelector on the same peer (AND semantics). The diagram formats selectors via formatKubernetesLabelSelector, so matchExpressions are not shown as "all pods". Vitest covers the helpers and renderer/diagram HTML expectations.

Reviewed by Cursor Bugbot for commit af6bae0. Bugbot is set up for automated code reviews on this repo. Configure here.

…olumn

A policy that omits policyTypes isolates ingress (and egress when it has
egress rules) — the classic default-deny is exactly that shape — but the
list column showed it as "-" and the detail page and diagram showed no
rules at all. One shared helper now applies Kubernetes' defaulting for all
three, and the detail page says when the type was defaulted rather than
declared. A peer that sets both podSelector and namespaceSelector is an AND
and is now shown as one; matchExpressions no longer read as "all pods";
endPort ranges appear in the rule list.
@nadaverell
nadaverell requested a review from hisco as a code owner September 13, 2026 20:15
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Correct NetworkPolicy semantics across list, detail, and diagram

🐞 Bug fix 🧪 Tests 🕐 20-40 Minutes

Grey Divider

AI Description

• Apply Kubernetes policyTypes defaulting consistently across lists, details, and diagrams.
• Render combined selectors, matchExpressions, and valid port ranges without overstating access.
• Add focused tests protecting shared helpers and both visual surfaces independently.
Diagram

graph TD
  Spec["NetworkPolicy Spec"] --> Helper["Shared Semantics"] --> List["List Column"]
  Helper --> Detail["Detail Renderer"]
  Helper --> Diagram["Flow Diagram"]
  Selector["Selector Formatter"] --> Diagram
Loading
High-Level Assessment

The shared-helper approach is appropriate because it gives all three presentation surfaces one implementation of Kubernetes defaulting and port semantics while reusing the established selector formatter. Keeping separate formatting logic or introducing a larger normalized view-model layer would either preserve divergence risk or add unnecessary scope.

Files changed (7) +238 / -54

Enhancement (1) +1 / -0
index.tsExport shared NetworkPolicy utilities +1/-0

Export shared NetworkPolicy utilities

• Adds the NetworkPolicy presentation helpers to the package utility barrel without removing or renaming existing exports.

packages/k8s-ui/src/utils/index.ts

Bug fix (4) +120 / -54
NetworkPolicyDiagram.tsxAlign diagram output with Kubernetes NetworkPolicy semantics +9/-16

Align diagram output with Kubernetes NetworkPolicy semantics

• Uses shared effective policy types and port formatting so omitted types and numeric ranges render correctly. Reuses the Kubernetes selector formatter so matchExpressions are displayed instead of being mistaken for an all-pods selector.

packages/k8s-ui/src/components/resources/renderers/NetworkPolicyDiagram.tsx

NetworkPolicyRenderer.tsxCorrect NetworkPolicy detail-page rule descriptions +50/-36

Correct NetworkPolicy detail-page rule descriptions

• Displays effective policy types and identifies when Kubernetes defaulting applies. It also formats port ranges through the shared helper and renders pod and namespace selectors together to preserve their AND semantics.

packages/k8s-ui/src/components/resources/renderers/NetworkPolicyRenderer.tsx

resource-utils.tsShow effective policy types in NetworkPolicy lists +2/-2

Show effective policy types in NetworkPolicy lists

• Changes the NetworkPolicy type accessor to return Kubernetes-effective type names, ensuring omitted policyTypes display Ingress rather than a dash.

packages/k8s-ui/src/components/resources/resource-utils.ts

network-policy.tsCentralize NetworkPolicy presentation semantics +59/-0

Centralize NetworkPolicy presentation semantics

• Introduces shared helpers for Kubernetes policyTypes defaulting, effective type naming, and NetworkPolicy port formatting. The helpers provide one semantic source for list, detail, and diagram views.

packages/k8s-ui/src/utils/network-policy.ts

Tests (2) +117 / -0
NetworkPolicyRenderer.test.tsxTest NetworkPolicy detail and diagram semantics +75/-0

Test NetworkPolicy detail and diagram semantics

• Adds server-rendered component tests for defaulted policy types, explicit-type labeling, combined peer selectors, matchExpressions, port ranges, and empty-selector diagram behavior.

packages/k8s-ui/src/components/resources/renderers/NetworkPolicyRenderer.test.tsx

network-policy.test.tsTest policy defaulting and port formatting helpers +42/-0

Test policy defaulting and port formatting helpers

• Covers explicit and defaulted policy types, deterministic type ordering, egress inference, single and ranged ports, named ports, protocol-only entries, and invalid range combinations.

packages/k8s-ui/src/utils/network-policy.test.ts

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider

Great, no issues found!

Qodo reviewed your code and found no material issues that require review

Grey Divider

Tip of the day
💡 Did you know, you can start a comment with 'qodo' or '@qodo' to chat about any finding

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

@nadaverell
nadaverell merged commit 741cfaa into main Sep 13, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant