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/05 16:38:39 UTC

(camel-k) branch main 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 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 5aed911f5 fix(#4961): Improve cross-namespace check for Kamelet refs
5aed911f5 is described below

commit 5aed911f5ec60a253b72ddf9110df99c97dd36ed
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      |  11 +++
 pkg/util/bindings/catalog_test.go | 197 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 208 insertions(+)

diff --git a/pkg/util/bindings/catalog.go b/pkg/util/bindings/catalog.go
index 7cd2552b0..6fa218ec1 100644
--- a/pkg/util/bindings/catalog.go
+++ b/pkg/util/bindings/catalog.go
@@ -23,6 +23,7 @@ import (
 
 	v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
 	"github.com/apache/camel-k/v2/pkg/apis/camel/v1alpha1"
+	"github.com/apache/camel-k/v2/pkg/platform"
 )
 
 var bindingProviders []BindingProvider
@@ -75,6 +76,11 @@ func validateEndpoint(ctx BindingContext, e v1.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 {
+		// referencing default Kamelets in operator namespace is allowed
+		if e.Ref.Kind == v1.KameletKind && e.Ref.Namespace == platform.GetOperatorNamespace() {
+			return nil
+		}
+
 		return errors.New("cross-namespace references are not allowed in Pipe")
 	}
 	return nil
@@ -104,6 +110,11 @@ func validateEndpointV1alpha1(ctx V1alpha1BindingContext, e v1alpha1.Endpoint) e
 		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 {
+		// referencing default Kamelets in operator namespace is allowed
+		if e.Ref.Kind == v1.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..b2b59f420
--- /dev/null
+++ b/pkg/util/bindings/catalog_test.go
@@ -0,0 +1,197 @@
+/*
+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/v2/pkg/apis/camel/v1"
+	corev1 "k8s.io/api/core/v1"
+	eventing "knative.dev/eventing/pkg/apis/eventing/v1"
+
+	"github.com/apache/camel-k/v2/pkg/util/test"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestValidateEndpoint(t *testing.T) {
+	testcases := []struct {
+		name              string
+		namespace         string
+		operatorNamespace string
+		endpoint          v1.Endpoint
+	}{
+		{
+			name:      "kamelet-ref",
+			namespace: "test",
+			endpoint: v1.Endpoint{
+				Ref: &corev1.ObjectReference{
+					Kind:       v1.KameletKind,
+					APIVersion: v1.SchemeGroupVersion.String(),
+					Name:       "foo-kamelet",
+				},
+			},
+		},
+		{
+			name:      "kamelet-ref-in-namespace",
+			namespace: "test",
+			endpoint: v1.Endpoint{
+				Ref: &corev1.ObjectReference{
+					Kind:       v1.KameletKind,
+					Namespace:  "test",
+					APIVersion: v1.SchemeGroupVersion.String(),
+					Name:       "foo-kamelet",
+				},
+			},
+		},
+		{
+			name:              "kamelet-ref-in-operator-namespace",
+			namespace:         "test",
+			operatorNamespace: "global",
+			endpoint: v1.Endpoint{
+				Ref: &corev1.ObjectReference{
+					Kind:       v1.KameletKind,
+					Namespace:  "global",
+					APIVersion: v1.SchemeGroupVersion.String(),
+					Name:       "foo-kamelet",
+				},
+			},
+		},
+		{
+			name:      "knative-broker-ref",
+			namespace: "test",
+			endpoint: v1.Endpoint{
+				Ref: &corev1.ObjectReference{
+					Kind:       "Broker",
+					APIVersion: eventing.SchemeGroupVersion.String(),
+					Name:       "foo-broker",
+				},
+			},
+		},
+		{
+			name:      "knative-broker-ref-in-namespace",
+			namespace: "test",
+			endpoint: v1.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          v1.Endpoint
+	}{
+		{
+			name:      "kamelet-ref-and-uri",
+			namespace: "test",
+			endpoint: v1.Endpoint{
+				URI: &uri,
+				Ref: &corev1.ObjectReference{
+					Kind:       v1.KameletKind,
+					APIVersion: v1.SchemeGroupVersion.String(),
+					Name:       "foo-kamelet",
+				},
+			},
+		},
+		{
+			name:      "kamelet-ref-cross-namespace",
+			namespace: "test",
+			endpoint: v1.Endpoint{
+				Ref: &corev1.ObjectReference{
+					Kind:       v1.KameletKind,
+					Namespace:  "other",
+					APIVersion: v1.SchemeGroupVersion.String(),
+					Name:       "foo-kamelet",
+				},
+			},
+		},
+		{
+			name:              "knative-broker-ref-in-operator-namespace",
+			namespace:         "test",
+			operatorNamespace: "global",
+			endpoint: v1.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")
+		})
+	}
+}