Summary
The COS controller currently uses the olm.operatorframework.io/owner-name label to group revisions and manage succession (archiving previous revisions after a new one succeeds). This should be replaced with an immutable, required spec.group field, making revision grouping a first-class API concept rather than a label convention.
Motivation
The label-based grouping has two problems:
- It's not part of the API contract — labels are metadata, not schema-validated fields. Nothing prevents a label from being omitted, changed, or set incorrectly.
- No authorization boundary — any actor that can create a COS can set the owner-name label to any value, allowing them to inject revisions into another actor's group and take over object ownership.
Proposal
1. Add spec.group field
Add a required, immutable string field spec.group to ClusterObjectSetSpec:
- Required on creation
- Immutable after creation (CEL validation rule:
self == oldSelf)
- Used by
listPreviousRevisions to find sibling revisions (replaces the label selector on olm.operatorframework.io/owner-name)
2. Update listPreviousRevisions
Change from:
client.MatchingLabels{labels.OwnerNameKey: ownerLabel}
To matching on spec.group (via field selector or filtered list).
3. Per-group authorization via VAP + RBAC
Document (and optionally ship) a ValidatingAdmissionPolicy that enforces group-level authorization using the CEL authorizer API:
validations:
- expression: >
authorizer.group('olm.operatorframework.io')
.resource('clusterobjectsets')
.subresource('groups')
.name(object.spec.group)
.check('manage').allowed
message: "user is not authorized to manage revisions in this group"
Cluster admins grant per-group access via RBAC:
# Scoped: can only manage revisions in the "widget-operator" group
rules:
- apiGroups: ["olm.operatorframework.io"]
resources: ["clusterobjectsets/groups"]
resourceNames: ["widget-operator"]
verbs: ["manage"]
# ClusterExtension SA: can manage all groups
rules:
- apiGroups: ["olm.operatorframework.io"]
resources: ["clusterobjectsets/groups"]
verbs: ["manage"]
4. Auto-incrementing revision via mutating webhook
Optionally ship a mutating webhook that auto-increments spec.revision when unset on CREATE:
- Query existing COS with the same
spec.group
- Set
spec.revision to max existing revision + 1
- Use leader election to avoid races across webhook replicas
This allows clients to create COS without knowing the current revision state.
Migration
Existing COS objects created by ClusterExtension use the olm.operatorframework.io/owner-name label. Migration path:
- Backfill
spec.group from the existing label value
- Remove label-based lookup after migration
Note: Duplicate revisions within a group (two COS with the same spec.group and spec.revision) should be validated against — either via VAP or webhook. Currently, duplicates cause both COS controllers to fight over object ownership via SSA, creating an infinite reconcile loop and unnecessary API server load. Neither revision backs off because boxcutter only yields to higher revision numbers.
Summary
The COS controller currently uses the
olm.operatorframework.io/owner-namelabel to group revisions and manage succession (archiving previous revisions after a new one succeeds). This should be replaced with an immutable, requiredspec.groupfield, making revision grouping a first-class API concept rather than a label convention.Motivation
The label-based grouping has two problems:
Proposal
1. Add
spec.groupfieldAdd a required, immutable string field
spec.grouptoClusterObjectSetSpec:self == oldSelf)listPreviousRevisionsto find sibling revisions (replaces the label selector onolm.operatorframework.io/owner-name)2. Update
listPreviousRevisionsChange from:
To matching on
spec.group(via field selector or filtered list).3. Per-group authorization via VAP + RBAC
Document (and optionally ship) a
ValidatingAdmissionPolicythat enforces group-level authorization using the CELauthorizerAPI:Cluster admins grant per-group access via RBAC:
4. Auto-incrementing revision via mutating webhook
Optionally ship a mutating webhook that auto-increments
spec.revisionwhen unset on CREATE:spec.groupspec.revisionto max existing revision + 1This allows clients to create COS without knowing the current revision state.
Migration
Existing COS objects created by ClusterExtension use the
olm.operatorframework.io/owner-namelabel. Migration path:spec.groupfrom the existing label value