Skip to content

Repository files navigation

Calico & Kubernetes Network Policy Visualiser

A browser-based tool for visualizing Calico and Kubernetes network policies. Import YAML, see an interactive graph, highlighted source, and plain-English explanation. Everything runs client-side.

Calico Policy Visualiser screenshot

Try it now — a live version is available at https://sbulav.github.io/calico-visualiser/

Motivation

Cilium has the free Network Policy Editor for Kubernetes network policies. Calico does not. Its visualization tools are in the paid Cloud and Enterprise versions.

This project is a free alternative. Load your Calico or Kubernetes NetworkPolicy YAML. Get a graph of rules by traffic scope. See a text breakdown of what the policy allows or blocks.

Features

  • Three panels: YAML editor, graph visualization, explanation text. They sync on hover and selection.
  • YAML editor: Editable CodeMirror editor with syntax highlighting. Edit the YAML directly and the graph and explanation update live (debounced at 400 ms). While the YAML is mid-edit and temporarily invalid, the last valid visualization stays on screen and an error banner shows the parse issue. Hover a rule in the graph to highlight the matching YAML lines and scroll to them.
  • Graph: React Flow canvas. Central policy node connects to six rule categories (three for ingress, three for egress). Edges show action colors: green for Allow, red for Deny, amber for Log or mixed.
  • Rule groups: Outside Cluster (CIDRs), In Namespace (pod selectors), In Cluster (cross-namespace). Each has rule cards with ports, selectors, services, and negation fields.
  • Inferred access: Graph shows if Kubernetes DNS, any pod in namespace, or everything in cluster is allowed, denied, or uncertain. Defaults start as deny but catch-all rules override.
  • Explanation: Bottom panel with policy details, flag descriptions (doNotTrack, preDNAT, applyOnForward), effective defaults, and per-rule text. Recognizes 20 well-known ports like Redis (6379), K8s API (6443), PostgreSQL (5432).
  • Supported resources:
    • Calico projectcalico.org/v3: NetworkPolicy, GlobalNetworkPolicy (full existing support)
    • Kubernetes networking.k8s.io/v1: NetworkPolicy (pod/namespace selectors, ipBlock with except, named ports, endPort, policyTypes defaults)
  • Samples: Built-in examples for both Calico and Kubernetes NetworkPolicy.
  • Privacy: No backend. No data sent anywhere.

Quick start

With Docker

docker run --rm -p 8080:8080 ghcr.io/sbulav/calico-policy-visualiser:latest

Open http://localhost:8080. The image serves the static SPA with Nginx and exposes a /health endpoint for container and Kubernetes probes.

To build locally:

docker build -t calico-policy-visualiser .

The Dockerfile supports private base-image mirrors without changing the file:

docker build \
  --build-arg NODE_IMAGE=your-registry/node:22-alpine \
  --build-arg NGINX_IMAGE=your-registry/nginx:1.27-alpine \
  -t calico-policy-visualiser .

Kubernetes

kubectl apply -f deploy/kubernetes/calico-policy-visualiser.yaml

The example creates a Deployment and ClusterIP Service on port 80. Copy deploy/kubernetes/ingress.example.yaml if you want to expose it through an ingress controller.

With Nix

nix develop
make init  # npm install
make dev   # http://localhost:5173

Without Nix

Node.js 22 or later.

npm install
npm run dev  # http://localhost:5173

Load a sample or import YAML. Hover rules in the graph. Read the explanation.

Usage

Click Import YAML in the toolbar and pick a .yaml or .yml file with:

  • Calico NetworkPolicy / GlobalNetworkPolicy (projectcalico.org/v3), or
  • Kubernetes NetworkPolicy (networking.k8s.io/v1)

Or use one of the sample buttons to load a built-in example. You can also type or paste YAML directly into the editor — the visualization updates as you type.

In the graph:

  • Drag nodes to rearrange.
  • Zoom with mouse wheel or on-screen controls.
  • Hover rule cards to highlight the corresponding YAML lines.

Resize panels by dragging the divider handles. Collapse the explanation panel with its toggle.

Example: load the NetworkPolicy sample. One ingress rule appears in the "In Cluster" group. The edge is green (Allow). The explanation panel shows "[ALLOW] incoming TCP to port 6379 (Redis)".

Deep links (auto-load policy from URL)

The app can auto-load a policy from the URL. This is useful for integrating with other tools (e.g., a Kubernetes policy viewer) so users can click a link and land here with the policy already loaded.

Supported parameters (query string or hash):

  • ?url= — fetch YAML from a remote URL (recommended for real policies)
  • ?policy= — inline YAML (useful for short examples)
  • ?policy=lz: — inline LZ-String compressed YAML (recommended for longer inline policies)
  • #policy= — same as ?policy=, but in the hash fragment

