mirror of
https://github.com/coder/coder.git
synced 2026-06-02 20:48:20 +00:00
623893708b
This is a feature to create Role & RoleBinding entries on a per namespace basis to support deploying workspaces in separate namespace to where Coder is deployed. The idea behind this is to avoid the creation of custom RBAC entries or the use of ClusterRoles (in order to maintain priciple of least privilege). > If you have used AI to produce some or all of this PR, please ensure you have read our [AI Contribution guidelines](https://coder.com/docs/about/contributing/AI_CONTRIBUTING) before submitting. This is a blink assisted PR. Example `helm template` without `coder.serviceAccount.workspaceNamespaces` enabled (existing behaviour as of current release) is below. Outcome = 1 x SA, 1 x Role, 1 x RoleBinding, all in the coder (`.Release.Namespace`) namespace. ``` ➜ coder git:(feat/helm_namespace_rbac_improvements) ✗ helm template -n coder coder . --set coder.image.tag=v2.25.1 --- ... --- # Source: coder/templates/rbac.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: coder-workspace-perms namespace: coder rules: - apiGroups: [""] resources: ["pods"] verbs: - create - delete - deletecollection - get - list - patch - update - watch - apiGroups: [""] resources: ["persistentvolumeclaims"] verbs: - create - delete - deletecollection - get - list - patch - update - watch - apiGroups: - apps resources: - deployments verbs: - create - delete - deletecollection - get - list - patch - update - watch --- # Source: coder/templates/rbac.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: "coder" namespace: coder subjects: - kind: ServiceAccount name: "coder" roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: coder-workspace-perms --- ``` Example `helm template` *with* `coder.serviceAccount.workspaceNamespaces` enabled is below. Outcome = 1 x SA, 1 x Role, 1 x RoleBinding, all in the coder (`.Release.Namespace`) namespace PLUS a Role and RoleBinding in the `dev-ws` namespace with each of the RoleBindings referencing the coder SA in the coder (`.Release.Namespace`) namespace: ``` ➜ coder git:(feat/helm_namespace_rbac_improvements) ✗ helm template -n coder coder . --set coder.image.tag=v2.25.1 --set-json 'coder.serviceAccount.workspaceNamespaces=[{"name":"dev-ws","workspacePerms":true,"enableDeployments":true,"extraRules":[]}]' --- ... --- # Source: coder/templates/rbac.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: coder-workspace-perms namespace: coder rules: - apiGroups: [""] resources: ["pods"] verbs: - create - delete - deletecollection - get - list - patch - update - watch - apiGroups: [""] resources: ["persistentvolumeclaims"] verbs: - create - delete - deletecollection - get - list - patch - update - watch - apiGroups: - apps resources: - deployments verbs: - create - delete - deletecollection - get - list - patch - update - watch --- # Source: coder/templates/rbac.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: coder-workspace-perms namespace: dev-ws rules: - apiGroups: [""] resources: ["pods"] verbs: - create - delete - deletecollection - get - list - patch - update - watch - apiGroups: [""] resources: ["persistentvolumeclaims"] verbs: - create - delete - deletecollection - get - list - patch - update - watch - apiGroups: - apps resources: - deployments verbs: - create - delete - deletecollection - get - list - patch - update - watch --- # Source: coder/templates/rbac.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: "coder" namespace: coder subjects: - kind: ServiceAccount name: "coder" roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: coder-workspace-perms --- # Source: coder/templates/rbac.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: "coder" namespace: dev-ws subjects: - kind: ServiceAccount name: "coder" namespace: coder roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: coder-workspace-perms --- ```
90 lines
3.5 KiB
YAML
90 lines
3.5 KiB
YAML
{{- define "libcoder.rbac.forNamespace" -}}
|
|
{{- $nsPerms := ternary .workspacePerms .Top.Values.coder.serviceAccount.workspacePerms (hasKey . "workspacePerms") -}}
|
|
{{- $nsDeploy := ternary .enableDeployments .Top.Values.coder.serviceAccount.enableDeployments (hasKey . "enableDeployments") -}}
|
|
{{- $nsExtra := ternary .extraRules .Top.Values.coder.serviceAccount.extraRules (hasKey . "extraRules") -}}
|
|
|
|
{{- if or $nsPerms (or $nsDeploy $nsExtra) }}
|
|
---
|
|
apiVersion: rbac.authorization.k8s.io/v1
|
|
kind: Role
|
|
metadata:
|
|
name: {{ .Top.Values.coder.serviceAccount.name }}-workspace-perms
|
|
namespace: {{ .NS }}
|
|
rules:
|
|
{{- if $nsPerms }}
|
|
{{ include "libcoder.rbac.rules.basic" .Top | trimPrefix "\n" | indent 2 }}
|
|
{{- end }}
|
|
{{- if $nsDeploy }}
|
|
{{ include "libcoder.rbac.rules.deployments" .Top | trimPrefix "\n" | indent 2 }}
|
|
{{- end }}
|
|
{{- if $nsExtra }}
|
|
{{- if kindIs "slice" $nsExtra }}
|
|
{{ toYaml $nsExtra | trimPrefix "\n" | indent 2 }}
|
|
{{- else }}
|
|
{{ toYaml (list $nsExtra) | trimPrefix "\n" | indent 2 }}
|
|
{{- end }}
|
|
{{- end }}
|
|
---
|
|
apiVersion: rbac.authorization.k8s.io/v1
|
|
kind: RoleBinding
|
|
metadata:
|
|
name: {{ .Top.Values.coder.serviceAccount.name | quote }}
|
|
namespace: {{ .NS }}
|
|
subjects:
|
|
- kind: ServiceAccount
|
|
name: {{ .Top.Values.coder.serviceAccount.name | quote }}
|
|
{{- if ne .NS .Top.Release.Namespace }}
|
|
namespace: {{ .Top.Release.Namespace }}
|
|
{{- end }}
|
|
roleRef:
|
|
apiGroup: rbac.authorization.k8s.io
|
|
kind: Role
|
|
name: {{ .Top.Values.coder.serviceAccount.name }}-workspace-perms
|
|
{{- end }}
|
|
{{- end -}}
|
|
|
|
{{- define "libcoder.rbac.core" -}}
|
|
{{- $top := . -}}
|
|
{{- $rootPerms := $top.Values.coder.serviceAccount.workspacePerms | default false -}}
|
|
{{- $rootDeploy := $top.Values.coder.serviceAccount.enableDeployments | default false -}}
|
|
{{- $rootExtra := $top.Values.coder.serviceAccount.extraRules | default (list) -}}
|
|
|
|
{{- $rootParams := dict
|
|
"Top" $top
|
|
"NS" $top.Release.Namespace
|
|
"workspacePerms" $rootPerms
|
|
"enableDeployments" $rootDeploy
|
|
"extraRules" $rootExtra -}}
|
|
{{ include "libcoder.rbac.forNamespace" $rootParams }}
|
|
|
|
{{- $wsnsRaw := get $top.Values.coder.serviceAccount "workspaceNamespaces" -}}
|
|
{{- $extra := default (list) $wsnsRaw -}}
|
|
|
|
{{- range $_, $ns := $extra }}
|
|
{{- $nsName := ternary $ns.name $ns (kindIs "map" $ns) -}}
|
|
{{- if $nsName }}
|
|
{{- $params := dict "Top" $top "NS" $nsName -}}
|
|
{{- if kindIs "map" $ns }}
|
|
{{- if hasKey $ns "workspacePerms" }}{{- $_ := set $params "workspacePerms" $ns.workspacePerms }}{{- else }}{{- $_ := set $params "workspacePerms" $rootPerms }}{{- end }}
|
|
{{- if hasKey $ns "enableDeployments" }}{{- $_ := set $params "enableDeployments" $ns.enableDeployments }}{{- else }}{{- $_ := set $params "enableDeployments" $rootDeploy }}{{- end }}
|
|
{{- if hasKey $ns "extraRules" }}{{- $_ := set $params "extraRules" $ns.extraRules }}{{- else }}{{- $_ := set $params "extraRules" $rootExtra }}{{- end }}
|
|
{{- else }}
|
|
{{- $_ := set $params "workspacePerms" $rootPerms -}}
|
|
{{- $_ := set $params "enableDeployments" $rootDeploy -}}
|
|
{{- $_ := set $params "extraRules" $rootExtra -}}
|
|
{{- end }}
|
|
{{ include "libcoder.rbac.forNamespace" $params }}
|
|
{{- end }}
|
|
{{- end }}
|
|
{{- end -}}
|
|
|
|
{{- define "libcoder.rbac.tpl" -}}
|
|
{{- if not .Values.coder.serviceAccount.disableCreate -}}
|
|
{{ include "libcoder.rbac.core" . }}
|
|
{{- end }}
|
|
{{- end -}}
|
|
|
|
{{- define "libcoder.namespace.rbac.tpl" -}}
|
|
{{ include "libcoder.rbac.core" . }}
|
|
{{- end -}}
|