Repository: envoyproxy/ai-gateway (go)
Issue: controller: mark all volume mounts readOnly=true
*Description*:

The AI Gateway ExtProc deployment/containers mount some secrets/configmaps. However, it only needs to read the contents, and so the write permission is unnecessary.

[optional *Relevant Links*:]

I would like the `corev1.VolumeMount`'s ReadOnly flag to always true in https://github.com/envoyproxy/ai-gateway/blob/main/internal/controller/sink.go

Pull request description: controller: mark all volume mounts ReadOnly=true
**Commit Message**

Mark all volume mounts readonly to ensure security.


**Related Issues/PRs (if applicable)**

Fix #250

Patch:
diff --git a/internal/controller/sink.go b/internal/controller/sink.go
index 3005b94..9bf46b9 100644
--- a/internal/controller/sink.go
+++ b/internal/controller/sink.go
@@ -491,7 +491,11 @@ func (c *configSink) syncExtProcDeployment(ctx context.Context, aiGatewayRoute *
 										"-logLevel", c.extProcLogLevel,
 									},
 									VolumeMounts: []corev1.VolumeMount{
-										{Name: "config", MountPath: "/etc/ai-gateway/extproc"},
+										{
+											Name:      "config",
+											MountPath: "/etc/ai-gateway/extproc",
+											ReadOnly:  true,
+										},
 									},
 								},
 							},
@@ -613,6 +617,7 @@ func (c *configSink) mountBackendSecurityPolicySecrets(spec *corev1.PodSpec, aiG
 				container.VolumeMounts = append(container.VolumeMounts, corev1.VolumeMount{
 					Name:      volumeName,
 					MountPath: backendSecurityMountPath(volumeName),
+					ReadOnly:  true,
 				})
 			}
 		}


Test patch:
diff --git a/internal/controller/sink_test.go b/internal/controller/sink_test.go
index 7addc24..3cdd3cb 100644
--- a/internal/controller/sink_test.go
+++ b/internal/controller/sink_test.go
@@ -639,6 +639,10 @@ func TestConfigSink_SyncExtprocDeployment(t *testing.T) {
 			require.Equal(t, "AIGatewayRoute", extProcDeployment.OwnerReferences[0].Kind)
 			require.Equal(t, int32(456), *extProcDeployment.Spec.Replicas)
 			require.Equal(t, newResourceLimits, &extProcDeployment.Spec.Template.Spec.Containers[0].Resources)
+
+			for _, v := range extProcDeployment.Spec.Template.Spec.Containers[0].VolumeMounts {
+				require.True(t, v.ReadOnly)
+			}
 			return true
 		}, 30*time.Second, 200*time.Millisecond)
 	})
@@ -755,25 +759,18 @@ func TestConfigSink_MountBackendSecurityPolicySecrets(t *testing.T) {
 	spec := corev1.PodSpec{
 		Volumes: []corev1.Volume{
 			{
-				Name: "some-cm-policy",
+				Name: "extproc-config",
 				VolumeSource: corev1.VolumeSource{
 					ConfigMap: &corev1.ConfigMapVolumeSource{
 						LocalObjectReference: corev1.LocalObjectReference{
-							Name: "some-cm-policy",
+							Name: "extproc-config",
 						},
 					},
 				},
 			},
 		},
 		Containers: []corev1.Container{
-			{
-				VolumeMounts: []corev1.VolumeMount{
-					{
-						Name:      "some-cm-policy",
-						MountPath: "some-path",
-					},
-				},
-			},
+			{VolumeMounts: []corev1.VolumeMount{{Name: "extproc-config", MountPath: "some-path", ReadOnly: true}}},
 		},
 	}
 
@@ -821,6 +818,10 @@ func TestConfigSink_MountBackendSecurityPolicySecrets(t *testing.T) {
 	require.Equal(t, "rule0-backref0-some-other-backend-security-policy-2", updatedSpec.Volumes[1].Name)
 	require.Equal(t, "rule0-backref0-some-other-backend-security-policy-2", updatedSpec.Containers[0].VolumeMounts[1].Name)
 	require.Equal(t, "/etc/backend_security_policy/rule0-backref0-some-other-backend-security-policy-2", updatedSpec.Containers[0].VolumeMounts[1].MountPath)
+
+	for _, v := range updatedSpec.Containers[0].VolumeMounts {
+		require.True(t, v.ReadOnly, v.Name)
+	}
 }
 
 func Test_backendSecurityPolicyVolumeName(t *testing.T) {