Releases: hardbyte/netchecks
v0.10.0 — PostgreSQL Probes
v0.10.0 — PostgreSQL Probes
New probe types
postgres — SQL assertions
Run a single SQL statement against a PostgreSQL database and validate the result with CEL. Defaults to a read-only transaction that rolls back, so probes have no side-effects.
```yaml
- name: database-responds
type: postgres
dsn: "{{ database.DATABASE_URL }}"
query: "select count(*) as n from orders where status = 'pending'"
validate:
pattern: "data.success == true && data.rows[0].n >= 0"
```
postgres-grants — effective privilege checks
Verify that your database access controls are actually enforced. Uses PostgreSQL's has_*_privilege family of functions so role membership, PUBLIC grants, and inheritance are all accounted for — not just raw ACL arrays.
```yaml
- name: billing-schema-is-team-only
type: postgres-grants
dsn: "{{ database.DATABASE_URL }}"
rules:- name: non-billing-roles-cannot-use-billing
mode: deny
roles:
login: true
exclude-member-of: [team_billing]
objects:
type: schema
names: [billing]
privileges: [USAGE, CREATE]
```
- name: non-billing-roles-cannot-use-billing
Both probe types are supported via NetworkAssertion in Kubernetes and via the netcheck postgres CLI command. Grant checks are config/NetworkAssertion-only (multi-rule by nature).
Security note
DSNs are redacted from probe output by default. The PostgreSQL probe docs include a least-privilege setup guide — in particular, avoid superuser DSNs: COPY ... TO PROGRAM can execute shell commands on the database server even inside a read-only transaction.
Other changes
tcp.py: timestamp fields are now timezone-aware UTC (matchedhttp,dns, andpostgres)- Operator CRD doc comment updated to list all supported probe types
Upgrade notes
No breaking changes. psycopg[binary]>=3,<4 is a new dependency of the netcheck Python package (pulled in automatically via pip/uv). The Kubernetes operator image is unchanged — postgres probes run inside the existing probe container.
netchecks-0.3.1
Netchecks proactively verifies whether your security controls are working as intended.
v0.9.0
Highlights
PolicyReport v1beta1 storage write (#306-era follow-up)
The operator now writes PolicyReports directly as wgpolicyk8s.io/v1beta1 — the chart's CRD already had v1beta1 as the storage version, so this just removes the Kubernetes-side conversion hop. Consumers reading raw etcd or watching the storage version (kyverno/policy-reporter 3.x+) get the modern shape verbatim. The v1alpha2 endpoint is still served.
Grafana dashboard, alerts, and observability examples
A turn-key path to Grafana for the operator's OTLP metrics:
operator ──OTLP──► OTel Collector ──Prom scrape──► Prometheus ──► Grafana
docs/grafana/netchecks-dashboard.json— 11 panels: reconcile throughput / errors / duration, in-flight reconciliations, assertion processing, PolicyReport upserts, probe duration p50/p95/p99 by probe type, plus four headline stat panels.docs/grafana/alerts/netchecks-alerts.yaml— five Grafana unified-alerting rules.operator/examples/observability/— minimal OTel Collector deployment + ServiceMonitor.
Validated end-to-end against kube-prometheus-stack on kind 1.32.
Compliance annotations
- New docs page
Compliance Annotationscoveringnetchecks.io/controls,netchecks.io/description,netchecks.io/severity. - Three example NetworkAssertions: PCI-DSS v4.0 CDE isolation, SOC 2 boundary protection, CIS Kubernetes Benchmark default-deny.
Helm chart
- Chart version 0.2.2 → 0.3.0,
appVersion0.9.0. policy-reportersubchart 2.22.4 → 3.7.4 (major). Subchart is opt-in (policy-reporter.enabled=falseby default). If you've customised values under thepolicy-reporter:key, review the upstream changelog. The keys netchecks itself sets (enabled,ui.enabled) are unchanged.
Cilium example
The TCP-egress example netpol now uses toEntities: [kube-apiserver] instead of toServices: [kubernetes]. Cilium 1.17+ changed how toServices matching interacts with kube-proxy DNAT; the new rule works on Cilium 1.16+ and is the idiomatic post-1.17 pattern.
Internal / CI
- Rust deps: opentelemetry 0.31 → 0.32 (operator), kube-rs 3.0 → 3.1, plus lockfile refresh.
- CLI deps: pydantic 2.12 → 2.13, typer 0.24 → 0.25, requests 2.32 → 2.34, urllib3 2.6 → 2.7, ruff 0.15.5 → 0.15.12.
richconstraint relaxed to<16.0.0; locked at 15.0.0. - CI: pytest 8 → 9, kind 0.18 → 0.27, kubectl 1.26.3 → 1.32.2, kindest/node v1.32.2, Cilium 1.14.3 → 1.19.3, cilium-cli v0.15.11 → v0.19.2.
- GitHub Actions: bumped to Node 24-capable versions ahead of the September 2026 deprecation (checkout v6, setup-python v6, upload-artifact v7, download-artifact v8, docker/* family bumped, setup-uv v7).
- Dependabot: replaced the dead
pip /operatorecosystem withcargo /operator.
See CHANGELOG.md for the full list.
netchecks-0.3.0
Netchecks proactively verifies whether your security controls are working as intended.
v0.8.0
Features
Default probe resource requests/limits (#147)
The operator now applies a configurable resources block to every probe Job it creates. Set probeConfig.resources in the Helm chart values:
probeConfig:
resources:
requests:
cpu: "20m"
memory: "64Mi"
limits:
cpu: "100m"
memory: "128Mi"The chart wires it through to the operator via a new PROBE_RESOURCES env var (JSON-encoded ResourceRequirements). Unset or malformed values fall back to the cluster default — a typo in Helm values cannot crash-loop the operator.
Source IP binding for TCP, HTTP, and DNS probes (#70)
All three probe types accept a --source-ip CLI flag (and a matching source-ip field in netcheck run configs):
netcheck tcp --host github.com --port 443 --source-ip 192.168.1.10
netcheck http --url https://example.com --source-ip 192.168.1.10
netcheck dns --host example.com --source-ip 192.168.1.10The source IP echoes back in the probe spec so it shows up in PolicyReport evidence.
Operator / Helm Chart
- Helm chart version bumped to 0.2.2.
- New env var
PROBE_RESOURCES(JSON-encodedResourceRequirements).
Documentation / Site
- Bumped
next14.2.32 → 14.2.35 for SNYK-JS-NEXT-14400636 (Next.js high-severity deserialization vuln).
netchecks-0.2.2
Netchecks proactively verifies whether your security controls are working as intended.
v0.7.0
Major Changes
-
Operator rewritten from Python to Rust — The Kubernetes operator has been completely replaced with a Rust implementation using kube-rs 3.0. This brings significantly lower memory usage (~5MB vs ~50MB), faster startup, and compile-time type safety. The operator container now uses a distroless base image (
chainguard/static). -
TCP probe type — New
tcpprobe for testing raw socket connectivity. Available as a CLI command (netcheck tcp --host <host> --port <port>) and in NetworkAssertion rules. Useful for verifying non-HTTP services and network policy enforcement.
Features
-
Status conditions on NetworkAssertion — The operator now writes reconciliation status back to the NetworkAssertion resource. Visible via
kubectl get nas(Ready/Reason columns) andkubectl describe. Conditions reportReconciled=Truewith probe result summaries, orReconciled=Falsewith error details for invalid specs or API errors. -
Event-driven CronJob processing — The controller now watches CronJob changes (
.owns(cronjobs)), so scheduled assertion results are processed via events rather than polling. The periodic safety-net requeue interval has been relaxed from 60s to 300s. -
Structured JSON logging — Operator logs are emitted as structured JSON via the
tracingcrate, with configurable log levels viaRUST_LOGenvironment variable. -
OTLP metrics export — Optional OpenTelemetry metrics (reconciliation duration, probe duration, assertion counts, PolicyReport updates) exported when
OTEL_EXPORTER_OTLP_ENDPOINTis set. -
Health endpoints — New
/livezand/readyzendpoints (with/healthzcompatibility) for Kubernetes probes.
Bug Fixes
-
PolicyReport server-side apply — Removed invalid
scope.apiGroupfield from PolicyReport data that caused 500 errors with the v1alpha2 CRD schema. Extended fallback to handle both 422 and 500 responses. -
PolicyReport summary format — Summary now omits zero-valued counts (e.g. no
failkey when all probes pass), matching the original operator behavior and integration test expectations. -
Multi-platform Docker build — Fixed BuildKit cache mount collisions between amd64 and arm64 builds by using platform-specific cache IDs.
Operator / Helm Chart
- Helm chart version bumped to 0.2.1.
- CRD updated with
subresources: status: {}to enable the status subresource endpoint. - New printer columns on
kubectl get networkassertions: Schedule, Ready, Reason, Status. - Tighter RBAC — removed Kopf-specific permissions.
- Operator configuration via environment variables:
PROBE_IMAGE_REPOSITORY,PROBE_IMAGE_TAG,PROBE_IMAGE_PULL_POLICY,POLICY_REPORT_MAX_RESULTS.
Breaking Changes
- CRD upgrade required — The NetworkAssertion CRD now includes the status subresource. Existing clusters must re-apply the CRD (
kubectl apply -f crds/networkassertions.yaml) since Helm does not update CRDs onhelm upgrade. - Operator image changed — The operator container image is now built from Rust instead of Python. The image name (
ghcr.io/hardbyte/netchecks-operator) is unchanged. - Removed Kopf peering CRDs — The operator no longer uses
ClusterKopfPeeringorNamespacedKopfPeeringresources.
Full Changelog: v0.6.0...v0.7.0
netchecks-0.2.1
Netchecks proactively verifies whether your security controls are working as intended.
v0.6.0
Highlights
- Rust CEL engine: Switched from Python
celpyto the Rust-basedcommon-expression-language(0.5.6) for CEL expression evaluation — better performance and native dict subclass support - Pydantic v2: Migrated both CLI and operator from Pydantic v1 to v2
- Operator dependency updates: All operator dependencies upgraded to latest compatible versions (kopf, kubernetes, structlog, OpenTelemetry, etc.)
Changes
CEL Library Migration
- Replaced
cel-pythonwithcommon-expression-language0.5.6 - New API:
cel.Contextandcel.evaluate(replacescelpy.Environment) - Custom functions (
parse_json,parse_yaml,b64decode,b64encode) continue to work identically LazyFileLoadingDictnow works directly with CEL (dict subclass support in 0.5.6)
Pydantic 2.x Migration
- Upgraded
pydanticto^2.0in both CLI and operator - Added
pydantic-settings^2.0to operator - Migrated operator config to
SettingsConfigDictandPydanticBaseSettingsSource
Security & Robustness
- Added path traversal protection to
LazyFileLoadingDict - Added filtering of Kubernetes ConfigMap metadata files (symlinks like
..data) - Improved CEL error handling: parse errors raise
ValueError, runtime errors returnFalse
Testing
- New test suites: CEL validation (12 tests), LazyFileLoadingDict (8 tests), operator config (11 tests)
- Integration test debugging: pod logs captured on failure
- All CI checks green across Python 3.11/3.12 on Linux, macOS, Windows
Other
- CLI dependencies updated to latest versions
- Added
AGENTS.mdwith architecture docs and local development instructions - Dockerfile fix: re-enabled
VIRTUAL_ENVfor package discovery - US spelling standardization throughout codebase
Breaking Changes
None — all changes are internal. The external CLI and operator APIs remain unchanged.
Full Changelog: v0.5.6...v0.6.0
v0.5.6: Include submodules in setuptools build (#301)
Minor release to fix setuptools/uv packaging of CLI wheel