This is an automated email from the ASF dual-hosted git repository.
squakez pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git
The following commit(s) were added to refs/heads/main by this push:
new 2b49410af Fix #6952: Move StorageClass RBAC to a ClusterRole for all
install modes
2b49410af is described below
commit 2b49410afb5be6a25f0ce38a3c71451747f93cde
Author: SnehaNprog <[email protected]>
AuthorDate: Tue Nov 10 21:17:04 2026 +0530
Fix #6952: Move StorageClass RBAC to a ClusterRole for all install modes
---
helm/camel-k/templates/rbacs-common.yaml | 30 +++++++++++++
helm/camel-k/templates/rbacs-descoped.yaml | 7 ---
helm/camel-k/templates/rbacs-namespaced.yaml | 7 ---
.../rbac/descoped/operator-cluster-role.yaml | 7 ---
...> get-storageclasses-cluster-role-binding.yaml} | 30 ++++++-------
...n.yaml => get-storageclasses-cluster-role.yaml} | 31 ++++++-------
pkg/resources/config/rbac/kustomization.yaml | 2 +
.../config/rbac/namespaced/operator-role.yaml | 7 ---
pkg/resources/resources_test.go | 52 ++++++++++++++++++++++
9 files changed, 111 insertions(+), 62 deletions(-)
diff --git a/helm/camel-k/templates/rbacs-common.yaml
b/helm/camel-k/templates/rbacs-common.yaml
index 4df1868df..86899d111 100644
--- a/helm/camel-k/templates/rbacs-common.yaml
+++ b/helm/camel-k/templates/rbacs-common.yaml
@@ -185,6 +185,21 @@ rules:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ labels:
+ app: camel-k
+ name: {{ include "camel-k.fullname" . }}-operator-storageclasses
+rules:
+- apiGroups:
+ - storage.k8s.io
+ resources:
+ - storageclasses
+ verbs:
+ - get
+ - list
+---
+apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
@@ -255,3 +270,18 @@ subjects:
- kind: ServiceAccount
name: {{ include "camel-k.fullname" . }}-operator
namespace: '{{ .Release.Namespace }}'
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ labels:
+ app: camel-k
+ name: {{ include "camel-k.fullname" . }}-operator-storageclasses
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: {{ include "camel-k.fullname" . }}-operator-storageclasses
+subjects:
+- kind: ServiceAccount
+ name: {{ include "camel-k.fullname" . }}-operator
+ namespace: '{{ .Release.Namespace }}'
diff --git a/helm/camel-k/templates/rbacs-descoped.yaml
b/helm/camel-k/templates/rbacs-descoped.yaml
index eb11fa0d6..5f315c641 100644
--- a/helm/camel-k/templates/rbacs-descoped.yaml
+++ b/helm/camel-k/templates/rbacs-descoped.yaml
@@ -149,13 +149,6 @@ rules:
- list
- patch
- watch
-- apiGroups:
- - storage.k8s.io
- resources:
- - storageclasses
- verbs:
- - get
- - list
- apiGroups:
- ""
resources:
diff --git a/helm/camel-k/templates/rbacs-namespaced.yaml
b/helm/camel-k/templates/rbacs-namespaced.yaml
index 5c53106a8..e6d421037 100644
--- a/helm/camel-k/templates/rbacs-namespaced.yaml
+++ b/helm/camel-k/templates/rbacs-namespaced.yaml
@@ -199,13 +199,6 @@ rules:
- get
- list
- watch
-- apiGroups:
- - storage.k8s.io
- resources:
- - storageclasses
- verbs:
- - get
- - list
- apiGroups:
- ""
resources:
diff --git a/pkg/resources/config/rbac/descoped/operator-cluster-role.yaml
b/pkg/resources/config/rbac/descoped/operator-cluster-role.yaml
index 5e51a35c8..4764e2451 100644
--- a/pkg/resources/config/rbac/descoped/operator-cluster-role.yaml
+++ b/pkg/resources/config/rbac/descoped/operator-cluster-role.yaml
@@ -153,13 +153,6 @@ rules:
- patch
- watch
# Required by mount trait
-- apiGroups:
- - storage.k8s.io
- resources:
- - storageclasses
- verbs:
- - get
- - list
- apiGroups:
- ""
resources:
diff --git a/pkg/resources/config/rbac/kustomization.yaml
b/pkg/resources/config/rbac/get-storageclasses-cluster-role-binding.yaml
similarity index 67%
copy from pkg/resources/config/rbac/kustomization.yaml
copy to pkg/resources/config/rbac/get-storageclasses-cluster-role-binding.yaml
index 9df92da16..6cd3db353 100644
--- a/pkg/resources/config/rbac/kustomization.yaml
+++ b/pkg/resources/config/rbac/get-storageclasses-cluster-role-binding.yaml
@@ -15,20 +15,16 @@
# limitations under the License.
# ---------------------------------------------------------------------------
-#
-# rbac resources applicable for all kubernetes platforms
-#
-apiVersion: kustomize.config.k8s.io/v1beta1
-kind: Kustomization
-
-resources:
-- builder-role.yaml
-- builder-role-openshift.yaml
-- dev-registry-role.yaml
-- kamelets-viewer-role.yaml
-- builder-role-binding.yaml
-- builder-role-binding-openshift.yaml
-- dev-registry-role-binding.yaml
-- kamelets-viewer-role-binding.yaml
-- get-namespaces-cluster-role.yaml
-- get-namespaces-cluster-role-binding.yaml
+kind: ClusterRoleBinding
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+ name: camel-k-operator-storageclasses
+ labels:
+ app: "camel-k"
+subjects:
+- kind: ServiceAccount
+ name: camel-k-operator
+roleRef:
+ kind: ClusterRole
+ name: camel-k-operator-storageclasses
+ apiGroup: rbac.authorization.k8s.io
diff --git a/pkg/resources/config/rbac/kustomization.yaml
b/pkg/resources/config/rbac/get-storageclasses-cluster-role.yaml
similarity index 67%
copy from pkg/resources/config/rbac/kustomization.yaml
copy to pkg/resources/config/rbac/get-storageclasses-cluster-role.yaml
index 9df92da16..ec219ffa9 100644
--- a/pkg/resources/config/rbac/kustomization.yaml
+++ b/pkg/resources/config/rbac/get-storageclasses-cluster-role.yaml
@@ -15,20 +15,17 @@
# limitations under the License.
# ---------------------------------------------------------------------------
-#
-# rbac resources applicable for all kubernetes platforms
-#
-apiVersion: kustomize.config.k8s.io/v1beta1
-kind: Kustomization
-
-resources:
-- builder-role.yaml
-- builder-role-openshift.yaml
-- dev-registry-role.yaml
-- kamelets-viewer-role.yaml
-- builder-role-binding.yaml
-- builder-role-binding-openshift.yaml
-- dev-registry-role-binding.yaml
-- kamelets-viewer-role-binding.yaml
-- get-namespaces-cluster-role.yaml
-- get-namespaces-cluster-role-binding.yaml
+kind: ClusterRole
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+ name: camel-k-operator-storageclasses
+ labels:
+ app: "camel-k"
+rules:
+- apiGroups:
+ - storage.k8s.io
+ resources:
+ - storageclasses
+ verbs:
+ - get
+ - list
diff --git a/pkg/resources/config/rbac/kustomization.yaml
b/pkg/resources/config/rbac/kustomization.yaml
index 9df92da16..4fbda038e 100644
--- a/pkg/resources/config/rbac/kustomization.yaml
+++ b/pkg/resources/config/rbac/kustomization.yaml
@@ -32,3 +32,5 @@ resources:
- kamelets-viewer-role-binding.yaml
- get-namespaces-cluster-role.yaml
- get-namespaces-cluster-role-binding.yaml
+- get-storageclasses-cluster-role.yaml
+- get-storageclasses-cluster-role-binding.yaml
diff --git a/pkg/resources/config/rbac/namespaced/operator-role.yaml
b/pkg/resources/config/rbac/namespaced/operator-role.yaml
index c9054a877..276fcac2b 100644
--- a/pkg/resources/config/rbac/namespaced/operator-role.yaml
+++ b/pkg/resources/config/rbac/namespaced/operator-role.yaml
@@ -204,13 +204,6 @@ rules:
- get
- list
- watch
-- apiGroups:
- - storage.k8s.io
- resources:
- - storageclasses
- verbs:
- - get
- - list
# Service Accounts (dynamic SA creation)
- apiGroups:
- ""
diff --git a/pkg/resources/resources_test.go b/pkg/resources/resources_test.go
index 42bb9cd27..8d45de4b9 100644
--- a/pkg/resources/resources_test.go
+++ b/pkg/resources/resources_test.go
@@ -18,10 +18,13 @@ limitations under the License.
package resources
import (
+ "slices"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ rbacv1 "k8s.io/api/rbac/v1"
+ "sigs.k8s.io/yaml"
)
func NoErrorAndNotEmptyBytes(t *testing.T, path string, callable func(path
string) ([]byte, error)) {
@@ -128,3 +131,52 @@ func TestCRDResources(t *testing.T) {
NoErrorAndNotEmptyBytes(t,
"/config/crd/bases/camel.apache.org_kamelets.yaml", Resource)
NoErrorAndNotEmptyBytes(t,
"/config/crd/bases/camel.apache.org_pipes.yaml", Resource)
}
+
+// StorageClass is a cluster scoped resource: a namespaced Role can never
grant access to it,
+// so the permission must be granted through a dedicated ClusterRole in every
installation mode.
+func TestStorageClassesRBACIsClusterScoped(t *testing.T) {
+ hasStorageClasses := func(rules []rbacv1.PolicyRule) bool {
+ for _, rule := range rules {
+ if slices.Contains(rule.Resources, "storageclasses") {
+ return true
+ }
+ }
+
+ return false
+ }
+
+ var role rbacv1.Role
+ data, err := Resource("config/rbac/namespaced/operator-role.yaml")
+ require.NoError(t, err)
+ require.NoError(t, yaml.Unmarshal(data, &role))
+ assert.False(t, hasStorageClasses(role.Rules), "namespaced operator
Role cannot grant access to cluster scoped storageclasses")
+
+ var descopedRole rbacv1.ClusterRole
+ data, err = Resource("config/rbac/descoped/operator-cluster-role.yaml")
+ require.NoError(t, err)
+ require.NoError(t, yaml.Unmarshal(data, &descopedRole))
+ assert.False(t, hasStorageClasses(descopedRole.Rules), "storageclasses
must be granted by the common ClusterRole only")
+
+ var clusterRole rbacv1.ClusterRole
+ data, err = Resource("config/rbac/get-storageclasses-cluster-role.yaml")
+ require.NoError(t, err)
+ require.NoError(t, yaml.Unmarshal(data, &clusterRole))
+ require.True(t, hasStorageClasses(clusterRole.Rules))
+ assert.Equal(t, []string{"storage.k8s.io"},
clusterRole.Rules[0].APIGroups)
+ assert.ElementsMatch(t, []string{"get", "list"},
clusterRole.Rules[0].Verbs)
+
+ var binding rbacv1.ClusterRoleBinding
+ data, err =
Resource("config/rbac/get-storageclasses-cluster-role-binding.yaml")
+ require.NoError(t, err)
+ require.NoError(t, yaml.Unmarshal(data, &binding))
+ assert.Equal(t, clusterRole.Name, binding.RoleRef.Name)
+ assert.Equal(t, "ClusterRole", binding.RoleRef.Kind)
+ require.Len(t, binding.Subjects, 1)
+ assert.Equal(t, "camel-k-operator", binding.Subjects[0].Name)
+
+ // the common RBAC kustomization must ship them, so they apply to every
installation mode
+ kustomization, err := ResourceAsString("config/rbac/kustomization.yaml")
+ require.NoError(t, err)
+ assert.Contains(t, kustomization,
"get-storageclasses-cluster-role.yaml")
+ assert.Contains(t, kustomization,
"get-storageclasses-cluster-role-binding.yaml")
+}