feat: Add fine-grained aggregatable ClusterRoles for RBAC#852
Conversation
3c8ea82 to
430eaa2
Compare
|
@Melonbun233 Hello. Please sign the DCO :) Thanks. |
Skarlso
left a comment
There was a problem hiding this comment.
There are a few things that needs cleanup and restructuring. Thanks for the PR! :)
deploy/templates/role.yaml
Outdated
| labels: {{ $.Values.manager.clusterRole.labels | toJson }} | ||
| labels: | ||
| {{- if .Values.manager.clusterRole.labels }} | ||
| {{- toYaml .Values.manager.clusterRole.labels | nindent 4 }} | ||
| {{- end }} |
There was a problem hiding this comment.
This is a change that will trigger any gitops flow because it changes how the labels are set from json to yaml.
I would recommend keeping the JSON format. We could also try and talk to people about this first, create a minor version, and explicit document that updating will trigger a flurry of updates through gitops flow. Any particular reason for this change?
There was a problem hiding this comment.
I reverted back to the Json format.
deploy/values.yaml
Outdated
| coreReader: | ||
| enabled: true | ||
| aggregateToView: true | ||
| aggregateToController: true |
There was a problem hiding this comment.
You aren't using aggregateToController. You hardcoded adding ocm.software/aggregate-to-controller: "true" everywhere. So someone setting this to false won't actually do anything.
There was a problem hiding this comment.
Thanks, I removed the this control because OCM controller need the fine grained roles the same as the legacy behavior.
| {{- if .Values.manager.clusterRole.aggregation.enabled }} | ||
| {{- /* AGGREGATION MODE: Create fine-grained ClusterRoles */ -}} | ||
|
|
||
| --- |
There was a problem hiding this comment.
If nothing is enabled, these separators will end up as:
---
---
---Move them inside the if statements.
There was a problem hiding this comment.
Thanks for the comment. I moved all the separators into the if statements.
deploy/values.yaml
Outdated
| admin: | ||
| # Admin inherits from edit automatically in K8s | ||
| # This setting has no effect (included for documentation) | ||
| enabled: false |
There was a problem hiding this comment.
I don't see any purpose of this even if documented. If something is there, it needs a purpose. If it doesn't have any, just remove it.
There was a problem hiding this comment.
Thanks, the admin has been removed.
deploy/templates/role.yaml
Outdated
|
|
||
| --- | ||
| # 5. OCM Writer - Full management of OCM CRDs | ||
| {{- if .Values.manager.clusterRole.aggregation.roles.ocmWriter.enabled }} |
There was a problem hiding this comment.
These rules are supposed to be additive. All your writing rules including reading permissions. These should ONLY be in the reading rules. Then, you combine reading with writing, where writing provides ONLY writing rules. So move out any duplications from the write rules that have reading permissions so these rules can then be combined which is the whole purpose of aggregation. Same goes for fluxReading and fluxWriting.
There was a problem hiding this comment.
Thanks for the comment. I removed the reading rules in the writing roles so there's no duplications.
deploy/templates/role.yaml
Outdated
| {{- define "ocm-controller.aggregationLabels" -}} | ||
| {{- $config := .config -}} | ||
| ocm.software/aggregate-to-controller: "true" | ||
| {{- if and (hasKey $config "aggregateToView") $config.aggregateToView }} |
There was a problem hiding this comment.
Instead of using 'and ( hasKey ... ) for the safely checking aggregateToEdit you should be able to use 'dig'.
e.g.
dig "aggregateToEdit" "" $config
This will give you the value of aggregateToEdit if it is present or empty string if it is not.
There was a problem hiding this comment.
Thanks for the review. I changed to the dig function instead.
dee0sap
left a comment
There was a problem hiding this comment.
While this seems a bit overly complex I do think it work.
So, I approve but of course the OCM team is going to have to weigh in :)
This commit addresses all feedback from PR open-component-model#852 review: 1. Fix YAML separator placement - Move separators inside conditional blocks to prevent orphaned `---` - Separators now only appear when roles are actually rendered 2. Remove duplicate read permissions from write roles - Removed get/list/watch verbs from all writer roles - Writers now only contain write verbs (create, delete, patch, update) - Enables proper aggregation: reader + writer = full access - Affected roles: core-writer, ocm-writer, flux-writer-source, flux-writer-deploy 3. Maintain consistent label formatting - Reverted to original `toJson` format instead of `toYaml` - Prevents triggering GitOps reconciliation on label changes - Maintains backward compatibility 4. Remove non-functional admin.enabled field - Kubernetes admin role inherits from edit automatically - Configuration field had no effect and caused confusion 5. Make aggregateToController flag functional - Added conditional check in helper template - Label now respects user configuration instead of being hardcoded - Users can disable controller aggregation per role if needed Testing: - Legacy mode renders correctly (backward compatible) - Aggregation mode renders 9 ClusterRoles properly - No orphaned YAML separators - Write roles contain only write verbs - aggregateToController flag works as expected Related: open-component-model#852 Signed-off-by: Henry Zeng <zeng_zh@foxmail.com>
This commit implements support for Kubernetes ClusterRole aggregation
to enable more flexible RBAC configurations. The monolithic ClusterRole
has been refactored into 9 fine-grained roles that can be selectively
aggregated to standard K8s roles (view, edit, admin).
Key features:
- Separate ClusterRoles for read vs write permissions
- Isolated secrets access (not aggregated to view role by default)
- Configurable aggregation via values.yaml
- 100% backward compatible (aggregation disabled by default)
This enables use cases such as:
- Grant read-only access to OCM/Flux CRDs without exposing secrets
- Compose custom permission sets for different user personas
- Follow Kubernetes RBAC best practices
The 9 ClusterRoles created in aggregation mode:
1. ocm-controller-core-reader - Read configmaps & serviceaccounts
2. ocm-controller-secrets-reader - Read secrets (isolated)
3. ocm-controller-core-writer - Manage pods, services, deployments
4. ocm-controller-ocm-reader - Read OCM CRDs
5. ocm-controller-ocm-writer - Manage OCM CRDs
6. ocm-controller-flux-reader - Read Flux source CRDs
7. ocm-controller-flux-writer-source - Manage Flux source repos
8. ocm-controller-flux-writer-deploy - Manage Flux deployments
9. ocm-controller-manager-role - Main aggregating role
Configuration example:
```yaml
manager:
clusterRole:
aggregation:
enabled: true
standardRoles:
view:
enabled: true
```
Fixes open-component-model/ocm#1848
Signed-off-by: Henry Zeng <zeng_zh@foxmail.com>
This commit addresses all feedback from PR open-component-model#852 review: 1. Fix YAML separator placement - Move separators inside conditional blocks to prevent orphaned `---` - Separators now only appear when roles are actually rendered 2. Remove duplicate read permissions from write roles - Removed get/list/watch verbs from all writer roles - Writers now only contain write verbs (create, delete, patch, update) - Enables proper aggregation: reader + writer = full access - Affected roles: core-writer, ocm-writer, flux-writer-source, flux-writer-deploy 3. Maintain consistent label formatting - Reverted to original `toJson` format instead of `toYaml` - Prevents triggering GitOps reconciliation on label changes - Maintains backward compatibility 4. Remove non-functional admin.enabled field - Kubernetes admin role inherits from edit automatically - Configuration field had no effect and caused confusion 5. Make aggregateToController flag functional - Added conditional check in helper template - Label now respects user configuration instead of being hardcoded - Users can disable controller aggregation per role if needed Testing: - Legacy mode renders correctly (backward compatible) - Aggregation mode renders 9 ClusterRoles properly - No orphaned YAML separators - Write roles contain only write verbs - aggregateToController flag works as expected Related: open-component-model#852 Signed-off-by: Henry Zeng <zeng_zh@foxmail.com>
Replace 'and (hasKey ...)' pattern with idiomatic 'dig' function for checking aggregation flags. This is the Helm best practice for safely accessing potentially missing keys. Benefits: - Cleaner, more readable syntax - Single function call instead of nested conditions - Safer with explicit default values - More idiomatic Helm template code All three aggregation flags now use consistent pattern: - aggregateToController: dig "aggregateToController" false $config - aggregateToView: dig "aggregateToView" false $config - aggregateToEdit: dig "aggregateToEdit" false $config Signed-off-by: Henry Zeng <zeng_zh@foxmail.com>
Remove aggregateToController configuration flag and always apply the controller aggregation label to all fine-grained roles. Rationale: - The controller ALWAYS needs all permissions from fine-grained roles - Making this configurable adds unnecessary complexity - Users should not be able to disable controller permissions - Simplifies configuration by removing 8 redundant flags Changes: - Removed conditional check for aggregateToController in helper template - Label 'ocm.software/aggregate-to-controller: true' is now always added - Removed aggregateToController field from all 8 roles in values.yaml - Controller will always receive full aggregated permissions This ensures the controller functions correctly regardless of user configuration while still allowing users to control view/edit aggregation. Signed-off-by: Henry Zeng <zeng_zh@foxmail.com>
e972689 to
5da7d68
Compare
|
Thanks for the changes 🙇 |
Merge the two Flux writer roles (flux-writer-source and flux-writer-deploy) into a single flux-writer role for simplicity and consistency. Expand flux-reader to include read access to all Flux resources: - helmrepositories and ocirepositories (previously write-only) - helmreleases and kustomizations (previously write-only) This provides a cleaner separation: - flux-reader: read access to ALL Flux CRDs - flux-writer: write access to ALL Flux CRDs Changes: - Merged ocm-controller-flux-writer-source and ocm-controller-flux-writer-deploy into single ocm-controller-flux-writer role - Added helmrepositories, ocirepositories, helmreleases, and kustomizations to flux-reader with get/list/watch permissions - Updated role count from 9 to 8 (7 fine-grained + 1 main) - Simplified values.yaml configuration (removed fluxWriterSource and fluxWriterDeploy, added single fluxWriter) Benefits: - Simpler configuration with fewer roles to manage - Consistent pattern: one reader + one writer per functional area - Users can grant read-only Flux access without complexity - Easier to understand and maintain Signed-off-by: Henry Zeng <zeng_zh@foxmail.com>
Description
This PR implements fine-grained aggregatable ClusterRoles to enable flexible Kubernetes RBAC configurations using the standard ClusterRole aggregation pattern.
Fixes open-component-model/ocm#1848
Problem Statement
The current monolithic ClusterRole consolidates all permissions (secrets, configmaps, OCM CRDs, Flux CRDs) into a single role, making it impossible to:
Solution
This PR refactors the ClusterRole into 8 fine-grained roles that can be selectively aggregated to standard K8s roles (
view,edit,admin):Fine-Grained ClusterRoles
Key Features
viewrolevalues.yamlConfiguration
Example 1: Grant read-only CRD access without secrets (the requested use case)
Result: Users with the
viewClusterRole can:Example 2: Default behavior (backward compatible)
Result: Uses the existing monolithic ClusterRole. Zero impact on existing deployments.
Example 3: Advanced configuration
Changes Made
1. Updated
deploy/values.yamlmanager.clusterRole.aggregationconfiguration sectionenabled: falsefor backward compatibilityadmin.enabledfield (admin inherits from edit automatically)fluxWriterSourceandfluxWriterDeployinto singlefluxWriter2. Refactored
deploy/templates/role.yamlaggregation.enabledflag---toJsonformat for backward compatibility (prevents GitOps reconciliation)digfunction: Idiomatic Helm pattern for safe key access instead ofhasKeyocm.software/aggregate-to-controller: "true"label3. Verified
deploy/templates/role_binding.yamlocm-controller-manager-roleReview Feedback Addressed
All feedback from @Skarlso has been addressed:
---toJsonformat instead oftoYamlfor backward compatibilityadmin.enabledfrom values.yamland (hasKey ...)with idiomaticdigfunction for safer key accessTesting
Helm templates validated in multiple configurations:
✅ Test 1: Legacy Mode (Default)
✅ Test 2: Aggregation Mode (All defaults)
aggregationRulewith selectorocm.software/aggregate-to-controller: "true"rbac.authorization.k8s.io/aggregate-to-view: "true"label (when enabled)✅ Test 3: Flux Reader Permissions
✅ Test 4: Flux Writer Permissions
✅ Test 5: View Aggregation Control
aggregate-to-viewlabels applied when disabled✅ Test 6: Individual Role Control
✅ Test 7: Edit Aggregation
editwhen configuredMigration Path
aggregation.enabled: trueBenefits
Checklist
Related Documentation