diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d6fbd682..988503c8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -362,6 +362,22 @@ jobs: done exit ${rc} + # Helm installs whatever sits in charts/; the umbrella's own guard holds + # it to Chart.yaml's ranges. kates 0.10.7 is the last chart whose + # ClusterRole read every Secret in the cluster. + - name: Check kates-platform refuses a stale subchart + run: | + tmp=$(mktemp -d) + cp -R charts/kates-platform "${tmp}/" + rm "${tmp}"/kates-platform/charts/kates-*.tgz + helm package charts/kates --version 0.10.7 --destination "${tmp}/kates-platform/charts" > /dev/null + if out=$(helm template p "${tmp}/kates-platform" 2>&1); then + echo "::error::kates-platform rendered with kates 0.10.7 in charts/" + exit 1 + fi + echo "${out}" | grep -q 'charts/ holds kates 0.10.7' || { echo "${out}"; exit 1; } + echo "OK: kates-platform refused kates 0.10.7" + - name: Install kubeconform uses: ./.github/actions/install-tools with: diff --git a/README.md b/README.md index 69066391..0c303600 100644 --- a/README.md +++ b/README.md @@ -212,7 +212,7 @@ When you install charts with Helm directly: | [`kafka-common`](charts/kafka-common/) | 0.1.0 | | Library chart — the templates the Strimzi charts share (names and labels, rails, Kafka client authentication, the Connect worker spec, KafkaUser, secret sync, NetworkPolicy and monitoring fragments, the Grafana grid, the preflight probe) | | [`kafka-ui`](charts/kafka-ui/) | 0.3.0 | v1.5.0 | A Helm chart for deploying Kafka UI (Kafbat) with Strimzi SCRAM-SHA-512 authentication | | [`kates-chaos`](charts/kates-chaos/) | 2.2.1 | 3.28.0 | Kates Chaos Engineering — wraps the LitmusChaos execution plane (operator, exporter, CRDs) with Kafka-specific RBAC, experiment/engine templating, and monitoring | -| [`kates-platform`](charts/kates-platform/) | 0.7.0 | 1.0.0 | Umbrella chart for the full Kates platform — Kafka, Kates, and supporting infrastructure | +| [`kates-platform`](charts/kates-platform/) | 0.8.0 | 1.0.0 | Umbrella chart for the full Kates platform — Kafka, Kates, and supporting infrastructure | | [`kates`](charts/kates/) | 0.11.6 | 1.27.0 | Kates — Kafka Advanced Testing & Engineering Suite | | [`legacy-kafka`](charts/legacy-kafka/) | 0.2.0 | 3.9.1 | A deliberately old Kafka (2.x on ZooKeeper, or 3.x on KRaft) to migrate FROM — the replication source that the pinned Strimzi release cannot deploy | | [`mirror-maker2`](charts/mirror-maker2/) | 0.11.6 | 4.3.1 | Strimzi KafkaMirrorMaker2 — cross-cluster replication, DR, and cross-version migration (2.x/3.x → 4.x) | diff --git a/charts/kates-platform/Chart.yaml b/charts/kates-platform/Chart.yaml index cd83b1c4..cd641e2b 100644 --- a/charts/kates-platform/Chart.yaml +++ b/charts/kates-platform/Chart.yaml @@ -2,11 +2,10 @@ apiVersion: v2 name: kates-platform description: Umbrella chart for the full Kates platform — Kafka, Kates, and supporting infrastructure type: application -# Minor bump: kafka-cluster 1.x (the platform's topics, users and client grants -# are its `platform` profile, which the umbrella selects), mirror-maker2 0.8 and -# connect-cluster 2.x (both built on the kafka-common library; Connect is new -# here, off by default). The ranges are tightened to those lines. -version: 0.7.0 +# Minor bump: each range's floor is the subchart version this umbrella was +# rendered and linted with, and templates/subchart-versions.yaml refuses to +# render a subchart in charts/ outside its range. +version: 0.8.0 appVersion: "1.0.0" keywords: - kafka @@ -17,27 +16,33 @@ maintainers: - name: Platform Team dependencies: - name: kafka-cluster - version: ">=1.0.0 <2.0.0" + version: ">=1.0.10 <2.0.0" repository: "file://../kafka-cluster" condition: kafka-cluster.enabled - name: kates - version: ">=0.5.0 <1.0.0" + version: ">=0.11.6 <1.0.0" repository: "file://../kates" condition: kates.enabled - name: apicurio-registry - version: ">=0.2.0 <1.0.0" + version: ">=0.4.0 <1.0.0" repository: "file://../apicurio-registry" condition: apicurio-registry.enabled # Off by default: a mirror needs a second cluster to mean anything, and the # chart's own defaults are a loopback on krafter for smoke-testing. Enable it # with a real mirrors[].source — see charts/mirror-maker2/README.md. - name: mirror-maker2 - version: ">=0.8.0 <1.0.0" + version: ">=0.11.6 <1.0.0" repository: "file://../mirror-maker2" condition: mirror-maker2.enabled # Off by default: `kates deploy` installs Connect as its own release, in its # own namespace, and the platform runs without it. - name: connect-cluster - version: ">=2.0.0 <3.0.0" + version: ">=2.1.8 <3.0.0" repository: "file://../connect-cluster" condition: connect-cluster.enabled +annotations: + artifacthub.io/changes: | + - kind: fixed + description: "ACTION REQUIRED for a platform built before this version — the umbrella installed whatever subcharts sat in its gitignored charts/ directory, and Helm never holds those to the ranges in Chart.yaml. A charts/ left from an earlier `helm dependency update` kept installing kates 0.9.1, whose ClusterRole granted get, list and watch on every Secret in the cluster, so the Kates API's service account could read every SCRAM password, CA key and token there; kates 0.10.8 dropped that rule. Each range's floor is now the version this umbrella was rendered with (kafka-cluster 1.0.10, kates 0.11.6, apicurio-registry 0.4.0, mirror-maker2 0.11.6, connect-cluster 2.1.8), and rendering fails, naming the subchart, while charts/ holds an enabled one outside its range. Run `make platform-chart-deps` (or `helm dependency update charts/kates-platform`) before installing or upgrading" + - kind: changed + description: "ACTION REQUIRED for INTEGRATION_CDC and for copied kates values — the kates subchart moves from 0.9.1 to 0.11.6. Its ClusterRole grants nothing on Secrets: a platform that runs INTEGRATION_CDC sets kates.rbac.cdcSecretNamespaces to the CDC database's namespace, or the run fails at DB_SETUP with Forbidden. Kates runs one pod: kates.replicaCount above 1, kates.autoscaling.enabled, a RollingUpdate kates.strategy and kates.podDisruptionBudget.minAvailable are refused by the kates schema, and an upgrade leaves the API unreachable until the new pod is Ready. The umbrella's own values are unchanged: kafka-cluster 1.0.10 still takes profile: platform, and the other subcharts take only enabled" diff --git a/charts/kates-platform/README.md b/charts/kates-platform/README.md index 153c6a11..470f1ae7 100644 --- a/charts/kates-platform/README.md +++ b/charts/kates-platform/README.md @@ -24,6 +24,7 @@ The Strimzi operator must be running (see `charts/strimzi-operator`) before the | `kafka-cluster.*` | subchart defaults | Full pass-through — see `charts/kafka-cluster/values.yaml` | | `kates.enabled` | `true` | Deploy the Kates application subchart | | `kates.*` | subchart defaults | Full pass-through — see `charts/kates/values.yaml` | +| `kates.rbac.cdcSecretNamespaces` | `[]` | Namespaces where the Kates API may read the `postgresql` Secret; INTEGRATION_CDC needs its database's namespace here, since the kates ClusterRole grants nothing on Secrets | | `apicurio-registry.enabled` | `false` | Deploy Apicurio Registry (KafkaSQL storage against the `kafka-cluster` subchart) | | `mirror-maker2.enabled` | `false` | Deploy MirrorMaker 2 (needs a real `mirrors[].source`) | | `connect-cluster.enabled` | `false` | Deploy Kafka Connect next to Kafka (`kates deploy` installs it as its own release instead) | @@ -32,4 +33,6 @@ Subchart values are validated by each subchart's own `values.schema.json`. ## Version pinning -`Chart.yaml` pins the subcharts with ranges (`>=1.0.0 <2.0.0` for kafka-cluster, `>=0.8.0 <1.0.0` for mirror-maker2, `>=2.0.0 <3.0.0` for connect-cluster, `>=0.5.0 <1.0.0` for kates, `>=0.2.0 <1.0.0` for apicurio-registry); the `file://` repository always resolves to the local working tree, and `Chart.lock` records the exact version at build time. +`Chart.yaml` pins the subcharts with ranges (`>=1.0.10 <2.0.0` for kafka-cluster, `>=0.11.6 <1.0.0` for mirror-maker2, `>=2.1.8 <3.0.0` for connect-cluster, `>=0.11.6 <1.0.0` for kates, `>=0.4.0 <1.0.0` for apicurio-registry); each floor is the version the umbrella was last rendered with. The `file://` repository always resolves to the local working tree, and `Chart.lock` records the exact version at build time. + +Helm installs whatever sits in `charts/` without checking it against those ranges, so the umbrella checks itself: rendering fails, naming the subchart, while `charts/` holds an enabled subchart outside its range. A `charts/` left from an older build would otherwise install its old subcharts, such as kates 0.9.1, whose ClusterRole read every Secret in the cluster. Run `make platform-chart-deps` to refresh it. diff --git a/charts/kates-platform/templates/subchart-versions.yaml b/charts/kates-platform/templates/subchart-versions.yaml new file mode 100644 index 00000000..bff6dc89 --- /dev/null +++ b/charts/kates-platform/templates/subchart-versions.yaml @@ -0,0 +1,12 @@ +{{- /* +Renders nothing. Helm installs whatever sits in charts/ and never holds it to +the ranges in Chart.yaml, so a charts/ directory left from an older build +installed its old subcharts: kates 0.9.1's ClusterRole read every Secret in +the cluster. Refuse each enabled subchart outside its range instead. +*/}} +{{- range .Chart.Dependencies }} +{{- $sub := index $.Subcharts .Name }} +{{- if and $sub (not (semverCompare .Version $sub.Chart.Version)) }} +{{- fail (printf "charts/ holds %s %s, outside %q in Chart.yaml: run `make platform-chart-deps` (helm dependency update charts/kates-platform)" .Name $sub.Chart.Version .Version) }} +{{- end }} +{{- end }} diff --git a/cli/go.mod b/cli/go.mod index c3c32a69..144e3377 100644 --- a/cli/go.mod +++ b/cli/go.mod @@ -2,7 +2,7 @@ module github.com/bmscomp/kates/cli go 1.26.0 -toolchain go1.27.2 +toolchain go1.27.3 require ( github.com/charmbracelet/bubbles v1.0.0 diff --git a/docs/book/appendix-d-versions.md b/docs/book/appendix-d-versions.md index 7679e8f4..fcdc07a8 100644 --- a/docs/book/appendix-d-versions.md +++ b/docs/book/appendix-d-versions.md @@ -21,7 +21,7 @@ Every version the platform pins, in one place. This table is generated from the | `kafka-common` chart | 0.1.0 (library) | `charts/kafka-common/Chart.yaml` | | `kafka-ui` chart | 0.3.0 (app v1.5.0) | `charts/kafka-ui/Chart.yaml` | | `kates-chaos` chart | 2.2.1 (app 3.28.0) | `charts/kates-chaos/Chart.yaml` | -| `kates-platform` chart | 0.7.0 (app 1.0.0) | `charts/kates-platform/Chart.yaml` | +| `kates-platform` chart | 0.8.0 (app 1.0.0) | `charts/kates-platform/Chart.yaml` | | `kates` chart | 0.11.6 (app 1.27.0) | `charts/kates/Chart.yaml` | | `legacy-kafka` chart | 0.2.0 (app 3.9.1) | `charts/legacy-kafka/Chart.yaml` | | `mirror-maker2` chart | 0.11.6 (app 4.3.1) | `charts/mirror-maker2/Chart.yaml` |