Commit Graph
4259 Commits
Author SHA1 Message Date
Aleksei Sviridkin 3ece61ba04 test(e2e): make the LoadBalancer announcer detection failover-robust
The dataplane diagnostic's announcer-node detection reported the wrong
node in two failover situations and could match the wrong IP:

  - A node that announced an IP and then withdrew it (with no
    re-announce) was still reported as the announcer, because a withdraw
    did not retract a prior announce.
  - Speaker logs are concatenated per-pod, not globally time-sorted, so
    a stale former owner's announce could outrank the true current
    owner purely by its position in the input.
  - The IP was matched as a substring, so a query for 192.0.2.5 also
    matched a 192.0.2.50 line.

Reimplement the detection to report a node only when that node's LAST
own announce/withdraw event for the exact IP is an announce, which is
robust to both concat order and L2 failover, and anchor the IP match to
a whole IP-literal token instead of a substring.

Also fix the heavy-capture budget: the MAX_LBS cap counted every
enumerated LB, so a broken LB enumerated after a cap's worth of
reachable LBs was never captured. Count only LBs actually captured, via
a small pure budget helper, so reachable/skipped LBs do not consume the
budget. Document that this cap bounds work, not wall-clock -- at two or
more unreachable LBs the real wall-clock bound is the outer backstop at
the call site.

Add bats coverage pinning the fixed announcer behavior (withdraw,
concat-order, exact-IP) and the captured-budget accounting.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
2026-06-25 17:07:16 +03:00
Aleksei Sviridkin 631cdaa069 test(e2e): capture the LoadBalancer datapath when an LB IP is unreachable
The on-failure dataplane diagnostic only captured host->pod CNI state for
NotReady pods. A recurrent flake presents differently: a tenant Service
type=LoadBalancer IP goes unreachable while its backend pod/VMI stays Ready
and Running, so there is no NotReady pod and the hook captured nothing --
leaving the host->cross-node->bridged-worker-VMI->nodePort path
uncharacterised, which is exactly where root-causing has stalled.

Add a gated LoadBalancer-datapath section. It enumerates LoadBalancer
services with an ingress IP, derives the EndpointSlice backend, the
nodePort/externalTrafficPolicy, and the announcer node from the hostNetwork
MetalLB speaker logs, then probes the LB IP from a host netns. Only an LB
whose every probe fails gets the heavy capture, and that probe doubles as
the traffic for the tcpdumps. For a failing LB it captures, on both the
announcer and endpoint nodes, the host cilium LB map, kernel
conntrack/neigh, br-int flows, ovn-controller timing, and a live tcpdump on
the geneve tunnel and the backend tap -- localising the failing hop to
host-cilium programming vs kube-ovn delivery. In-guest VMI capture is
documented as a deferred stretch that needs tenant-cluster access.

The existing NotReady-pod capture is unchanged. The new section is
best-effort and time-boxed like the rest of the script, and a unit test
pins the pure enumeration, announcer-node, and capture-or-skip logic against
mock input.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
2026-06-25 16:49:33 +03:00
Aleksei Sviridkin 594c887916 test(e2e): capture OVN flow-programming datums in dataplane diagnostic
Extend the host->pod data-plane capture with the three datums that make an
OVN incremental-processing lag dispositive on the next recurrence, all
diagnostic-only and gated on the existing on-failure path:

- ovn-controller.log from the ovs-ovn pod (grep for physical_flow_output,
  if_status_mgr, took <N>ms, recompute, long poll interval; plus a bounded
  tail) -- shows whether ovn-installed was set before the LSP local-delivery
  flow was programmed.
- per-interface ovn-installed flag + ovn-installed-ts on the pod's OVS
  interface, looked up by iface-id <pod>.<ns>.
- ovs-ovn cgroup cpu.stat (nr_throttled / throttled_usec, cgroup v2 with v1
  fallback) -- shows whether ovn-controller was CPU-starved.

Node-global captures land in node-<node>.txt, the per-interface flag in the
per-pod file. Every command stays timeboxed and || true, no behavior or
exit-code change.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
2026-06-25 02:37:30 +03:00
Aleksei Sviridkin 079e4079d3 test(e2e): capture host->pod data-plane on failure
The E2E install intermittently fails on a CNI host->local-pod data-plane
transient: kubelet on a node reaches a local pod's readiness/startup probe
with "connection refused" for several minutes while overlay pod->pod
traffic works, then it self-heals. This is rooted in the cilium+kube-ovn
chaining config (forced enable-host-legacy-routing, CNI
InstallEndpointRoute:false), which delegates host->local-pod routing to
kube-ovn/ovn0. The crust-gather failure snapshot records Kubernetes object
state but not the node's L3 forwarding state, so the mechanism cannot be
root-caused after the fact.

On test failure, for each NotReady pod that is scheduled, has a podIP, and is
not terminal (Succeeded/Failed excluded), collect the host->pod data-plane
state from the pod's node into the crust-gather snapshot dir (so it ships in
the uploaded report):

- host netns via the kube-ovn cni-server (hostNetwork): ip route get <podIP>,
  ip neigh, ip rule, ip addr show ovn0, and the KERNEL conntrack entries for
  the podIP (conntrack -L, falling back to /proc/net/nf_conntrack). Under
  enable-host-legacy-routing the host->local-pod path traverses the kernel
  netfilter stack, not cilium BPF, so this is the authoritative conntrack
  table and route/rule state for the transient;
- cilium-agent on the node: endpoint list, bpf CT entries for the podIP, a
  bounded monitor --type drop, and hubble dropped verdicts when present
  (complementary: confirms the path is not handled in BPF);
- OVS/OVN on the node: ovs-ofctl dump-flows br-int, the OVN Port_Binding /
  Logical_Switch_Port for the pod, and a bounded ovn-sbctl lflow-list.

