Skip to content

Commit 693a43c

Browse files
authored
fix(rbac): permit managed ServiceMonitor reconciliation (#479)
Signed-off-by: Roel de Cort <roel.decort@adfinis.com>
1 parent 1249adc commit 693a43c

21 files changed

Lines changed: 1970 additions & 19 deletions

File tree

charts/openbao-operator/templates/admission/lock-managed-resources.yaml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,55 @@ spec:
144144
- name: is_service_request
145145
expression: >-
146146
request.kind.group == "" && request.kind.kind == "Service"
147+
- name: is_service_monitor_request
148+
expression: >-
149+
request.kind.group == "monitoring.coreos.com" && request.kind.kind == "ServiceMonitor"
150+
- name: current_service_monitor_is_operator_owned
151+
expression: >-
152+
object != null &&
153+
has(object.metadata) &&
154+
request.namespace != "" &&
155+
object.metadata.name.endsWith("-metrics") &&
156+
has(object.metadata.labels) &&
157+
("app.kubernetes.io/managed-by" in object.metadata.labels) &&
158+
object.metadata.labels["app.kubernetes.io/managed-by"] == "openbao-operator" &&
159+
("app.kubernetes.io/component" in object.metadata.labels) &&
160+
object.metadata.labels["app.kubernetes.io/component"] == "metrics" &&
161+
("openbao.org/component" in object.metadata.labels) &&
162+
object.metadata.labels["openbao.org/component"] == "metrics" &&
163+
("openbao.org/cluster" in object.metadata.labels) &&
164+
object.metadata.labels["openbao.org/cluster"] != "" &&
165+
object.metadata.name == object.metadata.labels["openbao.org/cluster"] + "-metrics" &&
166+
has(object.metadata.ownerReferences) &&
167+
object.metadata.ownerReferences.exists(ref,
168+
ref.apiVersion == "openbao.org/v1alpha1" &&
169+
ref.kind == "OpenBaoCluster" &&
170+
ref.name == object.metadata.labels["openbao.org/cluster"] &&
171+
has(ref.controller) &&
172+
ref.controller == true)
173+
- name: old_service_monitor_is_operator_owned
174+
expression: >-
175+
oldObject != null &&
176+
has(oldObject.metadata) &&
177+
request.namespace != "" &&
178+
oldObject.metadata.name.endsWith("-metrics") &&
179+
has(oldObject.metadata.labels) &&
180+
("app.kubernetes.io/managed-by" in oldObject.metadata.labels) &&
181+
oldObject.metadata.labels["app.kubernetes.io/managed-by"] == "openbao-operator" &&
182+
("app.kubernetes.io/component" in oldObject.metadata.labels) &&
183+
oldObject.metadata.labels["app.kubernetes.io/component"] == "metrics" &&
184+
("openbao.org/component" in oldObject.metadata.labels) &&
185+
oldObject.metadata.labels["openbao.org/component"] == "metrics" &&
186+
("openbao.org/cluster" in oldObject.metadata.labels) &&
187+
oldObject.metadata.labels["openbao.org/cluster"] != "" &&
188+
oldObject.metadata.name == oldObject.metadata.labels["openbao.org/cluster"] + "-metrics" &&
189+
has(oldObject.metadata.ownerReferences) &&
190+
oldObject.metadata.ownerReferences.exists(ref,
191+
ref.apiVersion == "openbao.org/v1alpha1" &&
192+
ref.kind == "OpenBaoCluster" &&
193+
ref.name == oldObject.metadata.labels["openbao.org/cluster"] &&
194+
has(ref.controller) &&
195+
ref.controller == true)
147196
- name: is_kubelet_node
148197
expression: >-
149198
request.userInfo.username.startsWith("system:node:")
@@ -295,6 +344,15 @@ spec:
295344
check("maintenance").
296345
allowed()
297346
validations:
347+
- expression: >-
348+
!(variables.is_operator_controller || variables.is_operator_provisioner) ||
349+
!variables.is_service_monitor_request ||
350+
(
351+
(request.operation == "CREATE" && variables.current_service_monitor_is_operator_owned) ||
352+
(request.operation == "UPDATE" && variables.current_service_monitor_is_operator_owned && variables.old_service_monitor_is_operator_owned) ||
353+
(request.operation == "DELETE" && variables.old_service_monitor_is_operator_owned)
354+
)
355+
message: The operator can only create, update, or delete ServiceMonitors that match the OpenBao metrics ownership shape.
298356
- expression: >-
299357
!variables.is_managed ||
300358
variables.is_operator_controller ||

charts/openbao-operator/templates/admission/provisioner-rbac.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,15 @@ spec:
194194
rule.verbs != null &&
195195
rule.verbs.all(v, v in ['create', 'delete', 'get', 'list', 'patch', 'update', 'watch'])
196196
) ||
197+
(
198+
rule.apiGroups.size() == 1 &&
199+
rule.apiGroups[0] == 'monitoring.coreos.com' &&
200+
rule.resources != null &&
201+
rule.resources.size() == 1 &&
202+
rule.resources[0] == 'servicemonitors' &&
203+
rule.verbs != null &&
204+
rule.verbs.all(v, v in ['create', 'delete', 'get', 'patch'])
205+
) ||
197206
(
198207
rule.apiGroups.size() == 1 &&
199208
rule.apiGroups[0] == 'rbac.authorization.k8s.io' &&

charts/openbao-operator/templates/rbac/single-tenant-clusterrole.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,15 @@ rules:
164164
- update
165165
- watch{{- end }}
166166

167+
- apiGroups:
168+
- monitoring.coreos.com
169+
resources:
170+
- servicemonitors
171+
verbs:
172+
- create
173+
- delete
174+
- get
175+
- patch
167176
- apiGroups:
168177
- rbac.authorization.k8s.io
169178
resources:

config/overlays/single-tenant-custom-identity/single_tenant_clusterrole.yaml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,7 @@ rules:
2323
- create
2424
- delete
2525
- get
26-
- list
2726
- patch
28-
- update
29-
- watch
3027
- apiGroups:
3128
- openbao.org
3229
resources:
@@ -168,6 +165,15 @@ rules:
168165
- patch
169166
- update
170167
- watch
168+
- apiGroups:
169+
- monitoring.coreos.com
170+
resources:
171+
- servicemonitors
172+
verbs:
173+
- create
174+
- delete
175+
- get
176+
- patch
171177
- apiGroups:
172178
- rbac.authorization.k8s.io
173179
resources:

config/overlays/single-tenant/single_tenant_clusterrole.yaml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,7 @@ rules:
2323
- create
2424
- delete
2525
- get
26-
- list
2726
- patch
28-
- update
29-
- watch
3027
- apiGroups:
3128
- openbao.org
3229
resources:
@@ -168,6 +165,15 @@ rules:
168165
- patch
169166
- update
170167
- watch
168+
- apiGroups:
169+
- monitoring.coreos.com
170+
resources:
171+
- servicemonitors
172+
verbs:
173+
- create
174+
- delete
175+
- get
176+
- patch
171177
- apiGroups:
172178
- rbac.authorization.k8s.io
173179
resources:

config/policy/openbao-lock-managed-resource-mutations.yaml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,55 @@ spec:
141141
- name: is_service_request
142142
expression: >-
143143
request.kind.group == "" && request.kind.kind == "Service"
144+
- name: is_service_monitor_request
145+
expression: >-
146+
request.kind.group == "monitoring.coreos.com" && request.kind.kind == "ServiceMonitor"
147+
- name: current_service_monitor_is_operator_owned
148+
expression: >-
149+
object != null &&
150+
has(object.metadata) &&
151+
request.namespace != "" &&
152+
object.metadata.name.endsWith("-metrics") &&
153+
has(object.metadata.labels) &&
154+
("app.kubernetes.io/managed-by" in object.metadata.labels) &&
155+
object.metadata.labels["app.kubernetes.io/managed-by"] == "openbao-operator" &&
156+
("app.kubernetes.io/component" in object.metadata.labels) &&
157+
object.metadata.labels["app.kubernetes.io/component"] == "metrics" &&
158+
("openbao.org/component" in object.metadata.labels) &&
159+
object.metadata.labels["openbao.org/component"] == "metrics" &&
160+
("openbao.org/cluster" in object.metadata.labels) &&
161+
object.metadata.labels["openbao.org/cluster"] != "" &&
162+
object.metadata.name == object.metadata.labels["openbao.org/cluster"] + "-metrics" &&
163+
has(object.metadata.ownerReferences) &&
164+
object.metadata.ownerReferences.exists(ref,
165+
ref.apiVersion == "openbao.org/v1alpha1" &&
166+
ref.kind == "OpenBaoCluster" &&
167+
ref.name == object.metadata.labels["openbao.org/cluster"] &&
168+
has(ref.controller) &&
169+
ref.controller == true)
170+
- name: old_service_monitor_is_operator_owned
171+
expression: >-
172+
oldObject != null &&
173+
has(oldObject.metadata) &&
174+
request.namespace != "" &&
175+
oldObject.metadata.name.endsWith("-metrics") &&
176+
has(oldObject.metadata.labels) &&
177+
("app.kubernetes.io/managed-by" in oldObject.metadata.labels) &&
178+
oldObject.metadata.labels["app.kubernetes.io/managed-by"] == "openbao-operator" &&
179+
("app.kubernetes.io/component" in oldObject.metadata.labels) &&
180+
oldObject.metadata.labels["app.kubernetes.io/component"] == "metrics" &&
181+
("openbao.org/component" in oldObject.metadata.labels) &&
182+
oldObject.metadata.labels["openbao.org/component"] == "metrics" &&
183+
("openbao.org/cluster" in oldObject.metadata.labels) &&
184+
oldObject.metadata.labels["openbao.org/cluster"] != "" &&
185+
oldObject.metadata.name == oldObject.metadata.labels["openbao.org/cluster"] + "-metrics" &&
186+
has(oldObject.metadata.ownerReferences) &&
187+
oldObject.metadata.ownerReferences.exists(ref,
188+
ref.apiVersion == "openbao.org/v1alpha1" &&
189+
ref.kind == "OpenBaoCluster" &&
190+
ref.name == oldObject.metadata.labels["openbao.org/cluster"] &&
191+
has(ref.controller) &&
192+
ref.controller == true)
144193
- name: is_kubelet_node
145194
expression: >-
146195
request.userInfo.username.startsWith("system:node:")
@@ -292,6 +341,15 @@ spec:
292341
check("maintenance").
293342
allowed()
294343
validations:
344+
- expression: >-
345+
!(variables.is_operator_controller || variables.is_operator_provisioner) ||
346+
!variables.is_service_monitor_request ||
347+
(
348+
(request.operation == "CREATE" && variables.current_service_monitor_is_operator_owned) ||
349+
(request.operation == "UPDATE" && variables.current_service_monitor_is_operator_owned && variables.old_service_monitor_is_operator_owned) ||
350+
(request.operation == "DELETE" && variables.old_service_monitor_is_operator_owned)
351+
)
352+
message: The operator can only create, update, or delete ServiceMonitors that match the OpenBao metrics ownership shape.
295353
- expression: >-
296354
!variables.is_managed ||
297355
variables.is_operator_controller ||

config/policy/openbao-restrict-provisioner-rbac.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,15 @@ spec:
191191
rule.verbs != null &&
192192
rule.verbs.all(v, v in ['create', 'delete', 'get', 'list', 'patch', 'update', 'watch'])
193193
) ||
194+
(
195+
rule.apiGroups.size() == 1 &&
196+
rule.apiGroups[0] == 'monitoring.coreos.com' &&
197+
rule.resources != null &&
198+
rule.resources.size() == 1 &&
199+
rule.resources[0] == 'servicemonitors' &&
200+
rule.verbs != null &&
201+
rule.verbs.all(v, v in ['create', 'delete', 'get', 'patch'])
202+
) ||
194203
(
195204
rule.apiGroups.size() == 1 &&
196205
rule.apiGroups[0] == 'rbac.authorization.k8s.io' &&

config/rbac/single_tenant_clusterrole.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,16 @@ rules:
190190
- patch
191191
- update
192192
- watch
193+
# Observability
194+
- apiGroups:
195+
- monitoring.coreos.com
196+
resources:
197+
- servicemonitors
198+
verbs:
199+
- create
200+
- delete
201+
- get
202+
- patch
193203
# RBAC for OpenBao pod discovery
194204
- apiGroups:
195205
- rbac.authorization.k8s.io

docs/security/infrastructure/rbac.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ The provisioner writes the RBAC that grants the controller access, but it does n
150150
{
151151
cells: [
152152
'Manage tenant-scoped workload resources',
153-
'StatefulSets, Services, ConfigMaps, Jobs, and related resources are the normal lifecycle surface.',
153+
'StatefulSets, Services, ConfigMaps, Jobs, ServiceMonitors, and related resources are the normal lifecycle surface.',
154154
'This access only exists where the provisioner already introduced the controller via RoleBinding.',
155155
],
156156
},

docs/user-guide/openbaocluster/configuration/observability.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,12 @@ spec:
303303
Keep the first alert set small. Availability, backup freshness, sustained read-pool degradation, and sustained reconcile failure are the highest-value starting signals.
304304
</CommandBlock>
305305

306+
<Callout type="note" title="Alert rules are not operator-managed">
307+
308+
The OpenBaoCluster controller manages the workload `ServiceMonitor` when `spec.observability.metrics` enables it. `PrometheusRule` resources are user-applied observability objects, so the ServiceAccount or GitOps controller applying the alert rules needs `monitoring.coreos.com` `prometheusrules` permissions in that namespace.
309+
310+
</Callout>
311+
306312
## Dashboards, logs, and health
307313

308314
<CommandBlock

0 commit comments

Comments
 (0)