From 494d7394a4b2e053e151d739c9932fe6ef7436f8 Mon Sep 17 00:00:00 2001
From: Luca Bianco <lbi@n-side.com>
Date: Wed, 8 Nov 2023 16:53:22 +0100
Subject: [PATCH 1/5] add feature to enable permission to manage Kubernates
 services inside helm

---
 helm/coder/values.yaml             |  3 +++
 helm/libcoder/templates/_rbac.yaml | 13 +++++++++++++
 2 files changed, 16 insertions(+)

diff --git a/helm/coder/values.yaml b/helm/coder/values.yaml
index 153d638037982..2c3188f0f23b5 100644
--- a/helm/coder/values.yaml
+++ b/helm/coder/values.yaml
@@ -94,6 +94,9 @@ coder:
     # coder.serviceAccount.enableDeployments -- Provides the service account permission
     # to manage Kubernetes deployments.
     enableDeployments: true
+    # coder.serviceAccount.enableServices -- Provides the service account permission
+    # to manage Kubernetes services.
+    enableServices: false
     # coder.serviceAccount.annotations -- The Coder service account annotations.
     annotations: {}
     # coder.serviceAccount.name -- The service account name
diff --git a/helm/libcoder/templates/_rbac.yaml b/helm/libcoder/templates/_rbac.yaml
index c60357ad2a796..114c1c92971db 100644
--- a/helm/libcoder/templates/_rbac.yaml
+++ b/helm/libcoder/templates/_rbac.yaml
@@ -43,6 +43,19 @@ rules:
     - update
     - watch
 {{- end }}
+{{- if .Values.coder.serviceAccount.enableServices }}
+  - apiGroups: [""]
+    resources: ["services"]
+    verbs:
+    - create
+    - delete
+    - deletecollection
+    - get
+    - list
+    - patch
+    - update
+    - watch
+{{- end }}
 ---
 apiVersion: rbac.authorization.k8s.io/v1
 kind: RoleBinding

From 5523485cc16231cf36d7289b725900260e39e6b7 Mon Sep 17 00:00:00 2001
From: Luca Bianco <lbi@n-side.com>
Date: Thu, 9 Nov 2023 14:35:17 +0100
Subject: [PATCH 2/5] allow user to specify custom perms as a property

---
 helm/coder/values.yaml             | 18 +++++++++++++++---
 helm/libcoder/templates/_rbac.yaml | 14 ++------------
 2 files changed, 17 insertions(+), 15 deletions(-)

diff --git a/helm/coder/values.yaml b/helm/coder/values.yaml
index 2c3188f0f23b5..b5a94e60de4c0 100644
--- a/helm/coder/values.yaml
+++ b/helm/coder/values.yaml
@@ -94,9 +94,21 @@ coder:
     # coder.serviceAccount.enableDeployments -- Provides the service account permission
     # to manage Kubernetes deployments.
     enableDeployments: true
-    # coder.serviceAccount.enableServices -- Provides the service account permission
-    # to manage Kubernetes services.
-    enableServices: false
+    # coder.serviceAccount.extraResources -- A list of service account permission
+    # to be menaged inside the workspace.
+    extraResources: []
+    # - apiGroups: [""]
+    #   resources: ["services"]
+    #   verbs:
+    #   - create
+    #   - delete
+    #   - deletecollection
+    #   - get
+    #   - list
+    #   - patch
+    #   - update
+    #   - watch
+
     # coder.serviceAccount.annotations -- The Coder service account annotations.
     annotations: {}
     # coder.serviceAccount.name -- The service account name
diff --git a/helm/libcoder/templates/_rbac.yaml b/helm/libcoder/templates/_rbac.yaml
index 114c1c92971db..659e48d4acfb3 100644
--- a/helm/libcoder/templates/_rbac.yaml
+++ b/helm/libcoder/templates/_rbac.yaml
@@ -43,18 +43,8 @@ rules:
     - update
     - watch
 {{- end }}