Diagnostic-only: it runs after the existing crust-gather collect and only on
an already-failed test, never mutates the cluster, and cannot change the
pass/fail outcome. Every live capture is time-boxed, every command is
|| true, the whole run has a wall-clock backstop, node-global captures are
deduped per node, and the pod count is capped. It no-ops cleanly when no
pods are affected or when a tool/pod is absent.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
2026-06-25 02:17:59 +03:00
Aleksei Sviridkin 29bf56f550 chore(images): bump opencost, multus, clickhouse-backup (#2900 partial) (#3000)
## What this PR does

Bumps three of the small components listed in #2900, each picking up
published security fixes:

- **opencost** chart `1.41.0 → 2.5.23` (app `1.111.0 → 1.120.3`). The
1.x→2.x chart-major bump's values schema is additive, so the cozystack
overrides (external prometheus vmselect endpoint, customPricing) stay
valid. The Makefile now pins `--version 2.5.23` and drops the upstream
snapshot test suite (it can't resolve in the cozystack render context);
cozystack ships its own helm-unittest.
- **multus-cni** `v4.2.3 → v4.3.0`, rebuilt multi-arch (builder
`golang:1.24 → 1.26` for the Go-stdlib CVEs). This also **folds the
`multusMasterCNI: 05-cilium.conflist` CNI-ordering fix into
`customize-deployment.patch`** — it was previously a raw daemonset
hand-edit that the next `make update` would have wiped, re-introducing
the kube-ovn-before-cilium startup race. A new helm-unittest pins it.
- **clickhouse-backup tool** `altinity/clickhouse-backup 2.6.32 →
2.7.2`, rebuilt multi-arch. The separate `clickhouse-backup` image
(clickhouse-server base) and the managed clickhouse-server version are
intentionally left as-is (multi-major server upgrade, out of scope).

Each package gains helm-unittest coverage (none shipped before).

**Deferred from #2900 (this PR does NOT close the issue):**

- **bootbox** — already at the latest upstream tag (no-op).
- **kubeovn-plunger** — first-party cozystack component, no upstream
release to bump.
- **etcd-operator** — held at 0.4.5: the 0.5.x Helm chart is not
published on the `ghcr.io/aenix-io/charts` OCI registry yet (only GitHub
releases exist), so `helm pull` can't fetch it. Needs an aenix-io chart
publish first.
- **ingress-nginx** — deliberately pinned to 4.11.2 (revert `5c900a746`
after the CVE-2025-1974 mitigation attempt); bumping needs a separate
investigation, not a routine sweep.

### Release note

```release-note
chore(images): bump opencost to 2.5.23, multus-cni to v4.3.0, and clickhouse-backup to 2.7.2
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Enhanced OpenCost Helm support for plugin installation/config
validation, cloud integration (secret or JSON), MCP server, and
`extraObjects` rendering
  * Added admin token secret creation and Pod Disruption Budget options
* Expanded UI/API/MCP exposure via Ingress, OpenShift Route, and Gateway
API HTTPRoute
* Improved internal Prometheus/Thanos endpoint handling and optional CA
trust update

* **Updates**
* Updated ClickHouse backup and Multus images; adjusted Multus “thick”
deployment behavior/resources and namespace usage
  * Refreshed OpenCost chart values/docs and bumped chart/app versions

* **Tests**
* Added/extended Helm unittest suites and rendering invariants for
backup, Multus, and OpenCost
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-24 15:18:29 +03:00
Aleksei Sviridkin a74b618e69 chore(cilium): bump cilium to 1.19.5 (#2972)
## What this PR does

Bumps cilium from 1.19.3 to 1.19.5 (latest 1.19 patch), picking up the
published security fixes the issue enumerates (incl. the
`moby/spdystream` and `golang.org/x/net` updates carried by 1.19.4) plus
upstream bug fixes: CiliumEgressGatewayPolicy NamespaceSelector
corruption, BGP PeerConfig status cleanup, and a reused-endpoint BPF
state race.

The change is a single self-contained commit:

- Re-vendors the chart via `make update` (helm pull cilium 1.19.5). The
two cozystack vendoring patches re-apply cleanly — the
SYS_MODULE/iptables capability lines and the k8s<1.30 AppArmor
annotation block are stripped (the Makefile guard confirms the AppArmor
block is gone, so there is no duplicate-mapping-key risk on the agent
DaemonSet).
- Points `images/cilium/Dockerfile` at `quay.io/cilium/cilium:v1.19.5`.
- Rebuilds the cozystack agent image multi-arch (linux/amd64 +
linux/arm64) and pins it in `values.yaml` (`1.19.5@sha256:8f0e898…`),
mirroring the rebuild-and-pin step done for the 1.19.3 bump — so the
deployed agent carries the fixes immediately, not just on the next
release rebuild.

Upstream dropped the dev-only `values.yaml.tmpl` / `README.md.gotmpl`
from the 1.19.5 release tarball (hence the large deletion). The defunct
`l2podAnnouncements.interface` and `loadBalancer.standalone` removals
don't affect cozystack, which uses neither.

Verified: `helm template` renders the agent at `1.19.5@sha256:8f0e898…`
across the talos/kilo/kubeovn/apparmor overlays; `helm lint` passes
aside from the expected wrapper-chart dependency artifact.

Closes #2893

### Release note

```release-note
chore(cilium): bump cilium to 1.19.5
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Chores**
* Upgraded the Cilium Helm chart to **1.19.5** and refreshed default
container images/digests across components.
  * Adjusted Helm packaging to exclude `*.tmpl`/`*.gotmpl` artifacts.
* **New Features**
  * Expanded RBAC to include **BGP peering policy** resources.
* Updated **L2 pod announcements** configuration to use
`interfacePattern`.
* **Bug Fixes**
* Improved ingress EndpointSlice readiness/labels for more consistent
endpoint behavior.
* Enabled IPv6 traffic to fall back to the kernel stack when the IPv6
datapath is disabled.
* **Refactor**
* Made the operator health `hostPort` configurable based on host
networking.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-24 15:13:15 +03:00
Aleksei Sviridkin d5816d38e7 chore(kilo): rebuild kilo image on current upstream and alpine 3.24 (#3007)
## What this PR does

Rebuilds the first-party `kilo` image to clear the published
`libpng16-16` / `libpng` advisories carried by the stale pinned layers,
and refreshes it onto current upstream.

- `images/kilo/Dockerfile`: `ARG VERSION` `fbce60d8` → `944dff57`
(current `squat/kilo` `main` HEAD); the rebuild also refreshes the
`golang:1.25` stdlib compiled into the `kg` / `kgctl` binaries. The
builder tag stays `golang:1.25` (upstream `go.mod` is `go 1.25.0`).
- runtime and `cni` base: `alpine:3.23` → `alpine:3.24`, which clears
the `libpng` advisories pulled in through the `graphviz` / `font-noto`
dependency chain.
- CNI plugins: `v1.9.0` → `v1.9.1`.
- `values.yaml`: re-pinned to the rebuilt multi-arch digest
(`linux/amd64` + `linux/arm64`); the human-readable tag handle moves
from `latest` to `v<version>` to match the sibling first-party images.

The in-repo cross-mesh-granularity feature patch still applies cleanly
on the new HEAD and is verified present in the built binary (`kg
--mesh-granularity` lists `cross`). Adds the package's first
helm-unittest coverage, pinning the image ref and the default mesh-arg
wiring.

### Release note

```release-note
chore(kilo): rebuild kilo image on current upstream and alpine 3.24 to clear the libpng advisories
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
  * Upgraded Kilo to **v1.5.0**.
  * Updated bundled CNI plugins to **v1.9.1**.
  * Updated Kilo build/runtime base to **Alpine 3.24**.
* **Tests**
* Added Helm/unit coverage to validate Kilo DaemonSet image pinning and
default/overridden argument behavior (including compatibility options).
  * Added a `test` make target to run Helm unit tests.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-24 15:00:29 +03:00
myasnikovdaniil 374cac1060 fix(deps): bump golang.org/x/crypto to v0.52.0 to close OSV advisories (#3019)
## What this PR does

Restores the OpenSSF Scorecard **Vulnerabilities** check to green. It
regressed to **0/10** after #2852: in the weeks since,
`golang.org/x/crypto v0.51.0` accrued **13 new advisories**
(`GO-2026-5005`, `5006`, `5013`–`5021`, `5023`, `5033`). An
`osv-scanner` pass over `main` confirmed all 13 trace to that single
package.

### Change

- **`golang.org/x/crypto 0.51.0 → 0.52.0`** (the fixed version for all
13). No transitive cascade — `go mod tidy` changed only this line plus
its two `go.sum` hashes.

Bumped with `go get` / `go mod tidy`, not by hand-editing the generated
`go.mod`.

### Verification

- `osv-scanner` after the bump: **No issues found** (0 advisories across
both modules).
- `go build ./...` passes.
- `make generate` produces **no drift** — `codegen-drift` stays green.

> Scorecard's report mentioned advisory IDs as low as `GO-2025-3512`
(kubevirt-csi, CVE-2024-1725). That package is **not** in `go.mod` or
`go.sum` — it isn't a cozystack dependency, so nothing to bump there.
The real cluster is the 13 x/crypto advisories this PR closes.

### Why this keeps happening (and the durable fix)

`x/crypto` is an **indirect** dependency, and the Renovate app isn't
actually opening PRs on this repo yet (no `renovate[bot]` PRs, no
Dependency Dashboard) — the org Renovate install needs
`cozystack/cozystack` added to its repo list. Until then, indirect-dep
and Go-toolchain advisories will keep knocking this check back to 0 and
need manual bumps like this one. Recommended follow-ups: enable Renovate
on the repo, and allow it to bump indirect deps (and optionally the Go
patch version).

### Release note

```release-note
fix(deps): bump golang.org/x/crypto to v0.52.0, closing 13 known OSV advisories (GO-2026-5005…5033)
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
* Updated cryptographic dependency to the latest patch version for
enhanced security and stability.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-24 11:48:37 +05:00
Andrei Kvapil fccf7a8351 docs(release): add changelog for v1.5.1 (#3024)
This PR adds the changelog for release `v1.5.1`.

✅ Changelog has been automatically generated in
`docs/changelogs/v1.5.1.md`.
2026-06-24 08:46:28 +02:00
Aleksei Sviridkin 73035527f0 ci: harden workflow token permissions and pin actions by SHA (#2849)
## What this PR does

Hardens GitHub Actions security posture to raise two OpenSSF Scorecard
checks that currently score **0/10**, as part of the push to ≥7.5 ahead
of CNCF Incubation due diligence. No workflow triggers, job graphs, or
step logic change — only `GITHUB_TOKEN` scopes and action pin refs.

### Token-Permissions (was 0/10)

The check failed because several workflows (`codegen-drift.yml`,
`pre-commit.yml`, `retest.yaml`, `tags.yaml`, …) declared **no
`permissions:` block at all**, so their jobs inherited the repository
default token — typically read/write across all scopes.

This PR applies the OpenSSF-recommended pattern to **every** workflow:

- A **top-level read-only default**: `permissions: { contents: read }`.
- An **explicit per-job `permissions:` block** granting only the writes
that job needs. Workflows that previously held write scopes at the
*workflow* level (`backport`, `pr-labeler`, `pr-size`, `stale`) now hold
them at *job* level, so the read-only default applies everywhere else.

Per-job scopes were derived from what each job actually calls:

| Workflow | Job | Scopes granted |
|---|---|---|
| auto-release | auto-release | `contents: write, pull-requests: read`
*(unchanged)* |
| backport | prepare | `contents: read` |
| backport | backport | `contents: write, pull-requests: write` |
| codegen-drift | codegen-drift | `contents: read` |
| labels | validate | `contents: read` |
| labels | sync | `contents: read, issues: write, pull-requests: write`
|
| pre-commit | pre-commit | `contents: read` |
| pr-labeler | label | `pull-requests: write` |
| pr-size | size | `pull-requests: write` |
| retest | retest | `actions: write, pull-requests: read` *(unchanged)*
|
| stale | stale | `issues: write, pull-requests: write` |
| update-releasenotes | update-releasenotes | `contents: write`
*(unchanged)* |
| pull-requests | detect-changes | `contents: read, pull-requests: read`
|
| pull-requests | build | `contents: read, packages: write`
*(unchanged)* |
| pull-requests | resolve_assets | `contents: read` |
| pull-requests | e2e | `contents: read, packages: read, checks: write`
*(unchanged)* |
| pull-requests-release | finalize | `contents: write` *(unchanged)* |
| tags | prepare-release | `contents/packages/pull-requests/actions:
write` *(unchanged)* |
| tags | generate-changelog | `contents: write, pull-requests: write`
*(unchanged)* |
| tags | update-website-docs | `contents: read` *(unchanged)* |

Self-hosted release jobs that push tags/branches/releases authenticate
via the `cozystack-ci` GitHub App token, so reducing the workflow
`GITHUB_TOKEN` does not affect them; the job-level write scopes they
already declared are preserved verbatim.

### Pinned-Dependencies (was 0/10)

Every GitHub-owned and third-party action is now pinned to a **full
commit SHA** with a human-readable version comment, e.g.
`actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4`.
`scorecard.yml` was already SHA-pinned in #2721; `breakpoint-action` was
already pinned. SHAs were resolved from each tag's current commit at
authoring time, so behavior is identical to the previously-referenced
tag.

> **Scope note:** this PR pins **GitHub Actions** only. Dockerfile
`FROM` digest pinning (≈40 images) is deliberately out of scope here —
it touches image builds and is higher blast-radius; tracked separately.

### Verification

- `actionlint` over all workflows: **exit 0**.
- All 14 workflow files parse as valid YAML.
- Diff is mechanical: only `permissions:` blocks and action `@ref`s
changed.

### Release note

```release-note
ci: declare least-privilege per-job GITHUB_TOKEN permissions and pin all GitHub Actions by commit SHA across CI workflows (OpenSSF Scorecard hardening)
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Chores**
* Tightened CI/CD security with least-privilege workflow token
permissions: workflows now default to read-only access (`contents:
read`), with select jobs requesting write or additional scopes only when
needed.
* Improved supply-chain safety and consistency by pinning GitHub Actions
(and related third-party actions) to specific commit SHAs across
multiple workflows, reducing reliance on floating version tags.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-24 09:35:24 +03:00
cozystack-ci[bot] 0245e5dc4d docs: add changelog for v1.5.1
Signed-off-by: cozystack-ci[bot] <274107086+cozystack-ci[bot]@users.noreply.github.com>
2026-06-24 01:50:45 +00:00
Myasnikov Daniil 7ee54d9324 fix(deps): bump golang.org/x/crypto to v0.52.0 to close OSV advisories
Restores the OpenSSF Scorecard Vulnerabilities check to green. It
regressed to 0/10 after #2852 because golang.org/x/crypto v0.51.0 accrued
13 new advisories (GO-2026-5005, 5006, 5013-5021, 5023, 5033). osv-scanner
confirms all 13 trace to that one indirect package; v0.52.0 is the fixed
version. go mod tidy changed only this line and its two go.sum hashes.

After the bump osv-scanner reports no issues, both modules build, and
'make generate' produces no drift. Versions were changed with go get /
go mod tidy, not by hand-editing the generated go.mod.

Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
Assisted-By: Claude <noreply@anthropic.com>
2026-06-23 17:16:40 +05:00
Aleksei Sviridkin 6df2b3a797 chore(packages/system/cilium): bump cilium to 1.19.5
Re-vendors the cilium chart from 1.19.3 to 1.19.5 (latest 1.19 patch) and
points the agent image build at v1.19.5. Picks up the published security
fixes plus upstream bug fixes (CiliumEgressGatewayPolicy NamespaceSelector
corruption, BGP PeerConfig status cleanup, reused-endpoint BPF state race).

The make-update vendoring patches re-apply cleanly: the SYS_MODULE/iptables
capability lines and the k8s<1.30 AppArmor annotation block are stripped (the
guard confirms the AppArmor block is gone, and the rendered agent DaemonSet
carries the annotation exactly once via cozystack podAnnotations). Upstream
dropped the dev-only values.yaml.tmpl / README.md.gotmpl from the 1.19.5
release tarball. The defunct l2podAnnouncements.interface removal does not
affect cozystack, which uses interfacePattern.

The BPF host patch (pass-ipv6-to-stack-when-ipv6-datapath-disabled.diff) is
refreshed against v1.19.5 bpf_host.c: identical logic, only context lines
re-synced.

The deployed agent image pin in values.yaml is intentionally left on the
current release-line digest; the multi-arch cilium agent is rebuilt and
re-pinned during release preparation.

Adaptations:
- charts/: re-vendored (helm pull cilium 1.19.5 + capability/AppArmor patches)
- images/cilium/Dockerfile: ARG VERSION v1.19.3 -> v1.19.5
- images/cilium/patches/: BPF host patch context refreshed for v1.19.5

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
2026-06-23 15:04:51 +03:00
Aleksei Sviridkin 1b4c8b6246 chore(kilo): rebuild kilo image on current upstream and alpine 3.24
Rebuilds the first-party kilo image to clear the published libpng advisories
carried by the stale pinned layers and to pick up current upstream:

- ARG VERSION: squat/kilo main fbce60d8 -> 944dff57 (the rebuild also refreshes
  the golang:1.25 stdlib compiled into the kg / kgctl binaries)
- runtime and cni base: alpine 3.23 -> 3.24, which clears the libpng16-16 /
  libpng advisories pulled in through the graphviz / font-noto chain
- CNI plugins: v1.9.0 -> v1.9.1
- values.yaml: re-pinned to the rebuilt multi-arch digest; the tag handle moves
  from latest to v<version> to match the sibling first-party images

The in-repo cross-mesh-granularity feature patch still applies cleanly on the
new HEAD and is verified in the built binary (kg --mesh-granularity lists
`cross`). Adds the package's first helm-unittest coverage, pinning the image
ref and the default mesh-arg wiring.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
2026-06-23 14:39:53 +03:00
Aleksei Sviridkin 7532cf59f9 chore(packages/apps/clickhouse): bump clickhouse-backup tool to 2.7.2
Rebuilds the altinity-clickhouse-backup sidecar image off the upstream
altinity/clickhouse-backup 2.6.32 -> 2.7.2 release (multi-arch) and pins the
new digest. Picks up the published security fixes in the backup tool. The
clickhouse-server version (24.9.2) is intentionally left as-is: moving it is a
multi-major server upgrade, out of scope for this maintenance bump.

Extends the existing backup helm-unittest to assert the sidecar image tag, so
the bump is guarded against regressions.

Adaptations:
- images/altinity-clickhouse-backup/Dockerfile: FROM altinity/clickhouse-backup 2.6.32 -> 2.7.2
- images/altinity-clickhouse-backup.tag: pin rebuilt multi-arch image digest
- tests/backup_test.yaml: assert the backup sidecar image tag

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
2026-06-23 14:39:14 +03:00
Aleksei Sviridkin c50b73fd9c chore(packages/system/multus): bump multus-cni to v4.3.0
Re-vendors the multus-cni thick-mode daemonset from upstream v4.2.3 to v4.3.0
and rebuilds the cozystack image (multi-arch, golang:1.26 builder; v4.3.0's
go.mod and the published security fixes warrant the stdlib bump from 1.24). The
fix-del-without-cache and customize-deployment patches both re-apply cleanly to
v4.3.0. The rebuilt image is pinned by digest in the daemonset.

Folds the previously hand-edited `multusMasterCNI: "05-cilium.conflist"`
CNI-ordering fix into customize-deployment.patch so it survives every make
update (it was a raw daemonset edit that the re-vendor would otherwise wipe,
re-introducing the kube-ovn-before-cilium startup race).

Adds helm-unittest coverage (the package shipped none): asserts the daemonset
runs the cozystack-built image and that the daemon-config pins multusMasterCNI
to the cilium conflist.

Adaptations:
- images/multus-cni/Dockerfile: builder golang:1.24 -> 1.26, ARG VERSION v4.2.3 -> v4.3.0
- templates/multus-daemonset-thick.yml: re-vendored v4.3.0 + customize patch; pin rebuilt multi-arch image
- patches/customize-deployment.patch: carry the multusMasterCNI CNI-ordering fix
- Makefile: add test target
- tests/multus_test.yaml: new helm-unittest coverage

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
2026-06-23 14:39:14 +03:00
Aleksei Sviridkin 4d507d1456 chore(packages/system/opencost): bump opencost chart to 2.5.23
Re-vendors the opencost chart from 1.41.0 to 2.5.23 (app 1.111.0 -> 1.120.3),
crossing the 1.x -> 2.x chart-major boundary, picking up the published security
fixes. The major bump's values-schema changes are additive (new clusterName,
pdb, extraObjects keys; no removals), so the cozystack overrides (external
prometheus vmselect endpoint, customPricing) stay valid -- confirmed by render.

Pins the update target to --version 2.5.23 and drops the upstream chart's own
snapshot-based helm-unittest suite (it fails in the cozystack render context).
Adds cozystack helm-unittest coverage: pins the image and the prometheus
endpoint wiring.

Adaptations:
- charts/: re-vendored via make update (helm pull opencost --version 2.5.23; upstream tests removed)
- Makefile: pin --version 2.5.23; add test target; strip upstream chart tests
- tests/opencost_test.yaml: new helm-unittest coverage

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
2026-06-23 14:39:14 +03:00
scooby87 0e2e6e19f0 feat(harbor): bump chart to 1.19.1 (Harbor 2.15.1) (#2966)
Bump the vendored Harbor Helm chart from 1.18.2 to 1.19.1, which
upgrades Harbor itself from appVersion 2.14.2 to 2.15.1.

The bump adds PodDisruptionBudget templates for the core, exporter,
jobservice, nginx, portal, registry and trivy components, improving
availability during voluntary disruptions (node drains/upgrades).

<!-- Thank you for making a contribution! Here are some tips for you:
- Use Conventional Commits for the PR title: `type(scope): description`
- Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore
- Scopes are not an exhaustive list — pick the most specific scope for
the change and extend the list when a genuinely new area appears.
Examples:
- System components: dashboard, platform, operator, cilium, kube-ovn,
linstor, fluxcd, cluster-api
- Managed apps: postgres, mariadb, redis, kafka, clickhouse,
virtual-machine, kubernetes
- Development and maintenance: api, hack, tests, ci, docs, maintenance
- Breaking changes: append `!` after type/scope (`feat(api)!: ...`) or
add a `BREAKING CHANGE:` footer
- If it's a work in progress, consider creating this PR as a draft.
- Don't hesistate to ask for opinion and review in the community chats,
even if it's still a draft.
- Add the label `backport` if it's a bugfix that needs to be backported
to a previous version.
-->

## What this PR does


### Screenshots

<!-- REQUIRED for UI changes: attach screenshots or screen recordings
demonstrating
the visual impact of your changes. PRs with UI changes without
screenshots will not be merged. -->

### Release note

<!--  Write a release note:
- Explain what has changed internally and for users.
- Start with the same `type(scope):` prefix as in the PR title
- Follow the guidelines at
https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md.
-->

```release-note
feat(harbor): bump Harbor to 2.15.1 and add PodDisruptionBudgets for core, portal, jobservice, nginx, registry, trivy and exporter
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

## Release Notes

* **New Features**
* Added Pod Disruption Budget support for core, portal, jobservice,
nginx, registry, trivy, and exporter.
* Made container health checks (liveness/readiness, plus core startup)
fully configurable per component.
  * Added configurable registry HTTP client timeout.
* Enhanced Gateway API route configuration (hostnames formatting and
backend reference details).

* **Improvements**
* Improved external Redis credential handling for registry usage (safer
secret guarding and URL-encoding).
  * Updated Harbor chart metadata and component images to **v2.15.1**.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Closes #2880
2026-06-23 14:32:43 +03:00
Aleksei Sviridkin 2a5ccf1d4d chore(monitoring): bump Grafana to 11.6.15, victorialogs datasource and alerta (#3011)
## What this PR does

Refreshes the `system/monitoring` image anchors onto current upstream to
clear the published advisories (8 CVEs, 1 critical) carried by the stale
pins.

- **grafana image**: base `grafana/grafana` `11.4.0` → `11.6.15` (latest
11.x). The rebuild clears the Go-dependency advisories in the grafana
binary (`x/crypto`, `moby/spdystream`, `jackc/pgx/v5`,
`russellhaering/goxmldsig`, `buger/jsonparser`, `golang-jwt/jwt/v4`,
`getkin/kin-openapi`). It stays on the 11.x line rather than 12.x to
keep the bundled panel plugins compatible (`grafana-worldmap-panel` is
deprecated upstream) and avoid a dashboard-schema migration.
- **victorialogs-datasource** plugin: `v0.14.1` → `v0.28.0`
(`grafanaDependency >=10.4.0`, so it loads on 11.6.15).
- **alerta-web**: `9.0.4` → `9.1.0`, clearing the python `cryptography`
advisory.
- `images/grafana.tag`: re-pinned to the rebuilt multi-arch digest
(`linux/amd64` + `linux/arm64`).

The built grafana image was verified in place: grafana `11.6.15`, all
four plugins present (`natel-discrete-panel`, `grafana-worldmap-panel`,
`marcusolsson-dynamictext-panel`, `victoriametrics-logs-datasource`),
vlogs `0.28.0`. helm-unittest passes (4/4).

Closes #2892

### Release note

```release-note
chore(monitoring): bump Grafana to 11.6.15, victorialogs-datasource to v0.28.0 and alerta-web to 9.1.0
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
* Updated Grafana monitoring dashboard base image to 11.6.15 and
VictoriaLogs datasource plugin to v0.28.0
  * Upgraded Alerta monitoring and alerting tool to 9.1.0

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-23 13:14:24 +03:00
Aleksei Sviridkin 2494843599 chore(testing): refresh e2e-sandbox tools and base to current upstream (#3010)
## What this PR does

Rebuilds the e2e test sandbox on current upstream to clear the published
advisories (containerd, helm, go-git, moby/spdystream, Go stdlib)
carried by the stale tool binaries and base layers.

- base: `ubuntu:22.04` → `24.04`; `netcat` → `netcat-openbsd` (on 24.04
`netcat` is a candidate-less virtual package, so the concrete provider
must be named)
- kubectl: `1.33.2` → `1.33.13` — stays on the 1.33 line that the e2e
control plane pins at `v1.33.12` (`hack/e2e-prepare-cluster.bats`), so
client/server skew is unchanged
- talosctl: `1.10.4` → `1.13.5` — aligns the client with the v1.13.x
Talos nodes the sandbox provisions
- helm: `3.18.3` → `3.21.2` (latest helm 3) — the e2e flow drives the v3
CLI, so it stays on the 3.x line rather than moving to the breaking 4.x
- yq: `4.44.3` → `4.53.3`
- `values.yaml`: re-pinned to the rebuilt multi-arch digest
(`linux/amd64` + `linux/arm64`)

`crust-gather` and `cozyhr` already track their latest releases; `flux`
and `mc` install the current release at build time. The built image's
tool versions were verified in place (kubectl `v1.33.13`, talosctl
`v1.13.5`, helm `v3.21.2`, yq `v4.53.3`, flux `2.8.8`, ubuntu `24.04`).

Closes #2891

### Release note

```release-note
chore(testing): refresh e2e-sandbox tools and base (ubuntu 24.04, kubectl 1.33.13, talosctl 1.13.5, helm 3.21.2)
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Chores**
* Updated the e2e sandbox image to a new fixed digest for more
consistent test runs.
* Refreshed the sandbox build environment (Ubuntu 24.04) and upgraded
tooling (Kubernetes, Talos, Helm, and yq) to newer stable versions.
* Improved OS package setup by switching from `netcat` to
`netcat-openbsd` and consolidating apt cleanup to reduce image size.
* **Documentation**
* Updated e2e testing guidance: removed the recommendation to pin the
management cluster Kubernetes version, and added guidance to
snapshot/restore cluster state between test groups.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-23 13:14:20 +03:00
Aleksei Sviridkin bebf4db0df chore(build): refresh first-party Alpine runtime bases to 3.24 (#3009)
## What this PR does

Moves the pinned Alpine runtime bases of the first-party images forward
to `alpine:3.24`, clearing the published `musl` / `zlib` advisories
carried by the stale layers.

| image | base |
| --- | --- |
| mariadb-backup | 3.20 → 3.24 |
| cozystack-operator | 3.22 → 3.24 |
| platform-migrations | 3.22 → 3.24 |
| grafana-dashboards | 3.22 → 3.24 |
| kubeovn-webhook | 3.21.3 → 3.24 |
| redis-operator | latest → 3.24 |

Each runtime `apk` set was verified to resolve on `alpine:3.24`. These
images rebuild on the release asset pipeline, which re-pins the digests
in `values.yaml` on the next build — matching how the rest of the ~30
first-party images pick up the shared base (the issue's "rebuild and run
the standard test pipeline").

**Scope notes:**

- The build-only `alpine AS source` stages (keycloak-operator,
objectstorage-controller) are left as-is: their final images are
distroless, so no Alpine layer ships.
- The s3manager base is owned by the separate bucket bump (#2887), and
kilo's base moves in its own image rebuild (#2898).
- **Side effect for platform-migrations**: its `kubectl` / `helm` come
from the Alpine repo, so the base bump moves them `1.33 → 1.36` and
`3.18 → 3.19`. Both are current upstream stable and in skew with the
modern control plane for the migration scripts' operations (apply / get
/ label / helm release ops).

Closes #2902

### Release note

```release-note
chore(images): refresh first-party Alpine runtime bases to 3.24 to clear the musl/zlib advisories
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Chores**
* Updated Alpine Linux base images across multiple application
containers to version 3.24 (including backup utilities,
platform/operator components, monitoring dashboards, and
networking/webhook components) to improve security and build
consistency.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-23 13:14:15 +03:00
Aleksei Sviridkin e83ba4e298 chore(coredns): refresh coredns chart to 1.46.0 (#3004)
## What this PR does

Re-vendors the CoreDNS Helm chart from `1.43.2` to `1.46.0` (chart
`appVersion` `1.12.3` → `1.13.1`) and pins the `make update` target to
`--version 1.46.0` so re-vendoring is reproducible (it was previously
tracking upstream `latest` silently).

The running CoreDNS **image is deliberately kept** at
`registry.k8s.io/coredns/coredns:v1.12.4`. It is pinned to the 1.12 line
that matches the Kubernetes-bundled kube-dns replacement, and v1.12.4 is
the latest patch of that line (itself a security release). The
cozystack-side `values.yaml` pins `coredns.image.tag: v1.12.4`, so the
chart's `appVersion` bump never reaches the deployed container — the
rendered Deployment still uses `v1.12.4`. The kube-dns overrides
(`k8sAppLabelOverride`, `service.name`, `serviceAccount.name`) stay
valid.

The new chart template logic (`dnsConfig`/`dnsPolicy`, ServiceMonitor
`scrapeTimeout`/`scheme`/`honorLabels`/`tlsConfig`/relabelings,
multicluster RBAC, `customAnnotations`, `automountServiceAccountToken`)
is inert under the cozystack values — none of those keys are set, so
every new conditional is skipped and the bump is behavior-neutral for
the pinned configuration.

This references #2899 but does **not** close it: that ticket asks to
advance the CoreDNS *image* for CVE remediation, which conflicts with
the kube-dns version alignment. Whether to move the bundled CoreDNS line
forward (and thus the image) is a platform-level call, left open on the
issue.

### Release note

```release-note
chore(coredns): refresh vendored CoreDNS chart to 1.46.0 (image held at v1.12.4 for kube-dns alignment)
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added DNS policy and custom DNS configuration options for deployments
  * Introduced pod labels support for custom pod labeling
* Expanded Prometheus monitoring with scrape timeout, TLS configuration,
and relabeling options
  * Added multicluster RBAC support capability

* **Chores**
  * Updated CoreDNS to version 1.13.1
  * Bumped Helm chart version to 1.46.0

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-23 13:14:10 +03:00
Aleksei Sviridkin fbf6415dbe chore(hami): bump HAMi to 2.9.0 (#2993)
## What this PR does

Re-vendors the HAMi vGPU chart from 2.8.1 to 2.9.0, moving the
device-plugin and scheduler-extender images to `projecthami/hami:v2.9.0`
and picking up the published security fixes.

**Vendoring approach changed for 2.9.0.** Upstream now gates the
scheduler and device-plugin templates on `.Values.dra.enabled` and
`.Values.podSecurityPolicy.enabled` across ~27 files, so the previous
approach (strip the dra/PSP values and remove the conditionals by hand)
would nil-pointer at render time. Instead the `dra:` and
`podSecurityPolicy:` blocks are KEPT at their upstream default
(`enabled: false`), which cleanly disables both paths; only the unused
`hami-dra` subchart and its values block are removed. The Makefile
vendoring notes are updated to document this.

Replays the `indent`→`nindent` patch on the custom Service labels block
— now extended to **both** Services that carry the upstream defect: the
device-plugin monitor Service and the scheduler Service (the latter was
previously unpatched and would emit invalid YAML if
`scheduler.service.labels` were set).

Adds helm-unittest coverage (the package shipped none): pins the
device-plugin image and guards the nindent patch on both Services. `helm
unittest` 3/3 pass.

Note: the vendored `charts/hami/README.md` still documents the old
`global.imageTag` default — that is an upstream autogenerated-doc bug
carried in by `make update`; per the vendoring policy it is left
untouched (the operative `values.yaml` default is correctly `v2.9.0`).

Closes #2897

### Release note

```release-note
chore(hami): bump HAMi to 2.9.0
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
  * Added DRA (Dynamic Resource Allocation) support with feature flag
  * Added Vastai device support
  * Added Prometheus ServiceMonitor templates for metrics collection
  * Enhanced scheduler with Kubernetes 1.22+ native API support

* **Improvements**
  * Upgraded HAMi to v2.9.0
  * Expanded Ascend device configuration options
  * Added legacy metrics compatibility mode
  * Improved PodSecurityPolicy support
  * Enhanced service selector labels for better traffic routing

* **Tests**
* Added chart rendering tests for version verification and label
validation

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-23 13:14:06 +03:00
Aleksei Sviridkin 9e57b8d103 chore(foundationdb-operator): bump fdb-operator to v2.30.0 (#2992)
## What this PR does

Re-vendors the FoundationDB Kubernetes operator chart from v2.13.0 to
v2.30.0 (chart 0.2.0 → 0.3.0), 17 minor releases forward, picking up the
published security fixes the issue enumerates. The operator +
init-monitor images advance to the current upstream tags that carry the
patched base packages.

The vendored tree is byte-identical to a fresh upstream `v2.30.0` clone
(templates + values + the three CRDs copied from `config/crd/bases/`).
The CRD changes are **additive only** — new fields, no property removals
(only the controller-gen / `foundationdb.org/release` version
annotations change) — so the `apps/foundationdb` FDB CR stays valid
against the new operator. cozystack overrides (`globalMode`,
`nodeReadClusterRole`) remain valid and consumed by the v2.30.0
templates. The one removed CLI flag (`genericclioption`) is not used by
cozystack; the chart's RBAC role binding is now unconditional
(previously globalMode-gated) — a no-op for cozystack, which sets
`globalMode=true`.

Adds helm-unittest coverage (the package shipped none): pins the
operator image.

Verified: `helm template` renders the operator at `v2.30.0`; `helm
unittest` 1/1 pass.

Closes #2879

### Release note

```release-note
chore(foundationdb-operator): bump fdb-operator to v2.30.0
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added support for custom environment variables plus additional pod
volumes and mounts for the operator.
* Expanded FoundationDB backup/cluster/restore CRD capabilities (new
backup modes, deletion policies, workload references, and pod template
options).

* **Bug Fixes**
* Adjusted RBAC service account binding behavior to use the release
namespace consistently.

* **Tests**
* Added image pin and global-mode rendering checks for operator
deployment.

* **Chores**
* Upgraded the FoundationDB operator Helm chart/app version and image to
v2.30.0; added a Helm unittest `test` target.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-23 13:14:01 +03:00
Aleksei Sviridkin f8a648abdc chore(openbao): bump openbao chart to 0.25.7 (#2991)
## What this PR does

Re-vendors the openbao-helm chart from 0.25.3 to 0.25.7 (appVersion
v2.5.0 → v2.5.1), the latest in the `^0.25` line the Makefile pins. The
vendored tree is byte-identical to a fresh upstream pull; cozystack
overrides (`injector.enabled: false`, `csi.enabled: false`) are
untouched and still render nothing, so the changed runtime surface is
the openbao server StatefulSet image.

**Security scope (honest accounting):** v2.5.1 fixes two OpenBao CVEs —
including the critical **CVE-2025-68121** (Go stdlib TLS, CVSS 10.0, via
a Go 1.25.7 rebuild) and **CVE-2026-24051** (otel/sdk). The issue also
lists `github.com/jackc/pgx/v5` — that is **not** addressed: pgx is
unchanged in v2.5.1 upstream, so it can't be closed by an in-`^0.25`
bump. `libcap2`/`libexpat` are base-image packages picked up
incidentally by the rebuild (not verified here). Widening past 0.25.x to
0.28.x (app v2.5.5) would need a CHART_VERSION constraint change plus a
0.26/0.27/0.28 changelog review and is intentionally left out.

Adds helm-unittest coverage (the package shipped none): pins the server
image and the injector/CSI-disabled invariants. `helm unittest` 3/3
pass.

Closes #2895

### Release note

```release-note
chore(openbao): bump openbao chart to 0.25.7 (app v2.5.1, fixes critical CVE-2025-68121)
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added support for configuring headless service annotations (including
HA standby headless service).
* Enhanced the Grafana dashboard with consistent dynamic job filtering
across Prometheus queries.
* **Updates**
  * Upgraded Helm chart to **0.25.7** (OpenBao app **v2.5.1**).
  * Updated snapshot agent image tag to **0.3.0**.
* **Tests**
* Added Helm unit test coverage via a `helm unittest` Makefile target
and new chart rendering invariants.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-23 13:13:57 +03:00
Aleksei Sviridkin 491b184948 feat(cozy-lib): add CA-only TLS trust-anchor helper for tenants (#2989)
## What this PR does

Part of #2814. Part of #2811.

This is the foundational ("keystone") piece of WS3: a canonical,
reusable trust-anchor object that lets a tenant obtain `ca.crt` to
verify a per-app TLS endpoint **without** read access to any object that
also carries a private key. It unblocks the per-app TLS series (WS4/WS5)
by giving every chart one agreed, key-free delivery shape instead of
each chart inventing its own.

### The problem (verified against current `main`)

Per-app TLS issues a per-release, self-signed CA. The only objects that
hold `ca.crt` today also hold private keys:

- the cert-manager CA Secret `<release>-ca` carries the CA private key
(`tls.key`) — full trust-chain compromise if leaked
(`packages/apps/nats/templates/certmanager.yaml`, the `isCA`
Certificate);
- the cert-manager leaf Secret `<release>-tls` carries the server
private key (`tls.key`) plus `ca.crt` (same file, the leaf Certificate);
- CNPG surfaces `ca.crt` only inside its user-credentials Secret
(`packages/apps/postgres/templates/db.yaml`, the operator-managed TLS
block).

So any RBAC path that hands a tenant `ca.crt` by granting read on one of
those Secrets also hands over a private key. On `main` today the
cert-manager apps grant tenants no access to those Secrets at all, so a
tenant currently cannot obtain `ca.crt` to verify the server — the gap
this object closes safely.

### Design decision: key-free Opaque object delivered through
`tenantsecrets`, not trust-manager

I evaluated the two candidate delivery mechanisms.

**Rejected — trust-manager.** A trust-manager `Bundle` reads its sources
only from trust-manager's single configured "trust namespace"; its
`namespaceSelector` governs only where the bundle is *distributed to*,
not where it is *sourced from*. A per-release self-signed CA lives in
the tenant namespace, so trust-manager cannot use it as a source, and
projecting one shared CA to all tenants would defeat per-release
isolation. I re-verified this against current upstream docs
(cert-manager.io trust-manager) and the open per-namespace-trust-bundle
request (cert-manager/trust-manager#131, which is target-side only). The
prior analysis still holds.

**Chosen — a `ca.crt`-only Opaque Secret surfaced through the existing
tenant-secret API.** This generalizes the reference pattern from the
redis work (#2729), where the operator publishes a CA-only Opaque Secret
and RBAC is scoped to it instead of to the CA-private-key Secret. The
new `cozy-lib.tls.caCertSecret` helper renders that object once,
identically, for every chart:

- `type: Opaque`, a single `ca.crt` data key, no `tls.key`/`tls.crt`;
- label `internal.cozystack.io/tenantresource: "true"`;
- fails closed on empty input and refuses any PEM that contains private
key material.

### How the RBAC wiring works (no new roles needed)

The label is the entire mechanism, and it routes through RBAC that
already exists:

- `pkg/registry/core/tenantsecret/rest.go` surfaces, under the virtual
resource `core.cozystack.io/tenantsecrets`, exactly the namespace
Secrets bearing `internal.cozystack.io/tenantresource=true`
(`buildTenantSelector`, lines 199-213; label constants
`pkg/apis/core/v1alpha1/tenantresource_types.go:3-4`; full `Data` copied
through by `secretToTenant`, lines 84-103).
- `packages/system/cozystack-basics/templates/clusterroles.yaml` grants
`get/list/watch` on `core.cozystack.io/tenantsecrets` to tenant
ServiceAccounts via `cozy:tenant:base` (lines 44-47) and to
`use`/`admin`/`super-admin` subjects via `cozy:tenant:use:base` (lines
179-180). None of this touches raw core `secrets`, so attaching the
label to a key-free object exposes the trust anchor and nothing else.
- `internal/backupcontroller/credentials_projector.go:128-133` relies on
the same rule in reverse — it deliberately *omits* the label so its
key-bearing projection is not promoted to a `TenantSecret`. This helper
is the positive counterpart: a key-free object that is safe to promote.

`view` deliberately does not receive the trust anchor through this path:
`cozy:tenant:view:base` grants only `core.cozystack.io/options` (lines
120-126), and `tenantsecrets` also includes credential Secrets, so
granting it to a read-only role would leak passwords. The trust anchor
reaches `use` and above plus tenant ServiceAccounts — the same access
level at which connection credentials are already surfaced (the
per-release dashboard Role binds at `use`, e.g.
`packages/apps/postgres/templates/dashboard-resourcemap.yaml` via
`cozy-lib.rbac.subjectsForTenantAndAccessLevel`). A chart that must show
`ca.crt` at `view` level in the dashboard can additionally name the
key-free Secret in its own per-release Role; that is a per-app detail,
not a base-role change.

### Why a library helper and not a controller here

Populating `ca.crt` stays the responsibility of whatever owns the PKI —
the app operator (as the redis fork does) or a cert-manager chain
resolved at the chart level. The helper is intentionally pure and
value-driven so it renders deterministically and is the single shape
every per-app PR converges on. A shared key-stripping projection
controller is a reasonable future generalization but is out of scope for
this foundational object.

### Convergence plan for the per-app TLS series (follow-up, not this PR)

I did not modify any of the open per-app branches. Each should adopt the
canonical object as follows:

- redis #2729 — already publishes an operator-side CA-only Opaque Secret
and already drops the grant on the CA-private-key Secret; converging
means emitting it through the helper / carrying the `tenantresource`
label so delivery matches the rest of the catalog.
- nats, qdrant (merged, cert-manager) — emit the canonical object via
the helper and withhold `<release>-ca` / `<release>-tls` from tenants.
- mariadb #2680, opensearch #2682, rabbitmq #2683, mongodb #2692 — same:
emit the canonical object, never grant a Secret that contains `tls.key`.

### Tests

`helm-unittest` in the cozy-lib test chart (`make -C
packages/tests/cozy-lib-tests test`) covers: the rendered object is
`Opaque` with `ca.crt` and no `tls.key`/`tls.crt`; the `tenantresource`
label is present; caller labels/annotations merge while the security
label always wins; the helper fails closed on empty `caCert`; and it
refuses a PEM that carries private key material.

### Release note

```release-note
NONE
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

## Release Notes

* **New Features**
* Added a Helm helper to generate CA-only Kubernetes TLS trust-anchor
secrets, including input validation (rejects private key material,
requires a properly formatted certificate, and ensures required
metadata).

* **Tests**
* Introduced a dedicated test suite covering successful rendering,
metadata and content assertions, tenant label enforcement,
label/annotation merging, and detailed failure cases for invalid inputs
and incorrect arguments.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-23 13:13:52 +03:00
Aleksei Sviridkin 51c5273d0b feat(platform): ACME wildcard certificate on the default ingress-nginx path (#2988)
## What this PR does

On the default ingress-nginx path (`gateway.enabled=false`) every
published hostname still minted its own per-host ACME certificate via
ingress-shim, even with a DNS-01 solver configured. That hits the Let's
Encrypt rate limit (50 certs per registered domain per week) once a
deployment exceeds ~50 endpoints. The Gateway API path already issues a
single per-apex wildcard in DNS-01 mode; this brings the ingress-nginx
path to parity. It implements the remaining ingress-nginx gap that #2400
was narrowed to in its triage comment (DNS-01 is already multi-provider,
and the Gateway path already issues wildcards).

The new `publishing.certificates.wildcard` toggle is opt-in and OFF by
default. When set to `true` with `solver=dns01` and no operator-provided
wildcard Secret, the platform issues one shared wildcard `Certificate`
for `<root-host>` + `*.<root-host>` and serves the resulting Secret as
the publishing controller's `--default-ssl-certificate`. The system
service Ingresses (dashboard, grafana, keycloak, harbor, …) then stop
requesting a per-host cert.

How it works:

- `core/platform` `apps.yaml` computes the effective wildcard Secret
name and a new `_cluster.wildcard-issue` signal. An operator-provided
`wildcardSecretName` (the BYO path) always wins and never triggers
issuance; HTTP-01 cannot issue wildcards; and when Gateway API is
enabled the TenantGateway controller issues the wildcard instead — so
all three are excluded from auto-issuance.
- `extra/ingress` renders the wildcard `Certificate` only on the
publishing controller (`Release.Namespace == expose-ingress`), because
the Secret must be same-namespace for ingress-nginx to read it. The
Certificate references the DNS-01 `ClusterIssuer` that
`cert-manager-issuers` already renders in `dns01` mode, so no per-tenant
Issuer is minted.

This reuses the existing wildcard-secret consumption path, so no
per-service Ingress template changes were needed — only the issuance
side is new.

Why opt-in (default off): the chosen wildcard Secret name rides the
`_cluster` channel, which every child tenant inherits verbatim, so this
is not root-tenant scoped. A single-label wildcard `*.<root-host>`
covers `<service>.<root-host>` but not a custom service host outside it
(a keycloak `ingress.host`, harbor `host`, or grafana `host` pointed at
another domain) nor a child tenant's nested host
(`<service>.<tenant>.<root-host>`). Enabling issuance makes every such
service drop its per-host ACME cert and fall back to the default
certificate, which does not cover it. Leaving it off by default means a
dns01 cluster is never silently switched on upgrade; an operator who
enables it accepts the same coverage responsibility as the
operator-provided wildcard path, which propagates identically. The
tradeoff is pinned by contract tests (keycloak custom host, bucket
nested child-tenant host). Per-tenant wildcards remain on the Gateway
path and are tracked separately.

Docs: cozystack/website#588

Closes #2400. Part of #2811.

### Screenshots

N/A — no UI changes.

### Release note

```release-note
feat(platform): add opt-in shared wildcard certificate issuance on the default ingress-nginx path via publishing.certificates.wildcard (default false). When enabled with a DNS-01 solver, the platform issues one *.<root-host> wildcard for system services instead of a per-host ACME certificate, avoiding Let's Encrypt rate limits at scale.
```



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added automatic wildcard certificate issuance support for DNS-01 ACME
solver.
* New `certificates.wildcard` configuration option to enable shared
wildcard TLS certificates.
* Ingress rules now properly utilize wildcard certificates when enabled.

* **Tests**
* Added comprehensive test suites validating wildcard certificate
generation and ingress integration across multiple scenarios.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-23 13:13:48 +03:00
Aleksei Sviridkin ad8367c9b6 chore(nats): bump nats to 1.3.16 (#2976)
## What this PR does

Bumps the nats chart from 1.3.13 to 1.3.16 (app 2.11.8 → 2.11.10), the
latest patch in the 1.3 line, picking up the published security fixes
the issue enumerates (nats-server 2.11.10 bumps `golang.org/x/crypto` to
v0.42.0 and the Go toolchain to 1.24.7) plus upstream bug fixes
(route-reconnect storms, stream interest loss when lowering
max-connections, JetStream meta performance).

Pins the `update` target to `--version 1.3.16` so `make update` stays on
the 1.3 line instead of floating to the 2.x chart restructure. The
cozystack overrides (PVC retention policy, cluster routeURLs domain,
prometheus exporter PodMonitor) stay valid.

Adds helm-unittest coverage (the package shipped none): pins the server
image, the PVC retention policy, and the PodMonitor invariant. `helm
unittest` 3/3 pass.

Verified: `helm template` renders `nats:2.11.10-alpine`, the retention
policy, and the PodMonitor; vendored tree is byte-identical to a fresh
upstream pull.

Closes #2890

### Release note

```release-note
chore(nats): bump nats to 1.3.16 (app 2.11.10)
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

## Release Notes

* **New Features**
* Added configurable Kubernetes `resources` (requests/limits) for the
NATS container and nats-box.

* **Chores**
  * Updated NATS image to `2.11.10-alpine`.
  * Updated config reloader image to `0.20.1`.
  * Updated nats-box image to `0.19.2`.
  * Updated the Helm chart to `1.3.16` (NATS appVersion to `2.11.10`).

* **Tests**
* Added automated Helm chart validation tests, including stricter
rendering checks.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-23 13:13:43 +03:00
Aleksei Sviridkin 5004af8810 chore(vertical-pod-autoscaler): bump VPA to 11.1.1 (#2975)
## What this PR does

Bumps the vertical-pod-autoscaler chart from 10.0.0 to 11.1.1 (app 1.3.0
→ 1.5.0, latest upstream), moving the VPA components
(admission-controller, recommender, updater) to
`registry.k8s.io/autoscaling/vpa-*:1.5.1` and picking up the published
security fixes the issue enumerates.

The chart-major bump keeps every cozystack override valid: the
recommender's prometheus storage config (`storage=prometheus`,
`prometheus-address`, container labels), `crds.enabled: false`, and the
updater/admissionController resource blocks.

Two Bitnami-adjacent details, both correctly neutralized:

- Upstream 11.0 switched the bundled CRD-install Job image to
`bitnamilegacy/kubectl`. cozystack disables that Job (`crds.enabled:
false`) and overrides `crds.image` to `docker.io/alpine/k8s`, so no
Bitnami image is ever pulled — verified by render.
- The `common` library subchart dependency moved off the sunset Bitnami
repo (`charts.bitnami.com` → `oci://ghcr.io/cowboysysop/charts`), a free
supply-chain improvement.

VPA 1.5 deprecations (humanized memory flag, UpdateMode `Auto`) are not
used by cozystack.

Adds helm-unittest coverage (the package shipped none): pins the
recommender prometheus args, the non-Bitnami `registry.k8s.io` image,
and the `crds.enabled=false` → no CRD-install Job invariant. `helm
unittest` 3/3 pass.

Closes #2882

### Release note

```release-note
chore(vertical-pod-autoscaler): bump VPA to 11.1.1 (app 1.5.0)
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
  * Added support for `InPlaceOrRecreate` pod update mode.
  * Improved OCI-based Helm install/upgrade documentation and examples.
* **Improvements**
* Updated chart/component versions (including VPA components to 1.5.x
and chart to 11.1.1).
* Hardened security defaults (seccomp RuntimeDefault and container
hardening) and added image integrity checks during upgrades.
* Expanded RBAC permissions for admission controller and event/workload
handling.
* **Chores**
* Updated the shared Helm library version and refreshed chart
tests/invariants.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-23 13:13:39 +03:00
Aleksei Sviridkin 713fcdcb32 chore(velero): bump velero to 12.0.3 (#2974)
## What this PR does

Bumps velero from 11.0.0 to 12.0.3 (appVersion 1.17.0 → 1.18.1, latest
upstream), picking up the published security fixes the issue enumerates
across the velero server and its backup plugins.

- Re-vendors the chart via `make update` (now pinned to `--version
12.0.3` for reproducible re-vendoring). The 12.0 major bump's
values-schema changes are backward-compatible (two required fields
relaxed, one optional key added), so all cozystack overrides
(`upgradeCRDs`, `initContainers`, `configuration.*`, `deployNodeAgent`)
stay valid.
- Moves the backup-plugin initContainers to their velero-1.18-aligned
releases: `velero-plugin-for-aws` v1.12.1 → v1.14.1 (the release that
bumps to velero 1.18.1; also corrects a pre-existing plugin/server skew)
and `kubevirt-velero-plugin` v0.8.0 → v0.9.0.
- Adds helm-unittest coverage (the package shipped none): pins the
server + plugin image tags and the `upgradeCRDs: false` → no
upgrade-crds Job invariant, which has silently regressed before.

The 1.18 "PVC selected-node" deprecation needs no action (velero handles
it transparently); CRD changes are additive.

Verified: `helm template` renders all three images; `helm unittest` 3/3
pass (mutation-checked).

**Upgrade note:** Helm v3 does not update CRDs on `helm upgrade`
(upgradeCRDs is disabled). On existing clusters the 1.18 CRDs must be
applied manually (`kubectl apply --filename
packages/system/velero/charts/velero/crds/`).

Closes #2886

### Release note

```release-note
chore(velero): bump velero to 12.0.3 (app 1.18.1) and backup plugins to velero-1.18-compatible releases
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added Backup status queue tracking (`queuePosition`) plus new `phase`
states.
* Added `caCertRef` Secret reference for BackupStorageLocation (with
`caCert` marked deprecated).
* Added incremental-bytes reporting (DataUpload, PodVolumeBackup) and
`snapshotSize` for PodVolumeRestore.
* Added `backupSyncPeriod` configuration and `nodeAgent.disableHostPath`
option.
* **Upgrades**
* Updated Velero to app 1.18.1 / chart 12.0.3, including plugin image
tag bumps and updated kubectl image defaults.
  * Added chart/app version labels across key resources.
* **Operational Improvements**
* Improved CRD cleanup/upgrade job execution and tuned the
“VeleroNoNewBackup” alert.
* **Tests**
* Added a `test` target (runs `helm unittest`) and expanded chart
rendering invariants checks.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-23 13:13:35 +03:00
Aleksei Sviridkin 553c0be708 chore(mongodb): bump psmdb-operator and CR to 1.22.0 (#2968)
## What this PR does

Bumps the Percona Operator for MongoDB stack from 1.21.x to 1.22.0
(latest upstream release), picking up the published security fixes in
the operator image that the issue enumerates.

Two coupled changes:

- `system/mongodb-operator`: re-vendors the upstream psmdb-operator
chart 1.21.2 → 1.22.0 via `make update` (operator image →
`percona/percona-server-mongodb-operator:1.22.0`). The vendored tree is
byte-for-byte identical to a fresh upstream pull.
- `apps/mongodb`: bumps the managed CR `spec.crVersion` 1.21.1 → 1.22.0
so the platform tracks the deployed operator instead of running at the
N-1 skew, plus the matching helm-unittest assertion.

The 1.22.0 CRD diff is additive (native MinIO backup storage, storage
scaling, `hookScript`, `PBMReady` condition, new `metrics.k8s.io` RBAC
that activates under our `watchAllNamespaces: true`). The only schema
removal — the restore-spec `replset` string, renamed upstream to
`replsetRemapping` — is unused by the cozystack mongodb app (restore
template uses `clusterName`/`pitr`/`backupSource` only). Deprecations
(PSMDB 6.0, PMM2, `enableVolumeExpansion`) stay backward-compatible. The
PBM (`2.11.0`) and PMM (`2.44.1`, disabled by default) sidecars stay
compatible with 1.22.0 and are out of scope here.

Verified: `helm unittest packages/apps/mongodb` 94/94 pass; `helm
template` renders the operator with the new image.

**Upgrade note:** Helm v3 does not update CRDs on `helm upgrade`. On
existing clusters the 1.22.0 CRD must be applied manually (`kubectl
apply --server-side -f .../crds/crd.yaml`); the operator pod itself runs
fine against the older CRD until then.

Closes #2888

### Release note

```release-note
chore(mongodb): bump psmdb-operator to 1.22.0 and managed CR to crVersion 1.22.0
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

## Release Notes

* **New Features**
* MongoDB Operator upgraded to version 1.22.0 with enhanced custom
resource definitions supporting backup storage configuration, hook
scripts, and storage autoscaling capabilities
* Added configurable namespace override for flexible operator deployment
  * Extended RBAC permissions for metrics collection

* **Chores**
  * Kubernetes minimum version requirement updated to 1.32+
  * Helm chart version bumped to 1.22.0

* **Documentation**
* Expanded CRD upgrade and installation guidance with multiple upgrade
strategies

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-23 13:13:31 +03:00
Aleksei Sviridkin 8c01706768 chore(kubernetes): refresh managed Kubernetes patch versions (#3014)
## What this PR does

Refreshes every supported Kubernetes minor in the `apps/kubernetes`
version map (`files/versions.yaml`) to its latest upstream patch,
picking up the published Go-stdlib / `x/net` fixes in the control-plane
component images:

| minor | from | to |
| --- | --- | --- |
| v1.35 | v1.35.1 | v1.35.6 |
| v1.34 | v1.34.4 | v1.34.9 |
| v1.33 | v1.33.8 | v1.33.13 |
| v1.32 | v1.32.12 | v1.32.13 |

`v1.31.14` and `v1.30.14` already track their latest patch. The
major/minor enum is unchanged, so `make generate` is a no-op (the values
schema, CRD and README are untouched). helm-unittest passes (129/129).

### Scope notes

- **Version range is intentionally held at v1.30-v1.35 and does NOT
advance to v1.36.** KubeVirt 1.8.2 rejects the kubelet checksum on
Kubernetes 1.36 (int32 CRD validation), leaving tenant VMIs stuck
`Scheduled` (tracked in #2769). The kamaji bump to `26.6.4-edge` raises
`KubeadmVersion` to `v1.36.0`, so `hack/update-versions.sh` would
otherwise pull v1.36 into this map — that expansion is deferred until
the KubeVirt regression is fixed.
- `hack/update-versions.sh` also caps the top minor at the exact
`KubeadmVersion` (`v1.35.0`), which would *downgrade* the current
`v1.35.1`. `v1.35` is set to the latest patch (`v1.35.6`) by hand
instead, matching the existing practice of running a patch above the
kubeadm tool version.
- The OS-package advisories from the scan (`libexpat`, `libpython3.13`,
`git`, `python3`, `perl`, …) live in the `ubuntu-container-disk` worker
images, built via `guestfish` from the floating `ubuntu noble/current`
base. Those clear when the release pipeline rebuilds them on the current
cloud image — the base is not digest-pinned, so no source change is
needed for them here.

Refs #2876

### Release note

```release-note
chore(kubernetes): refresh managed Kubernetes versions to latest patches (v1.35.6, v1.34.9, v1.33.13, v1.32.13)
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
* Updated Kubernetes version support for v1.35, v1.34, v1.33, and v1.32
with the latest patch releases.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-23 13:12:26 +03:00
Aleksei Sviridkin 16041736f2 chore(talos): bump core/talos to Talos v1.13.5 and matchbox v0.11.0 (#3008)
## What this PR does

Refreshes the `core/talos` asset/profile layer onto current upstream to
clear the published advisories the scanner flagged in the stale pinned
images (`libcrypto3` plus the Go-module advisories compiled into the
installer).

- **profiles**: regenerated by `hack/gen-profiles.sh v1.13.5`, moving
the base installer and every system extension to the v1.13.5 line —
installer `v1.13.0` → `v1.13.5`; `amdgpu`/`i915`/`drbd`/`zfs` to their
`-v1.13.5` builds; `amd-ucode` and the firmware blobs to the
`20260519`/`20260512` snapshots. The extension digests come verbatim
from the official `ghcr.io/siderolabs/extensions:v1.13.5`
`image-digests` manifest. v1.13.5 rebuilds the installer on the Go
1.26.4 toolchain and current runtime (kernel, containerd, runc,
OpenSSL).
- **matchbox**: base image `quay.io/poseidon/matchbox` `v0.10.0` →
`v0.11.0`, clearing the `libcrypto3` advisories in the matchbox runtime.

`v1.13.5` is the latest stable Talos release (no `v1.14` line yet).
`cozy-talos` ships no runtime templates — it drives the node-image /
installer / matchbox asset builds. The Talos installer and matchbox
images are rebuilt from these sources by the release asset pipeline (the
privileged imager build), which also re-pins the generated
`matchbox.tag` digest; this change is the source bump.

### Release note

```release-note
chore(talos): bump core/talos to Talos v1.13.5 and matchbox v0.11.0
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

## Chores
* Updated Talos infrastructure components to v1.13.5
* Updated matchbox service to v0.11.0
* Updated system extension firmware and driver components

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-23 13:12:22 +03:00
Aleksei Sviridkin 0bb15b98ea chore(images): refresh stale utility image references (#2969)
## What this PR does

Refreshes the stale utility image references the issue flags (2021-era
builds carrying long-fixed `golang.org/x/crypto` / `golang.org/x/net`):

- `kube-rbac-proxy` `v0.11.0` → `v0.22.0` (etcd metrics scrape proxy,
`monitoring-agents`) on the `quay.io/brancz` registry that
`etcd-operator` already standardized on. Only the two core flags
`--secure-listen-address` / `--upstream` are used; both are stable
across the version range.
- `matchbox` base image `v0.10.0` → `v0.11.0` (`core/talos` PXE image).
v0.11.0 only bumps butane and adds darwin arm64 artifacts; the `COPY`
asset paths are unchanged.
- `alpine/k8s` tools image `1.33.4` → `1.36.2`, applied to **every**
non-vendored reference so the repo runs a single current tools-image
version: seaweedfs resize/kubectl hooks, the cozystack-api post-upgrade
hook, the installer, the vm-disk and vm-instance resize hooks, the
vertical-pod-autoscaler CRD-install override, and the e2e cilium leak
healer. The two digest-pinned refs (installer, e2e healer) get the
matching multi-arch digest `sha256:44ef4942…`.

**Note on the issue text:** #2903 cites the seaweedfs `alpine/k8s` ref
as `1.28.4`, but that value only exists as the **vendored** subchart
default (`charts/seaweedfs/values.yaml`), which is left untouched per
the vendoring rules. The effective runtime value comes from the
non-vendored `values.yaml` override, which was already at `1.33.4` and
is bumped here to `1.36.2`.

Verified: `helm template` renders the new tags (incl. the digest-pinned
installer ref); `helm unittest` passes for seaweedfs (7) and
cozystack-api (6); no fixture pins any of these tags.

Closes #2903

### Release note

```release-note
chore(images): refresh kube-rbac-proxy (v0.22.0), matchbox (v0.11.0), and alpine/k8s (1.36.2) utility images
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Chores**
* Updated container images across system components, operational hooks,
and monitoring utilities to newer stable versions.

* **Security**
* Hardened several lifecycle hook Jobs and related pod templates to run
as non-root, use `seccompProfile: RuntimeDefault`, disallow privilege
escalation, and drop all Linux capabilities.

* **Tests**
* Added Helm unit test coverage to verify hook Jobs’ non-root security
settings and related Job fields.

* **Documentation**
* Added `helm unittest`-based `test` targets for relevant charts to
support the new coverage.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-23 13:12:18 +03:00
Aleksei Sviridkin 82db4e91fc chore(nfs-driver): bump csi-driver-nfs to 4.13.3 (#2967)
## What this PR does

Re-vendors the upstream `csi-driver-nfs` Helm chart from 4.11.0 to
4.13.3 (latest upstream release) via `make update`, picking up the
published security fixes in the bundled base layers and Go toolchain
that the issue enumerates.

All six CSI sidecar/plugin images move to current sig-storage releases:
nfsplugin v4.13.3, csi-provisioner v6.1.0, csi-resizer v2.0.0,
csi-snapshotter and snapshot-controller v8.4.0, livenessprobe v2.17.0,
node-driver-registrar v2.15.0.

The vendored tree is byte-for-byte identical to a fresh upstream pull
(no hand-edits). cozystack overrides are empty (`csi-driver-nfs: {}`)
and the platform pins the package by path, so nothing else needs
touching. New upstream defaults arrive with the bump and are
opt-in-safe: `enableSnapshotCompression`, the
`VolumeAttributesClass=false` feature-gate paired with the
provisioner/resizer majors, and a node-driver-registrar liveness probe.
`helm template` renders all images correctly.

Closes #2884

### Release note

```release-note
chore(nfs-driver): bump csi-driver-nfs chart and images to 4.13.3
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added support for generating multiple StorageClass resources from
chart values
  * Enabled snapshot compression for controller operations
* **Updates**
* Upgraded the NFS CSI driver chart/image version to **4.13.3** and
updated related container images
* Improved node-side setup with node-specific DNS handling and enhanced
node-driver-registrar health/liveness probing (including configurable
timeouts)
* **Configuration Enhancements**
* Extended CSI feature gates and improved StorageClass handling
(conditional annotations and per-class settings)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-23 13:12:13 +03:00
Aleksei Sviridkin a462e687a8 chore(keycloak): bump Keycloak server to 26.6.3 (#2964)
## What this PR does

Bumps the Keycloak server image from `26.5.2` to `26.6.3` (latest
upstream stable, published 2026-06-04), picking up the published
security fixes the issue enumerates (patched Netty 4.1.135+/4.2.15+ and
the bundled-package CVE fixes).

Keycloak 26.6 adds zero-downtime patch upgrades and startup/liveness
probes that report `UP` during DB migrations (smoother rolling updates
on Kubernetes). Targeting 26.6.3 specifically — 26.6.0/26.6.1 shipped a
migration-persistence bug (server exits with code 1 after an async realm
migration) that later patches fix.

The chart runs a plain Keycloak StatefulSet with no custom browser flows
or realm import, so the `MigrateTo26_6_0` realm migration and the 26.6
runtime breaking changes (outbound HTTP redirects now opt-in, stricter
WebAuthn attestation, SAML REDIRECT inflate capped at 128KB) don't
affect chart-managed config. The StatefulSet env (`KC_DB`,
`KC_CACHE=ispn`, `KC_PROXY_HEADERS`, health endpoints) stays valid in
26.6.

Verified locally: `helm unittest` 2/2 pass; `helm template` renders the
new image with cluster values.

Closes #2878

### Release note

```release-note
chore(keycloak): bump Keycloak server image to 26.6.3
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Chores**
  * Updated the Keycloak container image to version 26.6.3.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-23 13:11:21 +03:00
Aleksei Sviridkin b1662f7cf6 fix(cilium): pass IPv6 to kernel stack when IPv6 datapath is disabled (#2871)
## What this PR does

Cozystack enables Cilium's host firewall by default while the Cilium
IPv6 datapath stays disabled (`ipv6.enabled=false`). In upstream Cilium
this combination drops all node IPv6 on managed devices as "Unsupported
L3 protocol" (`DROP_UNKNOWN_L3` in `bpf_host.c`) before any policy
evaluation, in both directions. This breaks ICMPv6 Neighbor Discovery —
and with it all node-level IPv6, e.g. BGP unnumbered over link-local
addresses on L3 fabrics. No `CiliumClusterwideNetworkPolicy` can allow
this traffic, because the drop happens before policy enforcement
(upstream report: cilium/cilium#33155, closed stale).

The cozystack cilium image now carries a minimal BPF patch that passes
IPv6 to the kernel stack instead, mirroring the behavior with the host
firewall disabled:

- `packages/system/cilium/images/cilium/patches/` — three `ETH_P_IPV6`
passthrough cases under `#ifndef ENABLE_IPV6` in `bpf_host.c`. The
fourth `DROP_UNKNOWN_L3` site (`from_host_to_lxc`) is intentionally not
covered: bpf_lxc drops IPv6 without the v6 datapath regardless, so a
passthrough there restores nothing.
- The multi-stage Dockerfile applies the patch with `patch --fuzz=0`
plus a marker-count check, so upstream drift fails the image build
loudly.
- `make update` dry-runs the patch against the freshly vendored upstream
tag, so a cilium version bump surfaces drift immediately.
- `values.yaml` documents the consequence: Cilium host policies apply to
IPv4 only; node IPv6 is not filtered by Cilium.

The same fix was submitted upstream: cilium/cilium#46473. The local
patch is carried until it lands in a release Cozystack ships.

Verification: the image builds and contains the patched source; a
corrupted patch context fails the build with a clear error; the upstream
variant of this change passes new BPF unit tests that fail without the
fix with exactly the "Unsupported L3 protocol" drop from the field
report; existing host-firewall and IPv6 BPF tests still compile. PR e2e
exercises runtime BPF compilation of the patched source, since the agent
compiles `bpf_host.c` at startup.

Docs: cozystack/website#574

Closes #2806

### Screenshots

Not a UI change.

### Release note

```release-note
fix(cilium): node IPv6 (ICMPv6 Neighbor Discovery, BGP unnumbered over link-local) now works with the host firewall enabled; Cilium host policies apply to IPv4 only, node IPv6 is not filtered by Cilium
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Pass IPv6 traffic to the kernel stack when the Cilium IPv6 datapath is
disabled, preventing it from being treated as an unknown L3 protocol.
* **Documentation**
* Added clarification on host firewall behavior: with hostFirewall
enabled and IPv6 datapath disabled, policies apply to IPv4 only.
* **Chores**
* Improved the Cilium image build/update flow by validating the IPv6
patch against the upstream Cilium version to ensure compatibility.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-23 12:47:20 +03:00
Andrei Kvapil 27442bd31c fix(kubevirt-instancetypes): drop persistent EFI/TPM to unblock live-migration (#3006)
## What this PR does

Temporary revert. v1.5.0 restored persistent EFI/TPM state for the
`windows.11` / `windows.2k22` / `windows.2k25` profiles. With
persistence on, KubeVirt creates a backend-storage PVC
(`persistent-state-for-<vm>`) which, on the default `replicated`
StorageClass, is **ReadWriteOnce** — it pins the VM to its node and
**blocks live-migration and node drains**. With `evictionStrategy:
LiveMigrate` this can stall cluster upgrades. See #3005.

This strips persistent EFI/TPM from the preferences again — but via `yq
del` instead of the original `sed -d`, so an emptied `preferredTPM`
stays `{}` (the v1.8 CRD rejects `null`, which is the bug the original
strip caused). **Secure Boot and the vTPM remain present, just
non-persistent** — Windows VMs still boot; they just don't persist
EFI/TPM across reboots.

⚠️ **Temporary stopgap** until vm-state can request an RWX backend —
either RWX-Block via the upstream KubeVirt change
(kubevirt/kubevirt#18215), or an RWX-Filesystem `vmStateStorageClass`.
Once that lands, persistence can be re-enabled with live-migration
intact.

### Screenshots

No UI changes.

### Release note

```release-note
fix(kubevirt-instancetypes): temporarily disable persistent EFI/TPM state to unblock live-migration of Windows VMs. Persistence created a ReadWriteOnce backend-storage PVC on the default storage class, pinning the VM to its node. Secure Boot and vTPM remain available (non-persistent); to be re-enabled once vm-state can use RWX storage.
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Updated Windows virtual machine preferences to enable live migration
and drain operations
* Fixed compatibility issues with KubeVirt v1.8 virtual machine
preference configurations
* Removed persistent settings from TPM and EFI configurations to prevent
blocking behaviors on Windows 11 and Windows Server 2022/2025 variants

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-23 10:30:11 +02:00
Myasnikov Daniil 76ad921fdd ci: harden workflow token permissions and pin actions by SHA
Raise the OpenSSF Scorecard Token-Permissions and Pinned-Dependencies
checks (both currently 0/10) ahead of CNCF Incubation due diligence:

- Declare a top-level read-only default (permissions: contents: read) in
  every workflow, plus an explicit per-job permissions: block that grants
  only the writes that job actually needs. Workflows that previously held
  write scopes at the workflow level (backport, pr-labeler, pr-size,
  stale) now hold them at job level instead.
- Pin every GitHub-owned and third-party action to a full commit SHA with
  a version comment. scorecard.yml was already pinned in #2721.

No triggers, job graph, or step logic change; only token scopes and
action refs. Self-hosted release jobs keep the exact write scopes they
already declared.

Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
Assisted-By: Claude <noreply@anthropic.com>
2026-06-23 11:32:16 +05:00
Aleksei Sviridkin a1b88cfa6e docs(tests): drop the merged k8s-version pin from the in-flight e2e list
The "Pin the e2e management cluster Kubernetes version" item is no longer
in-flight — it is merged and live in hack/e2e-prepare-cluster.bats
(--kubernetes-version v1.33.12). Remove it from the "not yet the merged
standard" section; its rationale lives in the bats comment.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
2026-06-23 05:51:07 +03:00
Aleksei Sviridkin c3ebdb310e docs(tests): correct the e2e kube-version pin rationale for talosctl 1.13.5
talosctl 1.13.5 now defaults to Kubernetes 1.36.2, so the comment's premise
— that talosctl's bundled default predates the KCM VAP nil-pointer fix — no
longer holds (1.36.2 already carries that fix). The reason e2e pins v1.33.12
is now that 1.36 is outside cozystack's supported range; reword to lead with
that and keep the KCM VAP fix as the secondary property v1.33.12 carries.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
2026-06-23 05:41:03 +03:00
Aleksei Sviridkin 381edde331 chore(build): refresh first-party Alpine runtime bases to 3.24
Moves the pinned Alpine runtime bases of the first-party images forward to
alpine:3.24 to clear the published musl / zlib advisories carried by the stale
layers:

- mariadb-backup: 3.20 -> 3.24
- cozystack-operator: 3.22 -> 3.24
- platform-migrations: 3.22 -> 3.24
- grafana-dashboards: 3.22 -> 3.24
- kubeovn-webhook: 3.21.3 -> 3.24 (also drops the over-specific patch pin in
  favour of the minor-float convention used elsewhere)
- redis-operator: latest -> 3.24 (pins the previously-floating runtime base)

These rebuild on the release asset pipeline; the digests pinned in values.yaml
are re-pinned there on the next build, matching how the rest of the ~30
first-party images pick up the shared base.

Side effect for platform-migrations: its kubectl / helm come from the Alpine
repo, so the base bump moves them 1.33 -> 1.36 and 3.18 -> 3.19. Both are
current upstream stable and compatible with the management cluster; for the
cozystack migration scripts (apply / get / label / helm release ops) the newer
kubectl is in skew with the modern control plane.

The build-only `alpine AS source` stages (keycloak-operator,
objectstorage-controller) are left as-is: their final images are distroless, so
no Alpine layer ships. The s3manager base is owned by the separate bucket bump,
and kilo's base moves in its own image rebuild.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
2026-06-23 05:03:45 +03:00
Aleksei Sviridkin 992076df4e docs(velero): correct the stale upgradeCRDs disable rationale
The comment justified upgradeCRDs: false by a kubectl-image-compatibility
problem in the upgrade-crds Job. That rationale is obsolete in velero 12.x:
the Job now runs the velero image natively, not a kubectl image. The real,
current reason the Job stays disabled is that CRDs ship via the chart's
crds/ directory, making the Job redundant. Correct both the values.yaml
override comment and the helm-unittest comment to match.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
2026-06-23 05:02:48 +03:00
Aleksei Sviridkin 0297926f7d chore(packages/system/foundationdb-operator): bump fdb-operator to v2.30.0
Re-vendors the FoundationDB Kubernetes operator chart from v2.13.0 to v2.30.0
(chart 0.2.0 -> 0.3.0), 17 minor releases forward, picking up the published
security fixes. The CRD changes (FoundationDBCluster/Backup/Restore) are
additive only -- new fields, no property removals (only the controller-gen and
foundationdb.org/release version annotations change) -- so the apps/foundationdb
FDB CR stays valid against the new operator. cozystack overrides (globalMode,
nodeReadClusterRole) remain valid. The one removed CLI flag (genericclioption)
is not used by cozystack; the chart's rbac role binding is now unconditional
(previously globalMode-gated), a no-op for cozystack which sets globalMode=true.

Adds helm-unittest coverage (the package shipped none): pins the operator image.

Adaptations:
- Makefile: clone --branch v2.13.0 -> v2.30.0; add test target
- charts/: re-vendored (operator v2.30.0 + additive CRD schema)
- tests/fdb-operator_test.yaml: new helm-unittest image pin

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
2026-06-23 03:47:31 +03:00
Aleksei Sviridkin 041c73c709 chore(apps/openbao): bump app appVersion to 2.5.1
The managed-service app deploys the system openbao chart, whose server
image follows that chart's appVersion (now v2.5.1). The app Chart.yaml
appVersion ships verbatim on the openbao app CR, so leaving it at 2.5.0
makes every instance misreport its running OpenBAO version.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
2026-06-23 03:25:27 +03:00
Aleksei Sviridkin e62669013b chore(packages/system/openbao): bump openbao chart to 0.25.7
Re-vendors the openbao-helm chart from 0.25.3 to 0.25.7 (app v2.5.0 -> v2.5.1),
the latest in the ^0.25 line the Makefile pins, picking up the v2.5.1 security
fix. cozystack overrides (injector + csi disabled) stay valid and render
nothing, so the changed surface is the openbao server StatefulSet image only.

Widening past 0.25.x to 0.28.x (app v2.5.5) would need a CHART_VERSION constraint
change plus a 0.26/0.27/0.28 changelog review and is intentionally left out.

Adds helm-unittest coverage (the package shipped none): pins the server image
and the injector/csi-disabled invariants.

Adaptations:
- charts/: re-vendored via make update (helm pull openbao ^0.25 -> 0.25.7)
- Makefile: add test target
- tests/openbao_test.yaml: new helm-unittest coverage

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
2026-06-23 03:25:16 +03:00
Aleksei Sviridkin a0cd77d64f chore(kubernetes): refresh managed Kubernetes patch versions
Bumps every supported Kubernetes minor in the apps/kubernetes version map to its
latest upstream patch, picking up the published Go-stdlib / x/net fixes in the
control-plane component images:

- v1.35: v1.35.1 -> v1.35.6
- v1.34: v1.34.4 -> v1.34.9
- v1.33: v1.33.8 -> v1.33.13
- v1.32: v1.32.12 -> v1.32.13

v1.31 and v1.30 already track their latest patch (.14). The major/minor enum is
unchanged, so the generated values schema, CRD and README are untouched
(make generate is a no-op).

The version range is intentionally held at v1.30-v1.35 and does NOT advance to
v1.36: KubeVirt 1.8.2 rejects the kubelet checksum on Kubernetes 1.36 (int32 CRD
validation), leaving tenant VMIs stuck Scheduled. The kamaji bump to 26.6.4-edge
raises KubeadmVersion to v1.36.0, so hack/update-versions.sh would otherwise add
v1.36 here -- that expansion is deferred until the KubeVirt regression is fixed.
The script also caps the top minor at the exact KubeadmVersion (v1.35.0); v1.35
is set to the latest patch (v1.35.6) by hand instead, matching the existing
practice of running a patch above the kubeadm tool version.

The OS-package advisories in the scan live in the ubuntu-container-disk worker
images; those clear when the release pipeline rebuilds them on the floating
ubuntu noble/current base (no source change needed -- the base is not pinned).

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
2026-06-23 03:25:02 +03:00
Aleksei Sviridkin 73f6382d30 feat(cozy-lib): add CA-only TLS trust-anchor helper for tenants
Per-app TLS issues a per-release self-signed CA, but the only objects
that carry ca.crt — the cert-manager CA and leaf Secrets — also carry
private keys. Granting a tenant read on those to obtain the trust
anchor also hands over a server or CA private key.

Add cozy-lib.tls.caCertSecret, which renders a canonical Opaque Secret
holding only ca.crt and labelled internal.cozystack.io/tenantresource=
true. The tenantsecret registry surfaces label-bearing Secrets under
core.cozystack.io/tenantsecrets, which the base tenant roles already
grant, so tenants reach the trust anchor without any grant on a Secret
that contains tls.key. The helper fails closed on empty input and
refuses any PEM carrying private key material.

Covered by helm-unittest in the cozy-lib test chart.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
2026-06-23 03:12:17 +03:00
Aleksei Sviridkin 37dbc586dc chore(monitoring): bump Grafana to 11.6.15, victorialogs datasource and alerta
Refreshes the monitoring image anchors onto current upstream to clear the
published advisories carried by the stale pins.

- grafana image: base grafana/grafana 11.4.0 -> 11.6.15 (latest 11.x). The
  rebuild clears the Go-dependency advisories in the grafana binary (x/crypto,
  moby/spdystream, jackc/pgx/v5, russellhaering/goxmldsig, buger/jsonparser,
  golang-jwt/jwt/v4, getkin/kin-openapi). It stays on the 11.x line rather than
  12.x to keep the bundled panel plugins compatible (grafana-worldmap-panel is
  deprecated upstream) and avoid a dashboard-schema migration.
- victorialogs-datasource plugin: v0.14.1 -> v0.28.0 (grafanaDependency
  >=10.4.0, so it loads on 11.6.15).
- alerta-web: 9.0.4 -> 9.1.0, clearing the python cryptography advisory.
- images/grafana.tag: re-pinned to the rebuilt multi-arch digest.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
2026-06-23 02:41:49 +03:00
Aleksei Sviridkin e3ed42a608 chore(testing): refresh e2e-sandbox tools and base to current upstream
Rebuilds the e2e test sandbox on current upstream to clear the published
advisories (containerd, helm, go-git, moby/spdystream, Go stdlib) carried by the
stale tool binaries and base layers:

- base: ubuntu 22.04 -> 24.04; netcat -> netcat-openbsd, since `netcat` is a
  candidate-less virtual package on 24.04
- kubectl: 1.33.2 -> 1.33.13, staying on the 1.33 line that the e2e control
  plane pins at v1.33.12, so client/server skew is unchanged
- talosctl: 1.10.4 -> 1.13.5, aligning the client with the v1.13.x Talos nodes
  the sandbox provisions
- helm: 3.18.3 -> 3.21.2 (latest helm 3); the e2e flow drives the v3 CLI, so it
  stays on the 3.x line rather than moving to the breaking 4.x
- yq: 4.44.3 -> 4.53.3
- values.yaml: re-pinned to the rebuilt multi-arch digest

crust-gather and cozyhr already track their latest releases; flux and mc install
the current release at build time.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
2026-06-23 02:23:39 +03:00