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 2023/12/07 07:57:11 UTC

(camel-k) branch release-1.10.x updated: fix(#4961): Improve cross-namespace check for Kamelet refs

This is an automated email from the ASF dual-hosted git repository.

pcongiusti pushed a commit to branch release-1.10.x
in repository https://gitbox.apache.org/repos/asf/camel-k.git


The following commit(s) were added to refs/heads/release-1.10.x by this push:
     new 0dafa9b9c fix(#4961): Improve cross-namespace check for Kamelet refs
0dafa9b9c is described below

commit 0dafa9b9cc1f32179ef3c20b997c14a8b5e1383a
Author: Christoph Deppisch <cd...@redhat.com>
AuthorDate: Tue Dec 5 16:10:36 2023 +0100

    fix(#4961): Improve cross-namespace check for Kamelet refs
    
    - Allow explicit references to default Kamelets in operator namespace
    - Keep check on cross-namespace reference for other resources (e.g. Knative Broker)
    - Keep raising cross-namespace check errors for Kamelet references to other user namespaces
---
 pkg/util/bindings/catalog.go      |   9 +-
 pkg/util/bindings/catalog_test.go | 198 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 206 insertions(+), 1 deletion(-)

diff --git a/pkg/util/bindings/catalog.go b/pkg/util/bindings/catalog.go
index dd2e87fc6..fa32fa0b9 100644
--- a/pkg/util/bindings/catalog.go
+++ b/pkg/util/bindings/catalog.go
@@ -22,10 +22,12 @@ import (
 	"sort"
 
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/apache/camel-k/pkg/platform"
 )
 
 var bindingProviders []BindingProvider
 
+// RegisterBindingProvider --.
 func RegisterBindingProvider(bp BindingProvider) {
 	bindingProviders = append(bindingProviders, bp)
 	sort.Slice(bindingProviders, func(i, j int) bool {
@@ -58,7 +60,12 @@ func validateEndpoint(ctx BindingContext, e v1alpha1.Endpoint) error {
 		return errors.New("cannot use both ref and URI to specify an endpoint: only one of them should be used")
 	}
 	if e.Ref != nil && e.Ref.Namespace != "" && e.Ref.Namespace != ctx.Namespace {
-		return errors.New("cross-namespace references are not allowed in kamelet binding")
+		// referencing default Kamelets in operator namespace is allowed
+		if e.Ref.Kind == v1alpha1.KameletKind && e.Ref.Namespace == platform.GetOperatorNamespace() {
+			return nil
+		}
+
+		return errors.New("cross-namespace references are not allowed in KameletBinding")
 	}
 	return nil
 }
diff --git a/pkg/util/bindings/catalog_test.go b/pkg/util/bindings/catalog_test.go
new file mode 100644
index 000000000..e2f97f8f2
--- /dev/null
+++ b/pkg/util/bindings/catalog_test.go
@@ -0,0 +1,198 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package bindings
+
+import (
+	"context"
+	"fmt"
+	"testing"
+
+	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	corev1 "k8s.io/api/core/v1"
+	eventing "knative.dev/eventing/pkg/apis/eventing/v1"
+
+	"github.com/apache/camel-k/pkg/util/test"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestValidateEndpoint(t *testing.T) {
+	testcases := []struct {
+		name              string
+		namespace         string
+		operatorNamespace string
+		endpoint          v1alpha1.Endpoint
+	}{
+		{
+			name:      "kamelet-ref",
+			namespace: "test",
+			endpoint: v1alpha1.Endpoint{
+				Ref: &corev1.ObjectReference{
+					Kind:       v1alpha1.KameletKind,
+					APIVersion: v1.SchemeGroupVersion.String(),
+					Name:       "foo-kamelet",
+				},
+			},
+		},
+		{
+			name:      "kamelet-ref-in-namespace",
+			namespace: "test",
+			endpoint: v1alpha1.Endpoint{
+				Ref: &corev1.ObjectReference{
+					Kind:       v1alpha1.KameletKind,
+					Namespace:  "test",
+					APIVersion: v1.SchemeGroupVersion.String(),
+					Name:       "foo-kamelet",
+				},
+			},
+		},
+		{
+			name:              "kamelet-ref-in-operator-namespace",
+			namespace:         "test",
+			operatorNamespace: "global",
+			endpoint: v1alpha1.Endpoint{
+				Ref: &corev1.ObjectReference{
+					Kind:       v1alpha1.KameletKind,
+					Namespace:  "global",
+					APIVersion: v1.SchemeGroupVersion.String(),
+					Name:       "foo-kamelet",
+				},
+			},
+		},
+		{
+			name:      "knative-broker-ref",
+			namespace: "test",
+			endpoint: v1alpha1.Endpoint{
+				Ref: &corev1.ObjectReference{
+					Kind:       "Broker",
+					APIVersion: eventing.SchemeGroupVersion.String(),
+					Name:       "foo-broker",
+				},
+			},
+		},
+		{
+			name:      "knative-broker-ref-in-namespace",
+			namespace: "test",
+			endpoint: v1alpha1.Endpoint{
+				Ref: &corev1.ObjectReference{
+					Kind:       "Broker",
+					Namespace:  "test",
+					APIVersion: eventing.SchemeGroupVersion.String(),
+					Name:       "foo-broker",
+				},
+			},
+		},
+	}
+
+	for i, tc := range testcases {
+		t.Run(fmt.Sprintf("test-%d-%s", i, tc.name), func(t *testing.T) {
+			if tc.operatorNamespace != "" {
+				t.Setenv("NAMESPACE", tc.operatorNamespace)
+			}
+
+			ctx, cancel := context.WithCancel(context.Background())
+			defer cancel()
+
+			client, err := test.NewFakeClient()
+			assert.NoError(t, err)
+
+			bindingContext := BindingContext{
+				Ctx:       ctx,
+				Client:    client,
+				Namespace: tc.namespace,
+				Profile:   v1.DefaultTraitProfile,
+			}
+
+			err = validateEndpoint(bindingContext, tc.endpoint)
+			assert.NoError(t, err)
+		})
+	}
+}
+
+func TestValidateEndpointError(t *testing.T) {
+	uri := "log:info"
+
+	testcases := []struct {
+		name              string
+		namespace         string
+		operatorNamespace string
+		endpoint          v1alpha1.Endpoint
+	}{
+		{
+			name:      "kamelet-ref-and-uri",
+			namespace: "test",
+			endpoint: v1alpha1.Endpoint{
+				URI: &uri,
+				Ref: &corev1.ObjectReference{
+					Kind:       v1alpha1.KameletKind,
+					APIVersion: v1.SchemeGroupVersion.String(),
+					Name:       "foo-kamelet",
+				},
+			},
+		},
+		{
+			name:      "kamelet-ref-cross-namespace",
+			namespace: "test",
+			endpoint: v1alpha1.Endpoint{
+				Ref: &corev1.ObjectReference{
+					Kind:       v1alpha1.KameletKind,
+					Namespace:  "other",
+					APIVersion: v1.SchemeGroupVersion.String(),
+					Name:       "foo-kamelet",
+				},
+			},
+		},
+		{
+			name:              "knative-broker-ref-in-operator-namespace",
+			namespace:         "test",
+			operatorNamespace: "global",
+			endpoint: v1alpha1.Endpoint{
+				Ref: &corev1.ObjectReference{
+					Kind:       "Broker",
+					Namespace:  "global",
+					APIVersion: eventing.SchemeGroupVersion.String(),
+					Name:       "foo-broker",
+				},
+			},
+		},
+	}
+
+	for i, tc := range testcases {
+		t.Run(fmt.Sprintf("test-%d-%s", i, tc.name), func(t *testing.T) {
+			if tc.operatorNamespace != "" {
+				t.Setenv("NAMESPACE", tc.operatorNamespace)
+			}
+
+			ctx, cancel := context.WithCancel(context.Background())
+			defer cancel()
+
+			client, err := test.NewFakeClient()
+			assert.NoError(t, err)
+
+			bindingContext := BindingContext{
+				Ctx:       ctx,
+				Client:    client,
+				Namespace: tc.namespace,
+				Profile:   v1.DefaultTraitProfile,
+			}
+
+			err = validateEndpoint(bindingContext, tc.endpoint)
+			assert.Error(t, err, "cross-namespace references are not allowed in Pipe")
+		})
+	}
+}