-{{- if .Values.coder.serviceAccount.enableServices }}
-  - apiGroups: [""]
-    resources: ["services"]
-    verbs:
-    - create
-    - delete
-    - deletecollection
-    - get
-    - list
-    - patch
-    - update
-    - watch
+{{- with .Values.coder.serviceAccount.extraResources }}
+{{ toYaml . | nindent 2 }}
 {{- end }}
 ---
 apiVersion: rbac.authorization.k8s.io/v1

From 6efc65f0054c8c14e6f0387fd019a85e8a2f5b6f Mon Sep 17 00:00:00 2001
From: Dean Sheather <dean@deansheather.com>
Date: Thu, 9 Nov 2023 17:33:28 +0000
Subject: [PATCH 3/5] Fix helm test generation

---
 helm/coder/.gitignore                         |   1 +
 helm/coder/charts/libcoder-0.1.0.tgz          | Bin 2998 -> 0 bytes
 helm/coder/tests/chart_test.go                |  30 +++
 .../tests/testdata/sa_extra_rules.golden      | 204 ++++++++++++++++++
 helm/coder/tests/testdata/sa_extra_rules.yaml |  17 ++
 helm/coder/values.yaml                        |  26 +--
 helm/libcoder/templates/_rbac.yaml            |   2 +-
 7 files changed, 266 insertions(+), 14 deletions(-)
 create mode 100644 helm/coder/.gitignore
 delete mode 100644 helm/coder/charts/libcoder-0.1.0.tgz
 create mode 100644 helm/coder/tests/testdata/sa_extra_rules.golden
 create mode 100644 helm/coder/tests/testdata/sa_extra_rules.yaml

diff --git a/helm/coder/.gitignore b/helm/coder/.gitignore
new file mode 100644
index 0000000000000..ee3892e8794a0
--- /dev/null
+++ b/helm/coder/.gitignore
@@ -0,0 +1 @@
+charts/
diff --git a/helm/coder/charts/libcoder-0.1.0.tgz b/helm/coder/charts/libcoder-0.1.0.tgz
deleted file mode 100644
index baae560bb8310ac0d4377c369e40269ea51b9b42..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2998
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

diff --git a/helm/coder/tests/chart_test.go b/helm/coder/tests/chart_test.go
index 8a57cdec25d69..2b13dd21c3307 100644
--- a/helm/coder/tests/chart_test.go
+++ b/helm/coder/tests/chart_test.go
@@ -84,6 +84,10 @@ var testCases = []testCase{
 		name:          "prometheus",
 		expectedError: "",
 	},
