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
42 changes: 42 additions & 0 deletions charts/operator/templates/clusterrole.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{{- if and (not .Values.kubeconfigSecret.name) .Values.createClusterRole }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ include "zenith-operator.fullname" . }}
labels: {{ include "zenith-operator.labels" . | nindent 4 }}
rules:
# CRD management (applied at operator startup)
- apiGroups: ["apiextensions.k8s.io"]
resources: ["customresourcedefinitions"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
# Zenith custom resources watched and reconciled by the operator
- apiGroups: ["zenith.stackhpc.com"]
resources: ["reservations", "clients"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["zenith.stackhpc.com"]
resources: ["reservations/status", "clients/status"]
verbs: ["get", "update", "patch"]
# Secrets for SSH keypairs and client configuration
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# Services — read-only, used for upstream host resolution
- apiGroups: [""]
resources: ["services"]
verbs: ["get", "list", "watch"]
# ServiceAccounts created for MITM-proxy pods
- apiGroups: [""]
resources: ["serviceaccounts"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# Deployments for zenith-client pods (created and watched)
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# ClusterRoleBindings for MITM-proxy ServiceAccounts
# Note: Kubernetes prevents privilege escalation — the operator can only bind roles
# it already holds. To bind cluster-admin to MITM-proxy ServiceAccounts, set
# createClusterRole: false and clusterRoleName: cluster-admin explicitly.
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["clusterrolebindings"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
{{- end }}
2 changes: 1 addition & 1 deletion charts/operator/templates/clusterrolebinding.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ subjects:
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ .Values.clusterRoleName }}
name: {{ .Values.clusterRoleName | default (include "zenith-operator.fullname" .) }}
{{- end }}
109 changes: 105 additions & 4 deletions charts/operator/tests/__snapshot__/snapshot_test.yaml.snap
Original file line number Diff line number Diff line change
@@ -1,5 +1,106 @@
templated manifests should match snapshot:
1: |
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/instance: RELEASE-NAME
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: zenith-operator
app.kubernetes.io/version: main
helm.sh/chart: zenith-operator-0.1.0
name: release-name-zenith-operator
rules:
- apiGroups:
- apiextensions.k8s.io
resources:
- customresourcedefinitions
verbs:
- get
- list
- watch
- create
- update
- patch
- apiGroups:
- zenith.stackhpc.com
resources:
- reservations
- clients
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
- apiGroups:
- zenith.stackhpc.com
resources:
- reservations/status
- clients/status
verbs:
- get
- update
- patch
- apiGroups:
- ""
resources:
- secrets
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
- apiGroups:
- ""
resources:
- services
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- serviceaccounts
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
- apiGroups:
- apps
resources:
- deployments
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
- apiGroups:
- rbac.authorization.k8s.io
resources:
- clusterrolebindings
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
2: |
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
Expand All @@ -13,12 +114,12 @@ templated manifests should match snapshot:
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
name: release-name-zenith-operator
subjects:
- kind: ServiceAccount
name: release-name-zenith-operator
namespace: NAMESPACE
2: |
3: |
apiVersion: apps/v1
kind: Deployment
metadata:
Expand Down Expand Up @@ -71,7 +172,7 @@ templated manifests should match snapshot:
secretName: release-name-zenith-operator
- emptyDir: {}
name: tmp
3: |
4: |
apiVersion: v1
kind: Secret
metadata:
Expand All @@ -85,7 +186,7 @@ templated manifests should match snapshot:
stringData:
operator.yaml: |
defaultImageTag: main
4: |
5: |
apiVersion: v1
kind: ServiceAccount
metadata:
Expand Down
28 changes: 21 additions & 7 deletions charts/operator/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,29 @@ kubeconfigSecret:
# The key of the kubeconfig file in the secret
key: value

# The name of the clusterrole that the operator should be bound to
# When true, a purpose-scoped ClusterRole is created for the operator covering
# only the permissions it needs: zenith CRDs/CRs, secrets, services, service
# accounts, deployments, and clusterrolebindings.
#
# Note that in order for the operator to grant permissions to service accounts
# for MITM proxies, the operator itself needs to hold all of those permissions
# In particular, in order for the operator to grant the cluster-admin role
# to service accounts for MITM proxies, it must hold cluster-admin itself
# Set to false when you need to bind a pre-existing role (e.g. cluster-admin
# for MITM-proxy deployments that inject service-account tokens) and supply
# the role name in clusterRoleName below.
#
# Only used if kubeconfigSecret.name is not specified
clusterRoleName: cluster-admin
# Only used if kubeconfigSecret.name is not specified.
createClusterRole: true

# The name of the ClusterRole that the operator ServiceAccount is bound to.
#
# Defaults to the chart fullname (i.e. the scoped ClusterRole created above).
#
# IMPORTANT — privilege escalation: Kubernetes prevents an operator from granting
# a ClusterRole to a ServiceAccount unless the operator itself holds every
# permission in that role. If you use MITM-proxy auth-inject with a role that
# exceeds the scoped ClusterRole (e.g. cluster-admin), you must set this field
# explicitly to that role name and set createClusterRole: false.
#
# Only used if kubeconfigSecret.name is not specified.
clusterRoleName: ""

# The image to use for the operator
image:
Expand Down
Loading