Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,42 @@ make deploy IMG=ghcr.io/openclaw-rocks/openclaw-operator:latest

</details>

<details>
<summary>Restrict the operator to specific namespaces</summary>

To run the operator with namespaced RBAC instead of cluster-wide permissions,
list the namespaces it should watch. The chart switches from
`ClusterRole`/`ClusterRoleBinding` to per-namespace `Role`/`RoleBinding`, and
passes `--watch-namespaces` to the operator so its informer cache is scoped
to that list (plus the operator's own namespace, for backup credentials).

```bash
helm install openclaw-operator \
oci://ghcr.io/openclaw-rocks/charts/openclaw-operator \
--namespace openclaw-operator-system \
--create-namespace \
--set 'watchNamespaces={team-a,team-b}'
```

Each listed namespace must already exist; the chart does not create them.

To bring your own RBAC entirely (e.g. managed by a separate controller or
SecurityCenter policy), disable chart-managed RBAC:

```bash
helm install openclaw-operator \
oci://ghcr.io/openclaw-rocks/charts/openclaw-operator \
--namespace openclaw-operator-system \
--create-namespace \
--set rbac.create=false
```

The kubebuilder markers in `internal/controller/` and the manager rules helper
at `charts/openclaw-operator/templates/_helpers.tpl` document the minimum
permission set the operator requires.

</details>

### 2. Create a secret with your API keys

```yaml
Expand Down
89 changes: 89 additions & 0 deletions charts/openclaw-operator/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,92 @@ Create the name of the service account to use
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}

{{/*
Manager rules. Single source of truth so the same set of permissions is
rendered into the cluster-scoped ClusterRole or per-namespace Role.
hack/check-helm-rbac-sync.sh asserts this set is a superset of the
kubebuilder-generated config/rbac/role.yaml.
*/}}
{{- define "openclaw-operator.managerRules" -}}
# Core API resources
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
- apiGroups: [""]
resources: ["services"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: [""]
resources: ["serviceaccounts"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: [""]
resources: ["events"]
verbs: ["create", "patch"]
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
# Apps API
- apiGroups: ["apps"]
resources: ["statefulsets"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch", "delete"]
# Batch API (backup/restore Jobs, periodic backup CronJobs)
- apiGroups: ["batch"]
resources: ["jobs"]
verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: ["batch"]
resources: ["cronjobs"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# RBAC
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["roles", "rolebindings"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# Networking
- apiGroups: ["networking.k8s.io"]
resources: ["networkpolicies", "ingresses"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# Policy
- apiGroups: ["policy"]
resources: ["poddisruptionbudgets"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# Autoscaling
- apiGroups: ["autoscaling"]
resources: ["horizontalpodautoscalers"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# Monitoring
- apiGroups: ["monitoring.coreos.com"]
resources: ["servicemonitors", "prometheusrules"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# OpenClaw CRDs
- apiGroups: ["openclaw.rocks"]
resources: ["openclawinstances"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["openclaw.rocks"]
resources: ["openclawinstances/status"]
verbs: ["get", "update", "patch"]
- apiGroups: ["openclaw.rocks"]
resources: ["openclawinstances/finalizers"]
verbs: ["update"]
# OpenClawSelfConfig CRD
- apiGroups: ["openclaw.rocks"]
resources: ["openclawselfconfigs"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["openclaw.rocks"]
resources: ["openclawselfconfigs/status"]
verbs: ["get", "update", "patch"]
- apiGroups: ["openclaw.rocks"]
resources: ["openclawselfconfigs/finalizers"]
verbs: ["update"]
# OpenClawClusterDefaults singleton (#457)
- apiGroups: ["openclaw.rocks"]
resources: ["openclawclusterdefaults"]
verbs: ["get", "list", "watch"]
{{- end }}
3 changes: 3 additions & 0 deletions charts/openclaw-operator/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ spec:
- --metrics-bind-address=0
{{- end }}
- --zap-log-level={{ .Values.logLevel }}
{{- if gt (len .Values.watchNamespaces) 0 }}
- --watch-namespaces={{ join "," .Values.watchNamespaces }}
{{- end }}
{{- if .Values.otlp.enabled }}
{{- if not .Values.otlp.endpoint }}
{{- fail "otlp.endpoint is required when otlp.enabled is true" }}
Expand Down
2 changes: 1 addition & 1 deletion charts/openclaw-operator/templates/metrics-rbac.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }}
{{- if and .Values.rbac.create .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
Expand Down
143 changes: 52 additions & 91 deletions charts/openclaw-operator/templates/rbac.yaml
Original file line number Diff line number Diff line change
@@ -1,113 +1,73 @@
{{- if .Values.rbac.create -}}
{{- $managerName := printf "%s-manager-role" (include "openclaw-operator.fullname" .) -}}
{{- $managerBinding := printf "%s-manager-rolebinding" (include "openclaw-operator.fullname" .) -}}
{{- $saName := include "openclaw-operator.serviceAccountName" . -}}
{{- $saNamespace := .Release.Namespace -}}
{{- $labels := include "openclaw-operator.labels" . -}}
{{- if gt (len .Values.watchNamespaces) 0 -}}
{{- range $i, $ns := .Values.watchNamespaces }}
{{- if gt $i 0 }}
---
{{- end }}
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ $managerName }}
namespace: {{ $ns }}
labels:
{{- $labels | nindent 4 }}
rules:
{{- include "openclaw-operator.managerRules" $ | nindent 2 }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ $managerBinding }}
namespace: {{ $ns }}
labels:
{{- $labels | nindent 4 }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ $managerName }}
subjects:
- kind: ServiceAccount
name: {{ $saName }}
namespace: {{ $saNamespace }}
{{- end }}
{{- else }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ include "openclaw-operator.fullname" . }}-manager-role
name: {{ $managerName }}
labels:
{{- include "openclaw-operator.labels" . | nindent 4 }}
{{- $labels | nindent 4 }}
rules:
# Core API resources
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
- apiGroups: [""]
resources: ["services"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: [""]
resources: ["serviceaccounts"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: [""]
resources: ["events"]
verbs: ["create", "patch"]
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
# Apps API
- apiGroups: ["apps"]
resources: ["statefulsets"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch", "delete"]
# Batch API (backup/restore Jobs, periodic backup CronJobs)
- apiGroups: ["batch"]
resources: ["jobs"]
verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: ["batch"]
resources: ["cronjobs"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# RBAC
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["roles", "rolebindings"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# Networking
- apiGroups: ["networking.k8s.io"]
resources: ["networkpolicies", "ingresses"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# Policy
- apiGroups: ["policy"]
resources: ["poddisruptionbudgets"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# Autoscaling
- apiGroups: ["autoscaling"]
resources: ["horizontalpodautoscalers"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# Monitoring
- apiGroups: ["monitoring.coreos.com"]
resources: ["servicemonitors", "prometheusrules"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# OpenClaw CRDs
- apiGroups: ["openclaw.rocks"]
resources: ["openclawinstances"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["openclaw.rocks"]
resources: ["openclawinstances/status"]
verbs: ["get", "update", "patch"]
- apiGroups: ["openclaw.rocks"]
resources: ["openclawinstances/finalizers"]
verbs: ["update"]
# OpenClawSelfConfig CRD
- apiGroups: ["openclaw.rocks"]
resources: ["openclawselfconfigs"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["openclaw.rocks"]
resources: ["openclawselfconfigs/status"]
verbs: ["get", "update", "patch"]
- apiGroups: ["openclaw.rocks"]
resources: ["openclawselfconfigs/finalizers"]
verbs: ["update"]
# OpenClawClusterDefaults singleton (#457)
- apiGroups: ["openclaw.rocks"]
resources: ["openclawclusterdefaults"]
verbs: ["get", "list", "watch"]
{{- include "openclaw-operator.managerRules" . | nindent 2 }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ include "openclaw-operator.fullname" . }}-manager-rolebinding
name: {{ $managerBinding }}
labels:
{{- include "openclaw-operator.labels" . | nindent 4 }}
{{- $labels | nindent 4 }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ include "openclaw-operator.fullname" . }}-manager-role
name: {{ $managerName }}
subjects:
- kind: ServiceAccount
name: {{ include "openclaw-operator.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
name: {{ $saName }}
namespace: {{ $saNamespace }}
{{- end }}
{{- if .Values.leaderElection.enabled }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ include "openclaw-operator.fullname" . }}-leader-election-role
labels:
{{- include "openclaw-operator.labels" . | nindent 4 }}
{{- $labels | nindent 4 }}
rules:
- apiGroups: [""]
resources: ["configmaps"]
Expand All @@ -124,13 +84,14 @@ kind: RoleBinding
metadata:
name: {{ include "openclaw-operator.fullname" . }}-leader-election-rolebinding
labels:
{{- include "openclaw-operator.labels" . | nindent 4 }}
{{- $labels | nindent 4 }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ include "openclaw-operator.fullname" . }}-leader-election-role
subjects:
- kind: ServiceAccount
name: {{ include "openclaw-operator.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
name: {{ $saName }}
namespace: {{ $saNamespace }}
{{- end }}
{{- end }}
18 changes: 18 additions & 0 deletions charts/openclaw-operator/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,24 @@ serviceAccount:
annotations: {}
name: ""

# RBAC configuration
rbac:
# Whether the chart should render the operator's RBAC (ClusterRole/Role
# and bindings). Set to false to disable and supply your own out-of-band.
create: true

# Restrict the operator to a fixed list of namespaces. When empty (default),
# the operator watches OpenClawInstance resources cluster-wide and the chart
# renders cluster-scoped RBAC. When set to one or more namespaces, the
# operator watches only those namespaces and the chart renders a namespaced
# Role/RoleBinding pair in each one (instead of a ClusterRole/ClusterRoleBinding).
# Each listed namespace must already exist (the chart does not create them).
watchNamespaces: []
# Example:
# watchNamespaces:
# - team-a
# - team-b

# Pod annotations
podAnnotations: {}

Expand Down
Loading
Loading