Repository navigation
feat: share a resource in named namespaces alone - #47
Conversation
-shared-watch-namespaced-resources (chart: sharedWatches.namespacedResources) shares a resource in the namespaces named for it, for an identity granted it there with a Role, never a ClusterRole. A stream of it in any other namespace, or across every namespace, is the user's own and never reaches the shared identity. For RoleBindings: an application can watch the grants in its own namespace without the shared identity reading every grant in the cluster. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 52 minutes. View limit details
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Parse configuration and select streams internal/stream/shared.go, internal/stream/shared_test.go |
The stream configuration accepts comma-separated namespace/resource entries and groups repeated resources by namespace. Namespaced resources use the shared stream only in configured namespaces; other scopes use the user stream. Tests cover parsing, validation, stream selection, and authorization scope. |
Configure namespaced watches in the CLI cmd/krm-foyer/main.go, cmd/krm-foyer/main_test.go, docs/design.md, docs/watches.md |
The CLI adds -shared-watch-namespaced-resources, validates it with the other shared-watch options, and includes the parsed entries in SharedConfig. Tests cover valid and rejected configurations. Documentation describes scope selection and authorization behavior. |
Render namespace-scoped chart permissions charts/krm-foyer/values.schema.json, charts/krm-foyer/values.yaml, charts/krm-foyer/templates/*, charts/krm-foyer/README.md, cmd/krm-foyer/chart_test.go |
The chart accepts namespace-to-resource mappings and passes them to the application. It renders a Role and RoleBinding in each configured namespace, while cluster-scoped RBAC is conditional on cluster-wide resources. Chart tests check validation, rendered permissions, and application configuration. |
Priority:
Estimated code review effort: 3 (Moderate) | ~25 minutes
Change: Feature
Sequence Diagram(s)
sequenceDiagram
participant RequestScope
participant serves
participant SharedWatch
participant UserStream
RequestScope->>serves: Match resource and namespace
alt Namespace is configured
serves->>SharedWatch: Select shared identity
else Namespace is not configured or scope is all namespaces
serves->>UserStream: Select user identity
end
Merge Risk: 
Minimal · previous review eb2dc
-
The namespace-scoped watch change is mergeable after normal checks; no concrete blocking issue was identified.
Pre-merge checks: 
4 · 
1
-
Failed checks: 1 warning Passed checks: 4 passedFull details: Docstring Coverage
-
Explanation
Docstring coverage is 72.73% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 11 functions across 5 files. (7 skipped: 7 unsupported.)
Resolution
Write docstrings for the functions missing them to satisfy the coverage threshold.
-
Finishing Touches: 💡 1
-
📝 Generate docstrings: 💡
-
- Commit to this branch
- Create a new PR
🧪 Generate unit tests (beta)
-
- Commit to this branch
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Thanks 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 @coderabbitai help to get the list of available commands.
|
e2e is green on this code ( |
…paces The e2e fixture shares RoleBindings in foyer-shared alone. One spec opens them there, in another namespace, and across every namespace, as a user allowed in the shared namespace only and as one allowed in the other. It checks the streams' contents, the watch metrics, SubjectAccessReviews of the shared identity, and the audit log: the identity read RoleBindings in foyer-shared and nowhere else. Mutation-checked: with serves() ignoring the namespace, it fails. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Full e2e suite green at |
Lets a resource be shared in named namespaces only, for an identity granted it there with a Role, never a ClusterRole. The motivating case is RoleBindings: Voter wants to watch the grants in its own namespace (
voter), so a phone asks "what may I do?" again only when a grant changes, instead of polling a rules review every 4 s. Today, sharingrolebindingswould give the shared identity a ClusterRole that reads every grant in the cluster.docs/watches.mdalready names that as the reason krm-foyer doesn't watch RBAC.1.
-shared-watch-namespaced-resourcesvoter/rolebindings.rbac.authorization.k8s.io. Comma-separatednamespace/resource; the namespaces of one resource are gathered.serves(scope)sends a stream of such a resource to the shared watch only in its namespaces. In any other namespace, and across every namespace at once (nonamespace), the stream is the user's own, opened with their token, as for a resource not shared. The shared identity has no grant there, so routing it there would have been a terminalINTERNAL.GroupResourcenever hasAllowAllNamespaces. The parser andnewSharedboth force that off.-shared-watch-token-file, or without the sign-in flags.2. Chart:
sharedWatches.namespacedResourcesRoleandRoleBindingnamed<shared>-watchesin each namespace, withlist/watchon exactly those resources, plus the flag.-watchesClusterRole and ClusterRoleBinding render only whensharedWatches.resourcesis non-empty. A namespaced-only install has no cluster-wide watch grant at all, just the reviews ClusterRole.3. Tests
TestANamespacedResourceIsSharedInItsNamespacesAloneopens the resource in its namespace (twice), in another namespace and across all namespaces. It checks that only the first two use the shared token and the shared watch, that the others go with the user's token, and that no SubjectAccessReview is sent about any namespace but the shared one. Mutation-checked: withservesignoring the namespace, it fails.TestParseNamespacedResources: gathering, refusals, andNewrefusing both-lists and no-namespace configs.TestParseConfigSharedWatches/TestParseConfigRefuses: the flag on its own, plus the new refusals.TestChartGrantsANamespacedResourceInItsNamespacesAlone: covers the Roles and RoleBindings per namespace, the absence of any ClusterRole rule for those resources, and krm-foyer being told the same namespaces (round-tripped throughparseRendered).shares a namespaced resource in its namespace alone, and shows nothing of any other). The fixture now sharesrolebindingsin a fixedfoyer-sharednamespace. Each namespace holds a RoleBinding with a unique marker name. One spec checks:foyer-sharedonly: her stream there is served from the shared watch (shared-watch gauge +1) and contains that namespace's marker, never the other one.FORBIDDEN, with neither the marker nor the shared account's name in the stream. In the audit log, every request it led to was sent as alice, including the watch of that namespace's RoleBindings.foyer-shared./namespaces/foyer-shared/rolebindings.servesignores the namespace fails this spec. The routing of alice's request into another namespace goes through the shared path.4. Docs
docs/design.md(Shared watches) states the contract.docs/watches.mdhas a new section, "Shared in some namespaces only", plus updates to the identity's needs and to "Why not check only when something changes?".values.yamlcomments are updated.Validation
go test -race ./..., fuzz runs,node --test,helm lint, tidy and image smoke are green ateb2dc9d.eb2dc9d(comment below). The new spec passed at5e4fef4, and the full suite with it is running.golangci-lintlocally reportserrcheckatinternal/stream/stream_test.go:299(<-done). That line isn't touched here, and it fails the same way onmain: the devcontainer has golangci-lint 2.15.0, while CI pins 2.13.2. Left for a separate change.🤖 Generated with Claude Code
Summary by CodeRabbit