+	{
+		name:          "sa_extra_rules",
+		expectedError: "",
+	},
 }
 
 type testCase struct {
@@ -113,6 +117,9 @@ func TestRenderChart(t *testing.T) {
 
 	// Ensure that Helm is available in $PATH
 	helmPath := lookupHelm(t)
+	err := updateHelmDependencies(t, helmPath, "..")
+	require.NoError(t, err, "failed to build Helm dependencies")
+
 	for _, tc := range testCases {
 		tc := tc
 		t.Run(tc.name, func(t *testing.T) {
@@ -154,6 +161,9 @@ func TestUpdateGoldenFiles(t *testing.T) {
 	}
 
 	helmPath := lookupHelm(t)
+	err := updateHelmDependencies(t, helmPath, "..")
+	require.NoError(t, err, "failed to build Helm dependencies")
+
 	for _, tc := range testCases {
 		if tc.expectedError != "" {
 			t.Logf("skipping test case %q with render error", tc.name)
@@ -175,6 +185,26 @@ func TestUpdateGoldenFiles(t *testing.T) {
 	t.Log("Golden files updated. Please review the changes and commit them.")
 }
 
+// updateHelmDependencies runs `helm dependency update .` on the given chartDir.
+func updateHelmDependencies(t testing.TB, helmPath, chartDir string) error {
+	// Remove charts/ from chartDir if it exists.
+	err := os.RemoveAll(filepath.Join(chartDir, "charts"))
+	if err != nil {
+		return xerrors.Errorf("failed to remove charts/ directory: %w", err)
+	}
+
+	// Regenerate the chart dependencies.
+	cmd := exec.Command(helmPath, "dependency", "update", ".")
+	cmd.Dir = chartDir
+	t.Logf("exec command: %v", cmd.Args)
+	out, err := cmd.CombinedOutput()
+	if err != nil {
+		return xerrors.Errorf("failed to run `helm dependency build`: %w\noutput: %s", err, out)
+	}
+
+	return nil
+}
+
 // runHelmTemplate runs helm template on the given chart with the given values and
 // returns the raw output.
 func runHelmTemplate(t testing.TB, helmPath, chartDir, valuesFilePath string) (string, error) {
diff --git a/helm/coder/tests/testdata/sa_extra_rules.golden b/helm/coder/tests/testdata/sa_extra_rules.golden
new file mode 100644
index 0000000000000..5766f45c6c829
--- /dev/null
+++ b/helm/coder/tests/testdata/sa_extra_rules.golden
@@ -0,0 +1,204 @@
+---
+# Source: coder/templates/coder.yaml
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  annotations: {}
+  labels:
+    app.kubernetes.io/instance: release-name
+    app.kubernetes.io/managed-by: Helm
+    app.kubernetes.io/name: coder
+    app.kubernetes.io/part-of: coder
+    app.kubernetes.io/version: 0.1.0
+    helm.sh/chart: coder-0.1.0
+  name: coder
+---
+# Source: coder/templates/rbac.yaml
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+  name: coder-workspace-perms
+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
+
+  - apiGroups:
+    - ""
+    resources:
+    - services
+    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"
+subjects:
+  - kind: ServiceAccount
+    name: "coder"
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: Role
+  name: coder-workspace-perms
+---
+# Source: coder/templates/service.yaml
+apiVersion: v1
+kind: Service
+metadata:
+  name: coder
+  labels:
+    helm.sh/chart: coder-0.1.0
+    app.kubernetes.io/name: coder
+    app.kubernetes.io/instance: release-name
+    app.kubernetes.io/part-of: coder
+    app.kubernetes.io/version: "0.1.0"
+    app.kubernetes.io/managed-by: Helm
+  annotations:
+    {}
+spec:
+  type: LoadBalancer
+  sessionAffinity: None
+  ports:
+    - name: "http"
+      port: 80
+      targetPort: "http"
+      protocol: TCP
+      
+  externalTrafficPolicy: "Cluster"
+  selector:
+    app.kubernetes.io/name: coder
+    app.kubernetes.io/instance: release-name
+---
+# Source: coder/templates/coder.yaml
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  annotations: {}
+  labels:
+    app.kubernetes.io/instance: release-name
+    app.kubernetes.io/managed-by: Helm
+    app.kubernetes.io/name: coder
+    app.kubernetes.io/part-of: coder
+    app.kubernetes.io/version: 0.1.0
+    helm.sh/chart: coder-0.1.0
+  name: coder
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app.kubernetes.io/instance: release-name
+      app.kubernetes.io/name: coder
+  template:
+    metadata:
+      annotations: {}
+      labels:
+        app.kubernetes.io/instance: release-name
+        app.kubernetes.io/managed-by: Helm
+        app.kubernetes.io/name: coder
+        app.kubernetes.io/part-of: coder
+        app.kubernetes.io/version: 0.1.0
+        helm.sh/chart: coder-0.1.0
+    spec:
+      affinity:
+        podAntiAffinity:
+          preferredDuringSchedulingIgnoredDuringExecution:
+          - podAffinityTerm:
+              labelSelector:
+                matchExpressions:
+                - key: app.kubernetes.io/instance
+                  operator: In
+                  values:
+                  - coder
+              topologyKey: kubernetes.io/hostname
+            weight: 1
+      containers:
+      - args:
+        - server
+        command:
+        - /opt/coder
+        env:
+        - name: CODER_HTTP_ADDRESS
+          value: 0.0.0.0:8080
+        - name: CODER_PROMETHEUS_ADDRESS
+          value: 0.0.0.0:2112
+        - name: CODER_ACCESS_URL
+          value: http://coder.default.svc.cluster.local
+        - name: KUBE_POD_IP
+          valueFrom:
+            fieldRef:
+              fieldPath: status.podIP
+        - name: CODER_DERP_SERVER_RELAY_URL
+          value: http://$(KUBE_POD_IP):8080
+        image: ghcr.io/coder/coder:latest
+        imagePullPolicy: IfNotPresent
+        lifecycle: {}
+        livenessProbe:
+          httpGet:
+            path: /healthz
+            port: http
+            scheme: HTTP
+        name: coder
+        ports:
+        - containerPort: 8080
+          name: http
+          protocol: TCP
+        readinessProbe:
+          httpGet:
+            path: /healthz
+            port: http
+            scheme: HTTP
+        resources: {}
+        securityContext:
+          allowPrivilegeEscalation: false
+          readOnlyRootFilesystem: null
+          runAsGroup: 1000
+          runAsNonRoot: true
+          runAsUser: 1000
+          seccompProfile:
+            type: RuntimeDefault
+        volumeMounts: []
+      restartPolicy: Always
+      serviceAccountName: coder
+      terminationGracePeriodSeconds: 60
+      volumes: []
diff --git a/helm/coder/tests/testdata/sa_extra_rules.yaml b/helm/coder/tests/testdata/sa_extra_rules.yaml
new file mode 100644
index 0000000000000..f79970871488a
--- /dev/null
+++ b/helm/coder/tests/testdata/sa_extra_rules.yaml
@@ -0,0 +1,17 @@
+coder:
+  image:
+    tag: latest
+
+  serviceAccount:
+    extraRules:
+     - apiGroups: [""]
+       resources: ["services"]
+       verbs:
+         - create
+         - delete
+         - deletecollection
+         - get
+         - list
+         - patch
+         - update
+         - watch
diff --git a/helm/coder/values.yaml b/helm/coder/values.yaml
index b5a94e60de4c0..fae239de7fb9a 100644
--- a/helm/coder/values.yaml
+++ b/helm/coder/values.yaml
@@ -91,23 +91,23 @@ coder:
     # It is recommended to keep this on if you are using Kubernetes templates
     # within Coder.
     workspacePerms: true
-    # coder.serviceAccount.enableDeployments -- Provides the service account permission
-    # to manage Kubernetes deployments.
+    # coder.serviceAccount.enableDeployments -- Provides the service account
+    # permission to manage Kubernetes deployments. Depends on workspacePerms.
     enableDeployments: true
-    # coder.serviceAccount.extraResources -- A list of service account permission
-    # to be menaged inside the workspace.
-    extraResources: []
+    # coder.serviceAccount.extraRules -- Additional permissions added to the SA
+    # role. Depends on workspacePerms.
+    extraRules: []
     # - apiGroups: [""]
     #   resources: ["services"]
     #   verbs:
-    #   - create
-    #   - delete
-    #   - deletecollection
-    #   - get
-    #   - list
-    #   - patch
-    #   - update
-    #   - watch
+    #     - create
+    #     - delete
+    #     - deletecollection
+    #     - get
+    #     - list
+    #     - patch
+    #     - update
+    #     - watch
 
     # coder.serviceAccount.annotations -- The Coder service account annotations.
     annotations: {}
diff --git a/helm/libcoder/templates/_rbac.yaml b/helm/libcoder/templates/_rbac.yaml
index 659e48d4acfb3..1320c652c8a15 100644
--- a/helm/libcoder/templates/_rbac.yaml
+++ b/helm/libcoder/templates/_rbac.yaml
@@ -43,7 +43,7 @@ rules:
     - update
     - watch
 {{- end }}
-{{- with .Values.coder.serviceAccount.extraResources }}
+{{- with .Values.coder.serviceAccount.extraRules }}
 {{ toYaml . | nindent 2 }}
 {{- end }}
 ---

From 9e57830db79153cd27b789cfaa2c2b4a0719f65a Mon Sep 17 00:00:00 2001
From: Atif Ali <atif@coder.com>
Date: Tue, 14 Nov 2023 19:27:01 +0000
Subject: [PATCH 4/5] fmt

---
 helm/coder/tests/testdata/sa_extra_rules.yaml | 22 +++++++++----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/helm/coder/tests/testdata/sa_extra_rules.yaml b/helm/coder/tests/testdata/sa_extra_rules.yaml
index f79970871488a..22d6fe81d855c 100644
--- a/helm/coder/tests/testdata/sa_extra_rules.yaml
+++ b/helm/coder/tests/testdata/sa_extra_rules.yaml
@@ -4,14 +4,14 @@ coder:
 
   serviceAccount:
     extraRules:
-     - apiGroups: [""]
-       resources: ["services"]
-       verbs:
-         - create
-         - delete
-         - deletecollection
-         - get
-         - list
-         - patch
-         - update
-         - watch
+      - apiGroups: [""]
+        resources: ["services"]
+        verbs:
+          - create
+          - delete
+          - deletecollection
+          - get
+          - list
+          - patch
+          - update
+          - watch

From 92b4f4bffed191e7e50a3716973329b88fbb3616 Mon Sep 17 00:00:00 2001
From: Dean Sheather <dean@deansheather.com>
Date: Mon, 27 Nov 2023 03:24:55 +0000
Subject: [PATCH 5/5] fix lint

---
 helm/{coder => }/.gitignore                |   0
 helm/Makefile                              |   2 ++
 helm/coder/tests/chart_test.go             |   2 +-
 helm/provisioner/charts/libcoder-0.1.0.tgz | Bin 2999 -> 3012 bytes
 4 files changed, 3 insertions(+), 1 deletion(-)
 rename helm/{coder => }/.gitignore (100%)

diff --git a/helm/coder/.gitignore b/helm/.gitignore
similarity index 100%
rename from helm/coder/.gitignore
rename to helm/.gitignore
diff --git a/helm/Makefile b/helm/Makefile
index 4010cf42d64fb..467d4e6e36c9e 100644
--- a/helm/Makefile
+++ b/helm/Makefile
@@ -17,9 +17,11 @@ lint/helm: lint/helm/coder lint/helm/provisioner
 .PHONY: lint/helm
 
 lint/helm/coder:
+	helm dependency update --skip-refresh coder/
 	helm lint --strict --set coder.image.tag=v0.0.1 coder/
 .PHONY: lint/helm/coder
 
 lint/helm/provisioner:
+	helm dependency update --skip-refresh provisioner/
 	helm lint --strict --set coder.image.tag=v0.0.1 provisioner/
 .PHONY: lint/helm/provisioner
diff --git a/helm/coder/tests/chart_test.go b/helm/coder/tests/chart_test.go
index 2b13dd21c3307..d9bf4fee0c4ae 100644
--- a/helm/coder/tests/chart_test.go
+++ b/helm/coder/tests/chart_test.go
@@ -194,7 +194,7 @@ func updateHelmDependencies(t testing.TB, helmPath, chartDir string) error {
 	}
 
 	// Regenerate the chart dependencies.
-	cmd := exec.Command(helmPath, "dependency", "update", ".")
+	cmd := exec.Command(helmPath, "dependency", "update", "--skip-refresh", ".")
 	cmd.Dir = chartDir
 	t.Logf("exec command: %v", cmd.Args)
 	out, err := cmd.CombinedOutput()
diff --git a/helm/provisioner/charts/libcoder-0.1.0.tgz b/helm/provisioner/charts/libcoder-0.1.0.tgz
index 094e3f64207ad433f067378e1ee47af184460445..136a99f3a01de3de6a0513d238ca94f04c2e959e 100644
GIT binary patch
delta 2965
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
L3Jfo@06G8wfY`}k

delta 2952
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