Examples (GitHub Pages):

https://sbulav.github.io/calico-visualiser/?url=https%3A%2F%2Fexample.com%2Fpolicies%2Fdefault-deny.yaml
https://sbulav.github.io/calico-visualiser/?policy=apiVersion%3Aprojectcalico.org%2Fv3%0Akind%3ANetworkPolicy%0A...
https://sbulav.github.io/calico-visualiser/?policy=lz:N4Igzg9gTgpgBAHjAJgQwE4EsBOBLAOwA0IAnAsQG4C2ARhAHoB8c8A===
https://sbulav.github.io/calico-visualiser/#policy=apiVersion%3Aprojectcalico.org%2Fv3%0Akind%3ANetworkPolicy%0A...
https://sbulav.github.io/calico-visualiser/#policy=lz:N4Igzg9gTgpgBAHjAJgQwE4EsBOBLAOwA0IAnAsQG4C2ARhAHoB8c8A===

Notes:

  • ?url= requires the remote server to allow cross-origin requests (CORS).
  • Inline ?policy= is limited by URL length. To avoid proxy and browser limits, treat ~2 KB total URL as a safe ceiling and prefer ?url= for larger policies.
  • ?policy=lz: is compressed and more space-efficient, but still subject to URL length limits.

Encoding example (JS):

import { compressToEncodedURIComponent } from 'lz-string';

const param = `lz:${compressToEncodedURIComponent(yaml)}`;
const url = `https://sbulav.github.io/calico-visualiser/?policy=${param}`;

Development

Container Publishing

The GitHub Actions workflow in .github/workflows/container.yml validates the app with lint, test, and build, then publishes an OCI image to GitHub Container Registry on default-branch and v* tag pushes. Pull requests build the image but do not push it.

Published tags include branch names, sha-<shortsha>, semantic versions from tags like v0.9.2, and latest from the default branch.

Set repository variables NODE_IMAGE and NGINX_IMAGE if CI should build from private base-image mirrors.

Commands

Command What it does
npm run dev Vite dev server with hot reload
npm run build Type-check and production build to dist/
npm run test Run Vitest tests
npm run test:watch Tests in watch mode
npm run lint ESLint check
npm run preview Serve built app locally
npx tsc --noEmit Type-check only

make targets mirror these (e.g., make test, make build, make lint). Run make help for the full list.

Project structure

src/
  main.tsx        Entry point
  App.tsx         Root (PolicyProvider + layout)
  index.css       Tailwind v4, CSS variables, overrides
  context/        React Context + useReducer state
  hooks/          Reusable React hooks (debounce, etc.)
  types/          Calico and graph type definitions
  lib/
    formatPort.ts Shared port formatting
    ipUtils.ts    IP/CIDR helpers
    parser/       YAML parsing and validation
    transform/    Policy to React Flow nodes and edges
    explain/      Policy to human-readable text
    matcher/      Selector parsing, rule matching, access testing
  components/
    Layout/       App shell, resizable panels
    Editor/       CodeMirror YAML editor (editable, with live parsing)
    Visualization/  React Flow canvas, custom nodes, edges
    Explanation/  Bottom explanation panel
    AccessTester/ Interactive access testing panel
  samples/        Built-in YAML examples

Tech stack

  • React 19, TypeScript 5.9, Vite 7
  • React Flow (@xyflow/react) for the graph
  • CodeMirror 6 (@uiw/react-codemirror) for YAML
  • Tailwind CSS 4, dark theme with Slate palette
  • js-yaml for parsing
  • Vitest 4 for tests
  • State: React Context + useReducer (no external state library)

Strict TypeScript with verbatimModuleSyntax, noUnusedLocals, noUnusedParameters, and strictNullChecks.

Testing

329 tests across nine files.

File Tests Covers
yamlParser.test.ts 63 Parsing, validation, Calico + Kubernetes fields
yamlLineMapper.test.ts 9 Line ranges for editor highlighting
policyToGraph.test.ts 85 Rule groups, edges, inferred statuses, defaults
policyExplainer.test.ts 47 Text sections, port names, rule descriptions
selectorParser.test.ts 37 Calico selector expression parsing and evaluation
ruleMatcher.test.ts 37 Rule matching against traffic specifications
accessTester.test.ts 18 End-to-end access verdict evaluation
k8sSelector.test.ts 10 Kubernetes label selector normalization
ipUtils.test.ts 23 CIDR containment, private range coverage, port/CIDR validation
npm run test                                          # all tests
npx vitest run src/lib/parser/yamlParser.test.ts      # single file

License

MIT. See LICENSE. Author: Sergei Bulavintsev.

About

A browser-based tool for Calico NetworkPolicy and GlobalNetworkPolicy visualization.

Resources

Stars

13 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages