You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by pc...@apache.org on 2026/09/23 05:56:54 UTC
(camel-k) 02/02: Fix #6778: Improve denied Kamelet diagnostics
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
commit bb4a4955c6841f9928ba30286ad885aafa78075c
Author: AllanAlmeida <al...@gmail.com>
AuthorDate: Tue Sep 22 11:16:12 2026 -0300
Fix #6778: Improve denied Kamelet diagnostics
Generated-by: OpenAI Codex
---
pkg/trait/kamelets.go | 4 +--
pkg/trait/kamelets_test.go | 66 ++++++++++++++++++++++++++++++++--
pkg/util/kubernetes/permission_test.go | 36 +++++++++++++++++++
3 files changed, 101 insertions(+), 5 deletions(-)
diff --git a/pkg/trait/kamelets.go b/pkg/trait/kamelets.go
index 6b3c16133..dad678579 100644
--- a/pkg/trait/kamelets.go
+++ b/pkg/trait/kamelets.go
@@ -234,8 +234,8 @@ func (t *kameletsTrait) calculateNamespaces(e *Environment, defaultNamespaces ..
return nil, err
}
if !ok {
- return nil, fmt.Errorf("cross-namespace Integration reference authorization denied for the ServiceAccount %s and resources kamelets",
- e.Integration.Spec.ServiceAccountName)
+ return nil, fmt.Errorf("cross-namespace Integration reference authorization denied for the ServiceAccount %s and Kamelet %s in namespace %s",
+ e.Integration.Spec.ServiceAccountName, getKameletKey(kml), ns)
}
}
diff --git a/pkg/trait/kamelets_test.go b/pkg/trait/kamelets_test.go
index 91652f4dd..d471d4ed0 100644
--- a/pkg/trait/kamelets_test.go
+++ b/pkg/trait/kamelets_test.go
@@ -18,11 +18,14 @@ limitations under the License.
package trait
import (
+ "context"
"encoding/json"
+ "errors"
"testing"
v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
traitv1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1/trait"
+ camelclient "github.com/apache/camel-k/v2/pkg/client"
"github.com/apache/camel-k/v2/pkg/internal"
"github.com/apache/camel-k/v2/pkg/util/camel"
@@ -32,9 +35,21 @@ import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
+ kubernetesfake "k8s.io/client-go/kubernetes/fake"
+ authorizationclientv1 "k8s.io/client-go/kubernetes/typed/authorization/v1"
+ k8stesting "k8s.io/client-go/testing"
"k8s.io/utils/ptr"
)
+type authorizationClient struct {
+ camelclient.Client
+ authorization authorizationclientv1.AuthorizationV1Interface
+}
+
+func (c *authorizationClient) AuthorizationV1() authorizationclientv1.AuthorizationV1Interface {
+ return c.authorization
+}
+
func TestConfigurationNoKameletsUsed(t *testing.T) {
trait, environment := createKameletsTestEnvironment(`
- from:
@@ -772,7 +787,12 @@ func TestKameletNamespaceParameter(t *testing.T) {
func TestCalculateKameletNamespaces(t *testing.T) {
namespaces, err := calculateNamespaces(
- []string{"my-kamelet", "my-kamelet?kameletNamespace=ns1", "my-kamelet?kameletVersion=v2&kameletNamespace=ns2"},
+ []string{
+ "my-kamelet",
+ "my-kamelet?kameletNamespace=ns1",
+ "another-kamelet?kameletNamespace=ns1",
+ "my-kamelet?kameletVersion=v2&kameletNamespace=ns2",
+ },
)
require.NoError(t, err)
assert.Len(t, namespaces, 2)
@@ -780,6 +800,15 @@ func TestCalculateKameletNamespaces(t *testing.T) {
assert.Contains(t, namespaces, "ns2")
}
+func TestCalculateKameletNamespacesInvalidReference(t *testing.T) {
+ trait, environment := createKameletsTestEnvironment("")
+ trait.List = "invalid%reference?kameletNamespace=ns1"
+
+ namespaces, err := trait.calculateNamespaces(environment)
+ require.ErrorContains(t, err, "could not parse kamelet namespace")
+ assert.Nil(t, namespaces)
+}
+
func TestKameletMultiNamespace(t *testing.T) {
flow := `
- from:
@@ -835,7 +864,7 @@ func TestKameletMultiNamespace(t *testing.T) {
err = trait.Apply(environment)
require.Error(t, err)
assert.Equal(t, "cross-namespace Integration reference authorization denied for the ServiceAccount unauth-sa "+
- "and resources kamelets", err.Error())
+ "and Kamelet extra in namespace ns1", err.Error())
// Now we should good to go
environment.Integration.Namespace = "default"
environment.Integration.Spec.ServiceAccountName = "cross-ns-sa"
@@ -870,7 +899,38 @@ func TestKameletMultiNamespaceDeniedResource(t *testing.T) {
err = trait.Apply(environment)
require.Error(t, err)
assert.Equal(t, "cross-namespace Integration reference authorization denied for the ServiceAccount cross-ns-sa "+
- "and resources kamelets", err.Error())
+ "and Kamelet restricted-kamelet in namespace ns1", err.Error())
+}
+
+func TestKameletMultiNamespacePermissionCheckError(t *testing.T) {
+ flow := `
+- from:
+ uri: kamelet:timer
+ steps:
+ - to: kamelet:extra?kameletNamespace=ns1
+`
+ trait, environment := createKameletsTestEnvironment(flow)
+ environment.Ctx = context.Background()
+ environment.Integration.Namespace = "default"
+ environment.Integration.Spec.ServiceAccountName = "cross-ns-sa"
+
+ authorizationError := errors.New("subject access review failed")
+ client := kubernetesfake.NewSimpleClientset()
+ client.PrependReactor("create", "subjectaccessreviews", func(k8stesting.Action) (bool, runtime.Object, error) {
+ return true, nil, authorizationError
+ })
+ environment.Client = &authorizationClient{
+ Client: environment.Client,
+ authorization: client.AuthorizationV1(),
+ }
+
+ enabled, condition, err := trait.Configure(environment)
+ require.NoError(t, err)
+ assert.True(t, enabled)
+ assert.Nil(t, condition)
+
+ err = trait.Apply(environment)
+ require.ErrorIs(t, err, authorizationError)
}
func TestKameletMultiNamespaceMissing(t *testing.T) {
diff --git a/pkg/util/kubernetes/permission_test.go b/pkg/util/kubernetes/permission_test.go
index 10ed4f878..1d4182584 100644
--- a/pkg/util/kubernetes/permission_test.go
+++ b/pkg/util/kubernetes/permission_test.go
@@ -19,10 +19,13 @@ package kubernetes
import (
"context"
+ "errors"
"testing"
authorizationv1 "k8s.io/api/authorization/v1"
+ apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/kubernetes/fake"
k8stesting "k8s.io/client-go/testing"
@@ -61,3 +64,36 @@ func TestCheckServiceAccountPermissionByResourceName(t *testing.T) {
require.NoError(t, err)
require.False(t, allowed)
}
+
+func TestCheckServiceAccountPermissionForbidden(t *testing.T) {
+ client := fake.NewSimpleClientset()
+ client.PrependReactor("create", "subjectaccessreviews", func(k8stesting.Action) (bool, runtime.Object, error) {
+ return true, nil, apierrors.NewForbidden(
+ schema.GroupResource{Group: "authorization.k8s.io", Resource: "subjectaccessreviews"},
+ "",
+ errors.New("forbidden"),
+ )
+ })
+
+ allowed, err := CheckServiceAccountPermission(
+ context.Background(), client, "system:serviceaccount:source:integration",
+ "camel.apache.org", "kamelets", "target", "denied-kamelet", "get",
+ )
+ require.NoError(t, err)
+ require.False(t, allowed)
+}
+
+func TestCheckServiceAccountPermissionError(t *testing.T) {
+ expected := errors.New("subject access review failed")
+ client := fake.NewSimpleClientset()
+ client.PrependReactor("create", "subjectaccessreviews", func(k8stesting.Action) (bool, runtime.Object, error) {
+ return true, nil, expected
+ })
+
+ allowed, err := CheckServiceAccountPermission(
+ context.Background(), client, "system:serviceaccount:source:integration",
+ "camel.apache.org", "kamelets", "target", "denied-kamelet", "get",
+ )
+ require.ErrorIs(t, err, expected)
+ require.False(t, allowed)
+}