Repository navigation
feat(openbao): central platform instance and per-tenant transit provisioning - #4177
Draft
myasnikovdaniil wants to merge 2 commits into
Draft
myasnikovdaniil wants to merge 2 commits into
myasnikovdaniil wants to merge 2 commits into
Conversation
packages/system/openbao has never been a running instance: its component carries no install section, and package_reconciler.go creates a HelmRelease only for components that have one. It is the workload chart a tenant OpenBAO renders from, published for that purpose and nothing else, which is why its values are a stub. So the platform instance that #2787 asks for needs its own package, and this is it. HA Raft over cert-manager TLS, a Shamir seal because no cloud KMS is assumed on bare metal, a one-time init Job that persists the unseal keys and root token, a long-running unsealer that re-unseals pods after a restart, and a setup Job that enables the transit engine and Kubernetes auth the per-tenant seals will use. It wraps the same published chart artifact a tenant instance uses rather than vendoring the upstream chart again, so one `make update` in packages/system/openbao moves both consumers and they cannot drift to different upstream versions. Naming here is load-bearing rather than cosmetic, and nothing in Go checks it: the transit reconciler reaches this instance at https://openbao-system.cozy-openbao.svc:8200 and reads openbao-system-keys and openbao-system-ca from cozy-openbao. central_test.yaml pins the naming, the https scheme, the apiserver egress label and the raft topology so a values edit cannot quietly break tenant provisioning. Replicas default to three and are configurable down to one. Raft stays the backend at every count, because the backend a barrier was created under cannot be changed afterwards, so scaling 1 -> 3 has to be an in-place addition of voters. At one replica the retry_join set is omitted and the upstream chart's required hostname anti-affinity is dropped, which is what lets a single-node install schedule at all. Refs #2787 Assisted-By: LLM Signed-off-by: Myasnikov Daniil <[email protected]>
…al OpenBAO Phase 2 of #2787: the platform side of tenant auto-unseal. A tenant OpenBAO cannot be handed a transit seal until something has created its key on the central instance and given its pods a way to authenticate, and that has to be reactive because instances come and go with tenants. The reconciler watches inner OpenBAO HelmReleases carrying apps.cozystack.io/transit-unseal and, per instance, ensures a transit key, an unseal policy scoped to that key, and a Kubernetes-auth role bound to the instance's server ServiceAccount. It then publishes the central CA as the <name>-transit-ca ConfigMap, which is a public certificate rather than a Secret. No token is minted or delivered. The instance exchanges its own projected ServiceAccount token for a transit token at every boot, so there is no long-lived credential in the tenant namespace to store, rotate or leak. The CA ConfigMap is owner-referenced to the HelmRelease, so it is garbage-collected with the instance. Nothing emits that label yet, so this is inert until the tenant chart grows a transit seal. It ships here because it is the platform half of the feature and belongs with the central instance rather than with the chart that consumes it. Refs #2787 Assisted-By: LLM Signed-off-by: Myasnikov Daniil <[email protected]>
Contributor
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueThanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
1 of 12 tasks
2 tasks done
2 tasks done
Aleksei Sviridkin (lexfrei)
pushed a commit
that referenced
this pull request
Sep 30, 2026
Every openbao PR lands on area/uncategorized, because the labeler has no scope entry for it and there would be no label to apply if it did. #4168 and #4177 are both sitting on the fallback right now. labels.yml sets the bar for a new area at three open issues on the topic, and openbao is at three: #2787, #2483 and #2793. It also follows the shape already used for a single shipped component, next to area/kamaji, area/keycloak and area/cilium. Maps the plain `openbao` scope and `openbao-central` alongside it, since the platform instance lives in its own package and gets its own scope. Assisted-By: LLM Signed-off-by: Myasnikov Daniil <[email protected]>
Aleksei Sviridkin (lexfrei)
added a commit
that referenced
this pull request
Sep 30, 2026
…4182) ## What this PR does Every openbao PR lands on `area/uncategorized`. The labeler has no scope entry for it, and there would be no label to apply if it did, so both #4168 and #4177 are sitting on the fallback right now. `labels.yml` puts the bar for a new area at three open issues on the topic, and openbao is at three: #2787, #2483 and #2793. The shape follows what is already there for a single shipped component, next to `area/kamaji`, `area/keycloak` and `area/cilium`. The mapping takes the plain `openbao` scope and `openbao-central` alongside it, because the platform instance lives in its own package and carries its own scope. Checked that every `area/*` and `kind/*` the labeler references is declared in `labels.yml`: 27 referenced, none missing, before and after this change. zizmor and the pre-commit hooks pass, and the embedded script still parses under github-script semantics. ### Screenshots No UI change. ### Downstream repositories Walked the trigger map against the diff. Nothing matches: the change is two entries under `.github/`, and no trigger in the map is keyed on the label set or the labeler. No package added, renamed or removed, no platform component or variant, no `values.schema.json`, no `ApplicationDefinition`, no `hack/` layout change, no namespace rename. - [x] No downstream repository is affected by this change - [ ] [cozystack/website](https://github.com/cozystack/website) - follow-up: - [ ] [cozystack/terraform-provider-cozystack](https://github.com/cozystack/terraform-provider-cozystack) - follow-up: - [ ] [cozystack/ansible-cozystack](https://github.com/cozystack/ansible-cozystack) - follow-up: - [ ] [cozystack/ccp](https://github.com/cozystack/ccp) - follow-up: - [ ] [cozystack/talm](https://github.com/cozystack/talm) - follow-up: - [ ] [cozystack/cozyhr](https://github.com/cozystack/cozyhr) - follow-up: - [ ] [cozystack/cozy-proxy](https://github.com/cozystack/cozy-proxy) - follow-up: - [ ] [cozystack/cozystack-telemetry-server](https://github.com/cozystack/cozystack-telemetry-server) - follow-up: - [ ] [cozystack/external-apps-example](https://github.com/cozystack/external-apps-example) - follow-up: - [ ] [cozystack/examples](https://github.com/cozystack/examples) - follow-up: - [ ] [cozystack/community](https://github.com/cozystack/community) - follow-up: ### Release note ```release-note NONE ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added an `area/openbao` label for tracking issues and pull requests related to OpenBAO. - Updated automatic pull request labeling to apply this label to changes scoped to OpenBAO and OpenBAO Central. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this PR does
Phases 1 and 2 of #2787, the platform side of tenant OpenBAO auto-unseal. Two commits: the central instance, and the reconciler that provisions per tenant against it. The tenant half is not here, see the bottom.
Worth knowing before reading the diff, because it is why a new package exists at all:
packages/system/openbaohas never been a running instance. Its component carries noinstallsection, andpackage_reconciler.gocreates a HelmRelease only for components that have one, so nothing ever stood it up. It is the workload chart a tenant OpenBAO renders from, published for that purpose and nothing else, which is why its values are a five line stub. The platform instance therefore gets its own package rather than being loaded into that one.packages/system/openbao-centralis HA raft over cert-manager issued TLS, with a Shamir seal because no cloud KMS is assumed on bare metal. A one time init Job persists the unseal keys and root token, a long running unsealer re-unseals pods after a restart, and a setup Job enables the transit engine and kubernetes auth that the per-tenant seals will use. It wraps the same published chart artifact a tenant instance uses instead of vendoring the upstream chart a second time, so onemake updateinpackages/system/openbaomoves both consumers and they cannot drift to different upstream versions.Naming there is load-bearing and nothing in Go checks it: the reconciler reaches this instance at
https://openbao-system.cozy-openbao.svc:8200and readsopenbao-system-keysandopenbao-system-cafromcozy-openbao.central_test.yamlpins the naming, the https scheme, the apiserver egress label and the raft topology, so a values edit turns into a red test instead of broken tenant provisioning.Replicas default to 3 and go down to 1, which a single node install needs. Raft stays the backend at every count, including 1: the backend a barrier was created under cannot be changed afterwards, so scaling 1 to 3 has to be an in-place addition of voters rather than a file to raft migration nobody can perform. At one replica the
retry_joinset is omitted, because a lone node would retry a self join it cannot complete until the init Job promotes it, and the upstream chart's REQUIRED hostname anti-affinity is dropped, which is the other half of why a single node schedules at all. Rendering at 3 replicas is byte identical to the hardcoded config it replaces.The instance also carries
policy.cozystack.io/allow-to-apiserver. It runsservice_registration "kubernetes", and without that label cozystack's CiliumNetworkPolicy does not admit the egress, so the pods hang at startup with the listener open and nothing answering (#2793).The reconciler watches inner OpenBAO HelmReleases labelled
apps.cozystack.io/transit-unsealand ensures, per instance, a transit key, an unseal policy scoped to that key, and a kubernetes-auth role bound to the instance's server ServiceAccount. It then publishes the central CA as the<name>-transit-caConfigMap, a public certificate rather than a Secret. No token is minted or delivered: the instance exchanges its own projected ServiceAccount token for a transit token at every boot, so there is no long-lived credential in the tenant namespace to store, rotate or leak. Nothing emits that label yet, so the reconciler is inert until the tenant chart grows a transit seal.One cost to be explicit about rather than discover later: this installs a platform OpenBAO on every paas install, and with the tenant default in the next PR being the transit seal it cannot be made opt-in without breaking that default. Three replicas is the default and one is supported, so a small install can pay less, but it does pay something.
Not in this PR, and deliberately: the tenant seal stanza, the auto-init Job on the tenant side, the migration that pins existing instances, and the e2e. Those are the next PR, which also needs #4168 for the
seal.typeenum it extends with a third value.Verified:
make unit-testsgreen on this branch,go build ./...andgo test ./internal/operator/...clean, the central package renders at 1, 3 and 5 replicas and refuses 0, and the new suite was mutation checked (turning TLS off, keeping the anti-affinity at one replica and allowing a self join each turn a test red).Screenshots
No UI change.
Downstream repositories
Walked the trigger map in
docs/agents/contributing.mdagainst the diff. One hit, left unticked because the follow-up is not filed yet and I would rather a human decide whether it belongs onnextnow or with the tenant half: this adds a platform component, which the map routes to the website'scontent/en/docs/next/guides/platform-stack/_index.mdandoperations/configuration/licenses.md.Nothing else matches. The package is under
packages/system/, notpackages/apps/orpackages/extra/, so no reference page is generated for it and the websiteMakefileapp lists are unaffected. No appvalues.schema.json, noApplicationDefinition, norelease.prefix, no version enum and no hand-typed CRD changed, so terraform-provider-cozystack has nothing to mirror.packages/core/installer/values.yaml, the platform variants and the node prerequisites are untouched, so ansible-cozystack is unaffected. Thepackages/{apps,system,extra,core}split, thehack/layout and thecozy-*namespace names are unchanged, so ccp keeps its anchors.Release note