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 a1c6c6978 fix(#4336): Restrict Knative binding provider execution
a1c6c6978 is described below

commit a1c6c69783618c2d25977b8c16e6102db81aa84c
Author: Christoph Deppisch <[email protected]>
AuthorDate: Mon May 8 20:54:44 2023 +0200

    fix(#4336): Restrict Knative binding provider execution
    
    - Only run the binding provider when Knative is installed on the cluster
    - Only run the binding provider when referencing a known Knative resource 
(e.g. broker, channel, service)
---
 pkg/util/bindings/knative_ref.go      |  28 ++++++
 pkg/util/bindings/knative_ref_test.go | 155 ++++++++++++++++++++++++++++++++++
 2 files changed, 183 insertions(+)

diff --git a/pkg/util/bindings/knative_ref.go b/pkg/util/bindings/knative_ref.go
index 2859692a4..0bd0d7bcf 100644
--- a/pkg/util/bindings/knative_ref.go
+++ b/pkg/util/bindings/knative_ref.go
@@ -25,6 +25,8 @@ import (
        v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
        knativeapis "github.com/apache/camel-k/v2/pkg/apis/camel/v1/knative"
        v1alpha1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1alpha1"
+       corev1 "k8s.io/api/core/v1"
+       "k8s.io/apimachinery/pkg/runtime/schema"
 
        "github.com/apache/camel-k/v2/pkg/util/knative"
        "github.com/apache/camel-k/v2/pkg/util/uri"
@@ -46,6 +48,17 @@ func (k KnativeRefBindingProvider) Translate(ctx 
BindingContext, endpointCtx End
                return nil, nil
        }
 
+       if ok, err := isKnownKnativeResource(e.Ref); !ok {
+               // only operates on known Knative endpoint resources (e.g. 
channels, brokers)
+               return nil, err
+       }
+
+       if knativeInstalled, _ := knative.IsInstalled(ctx.Client); 
!knativeInstalled {
+               // works only when Knative is installed
+               return nil, fmt.Errorf("integration referencing Knative 
endpoint '%s' that cannot run, "+
+                       "because Knative is not installed on the cluster", 
e.Ref.Name)
+       }
+
        serviceType, err := knative.GetServiceType(*e.Ref)
        if err != nil {
                return nil, err
@@ -97,6 +110,21 @@ func (k KnativeRefBindingProvider) Translate(ctx 
BindingContext, endpointCtx End
        }, nil
 }
 
+func isKnownKnativeResource(ref *corev1.ObjectReference) (bool, error) {
+       gv, err := schema.ParseGroupVersion(ref.APIVersion)
+       if err != nil {
+               return false, err
+       }
+
+       for _, endpoint := range knative.KnownEndpointKinds {
+               if endpoint.Group == gv.Group && endpoint.Kind == ref.Kind {
+                       return true, nil
+               }
+       }
+
+       return false, nil
+}
+
 // Order --.
 func (k KnativeRefBindingProvider) Order() int {
        // Executes as last, as it can be used as fallback for all unknown 
object references
diff --git a/pkg/util/bindings/knative_ref_test.go 
b/pkg/util/bindings/knative_ref_test.go
new file mode 100644
index 000000000..9d06ebed3
--- /dev/null
+++ b/pkg/util/bindings/knative_ref_test.go
@@ -0,0 +1,155 @@
+/*
+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"
+
+       "github.com/apache/camel-k/v2/pkg/util/test"
+       "github.com/stretchr/testify/assert"
+       v1 "k8s.io/api/core/v1"
+
+       camelv1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
+)
+
+func TestKnativeRefBinding(t *testing.T) {
+       testcases := []struct {
+               endpoint camelv1.Endpoint
+               uri      string
+       }{
+               {
+                       endpoint: camelv1.Endpoint{
+                               Ref: &v1.ObjectReference{
+                                       Kind:       "Broker",
+                                       Name:       "default",
+                                       APIVersion: "eventing.knative.dev/v1",
+                               },
+                       },
+                       uri: 
"knative:event?apiVersion=eventing.knative.dev%2Fv1&kind=Broker&name=default",
+               },
+               {
+                       endpoint: camelv1.Endpoint{
+                               Ref: &v1.ObjectReference{
+                                       Kind:       "Channel",
+                                       Name:       "mychannel",
+                                       APIVersion: "messaging.knative.dev/v1",
+                               },
+                       },
+                       uri: 
"knative:channel/mychannel?apiVersion=messaging.knative.dev%2Fv1&kind=Channel",
+               },
+               {
+                       endpoint: camelv1.Endpoint{
+                               Ref: &v1.ObjectReference{
+                                       Kind:       "Service",
+                                       Name:       "myservice",
+                                       APIVersion: "serving.knative.dev/v1",
+                               },
+                       },
+                       uri: 
"knative:endpoint/myservice?apiVersion=serving.knative.dev%2Fv1&kind=Service",
+               },
+       }
+
+       for i, tc := range testcases {
+               t.Run(fmt.Sprintf("test-%d-%s", i, tc.endpoint.Ref.Kind), 
func(t *testing.T) {
+                       ctx, cancel := context.WithCancel(context.Background())
+                       defer cancel()
+
+                       client, err := test.NewFakeClient()
+                       assert.NoError(t, err)
+
+                       bindingContext := BindingContext{
+                               Ctx:       ctx,
+                               Client:    client,
+                               Namespace: "test",
+                               Profile:   camelv1.TraitProfileKnative,
+                       }
+
+                       binding, err := 
KnativeRefBindingProvider{}.Translate(bindingContext, EndpointContext{
+                               Type: camelv1.EndpointTypeSink,
+                       }, tc.endpoint)
+                       assert.NoError(t, err)
+                       assert.NotNil(t, binding)
+                       assert.Equal(t, tc.uri, binding.URI)
+                       assert.Equal(t, camelv1.Traits{}, binding.Traits)
+               })
+       }
+}
+
+func TestUnsupportedKnativeResource(t *testing.T) {
+       ctx, cancel := context.WithCancel(context.Background())
+       defer cancel()
+
+       client, err := test.NewFakeClient()
+       assert.NoError(t, err)
+
+       bindingContext := BindingContext{
+               Ctx:       ctx,
+               Client:    client,
+               Namespace: "test",
+               Profile:   camelv1.TraitProfileKnative,
+       }
+
+       endpoint := camelv1.Endpoint{
+               Ref: &v1.ObjectReference{
+                       Kind:       "Unknown",
+                       Name:       "default",
+                       APIVersion: "eventing.knative.dev/v1",
+               },
+       }
+
+       binding, err := KnativeRefBindingProvider{}.Translate(bindingContext, 
EndpointContext{
+               Type: camelv1.EndpointTypeSink,
+       }, endpoint)
+       assert.NoError(t, err)
+       assert.Nil(t, binding)
+}
+
+func TestKnativeNotInstalled(t *testing.T) {
+       ctx, cancel := context.WithCancel(context.Background())
+       defer cancel()
+
+       client, err := test.NewFakeClient()
+       assert.NoError(t, err)
+
+       // disable the knative service api
+       fakeClient := client.(*test.FakeClient) //nolint
+       fakeClient.DisableAPIGroupDiscovery("serving.knative.dev/v1")
+
+       bindingContext := BindingContext{
+               Ctx:       ctx,
+               Client:    client,
+               Namespace: "test",
+               Profile:   camelv1.TraitProfileKnative,
+       }
+
+       endpoint := camelv1.Endpoint{
+               Ref: &v1.ObjectReference{
+                       Kind:       "Broker",
+                       Name:       "default",
+                       APIVersion: "eventing.knative.dev/v1",
+               },
+       }
+
+       binding, err := KnativeRefBindingProvider{}.Translate(bindingContext, 
EndpointContext{
+               Type: camelv1.EndpointTypeSink,
+       }, endpoint)
+       assert.Error(t, err, "integration referencing Knative endpoint 
'default' that cannot run, because Knative is not installed on the cluster")
+       assert.Nil(t, binding)
+}

Reply via email to