You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by GitBox <gi...@apache.org> on 2021/08/18 04:54:27 UTC

[GitHub] [camel-k] claudio4j opened a new pull request #2577: trait: Add tests for route trait and read certificate from secrets

claudio4j opened a new pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577


   <!-- Description -->
   * Add parameters to read TLS certificates from secrets
   * Add unit tests for route TLS configuration
   * Add e2e tests for route TLS configuration
   * Add example in route trait documentation
   
   **Release Note**
   ```release-note
   trait/route: Add support to read certificates from secrets
   ```
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#issuecomment-912530975


   > I'm not sure I understand why it's necessary for users to deal with low level resource mounting and Quarkus properties. Could the user provide only the secret name and the termination type, then the trait would take care of mounting the secret and set the Quarkus properties accordingly?
   
   It just happen that using quarkus http requires these quarkus properties for [SSL setup](https://quarkus.io/guides/http-reference#ssl), whatever http client the user may choose it may require a different set of parameters to setup it. For example,   [Netty SSL](https://github.com/apache/camel-k/blob/main/examples/http/NettySecureServer.java#L18) requires mounting `-resource file:KeyStore.jks@/etc/ssl/keystore.jks ` to setup `sslContextParameters` object. With that said, it would be difficult to look at every SSL setup to automate in route trait.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#issuecomment-910519529


   retest this please
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] astefanutti commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
astefanutti commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r691060263



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,124 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/tls"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "my-combined-tls"
+	keyName = "my-key"
+	certName = "my-cert"
+	keyFilePath = "files/key.key"
+	certFilePath = "files/crt.crt"
+)
+
+func TestRunRouteTLS(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		createSecrets(ns)
+
+		refKey := secretName + "/" + keyName
+		refCert := secretName + "/" + certName
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/NettyServer.java",
+			"-t", "route.enabled=true",
+			"-t", "route.tls-termination=edge",
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+		).Execute()).To(Succeed())
+		Eventually(IntegrationPodPhase(ns, "netty-server"), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route https works", func(t *testing.T) {
+			route := Route(ns, "netty-server")
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request
+			time.Sleep(3 * time.Second)
+			response := httpsRequest(t, fmt.Sprintf("https://%s/hello", route().Spec.Host))
+			assert.Equal(t, "Hello World", response)
+		})
+		// Cleanup
+		Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+	// })
+	})
+}
+
+func httpsRequest(t *testing.T, url string) string {
+	transCfg := &http.Transport{
+		// ignore self signed SSL certificates
+		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},

Review comment:
       It would be better to use the CA that signed the certificate.

##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,124 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/tls"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "my-combined-tls"
+	keyName = "my-key"
+	certName = "my-cert"
+	keyFilePath = "files/key.key"

Review comment:
       To improve readability and maintainability, it'd be better to have those filles code-generated. You can find an example at https://github.com/apache/camel-k/blob/69f0a4bc95f4f1efa6458d241fbc503cb979a7b0/e2e/common/build/maven_ca_secret_test.go.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r701904115



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,382 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+	waitBeforeHttpRequest = 6 * time.Second
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+// self-signed certificate used when making the https request
+var certPem []byte
+
+// the e2e tests run on openshift3 in CI and there is no object to retrieve the base domain name
+// to create a valid hostname to later have it validate when doing the https request
+// as this a e2e test to validate the route object and not the certificate itself 
+// if the base domain name cannot be retrieved from dns/cluster we can safely skip TLS verification
+// if running on openshift4, there is the dns/cluster object to retrieve the base domain name, 
+// then in this case the http client validates the TLS certificate
+var skipClientTLSVerification = false
+
+func TestRunRoutes(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object across diferent tests
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		// they refer to the certificates create in the secret and are reused the different tests
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+
+		// =============================
+		// Insecure Route / No TLS
+		// =============================
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Edge
+		// =============================
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				"-t", "route.tls-termination=edge",
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("https://%s/hello?name=TLS_Edge", route().Spec.Host)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello TLS_Edge", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Passthrough
+		// =============================
+
+		t.Run("Route passthrough https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				// the --resource mounts the certificates inside secret as files in the integration pod
+				"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+				// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+				"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+				"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+				"-t", "route.tls-termination=passthrough",

Review comment:
       Only if user is using quarkus http. If user uses netty, vertx or other http endpoint, they may require different SSL setup, for example the user may setup the `sslContextParameters` to read certificates from a custom path.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] astefanutti commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
astefanutti commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r703238991



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,401 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+	waitBeforeHttpRequest = 6 * time.Second
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+// self-signed certificate used when making the https request
+var certPem []byte
+
+// the e2e tests run on openshift3 in CI and there is no object to retrieve the base domain name
+// to create a valid hostname to later have it validate when doing the https request
+// as this a e2e test to validate the route object and not the certificate itself 
+// if the base domain name cannot be retrieved from dns/cluster we can safely skip TLS verification
+// if running on openshift4, there is the dns/cluster object to retrieve the base domain name, 
+// then in this case the http client validates the TLS certificate
+var skipClientTLSVerification = true
+
+func TestRunRoutes(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object across diferent tests
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		// they refer to the certificates create in the secret and are reused the different tests
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+
+		// =============================
+		// Insecure Route / No TLS
+		// =============================
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Edge
+		// =============================
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java", "-t", "route.tls-termination=edge").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(60 * time.Second)
+			url := fmt.Sprintf("https://%s/hello?name=TLS_Edge", route().Spec.Host)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello TLS_Edge", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Edge with custom certificate
+		// =============================
+
+		t.Run("Route Edge (custom certificate) https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				"-t", "route.tls-termination=edge",
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			code := "TLS_EdgeCustomCertificate"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Passthrough
+		// =============================
+
+		t.Run("Route passthrough https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				// the --resource mounts the certificates inside secret as files in the integration pod
+				"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+				// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+				"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+				"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+				"-t", "route.tls-termination=passthrough",
+				"-t", "container.port=8443",
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			code := "TLS_Passthrough"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Reencrypt
+		// =============================
+
+		t.Run("Route Reencrypt https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				// the --resource mounts the certificates inside secret as files in the integration pod
+				"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+				// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+				"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+				"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+				"-t", "route.tls-termination=reencrypt",
+				// the destination CA certificate which the route service uses to validate the HTTP endpoint TLS certificate
+				"-t", "route.tls-destination-ca-certificate-secret=" + refCert,
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,
+				"-t", "container.port=8443",
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			code := "TLS_Reencrypt"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Reencrypt With Openshift Service Serving CA
+		// =============================
+
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+		t.Run("Route reencrypt (with openshift service CA) https works", func(t *testing.T) {
+			// --resource references a serving certificate secret not created yet, as it is to be created
+			// when the service is created and the annotation added to it
+			// as a result eventually there is the following warning message in the console, don't worry as the pod waits for the secret to be created
+			// Warn: serving-certificate Secret not found in **** namespace, make sure to provide it before the Integration can run
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				// the --resource mounts the certificates inside secret as files in the integration pod
+				// they are used only for the pod exposing the HTTP endpoint, not the router
+				"--resource", "secret:" + servingCertificateSecret + "@/etc/ssl/" + servingCertificateSecret,
+				// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+				// these certificates are used only in the pod, not the router
+				"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + servingCertificateSecret + "/tls.crt",
+				"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + servingCertificateSecret + "/tls.key",
+				"-t", "route.tls-termination=reencrypt",
+				// these certificates are used only in the router to encrypt the connection from the client to the router
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,
+				"-t", "container.port=8443",
+			).Execute()).To(Succeed())
+
+			// should wait a little time before the service is ready
+			time.Sleep(2 * time.Second)
+			Eventually(Service(ns, integrationName)()).ShouldNot(BeNil())
+			annotations := make(map[string]string)
+			annotations["service.beta.openshift.io/serving-cert-secret-name"] = servingCertificateSecret
+			err = addAnnotation(ns, integrationName, annotations)

Review comment:
       On one hand, these tests added-value is that they script the user actions, so they are more than just short lived e2e tests. In that case, users would not add the annotation on the Service, and we still don't have an answer. Plus, I wonder if that may actually cause the instability of the test. On the other hand, I appreciate that this PR has grown larger than anticipated, so to give us the time to find a proper solution, solve that instability issue, and have that PR merged, I think we can disable this test. WDYT?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] astefanutti commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
astefanutti commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r702644623



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,401 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+	waitBeforeHttpRequest = 6 * time.Second
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+// self-signed certificate used when making the https request
+var certPem []byte
+
+// the e2e tests run on openshift3 in CI and there is no object to retrieve the base domain name
+// to create a valid hostname to later have it validate when doing the https request
+// as this a e2e test to validate the route object and not the certificate itself 
+// if the base domain name cannot be retrieved from dns/cluster we can safely skip TLS verification
+// if running on openshift4, there is the dns/cluster object to retrieve the base domain name, 
+// then in this case the http client validates the TLS certificate
+var skipClientTLSVerification = true
+
+func TestRunRoutes(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object across diferent tests
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		// they refer to the certificates create in the secret and are reused the different tests
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+
+		// =============================
+		// Insecure Route / No TLS
+		// =============================
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Edge
+		// =============================
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java", "-t", "route.tls-termination=edge").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(60 * time.Second)
+			url := fmt.Sprintf("https://%s/hello?name=TLS_Edge", route().Spec.Host)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello TLS_Edge", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Edge with custom certificate
+		// =============================
+
+		t.Run("Route Edge (custom certificate) https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				"-t", "route.tls-termination=edge",
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			code := "TLS_EdgeCustomCertificate"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Passthrough
+		// =============================
+
+		t.Run("Route passthrough https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				// the --resource mounts the certificates inside secret as files in the integration pod
+				"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+				// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+				"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+				"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+				"-t", "route.tls-termination=passthrough",
+				"-t", "container.port=8443",
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			code := "TLS_Passthrough"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Reencrypt
+		// =============================
+
+		t.Run("Route Reencrypt https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				// the --resource mounts the certificates inside secret as files in the integration pod
+				"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+				// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+				"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+				"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+				"-t", "route.tls-termination=reencrypt",
+				// the destination CA certificate which the route service uses to validate the HTTP endpoint TLS certificate
+				"-t", "route.tls-destination-ca-certificate-secret=" + refCert,
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,
+				"-t", "container.port=8443",
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			code := "TLS_Reencrypt"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Reencrypt With Openshift Service Serving CA
+		// =============================
+
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))

Review comment:
       I think this can be removed. This causes the tests to fail.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r704400173



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,401 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+	waitBeforeHttpRequest = 6 * time.Second
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+// self-signed certificate used when making the https request
+var certPem []byte
+
+// the e2e tests run on openshift3 in CI and there is no object to retrieve the base domain name
+// to create a valid hostname to later have it validate when doing the https request
+// as this a e2e test to validate the route object and not the certificate itself 
+// if the base domain name cannot be retrieved from dns/cluster we can safely skip TLS verification
+// if running on openshift4, there is the dns/cluster object to retrieve the base domain name, 
+// then in this case the http client validates the TLS certificate
+var skipClientTLSVerification = true
+
+func TestRunRoutes(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object across diferent tests
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		// they refer to the certificates create in the secret and are reused the different tests
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+
+		// =============================
+		// Insecure Route / No TLS
+		// =============================
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Edge
+		// =============================
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java", "-t", "route.tls-termination=edge").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(60 * time.Second)

Review comment:
       Forgot to replace, thanks for reviewing.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r703053648



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,382 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+	waitBeforeHttpRequest = 6 * time.Second
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+// self-signed certificate used when making the https request
+var certPem []byte
+
+// the e2e tests run on openshift3 in CI and there is no object to retrieve the base domain name
+// to create a valid hostname to later have it validate when doing the https request
+// as this a e2e test to validate the route object and not the certificate itself 
+// if the base domain name cannot be retrieved from dns/cluster we can safely skip TLS verification
+// if running on openshift4, there is the dns/cluster object to retrieve the base domain name, 
+// then in this case the http client validates the TLS certificate
+var skipClientTLSVerification = false
+
+func TestRunRoutes(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object across diferent tests
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		// they refer to the certificates create in the secret and are reused the different tests
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+
+		// =============================
+		// Insecure Route / No TLS
+		// =============================
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Edge
+		// =============================
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				"-t", "route.tls-termination=edge",
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("https://%s/hello?name=TLS_Edge", route().Spec.Host)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello TLS_Edge", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Passthrough
+		// =============================
+
+		t.Run("Route passthrough https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				// the --resource mounts the certificates inside secret as files in the integration pod
+				"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+				// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+				"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+				"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+				"-t", "route.tls-termination=passthrough",

Review comment:
       Create https://github.com/apache/camel-k/issues/2619 to track further investigation about this topic. Thanks for reviewing.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r703054816



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,401 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+	waitBeforeHttpRequest = 6 * time.Second
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+// self-signed certificate used when making the https request
+var certPem []byte
+
+// the e2e tests run on openshift3 in CI and there is no object to retrieve the base domain name
+// to create a valid hostname to later have it validate when doing the https request
+// as this a e2e test to validate the route object and not the certificate itself 
+// if the base domain name cannot be retrieved from dns/cluster we can safely skip TLS verification
+// if running on openshift4, there is the dns/cluster object to retrieve the base domain name, 
+// then in this case the http client validates the TLS certificate
+var skipClientTLSVerification = true
+
+func TestRunRoutes(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object across diferent tests
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		// they refer to the certificates create in the secret and are reused the different tests
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+
+		// =============================
+		// Insecure Route / No TLS
+		// =============================
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Edge
+		// =============================
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java", "-t", "route.tls-termination=edge").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(60 * time.Second)
+			url := fmt.Sprintf("https://%s/hello?name=TLS_Edge", route().Spec.Host)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello TLS_Edge", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Edge with custom certificate
+		// =============================
+
+		t.Run("Route Edge (custom certificate) https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				"-t", "route.tls-termination=edge",
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			code := "TLS_EdgeCustomCertificate"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Passthrough
+		// =============================
+
+		t.Run("Route passthrough https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				// the --resource mounts the certificates inside secret as files in the integration pod
+				"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+				// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+				"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+				"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+				"-t", "route.tls-termination=passthrough",
+				"-t", "container.port=8443",
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			code := "TLS_Passthrough"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Reencrypt
+		// =============================
+
+		t.Run("Route Reencrypt https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				// the --resource mounts the certificates inside secret as files in the integration pod
+				"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+				// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+				"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+				"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+				"-t", "route.tls-termination=reencrypt",
+				// the destination CA certificate which the route service uses to validate the HTTP endpoint TLS certificate
+				"-t", "route.tls-destination-ca-certificate-secret=" + refCert,
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,
+				"-t", "container.port=8443",
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			code := "TLS_Reencrypt"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Reencrypt With Openshift Service Serving CA
+		// =============================
+
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))

Review comment:
       Oh, this got in the wrong place when I refactored into a single test run. It will be fixed in the next push.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#issuecomment-910824396


   There is a single test "Route reencrypt (with openshift service CA) https works" failing because the route host is not ready yet, that may occur occasionally, we may increase the timeout before the route object is ready for use, but it is my view the tests are in good shape.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] astefanutti merged pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
astefanutti merged pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577


   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] astefanutti commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
astefanutti commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r701718184



##########
File path: deploy/traits.yaml
##########
@@ -833,19 +842,39 @@ traits:
   - name: tls-termination
     type: string
     description: The TLS termination type, like `edge`, `passthrough` or `reencrypt`.Refer
-      to the OpenShift documentation for additional information.
+      to the OpenShift route documentation for additional information.
   - name: tls-certificate
     type: string
-    description: The TLS certificate contents.Refer to the OpenShift documentation
+    description: The TLS certificate contents.Refer to the OpenShift route documentation
       for additional information.
+  - name: tls-certificate-secret
+    type: string
+    description: The TLS certificate contents read from a secret. The format is "secret-name[/key-name]",

Review comment:
       If I understand it correctly, this is not the content read from a Secret. That is the reference of the secret name and key containing the TLS certificate.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r699527320



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,444 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"strings"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	ctrl "sigs.k8s.io/controller-runtime/pkg/client"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+var certPem []byte
+
+// this test uses a route with no TLS
+func TestRunRouteNoTLS(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())

Review comment:
       Done.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#issuecomment-916263407


   @astefanutti  rebase done. All checks are green.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] astefanutti commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
astefanutti commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r701708764



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,382 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+	waitBeforeHttpRequest = 6 * time.Second
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+// self-signed certificate used when making the https request
+var certPem []byte
+
+// the e2e tests run on openshift3 in CI and there is no object to retrieve the base domain name
+// to create a valid hostname to later have it validate when doing the https request
+// as this a e2e test to validate the route object and not the certificate itself 
+// if the base domain name cannot be retrieved from dns/cluster we can safely skip TLS verification
+// if running on openshift4, there is the dns/cluster object to retrieve the base domain name, 
+// then in this case the http client validates the TLS certificate
+var skipClientTLSVerification = false
+
+func TestRunRoutes(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object across diferent tests
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		// they refer to the certificates create in the secret and are reused the different tests
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+
+		// =============================
+		// Insecure Route / No TLS
+		// =============================
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Edge
+		// =============================
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				"-t", "route.tls-termination=edge",
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,

Review comment:
       Why is a secret needed with `edge` termination?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] astefanutti commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
astefanutti commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r703234687



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,401 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+	waitBeforeHttpRequest = 6 * time.Second
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+// self-signed certificate used when making the https request
+var certPem []byte
+
+// the e2e tests run on openshift3 in CI and there is no object to retrieve the base domain name
+// to create a valid hostname to later have it validate when doing the https request
+// as this a e2e test to validate the route object and not the certificate itself 
+// if the base domain name cannot be retrieved from dns/cluster we can safely skip TLS verification
+// if running on openshift4, there is the dns/cluster object to retrieve the base domain name, 
+// then in this case the http client validates the TLS certificate
+var skipClientTLSVerification = true
+
+func TestRunRoutes(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object across diferent tests
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		// they refer to the certificates create in the secret and are reused the different tests
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+
+		// =============================
+		// Insecure Route / No TLS
+		// =============================
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Edge
+		// =============================
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java", "-t", "route.tls-termination=edge").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(60 * time.Second)

Review comment:
       Probably to be replaced with `waitBeforeHttpRequest`.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] astefanutti commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
astefanutti commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r701923009



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,382 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+	waitBeforeHttpRequest = 6 * time.Second
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+// self-signed certificate used when making the https request
+var certPem []byte
+
+// the e2e tests run on openshift3 in CI and there is no object to retrieve the base domain name
+// to create a valid hostname to later have it validate when doing the https request
+// as this a e2e test to validate the route object and not the certificate itself 
+// if the base domain name cannot be retrieved from dns/cluster we can safely skip TLS verification
+// if running on openshift4, there is the dns/cluster object to retrieve the base domain name, 
+// then in this case the http client validates the TLS certificate
+var skipClientTLSVerification = false
+
+func TestRunRoutes(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object across diferent tests
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		// they refer to the certificates create in the secret and are reused the different tests
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+
+		// =============================
+		// Insecure Route / No TLS
+		// =============================
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Edge
+		// =============================
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				"-t", "route.tls-termination=edge",
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,

Review comment:
       One option is to keep that test as is, and add another one covering the scenario of `edge` termination with the router's default certificate, so we cover the most frequent scenario as well.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] squakez commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
squakez commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r699021504



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,124 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/tls"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "my-combined-tls"
+	keyName = "my-key"
+	certName = "my-cert"
+	keyFilePath = "files/key.key"
+	certFilePath = "files/crt.crt"
+)
+
+func TestRunRouteTLS(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		createSecrets(ns)
+
+		refKey := secretName + "/" + keyName
+		refCert := secretName + "/" + certName
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/NettyServer.java",
+			"-t", "route.enabled=true",
+			"-t", "route.tls-termination=edge",
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+		).Execute()).To(Succeed())
+		Eventually(IntegrationPodPhase(ns, "netty-server"), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route https works", func(t *testing.T) {
+			route := Route(ns, "netty-server")
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request
+			time.Sleep(3 * time.Second)
+			response := httpsRequest(t, fmt.Sprintf("https://%s/hello", route().Spec.Host))
+			assert.Equal(t, "Hello World", response)
+		})
+		// Cleanup
+		Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+	// })
+	})
+}
+
+func httpsRequest(t *testing.T, url string) string {
+	transCfg := &http.Transport{
+		// ignore self signed SSL certificates
+		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
+	}
+	client := &http.Client{Transport: transCfg}
+	response, err := client.Get(url)
+	defer func() {
+		if response != nil {
+			_ = response.Body.Close()
+		}
+	}()
+	assert.Nil(t, err)
+	buf := new(bytes.Buffer)
+	_, err = buf.ReadFrom(response.Body)
+	assert.Nil(t, err)
+	return buf.String()
+}
+
+func createSecrets(ns string) error {

Review comment:
       Yeah, I think it would be cleaner to have a `func NewBinarySecret(ns string, name string, data map[string][]byte) error` method which generically takes in a binary content. Then you use it from your private method with the certificates created for the purpose.

##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,444 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"strings"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	ctrl "sigs.k8s.io/controller-runtime/pkg/client"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+var certPem []byte
+
+// this test uses a route with no TLS
+func TestRunRouteNoTLS(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())

Review comment:
       In order reduce the execution time, I think it would be wiser to run the test into the same method. You will only install the operator once and reuse the same kit along all tests. I used the approach in the [user config test](https://github.com/apache/camel-k/blob/main/e2e/common/config/config_test.go).

##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,444 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"strings"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	ctrl "sigs.k8s.io/controller-runtime/pkg/client"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+var certPem []byte
+
+// this test uses a route with no TLS
+func TestRunRouteNoTLS(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+		// Cleanup all integrations when the test finishes
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(4 * time.Second)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+		})
+	})
+}
+
+func TestRunRouteTLS_Edge(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+		// delete secret when the test finishes
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		// they refer to the secret/certificates previsouly created
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			"-t", "route.tls-termination=edge",
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+		).Execute()).To(Succeed())
+		// Cleanup all integrations when the test finishes
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			url := fmt.Sprintf("https://%s/hello?name=TLS_Edge", route().Spec.Host)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello TLS_Edge", response)
+		})
+	})
+}
+
+func TestRunRouteTLS_Passthrough(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+			"-t", "route.tls-termination=passthrough",
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route passthrough https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_Passthrough"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+// This test uses a self-signed certificate to create a TLS route
+func TestRunRouteTLS_Reencrypt(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+			"-t", "route.tls-termination=reencrypt",
+			// the destination CA certificate which the route service uses to validate the HTTP endpoint TLS certificate
+			"-t", "route.tls-destination-ca-certificate-secret=" + refCert,
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route Reencrypt https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_Reencrypt"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+// This test uses a certificate provided by openshift "service serving certificates" to create a TLS route
+func TestRunRouteTLS_ReencryptWithServiceCA(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		// they refer to the secret previsouly created
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			// they are used only for the pod exposing the HTTP endpoint, not the router
+			"--resource", "secret:" + servingCertificateSecret + "@/etc/ssl/" + servingCertificateSecret,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			// these certificates are used only in the pod, not the router
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + servingCertificateSecret + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + servingCertificateSecret + "/tls.key",
+			"-t", "route.tls-termination=reencrypt",
+			// these certificates are used only in the router to encrypt the connection from the client to the router
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		time.Sleep(2 * time.Second)
+		Eventually(Service(ns, integrationName)()).ShouldNot(BeNil())
+		annotations := make(map[string]string)
+		annotations["service.beta.openshift.io/serving-cert-secret-name"] = servingCertificateSecret
+		err = addAnnotation(ns, integrationName, annotations)
+		assert.Nil(t, err)
+
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+		t.Run("Route reencrypt (with openshift service CA) https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_ReencryptWithServiceCAWithServiceCA"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+func httpRequest(t *testing.T, url string, tlsEnabled bool) (string, error) {
+	var client http.Client
+	if tlsEnabled {
+		certPool := x509.NewCertPool()
+		certPool.AppendCertsFromPEM(certPem)
+		transCfg := &http.Transport{
+			TLSClientConfig: &tls.Config {
+				RootCAs: certPool,
+			},
+		}
+		client = http.Client{Transport: transCfg}	
+	} else {
+		client = http.Client{}
+	}
+	response, err := client.Get(url)
+	defer func() {
+		if response != nil {
+			_ = response.Body.Close()
+		}
+	}()
+	if err != nil {
+		return "", err
+	}
+	assert.Nil(t, err)
+	buf := new(bytes.Buffer)
+	_, err = buf.ReadFrom(response.Body)
+	if err != nil {
+		return "", err
+	}
+	assert.Nil(t, err)
+	return buf.String(), nil
+}
+
+func createSecret(ns string) (corev1.Secret, error) {
+	keyCertPair := generateSampleKeyAndCertificate(ns)
+	sec := corev1.Secret{
+		TypeMeta: metav1.TypeMeta{
+			Kind:       "Secret",
+			APIVersion: corev1.SchemeGroupVersion.String(),
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: ns,
+			Name:      secretName,
+		},
+		Type: corev1.SecretTypeTLS,
+		Data: map[string][]byte{
+			corev1.TLSPrivateKeyKey: keyCertPair.Key,
+			corev1.TLSCertKey: keyCertPair.Certificate,
+		},
+	}
+	return sec, TestClient().Create(TestContext, &sec)
+}
+
+func generateSampleKeyAndCertificate(ns string) keyCertificatePair {
+	// Generate the TLS certificate
+	serialNumber := big.NewInt(rand2.Int63())
+	dnsHostname := integrationName + "-" + ns + "." + domainName()
+	x509Certificate := x509.Certificate{
+		SerialNumber: serialNumber,
+		Subject: pkix.Name{
+			Organization: []string{"Camel K test"},
+		},
+		IsCA: 				   true,
+		DNSNames:              []string{dnsHostname},
+		NotBefore:             time.Now(),
+		NotAfter:              time.Now().AddDate(1, 0, 0),
+		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
+		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
+		BasicConstraintsValid: true,
+	}
+
+	// generate the private key
+	certPrivateKey, err := rsa.GenerateKey(rand.Reader, 2048)
+	if err != nil {
+		fmt.Printf("Error generating private key: %s\n", err)
+	}
+
+	privateKeyBytes := x509.MarshalPKCS1PrivateKey(certPrivateKey)
+	// encode for storing into secret
+	privateKeyPem := pem.EncodeToMemory(
+		&pem.Block{
+			Type:  "RSA PRIVATE KEY",
+			Bytes: privateKeyBytes,
+		},
+	)
+	certBytes, err := x509.CreateCertificate(rand.Reader, &x509Certificate, &x509Certificate, &certPrivateKey.PublicKey, certPrivateKey)
+	if err != nil {
+		fmt.Printf("Error generating certificate: %s\n", err)
+	}
+
+	// encode for storing into secret
+	certPem = pem.EncodeToMemory(&pem.Block{
+		Type:  "CERTIFICATE",
+		Bytes: certBytes,
+	})
+
+	return keyCertificatePair {
+		Key: privateKeyPem,
+		Certificate: certPem,
+	}
+}
+
+func domainName() string {
+	consoleroute := Route("openshift-console", "console")()

Review comment:
       Any reason why to use `openshift-console`? Could we use something not bound to any product?

##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,444 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"strings"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	ctrl "sigs.k8s.io/controller-runtime/pkg/client"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+var certPem []byte
+
+// this test uses a route with no TLS
+func TestRunRouteNoTLS(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+		// Cleanup all integrations when the test finishes
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(4 * time.Second)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+		})
+	})
+}
+
+func TestRunRouteTLS_Edge(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+		// delete secret when the test finishes
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		// they refer to the secret/certificates previsouly created
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			"-t", "route.tls-termination=edge",
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+		).Execute()).To(Succeed())
+		// Cleanup all integrations when the test finishes
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			url := fmt.Sprintf("https://%s/hello?name=TLS_Edge", route().Spec.Host)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello TLS_Edge", response)
+		})
+	})
+}
+
+func TestRunRouteTLS_Passthrough(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+			"-t", "route.tls-termination=passthrough",
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route passthrough https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_Passthrough"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+// This test uses a self-signed certificate to create a TLS route
+func TestRunRouteTLS_Reencrypt(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+			"-t", "route.tls-termination=reencrypt",
+			// the destination CA certificate which the route service uses to validate the HTTP endpoint TLS certificate
+			"-t", "route.tls-destination-ca-certificate-secret=" + refCert,
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route Reencrypt https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_Reencrypt"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+// This test uses a certificate provided by openshift "service serving certificates" to create a TLS route
+func TestRunRouteTLS_ReencryptWithServiceCA(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		// they refer to the secret previsouly created
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			// they are used only for the pod exposing the HTTP endpoint, not the router
+			"--resource", "secret:" + servingCertificateSecret + "@/etc/ssl/" + servingCertificateSecret,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			// these certificates are used only in the pod, not the router
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + servingCertificateSecret + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + servingCertificateSecret + "/tls.key",
+			"-t", "route.tls-termination=reencrypt",
+			// these certificates are used only in the router to encrypt the connection from the client to the router
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		time.Sleep(2 * time.Second)
+		Eventually(Service(ns, integrationName)()).ShouldNot(BeNil())
+		annotations := make(map[string]string)
+		annotations["service.beta.openshift.io/serving-cert-secret-name"] = servingCertificateSecret
+		err = addAnnotation(ns, integrationName, annotations)
+		assert.Nil(t, err)
+
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+		t.Run("Route reencrypt (with openshift service CA) https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_ReencryptWithServiceCAWithServiceCA"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+func httpRequest(t *testing.T, url string, tlsEnabled bool) (string, error) {
+	var client http.Client
+	if tlsEnabled {
+		certPool := x509.NewCertPool()
+		certPool.AppendCertsFromPEM(certPem)
+		transCfg := &http.Transport{
+			TLSClientConfig: &tls.Config {
+				RootCAs: certPool,
+			},
+		}
+		client = http.Client{Transport: transCfg}	
+	} else {
+		client = http.Client{}
+	}
+	response, err := client.Get(url)
+	defer func() {
+		if response != nil {
+			_ = response.Body.Close()
+		}
+	}()
+	if err != nil {
+		return "", err
+	}
+	assert.Nil(t, err)
+	buf := new(bytes.Buffer)
+	_, err = buf.ReadFrom(response.Body)
+	if err != nil {
+		return "", err
+	}
+	assert.Nil(t, err)
+	return buf.String(), nil
+}
+
+func createSecret(ns string) (corev1.Secret, error) {
+	keyCertPair := generateSampleKeyAndCertificate(ns)
+	sec := corev1.Secret{
+		TypeMeta: metav1.TypeMeta{
+			Kind:       "Secret",
+			APIVersion: corev1.SchemeGroupVersion.String(),
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: ns,
+			Name:      secretName,
+		},
+		Type: corev1.SecretTypeTLS,
+		Data: map[string][]byte{
+			corev1.TLSPrivateKeyKey: keyCertPair.Key,
+			corev1.TLSCertKey: keyCertPair.Certificate,
+		},
+	}
+	return sec, TestClient().Create(TestContext, &sec)
+}
+
+func generateSampleKeyAndCertificate(ns string) keyCertificatePair {
+	// Generate the TLS certificate
+	serialNumber := big.NewInt(rand2.Int63())
+	dnsHostname := integrationName + "-" + ns + "." + domainName()
+	x509Certificate := x509.Certificate{
+		SerialNumber: serialNumber,
+		Subject: pkix.Name{
+			Organization: []string{"Camel K test"},
+		},
+		IsCA: 				   true,
+		DNSNames:              []string{dnsHostname},
+		NotBefore:             time.Now(),
+		NotAfter:              time.Now().AddDate(1, 0, 0),
+		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
+		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
+		BasicConstraintsValid: true,
+	}
+
+	// generate the private key
+	certPrivateKey, err := rsa.GenerateKey(rand.Reader, 2048)
+	if err != nil {
+		fmt.Printf("Error generating private key: %s\n", err)
+	}
+
+	privateKeyBytes := x509.MarshalPKCS1PrivateKey(certPrivateKey)
+	// encode for storing into secret
+	privateKeyPem := pem.EncodeToMemory(
+		&pem.Block{
+			Type:  "RSA PRIVATE KEY",
+			Bytes: privateKeyBytes,
+		},
+	)
+	certBytes, err := x509.CreateCertificate(rand.Reader, &x509Certificate, &x509Certificate, &certPrivateKey.PublicKey, certPrivateKey)
+	if err != nil {
+		fmt.Printf("Error generating certificate: %s\n", err)
+	}
+
+	// encode for storing into secret
+	certPem = pem.EncodeToMemory(&pem.Block{
+		Type:  "CERTIFICATE",
+		Bytes: certBytes,
+	})
+
+	return keyCertificatePair {
+		Key: privateKeyPem,
+		Certificate: certPem,
+	}
+}
+
+func domainName() string {
+	consoleroute := Route("openshift-console", "console")()
+	return strings.ReplaceAll(consoleroute.Spec.Host, "console-openshift-console.", "")
+}
+
+func getService(ns string, name string) (*corev1.Service, error) {
+	svc := corev1.Service{}
+	key := ctrl.ObjectKey{
+		Namespace: ns,
+		Name:      name,
+	}
+	err := TestClient().Get(TestContext, key, &svc)
+	return &svc, err
+}
+
+func addAnnotation(ns string, name string, annotations map[string]string) error {

Review comment:
       Same comment as for `addService` method

##########
File path: pkg/trait/route.go
##########
@@ -174,19 +196,83 @@ func (t *routeTrait) Apply(e *Environment) error {
 	return nil
 }
 
-func (t *routeTrait) getTLSConfig() *routev1.TLSConfig {
+func (t *routeTrait) getTLSConfig() (*routev1.TLSConfig, error) {
+	// a certificate is a multiline text, but to set it as value in a single line in CLI, the user must escape the new line character as \\n
+	// but in the TLS configuration, the certificates should be a multiline string
+	// then we need to replace the incoming escaped new lines \\n for a real new line \n
+	key := strings.ReplaceAll(t.TLSKey, "\\n", "\n")

Review comment:
       Probably I did not express my concern properly. I was thinking this part would be better read with an approach like the following:
   ```
   var key string
   if t.TLSKey != "" {
     if t.TLSKeySecret != "" {
       // error, both key and keysecret provided
     }
     key = // take value from t.TLSKey
   } else if t.TLSKeySecret != "" {
     key = // take value from t.TLSKeySecret
   } else {
     // error, missing key/key secret
   }
   ```

##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,444 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"strings"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	ctrl "sigs.k8s.io/controller-runtime/pkg/client"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+var certPem []byte
+
+// this test uses a route with no TLS
+func TestRunRouteNoTLS(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+		// Cleanup all integrations when the test finishes
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(4 * time.Second)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+		})
+	})
+}
+
+func TestRunRouteTLS_Edge(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+		// delete secret when the test finishes
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		// they refer to the secret/certificates previsouly created
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			"-t", "route.tls-termination=edge",
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+		).Execute()).To(Succeed())
+		// Cleanup all integrations when the test finishes
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			url := fmt.Sprintf("https://%s/hello?name=TLS_Edge", route().Spec.Host)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello TLS_Edge", response)
+		})
+	})
+}
+
+func TestRunRouteTLS_Passthrough(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+			"-t", "route.tls-termination=passthrough",
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route passthrough https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_Passthrough"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+// This test uses a self-signed certificate to create a TLS route
+func TestRunRouteTLS_Reencrypt(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+			"-t", "route.tls-termination=reencrypt",
+			// the destination CA certificate which the route service uses to validate the HTTP endpoint TLS certificate
+			"-t", "route.tls-destination-ca-certificate-secret=" + refCert,
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route Reencrypt https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_Reencrypt"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+// This test uses a certificate provided by openshift "service serving certificates" to create a TLS route
+func TestRunRouteTLS_ReencryptWithServiceCA(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		// they refer to the secret previsouly created
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			// they are used only for the pod exposing the HTTP endpoint, not the router
+			"--resource", "secret:" + servingCertificateSecret + "@/etc/ssl/" + servingCertificateSecret,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			// these certificates are used only in the pod, not the router
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + servingCertificateSecret + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + servingCertificateSecret + "/tls.key",
+			"-t", "route.tls-termination=reencrypt",
+			// these certificates are used only in the router to encrypt the connection from the client to the router
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		time.Sleep(2 * time.Second)
+		Eventually(Service(ns, integrationName)()).ShouldNot(BeNil())
+		annotations := make(map[string]string)
+		annotations["service.beta.openshift.io/serving-cert-secret-name"] = servingCertificateSecret
+		err = addAnnotation(ns, integrationName, annotations)
+		assert.Nil(t, err)
+
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+		t.Run("Route reencrypt (with openshift service CA) https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_ReencryptWithServiceCAWithServiceCA"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+func httpRequest(t *testing.T, url string, tlsEnabled bool) (string, error) {
+	var client http.Client
+	if tlsEnabled {
+		certPool := x509.NewCertPool()
+		certPool.AppendCertsFromPEM(certPem)
+		transCfg := &http.Transport{
+			TLSClientConfig: &tls.Config {
+				RootCAs: certPool,
+			},
+		}
+		client = http.Client{Transport: transCfg}	
+	} else {
+		client = http.Client{}
+	}
+	response, err := client.Get(url)
+	defer func() {
+		if response != nil {
+			_ = response.Body.Close()
+		}
+	}()
+	if err != nil {
+		return "", err
+	}
+	assert.Nil(t, err)
+	buf := new(bytes.Buffer)
+	_, err = buf.ReadFrom(response.Body)
+	if err != nil {
+		return "", err
+	}
+	assert.Nil(t, err)
+	return buf.String(), nil
+}
+
+func createSecret(ns string) (corev1.Secret, error) {
+	keyCertPair := generateSampleKeyAndCertificate(ns)
+	sec := corev1.Secret{
+		TypeMeta: metav1.TypeMeta{
+			Kind:       "Secret",
+			APIVersion: corev1.SchemeGroupVersion.String(),
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: ns,
+			Name:      secretName,
+		},
+		Type: corev1.SecretTypeTLS,
+		Data: map[string][]byte{
+			corev1.TLSPrivateKeyKey: keyCertPair.Key,
+			corev1.TLSCertKey: keyCertPair.Certificate,
+		},
+	}
+	return sec, TestClient().Create(TestContext, &sec)
+}
+
+func generateSampleKeyAndCertificate(ns string) keyCertificatePair {
+	// Generate the TLS certificate
+	serialNumber := big.NewInt(rand2.Int63())
+	dnsHostname := integrationName + "-" + ns + "." + domainName()
+	x509Certificate := x509.Certificate{
+		SerialNumber: serialNumber,
+		Subject: pkix.Name{
+			Organization: []string{"Camel K test"},
+		},
+		IsCA: 				   true,
+		DNSNames:              []string{dnsHostname},
+		NotBefore:             time.Now(),
+		NotAfter:              time.Now().AddDate(1, 0, 0),
+		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
+		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
+		BasicConstraintsValid: true,
+	}
+
+	// generate the private key
+	certPrivateKey, err := rsa.GenerateKey(rand.Reader, 2048)
+	if err != nil {
+		fmt.Printf("Error generating private key: %s\n", err)
+	}
+
+	privateKeyBytes := x509.MarshalPKCS1PrivateKey(certPrivateKey)
+	// encode for storing into secret
+	privateKeyPem := pem.EncodeToMemory(
+		&pem.Block{
+			Type:  "RSA PRIVATE KEY",
+			Bytes: privateKeyBytes,
+		},
+	)
+	certBytes, err := x509.CreateCertificate(rand.Reader, &x509Certificate, &x509Certificate, &certPrivateKey.PublicKey, certPrivateKey)
+	if err != nil {
+		fmt.Printf("Error generating certificate: %s\n", err)
+	}
+
+	// encode for storing into secret
+	certPem = pem.EncodeToMemory(&pem.Block{
+		Type:  "CERTIFICATE",
+		Bytes: certBytes,
+	})
+
+	return keyCertificatePair {
+		Key: privateKeyPem,
+		Certificate: certPem,
+	}
+}
+
+func domainName() string {
+	consoleroute := Route("openshift-console", "console")()
+	return strings.ReplaceAll(consoleroute.Spec.Host, "console-openshift-console.", "")
+}
+
+func getService(ns string, name string) (*corev1.Service, error) {

Review comment:
       If it's a generic method, and is not already present in test_support.go, we better move it there and have it available for anybody willing to use it.

##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,444 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"strings"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	ctrl "sigs.k8s.io/controller-runtime/pkg/client"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+var certPem []byte
+
+// this test uses a route with no TLS
+func TestRunRouteNoTLS(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+		// Cleanup all integrations when the test finishes
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(4 * time.Second)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+		})
+	})
+}
+
+func TestRunRouteTLS_Edge(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+		// delete secret when the test finishes
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		// they refer to the secret/certificates previsouly created
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			"-t", "route.tls-termination=edge",
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+		).Execute()).To(Succeed())
+		// Cleanup all integrations when the test finishes
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			url := fmt.Sprintf("https://%s/hello?name=TLS_Edge", route().Spec.Host)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello TLS_Edge", response)
+		})
+	})
+}
+
+func TestRunRouteTLS_Passthrough(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+			"-t", "route.tls-termination=passthrough",
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route passthrough https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_Passthrough"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+// This test uses a self-signed certificate to create a TLS route
+func TestRunRouteTLS_Reencrypt(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+			"-t", "route.tls-termination=reencrypt",
+			// the destination CA certificate which the route service uses to validate the HTTP endpoint TLS certificate
+			"-t", "route.tls-destination-ca-certificate-secret=" + refCert,
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route Reencrypt https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_Reencrypt"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+// This test uses a certificate provided by openshift "service serving certificates" to create a TLS route
+func TestRunRouteTLS_ReencryptWithServiceCA(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		// they refer to the secret previsouly created
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			// they are used only for the pod exposing the HTTP endpoint, not the router
+			"--resource", "secret:" + servingCertificateSecret + "@/etc/ssl/" + servingCertificateSecret,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			// these certificates are used only in the pod, not the router
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + servingCertificateSecret + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + servingCertificateSecret + "/tls.key",
+			"-t", "route.tls-termination=reencrypt",
+			// these certificates are used only in the router to encrypt the connection from the client to the router
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		time.Sleep(2 * time.Second)
+		Eventually(Service(ns, integrationName)()).ShouldNot(BeNil())
+		annotations := make(map[string]string)
+		annotations["service.beta.openshift.io/serving-cert-secret-name"] = servingCertificateSecret
+		err = addAnnotation(ns, integrationName, annotations)
+		assert.Nil(t, err)
+
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+		t.Run("Route reencrypt (with openshift service CA) https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_ReencryptWithServiceCAWithServiceCA"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+func httpRequest(t *testing.T, url string, tlsEnabled bool) (string, error) {
+	var client http.Client
+	if tlsEnabled {
+		certPool := x509.NewCertPool()
+		certPool.AppendCertsFromPEM(certPem)
+		transCfg := &http.Transport{
+			TLSClientConfig: &tls.Config {
+				RootCAs: certPool,
+			},
+		}
+		client = http.Client{Transport: transCfg}	
+	} else {
+		client = http.Client{}
+	}
+	response, err := client.Get(url)
+	defer func() {
+		if response != nil {
+			_ = response.Body.Close()
+		}
+	}()
+	if err != nil {
+		return "", err
+	}
+	assert.Nil(t, err)
+	buf := new(bytes.Buffer)
+	_, err = buf.ReadFrom(response.Body)
+	if err != nil {
+		return "", err
+	}
+	assert.Nil(t, err)
+	return buf.String(), nil
+}
+
+func createSecret(ns string) (corev1.Secret, error) {
+	keyCertPair := generateSampleKeyAndCertificate(ns)
+	sec := corev1.Secret{
+		TypeMeta: metav1.TypeMeta{
+			Kind:       "Secret",
+			APIVersion: corev1.SchemeGroupVersion.String(),
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: ns,
+			Name:      secretName,
+		},
+		Type: corev1.SecretTypeTLS,
+		Data: map[string][]byte{
+			corev1.TLSPrivateKeyKey: keyCertPair.Key,
+			corev1.TLSCertKey: keyCertPair.Certificate,
+		},
+	}
+	return sec, TestClient().Create(TestContext, &sec)
+}
+
+func generateSampleKeyAndCertificate(ns string) keyCertificatePair {
+	// Generate the TLS certificate
+	serialNumber := big.NewInt(rand2.Int63())
+	dnsHostname := integrationName + "-" + ns + "." + domainName()
+	x509Certificate := x509.Certificate{
+		SerialNumber: serialNumber,
+		Subject: pkix.Name{
+			Organization: []string{"Camel K test"},
+		},
+		IsCA: 				   true,
+		DNSNames:              []string{dnsHostname},
+		NotBefore:             time.Now(),
+		NotAfter:              time.Now().AddDate(1, 0, 0),
+		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
+		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
+		BasicConstraintsValid: true,
+	}
+
+	// generate the private key
+	certPrivateKey, err := rsa.GenerateKey(rand.Reader, 2048)
+	if err != nil {
+		fmt.Printf("Error generating private key: %s\n", err)
+	}
+
+	privateKeyBytes := x509.MarshalPKCS1PrivateKey(certPrivateKey)
+	// encode for storing into secret
+	privateKeyPem := pem.EncodeToMemory(
+		&pem.Block{
+			Type:  "RSA PRIVATE KEY",
+			Bytes: privateKeyBytes,
+		},
+	)
+	certBytes, err := x509.CreateCertificate(rand.Reader, &x509Certificate, &x509Certificate, &certPrivateKey.PublicKey, certPrivateKey)
+	if err != nil {
+		fmt.Printf("Error generating certificate: %s\n", err)
+	}
+
+	// encode for storing into secret
+	certPem = pem.EncodeToMemory(&pem.Block{
+		Type:  "CERTIFICATE",
+		Bytes: certBytes,
+	})
+
+	return keyCertificatePair {
+		Key: privateKeyPem,
+		Certificate: certPem,
+	}
+}
+
+func domainName() string {
+	consoleroute := Route("openshift-console", "console")()
+	return strings.ReplaceAll(consoleroute.Spec.Host, "console-openshift-console.", "")
+}
+
+func getService(ns string, name string) (*corev1.Service, error) {
+	svc := corev1.Service{}
+	key := ctrl.ObjectKey{
+		Namespace: ns,
+		Name:      name,
+	}
+	err := TestClient().Get(TestContext, key, &svc)
+	return &svc, err
+}
+
+func addAnnotation(ns string, name string, annotations map[string]string) error {

Review comment:
       Same comment as for `getService` method




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#issuecomment-908462204






-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#issuecomment-908467217


   > I think we can take the opportunity and make this more general than just `secret`. We should use the `path` concept (ie `TLSCertificatePath`) that will read a generic path on the runtime integration. That path will be filled by a secret/configmap/file/volume ... by the user via `--resource` option.
   
   It may not help in this case, because by using `--resource` the certificate files are mounted in the integration pod, but the openshift route for the edge case is created from the operator pod, so the certificate file just doesn't exist in operator pod file system.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] astefanutti commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
astefanutti commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r702651269



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,382 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+	waitBeforeHttpRequest = 6 * time.Second
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+// self-signed certificate used when making the https request
+var certPem []byte
+
+// the e2e tests run on openshift3 in CI and there is no object to retrieve the base domain name
+// to create a valid hostname to later have it validate when doing the https request
+// as this a e2e test to validate the route object and not the certificate itself 
+// if the base domain name cannot be retrieved from dns/cluster we can safely skip TLS verification
+// if running on openshift4, there is the dns/cluster object to retrieve the base domain name, 
+// then in this case the http client validates the TLS certificate
+var skipClientTLSVerification = false
+
+func TestRunRoutes(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object across diferent tests
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		// they refer to the certificates create in the secret and are reused the different tests
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+
+		// =============================
+		// Insecure Route / No TLS
+		// =============================
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Edge
+		// =============================
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				"-t", "route.tls-termination=edge",
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("https://%s/hello?name=TLS_Edge", route().Spec.Host)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello TLS_Edge", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Passthrough
+		// =============================
+
+		t.Run("Route passthrough https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				// the --resource mounts the certificates inside secret as files in the integration pod
+				"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+				// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+				"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+				"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+				"-t", "route.tls-termination=passthrough",

Review comment:
       Sure, these tests are already a great move forwards.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r701872130



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,382 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+	waitBeforeHttpRequest = 6 * time.Second
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+// self-signed certificate used when making the https request
+var certPem []byte
+
+// the e2e tests run on openshift3 in CI and there is no object to retrieve the base domain name
+// to create a valid hostname to later have it validate when doing the https request
+// as this a e2e test to validate the route object and not the certificate itself 
+// if the base domain name cannot be retrieved from dns/cluster we can safely skip TLS verification
+// if running on openshift4, there is the dns/cluster object to retrieve the base domain name, 
+// then in this case the http client validates the TLS certificate
+var skipClientTLSVerification = false
+
+func TestRunRoutes(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object across diferent tests
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		// they refer to the certificates create in the secret and are reused the different tests
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+
+		// =============================
+		// Insecure Route / No TLS
+		// =============================
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Edge
+		// =============================
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				"-t", "route.tls-termination=edge",
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("https://%s/hello?name=TLS_Edge", route().Spec.Host)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello TLS_Edge", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Passthrough
+		// =============================
+
+		t.Run("Route passthrough https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				// the --resource mounts the certificates inside secret as files in the integration pod
+				"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+				// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+				"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+				"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+				"-t", "route.tls-termination=passthrough",
+				"-t", "container.port=8443",
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			code := "TLS_Passthrough"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Reencrypt
+		// =============================
+
+		t.Run("Route Reencrypt https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				// the --resource mounts the certificates inside secret as files in the integration pod
+				"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+				// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+				"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+				"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+				"-t", "route.tls-termination=reencrypt",

Review comment:
       Same answer as above.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] astefanutti commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
astefanutti commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r702648770



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,401 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+	waitBeforeHttpRequest = 6 * time.Second
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+// self-signed certificate used when making the https request
+var certPem []byte
+
+// the e2e tests run on openshift3 in CI and there is no object to retrieve the base domain name
+// to create a valid hostname to later have it validate when doing the https request
+// as this a e2e test to validate the route object and not the certificate itself 
+// if the base domain name cannot be retrieved from dns/cluster we can safely skip TLS verification
+// if running on openshift4, there is the dns/cluster object to retrieve the base domain name, 
+// then in this case the http client validates the TLS certificate
+var skipClientTLSVerification = true
+
+func TestRunRoutes(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object across diferent tests
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		// they refer to the certificates create in the secret and are reused the different tests
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+
+		// =============================
+		// Insecure Route / No TLS
+		// =============================
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Edge
+		// =============================
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java", "-t", "route.tls-termination=edge").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(60 * time.Second)
+			url := fmt.Sprintf("https://%s/hello?name=TLS_Edge", route().Spec.Host)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello TLS_Edge", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Edge with custom certificate
+		// =============================
+
+		t.Run("Route Edge (custom certificate) https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				"-t", "route.tls-termination=edge",
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			code := "TLS_EdgeCustomCertificate"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Passthrough
+		// =============================
+
+		t.Run("Route passthrough https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				// the --resource mounts the certificates inside secret as files in the integration pod
+				"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+				// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+				"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+				"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+				"-t", "route.tls-termination=passthrough",
+				"-t", "container.port=8443",
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			code := "TLS_Passthrough"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Reencrypt
+		// =============================
+
+		t.Run("Route Reencrypt https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				// the --resource mounts the certificates inside secret as files in the integration pod
+				"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+				// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+				"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+				"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+				"-t", "route.tls-termination=reencrypt",
+				// the destination CA certificate which the route service uses to validate the HTTP endpoint TLS certificate
+				"-t", "route.tls-destination-ca-certificate-secret=" + refCert,
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,
+				"-t", "container.port=8443",
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			code := "TLS_Reencrypt"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Reencrypt With Openshift Service Serving CA
+		// =============================
+
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+		t.Run("Route reencrypt (with openshift service CA) https works", func(t *testing.T) {
+			// --resource references a serving certificate secret not created yet, as it is to be created
+			// when the service is created and the annotation added to it
+			// as a result eventually there is the following warning message in the console, don't worry as the pod waits for the secret to be created
+			// Warn: serving-certificate Secret not found in **** namespace, make sure to provide it before the Integration can run
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				// the --resource mounts the certificates inside secret as files in the integration pod
+				// they are used only for the pod exposing the HTTP endpoint, not the router
+				"--resource", "secret:" + servingCertificateSecret + "@/etc/ssl/" + servingCertificateSecret,
+				// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+				// these certificates are used only in the pod, not the router
+				"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + servingCertificateSecret + "/tls.crt",
+				"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + servingCertificateSecret + "/tls.key",
+				"-t", "route.tls-termination=reencrypt",
+				// these certificates are used only in the router to encrypt the connection from the client to the router
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,
+				"-t", "container.port=8443",
+			).Execute()).To(Succeed())
+
+			// should wait a little time before the service is ready
+			time.Sleep(2 * time.Second)
+			Eventually(Service(ns, integrationName)()).ShouldNot(BeNil())
+			annotations := make(map[string]string)
+			annotations["service.beta.openshift.io/serving-cert-secret-name"] = servingCertificateSecret
+			err = addAnnotation(ns, integrationName, annotations)

Review comment:
       The annotation should not be added to the Service directly. As it is a resource owned by the Integration, it's overwritten anytime the reconciliation of the Integration happens. One option is to define the annotation on the Integration, and have it transferred on the Service with the _owner_ trait. The problem with this approach is that the annotation will be transferred on all the owned resources. Another option would be to add an `annotations` parameter to the _service_ trait, so that extra annotations can be provided only to the Service. 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r704399703



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,401 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+	waitBeforeHttpRequest = 6 * time.Second
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+// self-signed certificate used when making the https request
+var certPem []byte
+
+// the e2e tests run on openshift3 in CI and there is no object to retrieve the base domain name
+// to create a valid hostname to later have it validate when doing the https request
+// as this a e2e test to validate the route object and not the certificate itself 
+// if the base domain name cannot be retrieved from dns/cluster we can safely skip TLS verification
+// if running on openshift4, there is the dns/cluster object to retrieve the base domain name, 
+// then in this case the http client validates the TLS certificate
+var skipClientTLSVerification = true
+
+func TestRunRoutes(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object across diferent tests
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		// they refer to the certificates create in the secret and are reused the different tests
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+
+		// =============================
+		// Insecure Route / No TLS
+		// =============================
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Edge
+		// =============================
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java", "-t", "route.tls-termination=edge").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(60 * time.Second)
+			url := fmt.Sprintf("https://%s/hello?name=TLS_Edge", route().Spec.Host)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello TLS_Edge", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Edge with custom certificate
+		// =============================
+
+		t.Run("Route Edge (custom certificate) https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				"-t", "route.tls-termination=edge",
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			code := "TLS_EdgeCustomCertificate"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Passthrough
+		// =============================
+
+		t.Run("Route passthrough https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				// the --resource mounts the certificates inside secret as files in the integration pod
+				"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+				// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+				"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+				"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+				"-t", "route.tls-termination=passthrough",
+				"-t", "container.port=8443",
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			code := "TLS_Passthrough"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Reencrypt
+		// =============================
+
+		t.Run("Route Reencrypt https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				// the --resource mounts the certificates inside secret as files in the integration pod
+				"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+				// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+				"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+				"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+				"-t", "route.tls-termination=reencrypt",
+				// the destination CA certificate which the route service uses to validate the HTTP endpoint TLS certificate
+				"-t", "route.tls-destination-ca-certificate-secret=" + refCert,
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,
+				"-t", "container.port=8443",
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			code := "TLS_Reencrypt"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Reencrypt With Openshift Service Serving CA
+		// =============================
+
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+		t.Run("Route reencrypt (with openshift service CA) https works", func(t *testing.T) {
+			// --resource references a serving certificate secret not created yet, as it is to be created
+			// when the service is created and the annotation added to it
+			// as a result eventually there is the following warning message in the console, don't worry as the pod waits for the secret to be created
+			// Warn: serving-certificate Secret not found in **** namespace, make sure to provide it before the Integration can run
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				// the --resource mounts the certificates inside secret as files in the integration pod
+				// they are used only for the pod exposing the HTTP endpoint, not the router
+				"--resource", "secret:" + servingCertificateSecret + "@/etc/ssl/" + servingCertificateSecret,
+				// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+				// these certificates are used only in the pod, not the router
+				"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + servingCertificateSecret + "/tls.crt",
+				"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + servingCertificateSecret + "/tls.key",
+				"-t", "route.tls-termination=reencrypt",
+				// these certificates are used only in the router to encrypt the connection from the client to the router
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,
+				"-t", "container.port=8443",
+			).Execute()).To(Succeed())
+
+			// should wait a little time before the service is ready
+			time.Sleep(2 * time.Second)
+			Eventually(Service(ns, integrationName)()).ShouldNot(BeNil())
+			annotations := make(map[string]string)
+			annotations["service.beta.openshift.io/serving-cert-secret-name"] = servingCertificateSecret
+			err = addAnnotation(ns, integrationName, annotations)

Review comment:
       Agreed.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] astefanutti commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
astefanutti commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r701718513



##########
File path: deploy/traits.yaml
##########
@@ -833,19 +842,39 @@ traits:
   - name: tls-termination
     type: string
     description: The TLS termination type, like `edge`, `passthrough` or `reencrypt`.Refer
-      to the OpenShift documentation for additional information.
+      to the OpenShift route documentation for additional information.
   - name: tls-certificate
     type: string
-    description: The TLS certificate contents.Refer to the OpenShift documentation
+    description: The TLS certificate contents.Refer to the OpenShift route documentation
       for additional information.
+  - name: tls-certificate-secret
+    type: string
+    description: The TLS certificate contents read from a secret. The format is "secret-name[/key-name]",
+      the value represents the secret name, if there is only one key in the secret
+      it will be read, otherwise you can set a key name separated with a "/".Refer
+      to the OpenShift route documentation for additional information.
   - name: tls-key
     type: string
-    description: The TLS certificate key contents.Refer to the OpenShift documentation
+    description: The TLS certificate key contents.Refer to the OpenShift route documentation
       for additional information.
+  - name: tls-key-secret
+    type: string
+    description: The TLS certificate key contents read from a secret. The format is
+      "secret-name[/key-name]", the value represents the secret name, if there is
+      only one key in the secret it will be read, otherwise you can set a key name
+      separated with a "/".Refer to the OpenShift route documentation for additional
+      information.
   - name: tls-ca-certificate
     type: string
     description: The TLS cert authority certificate contents.Refer to the OpenShift
-      documentation for additional information.
+      route documentation for additional information.
+  - name: tls-ca-certificate-secret
+    type: string
+    description: The TLS cert authority certificate contents read from a secret. The

Review comment:
       dito.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r698611373



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,124 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/tls"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "my-combined-tls"
+	keyName = "my-key"
+	certName = "my-cert"
+	keyFilePath = "files/key.key"
+	certFilePath = "files/crt.crt"
+)
+
+func TestRunRouteTLS(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		createSecrets(ns)
+
+		refKey := secretName + "/" + keyName
+		refCert := secretName + "/" + certName
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/NettyServer.java",
+			"-t", "route.enabled=true",
+			"-t", "route.tls-termination=edge",
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+		).Execute()).To(Succeed())
+		Eventually(IntegrationPodPhase(ns, "netty-server"), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route https works", func(t *testing.T) {
+			route := Route(ns, "netty-server")
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request
+			time.Sleep(3 * time.Second)
+			response := httpsRequest(t, fmt.Sprintf("https://%s/hello", route().Spec.Host))
+			assert.Equal(t, "Hello World", response)
+		})
+		// Cleanup
+		Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+	// })
+	})
+}
+
+func httpsRequest(t *testing.T, url string) string {
+	transCfg := &http.Transport{
+		// ignore self signed SSL certificates
+		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
+	}
+	client := &http.Client{Transport: transCfg}
+	response, err := client.Get(url)
+	defer func() {
+		if response != nil {
+			_ = response.Body.Close()
+		}
+	}()
+	assert.Nil(t, err)
+	buf := new(bytes.Buffer)
+	_, err = buf.ReadFrom(response.Body)
+	assert.Nil(t, err)
+	return buf.String()
+}
+
+func createSecrets(ns string) error {

Review comment:
       I didn't add this to test_support.go as this particular route secret is tied to generated self-signed certificate, not so generic at this point, but if we need to make a generic one, that would not be too difficult.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r701886287



##########
File path: deploy/traits.yaml
##########
@@ -833,19 +842,39 @@ traits:
   - name: tls-termination
     type: string
     description: The TLS termination type, like `edge`, `passthrough` or `reencrypt`.Refer
-      to the OpenShift documentation for additional information.
+      to the OpenShift route documentation for additional information.
   - name: tls-certificate
     type: string
-    description: The TLS certificate contents.Refer to the OpenShift documentation
+    description: The TLS certificate contents.Refer to the OpenShift route documentation
       for additional information.
+  - name: tls-certificate-secret
+    type: string
+    description: The TLS certificate contents read from a secret. The format is "secret-name[/key-name]",

Review comment:
       The certificate is stored in the `secret`, isn't the same thing for configuration purposes ? The user wants to setup the certificate to be sourced either from a `secret`  or directly from CLI. 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] astefanutti commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
astefanutti commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r701717079



##########
File path: deploy/traits.yaml
##########
@@ -820,8 +820,17 @@ traits:
   platform: false
   profiles:
   - OpenShift
-  description: The Route trait can be used to configure the creation of OpenShift
-    routes for the integration.
+  description: 'The Route trait can be used to configure the creation of OpenShift
+    routes for the integration. The certificate and key contents may be stored either

Review comment:
       I'd suggest: "may be sourced either from"




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] squakez commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
squakez commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r699025052



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,444 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"strings"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	ctrl "sigs.k8s.io/controller-runtime/pkg/client"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+var certPem []byte
+
+// this test uses a route with no TLS
+func TestRunRouteNoTLS(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+		// Cleanup all integrations when the test finishes
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(4 * time.Second)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+		})
+	})
+}
+
+func TestRunRouteTLS_Edge(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+		// delete secret when the test finishes
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		// they refer to the secret/certificates previsouly created
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			"-t", "route.tls-termination=edge",
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+		).Execute()).To(Succeed())
+		// Cleanup all integrations when the test finishes
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			url := fmt.Sprintf("https://%s/hello?name=TLS_Edge", route().Spec.Host)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello TLS_Edge", response)
+		})
+	})
+}
+
+func TestRunRouteTLS_Passthrough(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+			"-t", "route.tls-termination=passthrough",
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route passthrough https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_Passthrough"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+// This test uses a self-signed certificate to create a TLS route
+func TestRunRouteTLS_Reencrypt(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+			"-t", "route.tls-termination=reencrypt",
+			// the destination CA certificate which the route service uses to validate the HTTP endpoint TLS certificate
+			"-t", "route.tls-destination-ca-certificate-secret=" + refCert,
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route Reencrypt https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_Reencrypt"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+// This test uses a certificate provided by openshift "service serving certificates" to create a TLS route
+func TestRunRouteTLS_ReencryptWithServiceCA(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		// they refer to the secret previsouly created
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			// they are used only for the pod exposing the HTTP endpoint, not the router
+			"--resource", "secret:" + servingCertificateSecret + "@/etc/ssl/" + servingCertificateSecret,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			// these certificates are used only in the pod, not the router
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + servingCertificateSecret + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + servingCertificateSecret + "/tls.key",
+			"-t", "route.tls-termination=reencrypt",
+			// these certificates are used only in the router to encrypt the connection from the client to the router
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		time.Sleep(2 * time.Second)
+		Eventually(Service(ns, integrationName)()).ShouldNot(BeNil())
+		annotations := make(map[string]string)
+		annotations["service.beta.openshift.io/serving-cert-secret-name"] = servingCertificateSecret
+		err = addAnnotation(ns, integrationName, annotations)
+		assert.Nil(t, err)
+
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+		t.Run("Route reencrypt (with openshift service CA) https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_ReencryptWithServiceCAWithServiceCA"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+func httpRequest(t *testing.T, url string, tlsEnabled bool) (string, error) {
+	var client http.Client
+	if tlsEnabled {
+		certPool := x509.NewCertPool()
+		certPool.AppendCertsFromPEM(certPem)
+		transCfg := &http.Transport{
+			TLSClientConfig: &tls.Config {
+				RootCAs: certPool,
+			},
+		}
+		client = http.Client{Transport: transCfg}	
+	} else {
+		client = http.Client{}
+	}
+	response, err := client.Get(url)
+	defer func() {
+		if response != nil {
+			_ = response.Body.Close()
+		}
+	}()
+	if err != nil {
+		return "", err
+	}
+	assert.Nil(t, err)
+	buf := new(bytes.Buffer)
+	_, err = buf.ReadFrom(response.Body)
+	if err != nil {
+		return "", err
+	}
+	assert.Nil(t, err)
+	return buf.String(), nil
+}
+
+func createSecret(ns string) (corev1.Secret, error) {
+	keyCertPair := generateSampleKeyAndCertificate(ns)
+	sec := corev1.Secret{
+		TypeMeta: metav1.TypeMeta{
+			Kind:       "Secret",
+			APIVersion: corev1.SchemeGroupVersion.String(),
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: ns,
+			Name:      secretName,
+		},
+		Type: corev1.SecretTypeTLS,
+		Data: map[string][]byte{
+			corev1.TLSPrivateKeyKey: keyCertPair.Key,
+			corev1.TLSCertKey: keyCertPair.Certificate,
+		},
+	}
+	return sec, TestClient().Create(TestContext, &sec)
+}
+
+func generateSampleKeyAndCertificate(ns string) keyCertificatePair {
+	// Generate the TLS certificate
+	serialNumber := big.NewInt(rand2.Int63())
+	dnsHostname := integrationName + "-" + ns + "." + domainName()
+	x509Certificate := x509.Certificate{
+		SerialNumber: serialNumber,
+		Subject: pkix.Name{
+			Organization: []string{"Camel K test"},
+		},
+		IsCA: 				   true,
+		DNSNames:              []string{dnsHostname},
+		NotBefore:             time.Now(),
+		NotAfter:              time.Now().AddDate(1, 0, 0),
+		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
+		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
+		BasicConstraintsValid: true,
+	}
+
+	// generate the private key
+	certPrivateKey, err := rsa.GenerateKey(rand.Reader, 2048)
+	if err != nil {
+		fmt.Printf("Error generating private key: %s\n", err)
+	}
+
+	privateKeyBytes := x509.MarshalPKCS1PrivateKey(certPrivateKey)
+	// encode for storing into secret
+	privateKeyPem := pem.EncodeToMemory(
+		&pem.Block{
+			Type:  "RSA PRIVATE KEY",
+			Bytes: privateKeyBytes,
+		},
+	)
+	certBytes, err := x509.CreateCertificate(rand.Reader, &x509Certificate, &x509Certificate, &certPrivateKey.PublicKey, certPrivateKey)
+	if err != nil {
+		fmt.Printf("Error generating certificate: %s\n", err)
+	}
+
+	// encode for storing into secret
+	certPem = pem.EncodeToMemory(&pem.Block{
+		Type:  "CERTIFICATE",
+		Bytes: certBytes,
+	})
+
+	return keyCertificatePair {
+		Key: privateKeyPem,
+		Certificate: certPem,
+	}
+}
+
+func domainName() string {
+	consoleroute := Route("openshift-console", "console")()
+	return strings.ReplaceAll(consoleroute.Spec.Host, "console-openshift-console.", "")
+}
+
+func getService(ns string, name string) (*corev1.Service, error) {
+	svc := corev1.Service{}
+	key := ctrl.ObjectKey{
+		Namespace: ns,
+		Name:      name,
+	}
+	err := TestClient().Get(TestContext, key, &svc)
+	return &svc, err
+}
+
+func addAnnotation(ns string, name string, annotations map[string]string) error {

Review comment:
       Same comment as for `getService` method




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r698606675



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,124 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/tls"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "my-combined-tls"
+	keyName = "my-key"
+	certName = "my-cert"
+	keyFilePath = "files/key.key"
+	certFilePath = "files/crt.crt"
+)
+
+func TestRunRouteTLS(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		createSecrets(ns)
+
+		refKey := secretName + "/" + keyName
+		refCert := secretName + "/" + certName
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/NettyServer.java",
+			"-t", "route.enabled=true",
+			"-t", "route.tls-termination=edge",
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+		).Execute()).To(Succeed())
+		Eventually(IntegrationPodPhase(ns, "netty-server"), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route https works", func(t *testing.T) {
+			route := Route(ns, "netty-server")
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request
+			time.Sleep(3 * time.Second)
+			response := httpsRequest(t, fmt.Sprintf("https://%s/hello", route().Spec.Host))
+			assert.Equal(t, "Hello World", response)
+		})
+		// Cleanup
+		Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+	// })
+	})
+}
+
+func httpsRequest(t *testing.T, url string) string {
+	transCfg := &http.Transport{
+		// ignore self signed SSL certificates
+		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},

Review comment:
       Done.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r699528030



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,444 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"strings"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	ctrl "sigs.k8s.io/controller-runtime/pkg/client"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+var certPem []byte
+
+// this test uses a route with no TLS
+func TestRunRouteNoTLS(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+		// Cleanup all integrations when the test finishes
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(4 * time.Second)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+		})
+	})
+}
+
+func TestRunRouteTLS_Edge(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+		// delete secret when the test finishes
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		// they refer to the secret/certificates previsouly created
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			"-t", "route.tls-termination=edge",
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+		).Execute()).To(Succeed())
+		// Cleanup all integrations when the test finishes
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			url := fmt.Sprintf("https://%s/hello?name=TLS_Edge", route().Spec.Host)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello TLS_Edge", response)
+		})
+	})
+}
+
+func TestRunRouteTLS_Passthrough(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+			"-t", "route.tls-termination=passthrough",
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route passthrough https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_Passthrough"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+// This test uses a self-signed certificate to create a TLS route
+func TestRunRouteTLS_Reencrypt(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+			"-t", "route.tls-termination=reencrypt",
+			// the destination CA certificate which the route service uses to validate the HTTP endpoint TLS certificate
+			"-t", "route.tls-destination-ca-certificate-secret=" + refCert,
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route Reencrypt https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_Reencrypt"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+// This test uses a certificate provided by openshift "service serving certificates" to create a TLS route
+func TestRunRouteTLS_ReencryptWithServiceCA(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		// they refer to the secret previsouly created
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			// they are used only for the pod exposing the HTTP endpoint, not the router
+			"--resource", "secret:" + servingCertificateSecret + "@/etc/ssl/" + servingCertificateSecret,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			// these certificates are used only in the pod, not the router
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + servingCertificateSecret + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + servingCertificateSecret + "/tls.key",
+			"-t", "route.tls-termination=reencrypt",
+			// these certificates are used only in the router to encrypt the connection from the client to the router
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		time.Sleep(2 * time.Second)
+		Eventually(Service(ns, integrationName)()).ShouldNot(BeNil())
+		annotations := make(map[string]string)
+		annotations["service.beta.openshift.io/serving-cert-secret-name"] = servingCertificateSecret
+		err = addAnnotation(ns, integrationName, annotations)
+		assert.Nil(t, err)
+
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+		t.Run("Route reencrypt (with openshift service CA) https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_ReencryptWithServiceCAWithServiceCA"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+func httpRequest(t *testing.T, url string, tlsEnabled bool) (string, error) {
+	var client http.Client
+	if tlsEnabled {
+		certPool := x509.NewCertPool()
+		certPool.AppendCertsFromPEM(certPem)
+		transCfg := &http.Transport{
+			TLSClientConfig: &tls.Config {
+				RootCAs: certPool,
+			},
+		}
+		client = http.Client{Transport: transCfg}	
+	} else {
+		client = http.Client{}
+	}
+	response, err := client.Get(url)
+	defer func() {
+		if response != nil {
+			_ = response.Body.Close()
+		}
+	}()
+	if err != nil {
+		return "", err
+	}
+	assert.Nil(t, err)
+	buf := new(bytes.Buffer)
+	_, err = buf.ReadFrom(response.Body)
+	if err != nil {
+		return "", err
+	}
+	assert.Nil(t, err)
+	return buf.String(), nil
+}
+
+func createSecret(ns string) (corev1.Secret, error) {
+	keyCertPair := generateSampleKeyAndCertificate(ns)
+	sec := corev1.Secret{
+		TypeMeta: metav1.TypeMeta{
+			Kind:       "Secret",
+			APIVersion: corev1.SchemeGroupVersion.String(),
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: ns,
+			Name:      secretName,
+		},
+		Type: corev1.SecretTypeTLS,
+		Data: map[string][]byte{
+			corev1.TLSPrivateKeyKey: keyCertPair.Key,
+			corev1.TLSCertKey: keyCertPair.Certificate,
+		},
+	}
+	return sec, TestClient().Create(TestContext, &sec)
+}
+
+func generateSampleKeyAndCertificate(ns string) keyCertificatePair {
+	// Generate the TLS certificate
+	serialNumber := big.NewInt(rand2.Int63())
+	dnsHostname := integrationName + "-" + ns + "." + domainName()
+	x509Certificate := x509.Certificate{
+		SerialNumber: serialNumber,
+		Subject: pkix.Name{
+			Organization: []string{"Camel K test"},
+		},
+		IsCA: 				   true,
+		DNSNames:              []string{dnsHostname},
+		NotBefore:             time.Now(),
+		NotAfter:              time.Now().AddDate(1, 0, 0),
+		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
+		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
+		BasicConstraintsValid: true,
+	}
+
+	// generate the private key
+	certPrivateKey, err := rsa.GenerateKey(rand.Reader, 2048)
+	if err != nil {
+		fmt.Printf("Error generating private key: %s\n", err)
+	}
+
+	privateKeyBytes := x509.MarshalPKCS1PrivateKey(certPrivateKey)
+	// encode for storing into secret
+	privateKeyPem := pem.EncodeToMemory(
+		&pem.Block{
+			Type:  "RSA PRIVATE KEY",
+			Bytes: privateKeyBytes,
+		},
+	)
+	certBytes, err := x509.CreateCertificate(rand.Reader, &x509Certificate, &x509Certificate, &certPrivateKey.PublicKey, certPrivateKey)
+	if err != nil {
+		fmt.Printf("Error generating certificate: %s\n", err)
+	}
+
+	// encode for storing into secret
+	certPem = pem.EncodeToMemory(&pem.Block{
+		Type:  "CERTIFICATE",
+		Bytes: certBytes,
+	})
+
+	return keyCertificatePair {
+		Key: privateKeyPem,
+		Certificate: certPem,
+	}
+}
+
+func domainName() string {
+	consoleroute := Route("openshift-console", "console")()

Review comment:
       Changed to use `dns/cluster` object instead.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r703055369



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,401 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+	waitBeforeHttpRequest = 6 * time.Second
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+// self-signed certificate used when making the https request
+var certPem []byte
+
+// the e2e tests run on openshift3 in CI and there is no object to retrieve the base domain name
+// to create a valid hostname to later have it validate when doing the https request
+// as this a e2e test to validate the route object and not the certificate itself 
+// if the base domain name cannot be retrieved from dns/cluster we can safely skip TLS verification
+// if running on openshift4, there is the dns/cluster object to retrieve the base domain name, 
+// then in this case the http client validates the TLS certificate
+var skipClientTLSVerification = true
+
+func TestRunRoutes(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object across diferent tests
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		// they refer to the certificates create in the secret and are reused the different tests
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+
+		// =============================
+		// Insecure Route / No TLS
+		// =============================
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Edge
+		// =============================
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java", "-t", "route.tls-termination=edge").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(60 * time.Second)
+			url := fmt.Sprintf("https://%s/hello?name=TLS_Edge", route().Spec.Host)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello TLS_Edge", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Edge with custom certificate
+		// =============================
+
+		t.Run("Route Edge (custom certificate) https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				"-t", "route.tls-termination=edge",
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			code := "TLS_EdgeCustomCertificate"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Passthrough
+		// =============================
+
+		t.Run("Route passthrough https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				// the --resource mounts the certificates inside secret as files in the integration pod
+				"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+				// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+				"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+				"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+				"-t", "route.tls-termination=passthrough",
+				"-t", "container.port=8443",
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			code := "TLS_Passthrough"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Reencrypt
+		// =============================
+
+		t.Run("Route Reencrypt https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				// the --resource mounts the certificates inside secret as files in the integration pod
+				"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+				// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+				"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+				"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+				"-t", "route.tls-termination=reencrypt",
+				// the destination CA certificate which the route service uses to validate the HTTP endpoint TLS certificate
+				"-t", "route.tls-destination-ca-certificate-secret=" + refCert,
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,
+				"-t", "container.port=8443",
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			code := "TLS_Reencrypt"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Reencrypt With Openshift Service Serving CA
+		// =============================
+
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+		t.Run("Route reencrypt (with openshift service CA) https works", func(t *testing.T) {
+			// --resource references a serving certificate secret not created yet, as it is to be created
+			// when the service is created and the annotation added to it
+			// as a result eventually there is the following warning message in the console, don't worry as the pod waits for the secret to be created
+			// Warn: serving-certificate Secret not found in **** namespace, make sure to provide it before the Integration can run
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				// the --resource mounts the certificates inside secret as files in the integration pod
+				// they are used only for the pod exposing the HTTP endpoint, not the router
+				"--resource", "secret:" + servingCertificateSecret + "@/etc/ssl/" + servingCertificateSecret,
+				// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+				// these certificates are used only in the pod, not the router
+				"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + servingCertificateSecret + "/tls.crt",
+				"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + servingCertificateSecret + "/tls.key",
+				"-t", "route.tls-termination=reencrypt",
+				// these certificates are used only in the router to encrypt the connection from the client to the router
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,
+				"-t", "container.port=8443",
+			).Execute()).To(Succeed())
+
+			// should wait a little time before the service is ready
+			time.Sleep(2 * time.Second)
+			Eventually(Service(ns, integrationName)()).ShouldNot(BeNil())
+			annotations := make(map[string]string)
+			annotations["service.beta.openshift.io/serving-cert-secret-name"] = servingCertificateSecret
+			err = addAnnotation(ns, integrationName, annotations)

Review comment:
       I see your point and I agree. As this is just a short lived e2e test, can we have it as it is and open a new issue to track this specific service annotation issue ?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r702177092



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,382 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+	waitBeforeHttpRequest = 6 * time.Second
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+// self-signed certificate used when making the https request
+var certPem []byte
+
+// the e2e tests run on openshift3 in CI and there is no object to retrieve the base domain name
+// to create a valid hostname to later have it validate when doing the https request
+// as this a e2e test to validate the route object and not the certificate itself 
+// if the base domain name cannot be retrieved from dns/cluster we can safely skip TLS verification
+// if running on openshift4, there is the dns/cluster object to retrieve the base domain name, 
+// then in this case the http client validates the TLS certificate
+var skipClientTLSVerification = false
+
+func TestRunRoutes(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object across diferent tests
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		// they refer to the certificates create in the secret and are reused the different tests
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+
+		// =============================
+		// Insecure Route / No TLS
+		// =============================
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Edge
+		// =============================
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				"-t", "route.tls-termination=edge",
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,

Review comment:
       Added another test route of type `edge` with default certificate. 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] astefanutti commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
astefanutti commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r701717079



##########
File path: deploy/traits.yaml
##########
@@ -820,8 +820,17 @@ traits:
   platform: false
   profiles:
   - OpenShift
-  description: The Route trait can be used to configure the creation of OpenShift
-    routes for the integration.
+  description: 'The Route trait can be used to configure the creation of OpenShift
+    routes for the integration. The certificate and key contents may be stored either

Review comment:
       I'd suggest: "may be source either from"




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r702181005



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,382 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+	waitBeforeHttpRequest = 6 * time.Second
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+// self-signed certificate used when making the https request
+var certPem []byte
+
+// the e2e tests run on openshift3 in CI and there is no object to retrieve the base domain name
+// to create a valid hostname to later have it validate when doing the https request
+// as this a e2e test to validate the route object and not the certificate itself 
+// if the base domain name cannot be retrieved from dns/cluster we can safely skip TLS verification
+// if running on openshift4, there is the dns/cluster object to retrieve the base domain name, 
+// then in this case the http client validates the TLS certificate
+var skipClientTLSVerification = false
+
+func TestRunRoutes(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object across diferent tests
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		// they refer to the certificates create in the secret and are reused the different tests
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+
+		// =============================
+		// Insecure Route / No TLS
+		// =============================
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Edge
+		// =============================
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				"-t", "route.tls-termination=edge",
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("https://%s/hello?name=TLS_Edge", route().Spec.Host)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello TLS_Edge", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Passthrough
+		// =============================
+
+		t.Run("Route passthrough https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				// the --resource mounts the certificates inside secret as files in the integration pod
+				"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+				// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+				"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+				"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+				"-t", "route.tls-termination=passthrough",

Review comment:
       Can this be worked on another separated issue ? May be we could verify other camel components that may benefit from such automatic SSL configuration.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r701871526



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,382 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+	waitBeforeHttpRequest = 6 * time.Second
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+// self-signed certificate used when making the https request
+var certPem []byte
+
+// the e2e tests run on openshift3 in CI and there is no object to retrieve the base domain name
+// to create a valid hostname to later have it validate when doing the https request
+// as this a e2e test to validate the route object and not the certificate itself 
+// if the base domain name cannot be retrieved from dns/cluster we can safely skip TLS verification
+// if running on openshift4, there is the dns/cluster object to retrieve the base domain name, 
+// then in this case the http client validates the TLS certificate
+var skipClientTLSVerification = false
+
+func TestRunRoutes(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object across diferent tests
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		// they refer to the certificates create in the secret and are reused the different tests
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+
+		// =============================
+		// Insecure Route / No TLS
+		// =============================
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Edge
+		// =============================
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				"-t", "route.tls-termination=edge",
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("https://%s/hello?name=TLS_Edge", route().Spec.Host)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello TLS_Edge", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Passthrough
+		// =============================
+
+		t.Run("Route passthrough https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				// the --resource mounts the certificates inside secret as files in the integration pod
+				"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+				// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+				"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+				"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+				"-t", "route.tls-termination=passthrough",

Review comment:
       It just happen that using quarkus http requires these quarkus properties for [SSL setup](https://quarkus.io/guides/http-reference#ssl), whatever http client the user may choose it may require a different set of parameters to setup it. For example,   [Netty SSL](https://github.com/apache/camel-k/blob/main/examples/http/NettySecureServer.java#L18) requires mounting `-resource file:KeyStore.jks@/etc/ssl/keystore.jks `. With that said, it would be difficult to look at every SSL setup to automate in route trait.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r702181005



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,382 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+	waitBeforeHttpRequest = 6 * time.Second
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+// self-signed certificate used when making the https request
+var certPem []byte
+
+// the e2e tests run on openshift3 in CI and there is no object to retrieve the base domain name
+// to create a valid hostname to later have it validate when doing the https request
+// as this a e2e test to validate the route object and not the certificate itself 
+// if the base domain name cannot be retrieved from dns/cluster we can safely skip TLS verification
+// if running on openshift4, there is the dns/cluster object to retrieve the base domain name, 
+// then in this case the http client validates the TLS certificate
+var skipClientTLSVerification = false
+
+func TestRunRoutes(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object across diferent tests
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		// they refer to the certificates create in the secret and are reused the different tests
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+
+		// =============================
+		// Insecure Route / No TLS
+		// =============================
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Edge
+		// =============================
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				"-t", "route.tls-termination=edge",
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("https://%s/hello?name=TLS_Edge", route().Spec.Host)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello TLS_Edge", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Passthrough
+		// =============================
+
+		t.Run("Route passthrough https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				// the --resource mounts the certificates inside secret as files in the integration pod
+				"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+				// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+				"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+				"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+				"-t", "route.tls-termination=passthrough",

Review comment:
       Can this be worked on another separated issue ?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] astefanutti commented on pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
astefanutti commented on pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#issuecomment-912539024


   > > I'm not sure I understand why it's necessary for users to deal with low level resource mounting and Quarkus properties. Could the user provide only the secret name and the termination type, then the trait would take care of mounting the secret and set the Quarkus properties accordingly?
   > 
   > It just happen that using quarkus http requires these quarkus properties for [SSL setup](https://quarkus.io/guides/http-reference#ssl), whatever http client the user may choose it may require a different set of parameters to setup it. For example, [Netty SSL](https://github.com/apache/camel-k/blob/main/examples/http/NettySecureServer.java#L18) requires mounting `-resource file:KeyStore.jks@/etc/ssl/keystore.jks ` to setup `sslContextParameters` object. With that said, it would be difficult to look at every SSL setup to automate in route trait.
   
   it's not clear to me why the `quarkus.http.ssl.certificate` properties could not be set automatically.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r701874307



##########
File path: deploy/traits.yaml
##########
@@ -820,8 +820,17 @@ traits:
   platform: false
   profiles:
   - OpenShift
-  description: The Route trait can be used to configure the creation of OpenShift
-    routes for the integration.
+  description: 'The Route trait can be used to configure the creation of OpenShift
+    routes for the integration. The certificate and key contents may be stored either

Review comment:
       suggestion accepted.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#issuecomment-908462204


   @astefanutti more e2e tests were added, to support 5 cases: no tls, edge, reencrypt, reencrypt with service signing and passthrough
   Also, added more examples in docs on how to run integrations with the different route options.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] astefanutti commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
astefanutti commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r701710732



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,382 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+	waitBeforeHttpRequest = 6 * time.Second
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+// self-signed certificate used when making the https request
+var certPem []byte
+
+// the e2e tests run on openshift3 in CI and there is no object to retrieve the base domain name
+// to create a valid hostname to later have it validate when doing the https request
+// as this a e2e test to validate the route object and not the certificate itself 
+// if the base domain name cannot be retrieved from dns/cluster we can safely skip TLS verification
+// if running on openshift4, there is the dns/cluster object to retrieve the base domain name, 
+// then in this case the http client validates the TLS certificate
+var skipClientTLSVerification = false
+
+func TestRunRoutes(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object across diferent tests
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		// they refer to the certificates create in the secret and are reused the different tests
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+
+		// =============================
+		// Insecure Route / No TLS
+		// =============================
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Edge
+		// =============================
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				"-t", "route.tls-termination=edge",
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("https://%s/hello?name=TLS_Edge", route().Spec.Host)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello TLS_Edge", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Passthrough
+		// =============================
+
+		t.Run("Route passthrough https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				// the --resource mounts the certificates inside secret as files in the integration pod
+				"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+				// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+				"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+				"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+				"-t", "route.tls-termination=passthrough",

Review comment:
       Can't this be automated by the route trait? The user could be able to provide the secret name and the termination type.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] squakez commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
squakez commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r699022900



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,444 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"strings"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	ctrl "sigs.k8s.io/controller-runtime/pkg/client"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+var certPem []byte
+
+// this test uses a route with no TLS
+func TestRunRouteNoTLS(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())

Review comment:
       In order reduce the execution time, I think it would be wiser to run the test into the same method. You will only install the operator once and reuse the same kit along all tests. I used the approach in the [user config test](https://github.com/apache/camel-k/blob/main/e2e/common/config/config_test.go).

##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,444 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"strings"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	ctrl "sigs.k8s.io/controller-runtime/pkg/client"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+var certPem []byte
+
+// this test uses a route with no TLS
+func TestRunRouteNoTLS(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+		// Cleanup all integrations when the test finishes
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(4 * time.Second)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+		})
+	})
+}
+
+func TestRunRouteTLS_Edge(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+		// delete secret when the test finishes
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		// they refer to the secret/certificates previsouly created
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			"-t", "route.tls-termination=edge",
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+		).Execute()).To(Succeed())
+		// Cleanup all integrations when the test finishes
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			url := fmt.Sprintf("https://%s/hello?name=TLS_Edge", route().Spec.Host)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello TLS_Edge", response)
+		})
+	})
+}
+
+func TestRunRouteTLS_Passthrough(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+			"-t", "route.tls-termination=passthrough",
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route passthrough https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_Passthrough"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+// This test uses a self-signed certificate to create a TLS route
+func TestRunRouteTLS_Reencrypt(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+			"-t", "route.tls-termination=reencrypt",
+			// the destination CA certificate which the route service uses to validate the HTTP endpoint TLS certificate
+			"-t", "route.tls-destination-ca-certificate-secret=" + refCert,
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route Reencrypt https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_Reencrypt"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+// This test uses a certificate provided by openshift "service serving certificates" to create a TLS route
+func TestRunRouteTLS_ReencryptWithServiceCA(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		// they refer to the secret previsouly created
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			// they are used only for the pod exposing the HTTP endpoint, not the router
+			"--resource", "secret:" + servingCertificateSecret + "@/etc/ssl/" + servingCertificateSecret,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			// these certificates are used only in the pod, not the router
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + servingCertificateSecret + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + servingCertificateSecret + "/tls.key",
+			"-t", "route.tls-termination=reencrypt",
+			// these certificates are used only in the router to encrypt the connection from the client to the router
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		time.Sleep(2 * time.Second)
+		Eventually(Service(ns, integrationName)()).ShouldNot(BeNil())
+		annotations := make(map[string]string)
+		annotations["service.beta.openshift.io/serving-cert-secret-name"] = servingCertificateSecret
+		err = addAnnotation(ns, integrationName, annotations)
+		assert.Nil(t, err)
+
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+		t.Run("Route reencrypt (with openshift service CA) https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_ReencryptWithServiceCAWithServiceCA"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+func httpRequest(t *testing.T, url string, tlsEnabled bool) (string, error) {
+	var client http.Client
+	if tlsEnabled {
+		certPool := x509.NewCertPool()
+		certPool.AppendCertsFromPEM(certPem)
+		transCfg := &http.Transport{
+			TLSClientConfig: &tls.Config {
+				RootCAs: certPool,
+			},
+		}
+		client = http.Client{Transport: transCfg}	
+	} else {
+		client = http.Client{}
+	}
+	response, err := client.Get(url)
+	defer func() {
+		if response != nil {
+			_ = response.Body.Close()
+		}
+	}()
+	if err != nil {
+		return "", err
+	}
+	assert.Nil(t, err)
+	buf := new(bytes.Buffer)
+	_, err = buf.ReadFrom(response.Body)
+	if err != nil {
+		return "", err
+	}
+	assert.Nil(t, err)
+	return buf.String(), nil
+}
+
+func createSecret(ns string) (corev1.Secret, error) {
+	keyCertPair := generateSampleKeyAndCertificate(ns)
+	sec := corev1.Secret{
+		TypeMeta: metav1.TypeMeta{
+			Kind:       "Secret",
+			APIVersion: corev1.SchemeGroupVersion.String(),
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: ns,
+			Name:      secretName,
+		},
+		Type: corev1.SecretTypeTLS,
+		Data: map[string][]byte{
+			corev1.TLSPrivateKeyKey: keyCertPair.Key,
+			corev1.TLSCertKey: keyCertPair.Certificate,
+		},
+	}
+	return sec, TestClient().Create(TestContext, &sec)
+}
+
+func generateSampleKeyAndCertificate(ns string) keyCertificatePair {
+	// Generate the TLS certificate
+	serialNumber := big.NewInt(rand2.Int63())
+	dnsHostname := integrationName + "-" + ns + "." + domainName()
+	x509Certificate := x509.Certificate{
+		SerialNumber: serialNumber,
+		Subject: pkix.Name{
+			Organization: []string{"Camel K test"},
+		},
+		IsCA: 				   true,
+		DNSNames:              []string{dnsHostname},
+		NotBefore:             time.Now(),
+		NotAfter:              time.Now().AddDate(1, 0, 0),
+		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
+		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
+		BasicConstraintsValid: true,
+	}
+
+	// generate the private key
+	certPrivateKey, err := rsa.GenerateKey(rand.Reader, 2048)
+	if err != nil {
+		fmt.Printf("Error generating private key: %s\n", err)
+	}
+
+	privateKeyBytes := x509.MarshalPKCS1PrivateKey(certPrivateKey)
+	// encode for storing into secret
+	privateKeyPem := pem.EncodeToMemory(
+		&pem.Block{
+			Type:  "RSA PRIVATE KEY",
+			Bytes: privateKeyBytes,
+		},
+	)
+	certBytes, err := x509.CreateCertificate(rand.Reader, &x509Certificate, &x509Certificate, &certPrivateKey.PublicKey, certPrivateKey)
+	if err != nil {
+		fmt.Printf("Error generating certificate: %s\n", err)
+	}
+
+	// encode for storing into secret
+	certPem = pem.EncodeToMemory(&pem.Block{
+		Type:  "CERTIFICATE",
+		Bytes: certBytes,
+	})
+
+	return keyCertificatePair {
+		Key: privateKeyPem,
+		Certificate: certPem,
+	}
+}
+
+func domainName() string {
+	consoleroute := Route("openshift-console", "console")()

Review comment:
       Any reason why to use `openshift-console`? Could we use something not bound to any product?

##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,444 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"strings"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	ctrl "sigs.k8s.io/controller-runtime/pkg/client"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+var certPem []byte
+
+// this test uses a route with no TLS
+func TestRunRouteNoTLS(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+		// Cleanup all integrations when the test finishes
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(4 * time.Second)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+		})
+	})
+}
+
+func TestRunRouteTLS_Edge(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+		// delete secret when the test finishes
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		// they refer to the secret/certificates previsouly created
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			"-t", "route.tls-termination=edge",
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+		).Execute()).To(Succeed())
+		// Cleanup all integrations when the test finishes
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			url := fmt.Sprintf("https://%s/hello?name=TLS_Edge", route().Spec.Host)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello TLS_Edge", response)
+		})
+	})
+}
+
+func TestRunRouteTLS_Passthrough(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+			"-t", "route.tls-termination=passthrough",
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route passthrough https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_Passthrough"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+// This test uses a self-signed certificate to create a TLS route
+func TestRunRouteTLS_Reencrypt(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+			"-t", "route.tls-termination=reencrypt",
+			// the destination CA certificate which the route service uses to validate the HTTP endpoint TLS certificate
+			"-t", "route.tls-destination-ca-certificate-secret=" + refCert,
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route Reencrypt https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_Reencrypt"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+// This test uses a certificate provided by openshift "service serving certificates" to create a TLS route
+func TestRunRouteTLS_ReencryptWithServiceCA(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		// they refer to the secret previsouly created
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			// they are used only for the pod exposing the HTTP endpoint, not the router
+			"--resource", "secret:" + servingCertificateSecret + "@/etc/ssl/" + servingCertificateSecret,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			// these certificates are used only in the pod, not the router
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + servingCertificateSecret + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + servingCertificateSecret + "/tls.key",
+			"-t", "route.tls-termination=reencrypt",
+			// these certificates are used only in the router to encrypt the connection from the client to the router
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		time.Sleep(2 * time.Second)
+		Eventually(Service(ns, integrationName)()).ShouldNot(BeNil())
+		annotations := make(map[string]string)
+		annotations["service.beta.openshift.io/serving-cert-secret-name"] = servingCertificateSecret
+		err = addAnnotation(ns, integrationName, annotations)
+		assert.Nil(t, err)
+
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+		t.Run("Route reencrypt (with openshift service CA) https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_ReencryptWithServiceCAWithServiceCA"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+func httpRequest(t *testing.T, url string, tlsEnabled bool) (string, error) {
+	var client http.Client
+	if tlsEnabled {
+		certPool := x509.NewCertPool()
+		certPool.AppendCertsFromPEM(certPem)
+		transCfg := &http.Transport{
+			TLSClientConfig: &tls.Config {
+				RootCAs: certPool,
+			},
+		}
+		client = http.Client{Transport: transCfg}	
+	} else {
+		client = http.Client{}
+	}
+	response, err := client.Get(url)
+	defer func() {
+		if response != nil {
+			_ = response.Body.Close()
+		}
+	}()
+	if err != nil {
+		return "", err
+	}
+	assert.Nil(t, err)
+	buf := new(bytes.Buffer)
+	_, err = buf.ReadFrom(response.Body)
+	if err != nil {
+		return "", err
+	}
+	assert.Nil(t, err)
+	return buf.String(), nil
+}
+
+func createSecret(ns string) (corev1.Secret, error) {
+	keyCertPair := generateSampleKeyAndCertificate(ns)
+	sec := corev1.Secret{
+		TypeMeta: metav1.TypeMeta{
+			Kind:       "Secret",
+			APIVersion: corev1.SchemeGroupVersion.String(),
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: ns,
+			Name:      secretName,
+		},
+		Type: corev1.SecretTypeTLS,
+		Data: map[string][]byte{
+			corev1.TLSPrivateKeyKey: keyCertPair.Key,
+			corev1.TLSCertKey: keyCertPair.Certificate,
+		},
+	}
+	return sec, TestClient().Create(TestContext, &sec)
+}
+
+func generateSampleKeyAndCertificate(ns string) keyCertificatePair {
+	// Generate the TLS certificate
+	serialNumber := big.NewInt(rand2.Int63())
+	dnsHostname := integrationName + "-" + ns + "." + domainName()
+	x509Certificate := x509.Certificate{
+		SerialNumber: serialNumber,
+		Subject: pkix.Name{
+			Organization: []string{"Camel K test"},
+		},
+		IsCA: 				   true,
+		DNSNames:              []string{dnsHostname},
+		NotBefore:             time.Now(),
+		NotAfter:              time.Now().AddDate(1, 0, 0),
+		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
+		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
+		BasicConstraintsValid: true,
+	}
+
+	// generate the private key
+	certPrivateKey, err := rsa.GenerateKey(rand.Reader, 2048)
+	if err != nil {
+		fmt.Printf("Error generating private key: %s\n", err)
+	}
+
+	privateKeyBytes := x509.MarshalPKCS1PrivateKey(certPrivateKey)
+	// encode for storing into secret
+	privateKeyPem := pem.EncodeToMemory(
+		&pem.Block{
+			Type:  "RSA PRIVATE KEY",
+			Bytes: privateKeyBytes,
+		},
+	)
+	certBytes, err := x509.CreateCertificate(rand.Reader, &x509Certificate, &x509Certificate, &certPrivateKey.PublicKey, certPrivateKey)
+	if err != nil {
+		fmt.Printf("Error generating certificate: %s\n", err)
+	}
+
+	// encode for storing into secret
+	certPem = pem.EncodeToMemory(&pem.Block{
+		Type:  "CERTIFICATE",
+		Bytes: certBytes,
+	})
+
+	return keyCertificatePair {
+		Key: privateKeyPem,
+		Certificate: certPem,
+	}
+}
+
+func domainName() string {
+	consoleroute := Route("openshift-console", "console")()
+	return strings.ReplaceAll(consoleroute.Spec.Host, "console-openshift-console.", "")
+}
+
+func getService(ns string, name string) (*corev1.Service, error) {
+	svc := corev1.Service{}
+	key := ctrl.ObjectKey{
+		Namespace: ns,
+		Name:      name,
+	}
+	err := TestClient().Get(TestContext, key, &svc)
+	return &svc, err
+}
+
+func addAnnotation(ns string, name string, annotations map[string]string) error {

Review comment:
       Same comment as for `addService` method

##########
File path: pkg/trait/route.go
##########
@@ -174,19 +196,83 @@ func (t *routeTrait) Apply(e *Environment) error {
 	return nil
 }
 
-func (t *routeTrait) getTLSConfig() *routev1.TLSConfig {
+func (t *routeTrait) getTLSConfig() (*routev1.TLSConfig, error) {
+	// a certificate is a multiline text, but to set it as value in a single line in CLI, the user must escape the new line character as \\n
+	// but in the TLS configuration, the certificates should be a multiline string
+	// then we need to replace the incoming escaped new lines \\n for a real new line \n
+	key := strings.ReplaceAll(t.TLSKey, "\\n", "\n")

Review comment:
       Probably I did not express my concern properly. I was thinking this part would be better read with an approach like the following:
   ```
   var key string
   if t.TLSKey != "" {
     if t.TLSKeySecret != "" {
       // error, both key and keysecret provided
     }
     key = // take value from t.TLSKey
   } else if t.TLSKeySecret != "" {
     key = // take value from t.TLSKeySecret
   } else {
     // error, missing key/key secret
   }
   ```

##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,444 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"strings"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	ctrl "sigs.k8s.io/controller-runtime/pkg/client"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+var certPem []byte
+
+// this test uses a route with no TLS
+func TestRunRouteNoTLS(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+		// Cleanup all integrations when the test finishes
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(4 * time.Second)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+		})
+	})
+}
+
+func TestRunRouteTLS_Edge(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+		// delete secret when the test finishes
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		// they refer to the secret/certificates previsouly created
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			"-t", "route.tls-termination=edge",
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+		).Execute()).To(Succeed())
+		// Cleanup all integrations when the test finishes
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			url := fmt.Sprintf("https://%s/hello?name=TLS_Edge", route().Spec.Host)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello TLS_Edge", response)
+		})
+	})
+}
+
+func TestRunRouteTLS_Passthrough(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+			"-t", "route.tls-termination=passthrough",
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route passthrough https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_Passthrough"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+// This test uses a self-signed certificate to create a TLS route
+func TestRunRouteTLS_Reencrypt(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+			"-t", "route.tls-termination=reencrypt",
+			// the destination CA certificate which the route service uses to validate the HTTP endpoint TLS certificate
+			"-t", "route.tls-destination-ca-certificate-secret=" + refCert,
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route Reencrypt https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_Reencrypt"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+// This test uses a certificate provided by openshift "service serving certificates" to create a TLS route
+func TestRunRouteTLS_ReencryptWithServiceCA(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		// they refer to the secret previsouly created
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			// they are used only for the pod exposing the HTTP endpoint, not the router
+			"--resource", "secret:" + servingCertificateSecret + "@/etc/ssl/" + servingCertificateSecret,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			// these certificates are used only in the pod, not the router
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + servingCertificateSecret + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + servingCertificateSecret + "/tls.key",
+			"-t", "route.tls-termination=reencrypt",
+			// these certificates are used only in the router to encrypt the connection from the client to the router
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		time.Sleep(2 * time.Second)
+		Eventually(Service(ns, integrationName)()).ShouldNot(BeNil())
+		annotations := make(map[string]string)
+		annotations["service.beta.openshift.io/serving-cert-secret-name"] = servingCertificateSecret
+		err = addAnnotation(ns, integrationName, annotations)
+		assert.Nil(t, err)
+
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+		t.Run("Route reencrypt (with openshift service CA) https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_ReencryptWithServiceCAWithServiceCA"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+func httpRequest(t *testing.T, url string, tlsEnabled bool) (string, error) {
+	var client http.Client
+	if tlsEnabled {
+		certPool := x509.NewCertPool()
+		certPool.AppendCertsFromPEM(certPem)
+		transCfg := &http.Transport{
+			TLSClientConfig: &tls.Config {
+				RootCAs: certPool,
+			},
+		}
+		client = http.Client{Transport: transCfg}	
+	} else {
+		client = http.Client{}
+	}
+	response, err := client.Get(url)
+	defer func() {
+		if response != nil {
+			_ = response.Body.Close()
+		}
+	}()
+	if err != nil {
+		return "", err
+	}
+	assert.Nil(t, err)
+	buf := new(bytes.Buffer)
+	_, err = buf.ReadFrom(response.Body)
+	if err != nil {
+		return "", err
+	}
+	assert.Nil(t, err)
+	return buf.String(), nil
+}
+
+func createSecret(ns string) (corev1.Secret, error) {
+	keyCertPair := generateSampleKeyAndCertificate(ns)
+	sec := corev1.Secret{
+		TypeMeta: metav1.TypeMeta{
+			Kind:       "Secret",
+			APIVersion: corev1.SchemeGroupVersion.String(),
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: ns,
+			Name:      secretName,
+		},
+		Type: corev1.SecretTypeTLS,
+		Data: map[string][]byte{
+			corev1.TLSPrivateKeyKey: keyCertPair.Key,
+			corev1.TLSCertKey: keyCertPair.Certificate,
+		},
+	}
+	return sec, TestClient().Create(TestContext, &sec)
+}
+
+func generateSampleKeyAndCertificate(ns string) keyCertificatePair {
+	// Generate the TLS certificate
+	serialNumber := big.NewInt(rand2.Int63())
+	dnsHostname := integrationName + "-" + ns + "." + domainName()
+	x509Certificate := x509.Certificate{
+		SerialNumber: serialNumber,
+		Subject: pkix.Name{
+			Organization: []string{"Camel K test"},
+		},
+		IsCA: 				   true,
+		DNSNames:              []string{dnsHostname},
+		NotBefore:             time.Now(),
+		NotAfter:              time.Now().AddDate(1, 0, 0),
+		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
+		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
+		BasicConstraintsValid: true,
+	}
+
+	// generate the private key
+	certPrivateKey, err := rsa.GenerateKey(rand.Reader, 2048)
+	if err != nil {
+		fmt.Printf("Error generating private key: %s\n", err)
+	}
+
+	privateKeyBytes := x509.MarshalPKCS1PrivateKey(certPrivateKey)
+	// encode for storing into secret
+	privateKeyPem := pem.EncodeToMemory(
+		&pem.Block{
+			Type:  "RSA PRIVATE KEY",
+			Bytes: privateKeyBytes,
+		},
+	)
+	certBytes, err := x509.CreateCertificate(rand.Reader, &x509Certificate, &x509Certificate, &certPrivateKey.PublicKey, certPrivateKey)
+	if err != nil {
+		fmt.Printf("Error generating certificate: %s\n", err)
+	}
+
+	// encode for storing into secret
+	certPem = pem.EncodeToMemory(&pem.Block{
+		Type:  "CERTIFICATE",
+		Bytes: certBytes,
+	})
+
+	return keyCertificatePair {
+		Key: privateKeyPem,
+		Certificate: certPem,
+	}
+}
+
+func domainName() string {
+	consoleroute := Route("openshift-console", "console")()
+	return strings.ReplaceAll(consoleroute.Spec.Host, "console-openshift-console.", "")
+}
+
+func getService(ns string, name string) (*corev1.Service, error) {

Review comment:
       If it's a generic method, and is not already present in test_support.go, we better move it there and have it available for anybody willing to use it.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] astefanutti commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
astefanutti commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r701708764



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,382 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+	waitBeforeHttpRequest = 6 * time.Second
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+// self-signed certificate used when making the https request
+var certPem []byte
+
+// the e2e tests run on openshift3 in CI and there is no object to retrieve the base domain name
+// to create a valid hostname to later have it validate when doing the https request
+// as this a e2e test to validate the route object and not the certificate itself 
+// if the base domain name cannot be retrieved from dns/cluster we can safely skip TLS verification
+// if running on openshift4, there is the dns/cluster object to retrieve the base domain name, 
+// then in this case the http client validates the TLS certificate
+var skipClientTLSVerification = false
+
+func TestRunRoutes(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object across diferent tests
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		// they refer to the certificates create in the secret and are reused the different tests
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+
+		// =============================
+		// Insecure Route / No TLS
+		// =============================
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Edge
+		// =============================
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				"-t", "route.tls-termination=edge",
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,

Review comment:
       Why is a secret is needed with `edge` termination?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r702180701



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,382 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+	waitBeforeHttpRequest = 6 * time.Second
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+// self-signed certificate used when making the https request
+var certPem []byte
+
+// the e2e tests run on openshift3 in CI and there is no object to retrieve the base domain name
+// to create a valid hostname to later have it validate when doing the https request
+// as this a e2e test to validate the route object and not the certificate itself 
+// if the base domain name cannot be retrieved from dns/cluster we can safely skip TLS verification
+// if running on openshift4, there is the dns/cluster object to retrieve the base domain name, 
+// then in this case the http client validates the TLS certificate
+var skipClientTLSVerification = false
+
+func TestRunRoutes(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object across diferent tests
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		// they refer to the certificates create in the secret and are reused the different tests
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+
+		// =============================
+		// Insecure Route / No TLS
+		// =============================
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Edge
+		// =============================
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				"-t", "route.tls-termination=edge",
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("https://%s/hello?name=TLS_Edge", route().Spec.Host)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello TLS_Edge", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Passthrough
+		// =============================
+
+		t.Run("Route passthrough https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				// the --resource mounts the certificates inside secret as files in the integration pod
+				"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+				// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+				"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+				"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+				"-t", "route.tls-termination=passthrough",
+				"-t", "container.port=8443",
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			code := "TLS_Passthrough"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Reencrypt
+		// =============================
+
+		t.Run("Route Reencrypt https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				// the --resource mounts the certificates inside secret as files in the integration pod
+				"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+				// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+				"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+				"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+				"-t", "route.tls-termination=reencrypt",

Review comment:
       done.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] astefanutti commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
astefanutti commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r691060263



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,124 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/tls"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "my-combined-tls"
+	keyName = "my-key"
+	certName = "my-cert"
+	keyFilePath = "files/key.key"
+	certFilePath = "files/crt.crt"
+)
+
+func TestRunRouteTLS(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		createSecrets(ns)
+
+		refKey := secretName + "/" + keyName
+		refCert := secretName + "/" + certName
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/NettyServer.java",
+			"-t", "route.enabled=true",
+			"-t", "route.tls-termination=edge",
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+		).Execute()).To(Succeed())
+		Eventually(IntegrationPodPhase(ns, "netty-server"), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route https works", func(t *testing.T) {
+			route := Route(ns, "netty-server")
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request
+			time.Sleep(3 * time.Second)
+			response := httpsRequest(t, fmt.Sprintf("https://%s/hello", route().Spec.Host))
+			assert.Equal(t, "Hello World", response)
+		})
+		// Cleanup
+		Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+	// })
+	})
+}
+
+func httpsRequest(t *testing.T, url string) string {
+	transCfg := &http.Transport{
+		// ignore self signed SSL certificates
+		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},

Review comment:
       It would be better to use the CA that signed the certificate.

##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,124 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/tls"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "my-combined-tls"
+	keyName = "my-key"
+	certName = "my-cert"
+	keyFilePath = "files/key.key"

Review comment:
       To improve readability and maintainability, it'd be better to have those filles code-generated. You can find an example at https://github.com/apache/camel-k/blob/69f0a4bc95f4f1efa6458d241fbc503cb979a7b0/e2e/common/build/maven_ca_secret_test.go.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r701867236



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,382 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+	waitBeforeHttpRequest = 6 * time.Second
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+// self-signed certificate used when making the https request
+var certPem []byte
+
+// the e2e tests run on openshift3 in CI and there is no object to retrieve the base domain name
+// to create a valid hostname to later have it validate when doing the https request
+// as this a e2e test to validate the route object and not the certificate itself 
+// if the base domain name cannot be retrieved from dns/cluster we can safely skip TLS verification
+// if running on openshift4, there is the dns/cluster object to retrieve the base domain name, 
+// then in this case the http client validates the TLS certificate
+var skipClientTLSVerification = false
+
+func TestRunRoutes(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object across diferent tests
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		// they refer to the certificates create in the secret and are reused the different tests
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+
+		// =============================
+		// Insecure Route / No TLS
+		// =============================
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Edge
+		// =============================
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				"-t", "route.tls-termination=edge",
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,

Review comment:
       To use `edge` termination a certificate is required and it comes from the `secret`.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] astefanutti commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
astefanutti commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r701718384



##########
File path: deploy/traits.yaml
##########
@@ -833,19 +842,39 @@ traits:
   - name: tls-termination
     type: string
     description: The TLS termination type, like `edge`, `passthrough` or `reencrypt`.Refer
-      to the OpenShift documentation for additional information.
+      to the OpenShift route documentation for additional information.
   - name: tls-certificate
     type: string
-    description: The TLS certificate contents.Refer to the OpenShift documentation
+    description: The TLS certificate contents.Refer to the OpenShift route documentation
       for additional information.
+  - name: tls-certificate-secret
+    type: string
+    description: The TLS certificate contents read from a secret. The format is "secret-name[/key-name]",
+      the value represents the secret name, if there is only one key in the secret
+      it will be read, otherwise you can set a key name separated with a "/".Refer
+      to the OpenShift route documentation for additional information.
   - name: tls-key
     type: string
-    description: The TLS certificate key contents.Refer to the OpenShift documentation
+    description: The TLS certificate key contents.Refer to the OpenShift route documentation
       for additional information.
+  - name: tls-key-secret
+    type: string
+    description: The TLS certificate key contents read from a secret. The format is

Review comment:
       dito.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] astefanutti commented on pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
astefanutti commented on pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#issuecomment-916144688


   @claudio4j could you please fix the conflicts in `route_test.go` and regenerate `resources.go`? Sorry about that.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] astefanutti commented on pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
astefanutti commented on pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#issuecomment-916264202


   @claudio4j thanks!


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] squakez commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
squakez commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r696595126



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,124 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/tls"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "my-combined-tls"
+	keyName = "my-key"
+	certName = "my-cert"
+	keyFilePath = "files/key.key"
+	certFilePath = "files/crt.crt"
+)
+
+func TestRunRouteTLS(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		createSecrets(ns)
+
+		refKey := secretName + "/" + keyName
+		refCert := secretName + "/" + certName
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/NettyServer.java",
+			"-t", "route.enabled=true",
+			"-t", "route.tls-termination=edge",
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+		).Execute()).To(Succeed())
+		Eventually(IntegrationPodPhase(ns, "netty-server"), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route https works", func(t *testing.T) {
+			route := Route(ns, "netty-server")
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request
+			time.Sleep(3 * time.Second)
+			response := httpsRequest(t, fmt.Sprintf("https://%s/hello", route().Spec.Host))
+			assert.Equal(t, "Hello World", response)
+		})
+		// Cleanup
+		Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+	// })
+	})
+}
+
+func httpsRequest(t *testing.T, url string) string {
+	transCfg := &http.Transport{
+		// ignore self signed SSL certificates
+		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
+	}
+	client := &http.Client{Transport: transCfg}
+	response, err := client.Get(url)
+	defer func() {
+		if response != nil {
+			_ = response.Body.Close()
+		}
+	}()
+	assert.Nil(t, err)
+	buf := new(bytes.Buffer)
+	_, err = buf.ReadFrom(response.Body)
+	assert.Nil(t, err)
+	return buf.String()
+}
+
+func createSecrets(ns string) error {

Review comment:
       We have already a [NewPlainTextSecret](https://github.com/apache/camel-k/blob/main/e2e/support/test_support.go#L768) method in test_support.go. You may include a NewBinarySecret beside it so it can be reusable by other tests.

##########
File path: pkg/trait/route.go
##########
@@ -174,19 +196,83 @@ func (t *routeTrait) Apply(e *Environment) error {
 	return nil
 }
 
-func (t *routeTrait) getTLSConfig() *routev1.TLSConfig {
+func (t *routeTrait) getTLSConfig() (*routev1.TLSConfig, error) {
+	// a certificate is a multiline text, but to set it as value in a single line in CLI, the user must escape the new line character as \\n
+	// but in the TLS configuration, the certificates should be a multiline string
+	// then we need to replace the incoming escaped new lines \\n for a real new line \n
+	key := strings.ReplaceAll(t.TLSKey, "\\n", "\n")

Review comment:
       I think each one of these parameters should be mutually exclusive. Ie, if TLSKey exists, then, TLSKeySecret must not exist and viceversa. 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r701902364



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,382 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+	waitBeforeHttpRequest = 6 * time.Second
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+// self-signed certificate used when making the https request
+var certPem []byte
+
+// the e2e tests run on openshift3 in CI and there is no object to retrieve the base domain name
+// to create a valid hostname to later have it validate when doing the https request
+// as this a e2e test to validate the route object and not the certificate itself 
+// if the base domain name cannot be retrieved from dns/cluster we can safely skip TLS verification
+// if running on openshift4, there is the dns/cluster object to retrieve the base domain name, 
+// then in this case the http client validates the TLS certificate
+var skipClientTLSVerification = false
+
+func TestRunRoutes(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object across diferent tests
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		// they refer to the certificates create in the secret and are reused the different tests
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+
+		// =============================
+		// Insecure Route / No TLS
+		// =============================
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Edge
+		// =============================
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				"-t", "route.tls-termination=edge",
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,

Review comment:
       I see the certificate is not required for `edge`, I can remove it, however as this is an e2e test it was my understanding to have the tests to cover all scenarios. I just tested locally with no certificate for edge and it works. Well, I can remove the certificate for edge ssl setup, if that's the case.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] squakez commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
squakez commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r699021504



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,124 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/tls"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "my-combined-tls"
+	keyName = "my-key"
+	certName = "my-cert"
+	keyFilePath = "files/key.key"
+	certFilePath = "files/crt.crt"
+)
+
+func TestRunRouteTLS(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		createSecrets(ns)
+
+		refKey := secretName + "/" + keyName
+		refCert := secretName + "/" + certName
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/NettyServer.java",
+			"-t", "route.enabled=true",
+			"-t", "route.tls-termination=edge",
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+		).Execute()).To(Succeed())
+		Eventually(IntegrationPodPhase(ns, "netty-server"), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route https works", func(t *testing.T) {
+			route := Route(ns, "netty-server")
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request
+			time.Sleep(3 * time.Second)
+			response := httpsRequest(t, fmt.Sprintf("https://%s/hello", route().Spec.Host))
+			assert.Equal(t, "Hello World", response)
+		})
+		// Cleanup
+		Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+	// })
+	})
+}
+
+func httpsRequest(t *testing.T, url string) string {
+	transCfg := &http.Transport{
+		// ignore self signed SSL certificates
+		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
+	}
+	client := &http.Client{Transport: transCfg}
+	response, err := client.Get(url)
+	defer func() {
+		if response != nil {
+			_ = response.Body.Close()
+		}
+	}()
+	assert.Nil(t, err)
+	buf := new(bytes.Buffer)
+	_, err = buf.ReadFrom(response.Body)
+	assert.Nil(t, err)
+	return buf.String()
+}
+
+func createSecrets(ns string) error {

Review comment:
       Yeah, I think it would be cleaner to have a `func NewBinarySecret(ns string, name string, data map[string][]byte) error` method which generically takes in a binary content. Then you use it from your private method with the certificates created for the purpose.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] astefanutti commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
astefanutti commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r701882780



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,382 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+	waitBeforeHttpRequest = 6 * time.Second
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+// self-signed certificate used when making the https request
+var certPem []byte
+
+// the e2e tests run on openshift3 in CI and there is no object to retrieve the base domain name
+// to create a valid hostname to later have it validate when doing the https request
+// as this a e2e test to validate the route object and not the certificate itself 
+// if the base domain name cannot be retrieved from dns/cluster we can safely skip TLS verification
+// if running on openshift4, there is the dns/cluster object to retrieve the base domain name, 
+// then in this case the http client validates the TLS certificate
+var skipClientTLSVerification = false
+
+func TestRunRoutes(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object across diferent tests
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		// they refer to the certificates create in the secret and are reused the different tests
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+
+		// =============================
+		// Insecure Route / No TLS
+		// =============================
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Edge
+		// =============================
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				"-t", "route.tls-termination=edge",
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("https://%s/hello?name=TLS_Edge", route().Spec.Host)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello TLS_Edge", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Passthrough
+		// =============================
+
+		t.Run("Route passthrough https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				// the --resource mounts the certificates inside secret as files in the integration pod
+				"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+				// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+				"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+				"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+				"-t", "route.tls-termination=passthrough",

Review comment:
       My point is more: could the trait set these properties automatically?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r699527695



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,444 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"strings"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	ctrl "sigs.k8s.io/controller-runtime/pkg/client"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+var certPem []byte
+
+// this test uses a route with no TLS
+func TestRunRouteNoTLS(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+		// Cleanup all integrations when the test finishes
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(4 * time.Second)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+		})
+	})
+}
+
+func TestRunRouteTLS_Edge(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+		// delete secret when the test finishes
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		// they refer to the secret/certificates previsouly created
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			"-t", "route.tls-termination=edge",
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+		).Execute()).To(Succeed())
+		// Cleanup all integrations when the test finishes
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			url := fmt.Sprintf("https://%s/hello?name=TLS_Edge", route().Spec.Host)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello TLS_Edge", response)
+		})
+	})
+}
+
+func TestRunRouteTLS_Passthrough(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+			"-t", "route.tls-termination=passthrough",
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route passthrough https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_Passthrough"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+// This test uses a self-signed certificate to create a TLS route
+func TestRunRouteTLS_Reencrypt(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+			"-t", "route.tls-termination=reencrypt",
+			// the destination CA certificate which the route service uses to validate the HTTP endpoint TLS certificate
+			"-t", "route.tls-destination-ca-certificate-secret=" + refCert,
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route Reencrypt https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_Reencrypt"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+// This test uses a certificate provided by openshift "service serving certificates" to create a TLS route
+func TestRunRouteTLS_ReencryptWithServiceCA(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		// they refer to the secret previsouly created
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			// they are used only for the pod exposing the HTTP endpoint, not the router
+			"--resource", "secret:" + servingCertificateSecret + "@/etc/ssl/" + servingCertificateSecret,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			// these certificates are used only in the pod, not the router
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + servingCertificateSecret + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + servingCertificateSecret + "/tls.key",
+			"-t", "route.tls-termination=reencrypt",
+			// these certificates are used only in the router to encrypt the connection from the client to the router
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		time.Sleep(2 * time.Second)
+		Eventually(Service(ns, integrationName)()).ShouldNot(BeNil())
+		annotations := make(map[string]string)
+		annotations["service.beta.openshift.io/serving-cert-secret-name"] = servingCertificateSecret
+		err = addAnnotation(ns, integrationName, annotations)
+		assert.Nil(t, err)
+
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+		t.Run("Route reencrypt (with openshift service CA) https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_ReencryptWithServiceCAWithServiceCA"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+func httpRequest(t *testing.T, url string, tlsEnabled bool) (string, error) {
+	var client http.Client
+	if tlsEnabled {
+		certPool := x509.NewCertPool()
+		certPool.AppendCertsFromPEM(certPem)
+		transCfg := &http.Transport{
+			TLSClientConfig: &tls.Config {
+				RootCAs: certPool,
+			},
+		}
+		client = http.Client{Transport: transCfg}	
+	} else {
+		client = http.Client{}
+	}
+	response, err := client.Get(url)
+	defer func() {
+		if response != nil {
+			_ = response.Body.Close()
+		}
+	}()
+	if err != nil {
+		return "", err
+	}
+	assert.Nil(t, err)
+	buf := new(bytes.Buffer)
+	_, err = buf.ReadFrom(response.Body)
+	if err != nil {
+		return "", err
+	}
+	assert.Nil(t, err)
+	return buf.String(), nil
+}
+
+func createSecret(ns string) (corev1.Secret, error) {
+	keyCertPair := generateSampleKeyAndCertificate(ns)
+	sec := corev1.Secret{
+		TypeMeta: metav1.TypeMeta{
+			Kind:       "Secret",
+			APIVersion: corev1.SchemeGroupVersion.String(),
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: ns,
+			Name:      secretName,
+		},
+		Type: corev1.SecretTypeTLS,
+		Data: map[string][]byte{
+			corev1.TLSPrivateKeyKey: keyCertPair.Key,
+			corev1.TLSCertKey: keyCertPair.Certificate,
+		},
+	}
+	return sec, TestClient().Create(TestContext, &sec)
+}
+
+func generateSampleKeyAndCertificate(ns string) keyCertificatePair {
+	// Generate the TLS certificate
+	serialNumber := big.NewInt(rand2.Int63())
+	dnsHostname := integrationName + "-" + ns + "." + domainName()
+	x509Certificate := x509.Certificate{
+		SerialNumber: serialNumber,
+		Subject: pkix.Name{
+			Organization: []string{"Camel K test"},
+		},
+		IsCA: 				   true,
+		DNSNames:              []string{dnsHostname},
+		NotBefore:             time.Now(),
+		NotAfter:              time.Now().AddDate(1, 0, 0),
+		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
+		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
+		BasicConstraintsValid: true,
+	}
+
+	// generate the private key
+	certPrivateKey, err := rsa.GenerateKey(rand.Reader, 2048)
+	if err != nil {
+		fmt.Printf("Error generating private key: %s\n", err)
+	}
+
+	privateKeyBytes := x509.MarshalPKCS1PrivateKey(certPrivateKey)
+	// encode for storing into secret
+	privateKeyPem := pem.EncodeToMemory(
+		&pem.Block{
+			Type:  "RSA PRIVATE KEY",
+			Bytes: privateKeyBytes,
+		},
+	)
+	certBytes, err := x509.CreateCertificate(rand.Reader, &x509Certificate, &x509Certificate, &certPrivateKey.PublicKey, certPrivateKey)
+	if err != nil {
+		fmt.Printf("Error generating certificate: %s\n", err)
+	}
+
+	// encode for storing into secret
+	certPem = pem.EncodeToMemory(&pem.Block{
+		Type:  "CERTIFICATE",
+		Bytes: certBytes,
+	})
+
+	return keyCertificatePair {
+		Key: privateKeyPem,
+		Certificate: certPem,
+	}
+}
+
+func domainName() string {
+	consoleroute := Route("openshift-console", "console")()
+	return strings.ReplaceAll(consoleroute.Spec.Host, "console-openshift-console.", "")
+}
+
+func getService(ns string, name string) (*corev1.Service, error) {

Review comment:
       Dropped this `getService` in favor of using `Service` from test_support.go.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r699560182



##########
File path: pkg/trait/route.go
##########
@@ -174,19 +196,83 @@ func (t *routeTrait) Apply(e *Environment) error {
 	return nil
 }
 
-func (t *routeTrait) getTLSConfig() *routev1.TLSConfig {
+func (t *routeTrait) getTLSConfig() (*routev1.TLSConfig, error) {
+	// a certificate is a multiline text, but to set it as value in a single line in CLI, the user must escape the new line character as \\n
+	// but in the TLS configuration, the certificates should be a multiline string
+	// then we need to replace the incoming escaped new lines \\n for a real new line \n
+	key := strings.ReplaceAll(t.TLSKey, "\\n", "\n")

Review comment:
       The parameters ending in`secret` have higher priority and are used. I added a documentation about reading keys and certificates from local filesystem or `secret`. 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#issuecomment-910503046


   I changed the e2e test to skip TLS certificate validation for client http request when it is unable to determine the dns base domain name (from dns/cluster object). So the route tests are green, but other unrelated tests are failing due to timeouts.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#issuecomment-912836666


   For testing I am using Openshift on IBM cloud and I noticed the operator-ingress uses a letsencrypt certificate CA to manage the serving service CA certificates, which are different than the serving certificates provided by a standard openshift 4 installation. They use different secrets to store the CA and certificate.s That said, I could not yet find a standard way to retrieve the certificate in either cloud services, to read them and set in the http client of the e2e tests. So, I disabled the https certificate verification on client side of the e2e route tests. So I ask to accept this tests as it is, and I can work on this specific certificate client side validation later on.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] astefanutti commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
astefanutti commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r701711093



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,382 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+	waitBeforeHttpRequest = 6 * time.Second
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+// self-signed certificate used when making the https request
+var certPem []byte
+
+// the e2e tests run on openshift3 in CI and there is no object to retrieve the base domain name
+// to create a valid hostname to later have it validate when doing the https request
+// as this a e2e test to validate the route object and not the certificate itself 
+// if the base domain name cannot be retrieved from dns/cluster we can safely skip TLS verification
+// if running on openshift4, there is the dns/cluster object to retrieve the base domain name, 
+// then in this case the http client validates the TLS certificate
+var skipClientTLSVerification = false
+
+func TestRunRoutes(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object across diferent tests
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		// they refer to the certificates create in the secret and are reused the different tests
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+
+		// =============================
+		// Insecure Route / No TLS
+		// =============================
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Edge
+		// =============================
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				"-t", "route.tls-termination=edge",
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("https://%s/hello?name=TLS_Edge", route().Spec.Host)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello TLS_Edge", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Passthrough
+		// =============================
+
+		t.Run("Route passthrough https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				// the --resource mounts the certificates inside secret as files in the integration pod
+				"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+				// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+				"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+				"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+				"-t", "route.tls-termination=passthrough",
+				"-t", "container.port=8443",
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			code := "TLS_Passthrough"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Reencrypt
+		// =============================
+
+		t.Run("Route Reencrypt https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				// the --resource mounts the certificates inside secret as files in the integration pod
+				"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+				// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+				"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+				"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+				"-t", "route.tls-termination=reencrypt",

Review comment:
       Can't this be automated by the route trait? The user could be able to provide the secret name and the termination type.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r696610226



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,124 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/tls"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "my-combined-tls"
+	keyName = "my-key"
+	certName = "my-cert"
+	keyFilePath = "files/key.key"

Review comment:
       Cool to have this, I already have this locally, will push it later. 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r698606675



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,124 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/tls"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "my-combined-tls"
+	keyName = "my-key"
+	certName = "my-cert"
+	keyFilePath = "files/key.key"
+	certFilePath = "files/crt.crt"
+)
+
+func TestRunRouteTLS(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		createSecrets(ns)
+
+		refKey := secretName + "/" + keyName
+		refCert := secretName + "/" + certName
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/NettyServer.java",
+			"-t", "route.enabled=true",
+			"-t", "route.tls-termination=edge",
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+		).Execute()).To(Succeed())
+		Eventually(IntegrationPodPhase(ns, "netty-server"), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route https works", func(t *testing.T) {
+			route := Route(ns, "netty-server")
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request
+			time.Sleep(3 * time.Second)
+			response := httpsRequest(t, fmt.Sprintf("https://%s/hello", route().Spec.Host))
+			assert.Equal(t, "Hello World", response)
+		})
+		// Cleanup
+		Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+	// })
+	})
+}
+
+func httpsRequest(t *testing.T, url string) string {
+	transCfg := &http.Transport{
+		// ignore self signed SSL certificates
+		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},

Review comment:
       Done.

##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,124 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/tls"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "my-combined-tls"
+	keyName = "my-key"
+	certName = "my-cert"
+	keyFilePath = "files/key.key"
+	certFilePath = "files/crt.crt"
+)
+
+func TestRunRouteTLS(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		createSecrets(ns)
+
+		refKey := secretName + "/" + keyName
+		refCert := secretName + "/" + certName
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/NettyServer.java",
+			"-t", "route.enabled=true",
+			"-t", "route.tls-termination=edge",
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+		).Execute()).To(Succeed())
+		Eventually(IntegrationPodPhase(ns, "netty-server"), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route https works", func(t *testing.T) {
+			route := Route(ns, "netty-server")
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request
+			time.Sleep(3 * time.Second)
+			response := httpsRequest(t, fmt.Sprintf("https://%s/hello", route().Spec.Host))
+			assert.Equal(t, "Hello World", response)
+		})
+		// Cleanup
+		Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+	// })
+	})
+}
+
+func httpsRequest(t *testing.T, url string) string {
+	transCfg := &http.Transport{
+		// ignore self signed SSL certificates
+		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
+	}
+	client := &http.Client{Transport: transCfg}
+	response, err := client.Get(url)
+	defer func() {
+		if response != nil {
+			_ = response.Body.Close()
+		}
+	}()
+	assert.Nil(t, err)
+	buf := new(bytes.Buffer)
+	_, err = buf.ReadFrom(response.Body)
+	assert.Nil(t, err)
+	return buf.String()
+}
+
+func createSecrets(ns string) error {

Review comment:
       I didn't add this to test_support.go as this particular route secret is tied to generated self-signed certificate, not so generic at this point, but if we need to make a generic one, that would not be too difficult.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#issuecomment-910273412


   There are issues running the route tests, related to openshift 3 test cluster (CI) complaining about different base domain names. I am investigating this issue.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] astefanutti commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
astefanutti commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r701918816



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,382 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+	waitBeforeHttpRequest = 6 * time.Second
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+// self-signed certificate used when making the https request
+var certPem []byte
+
+// the e2e tests run on openshift3 in CI and there is no object to retrieve the base domain name
+// to create a valid hostname to later have it validate when doing the https request
+// as this a e2e test to validate the route object and not the certificate itself 
+// if the base domain name cannot be retrieved from dns/cluster we can safely skip TLS verification
+// if running on openshift4, there is the dns/cluster object to retrieve the base domain name, 
+// then in this case the http client validates the TLS certificate
+var skipClientTLSVerification = false
+
+func TestRunRoutes(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object across diferent tests
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		// they refer to the certificates create in the secret and are reused the different tests
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+
+		// =============================
+		// Insecure Route / No TLS
+		// =============================
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Edge
+		// =============================
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				"-t", "route.tls-termination=edge",
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("https://%s/hello?name=TLS_Edge", route().Spec.Host)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello TLS_Edge", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Passthrough
+		// =============================
+
+		t.Run("Route passthrough https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				// the --resource mounts the certificates inside secret as files in the integration pod
+				"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+				// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+				"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+				"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+				"-t", "route.tls-termination=passthrough",
+				"-t", "container.port=8443",
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			code := "TLS_Passthrough"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Reencrypt
+		// =============================
+
+		t.Run("Route Reencrypt https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				// the --resource mounts the certificates inside secret as files in the integration pod
+				"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+				// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+				"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+				"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+				"-t", "route.tls-termination=reencrypt",

Review comment:
       As for `edge` termination, it may be simpler to rely on the router's default certificate, and closer to what a typical user would do.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] astefanutti commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
astefanutti commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r701917920



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,382 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+	waitBeforeHttpRequest = 6 * time.Second
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+// self-signed certificate used when making the https request
+var certPem []byte
+
+// the e2e tests run on openshift3 in CI and there is no object to retrieve the base domain name
+// to create a valid hostname to later have it validate when doing the https request
+// as this a e2e test to validate the route object and not the certificate itself 
+// if the base domain name cannot be retrieved from dns/cluster we can safely skip TLS verification
+// if running on openshift4, there is the dns/cluster object to retrieve the base domain name, 
+// then in this case the http client validates the TLS certificate
+var skipClientTLSVerification = false
+
+func TestRunRoutes(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object across diferent tests
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		// they refer to the certificates create in the secret and are reused the different tests
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+
+		// =============================
+		// Insecure Route / No TLS
+		// =============================
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Edge
+		// =============================
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				"-t", "route.tls-termination=edge",
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("https://%s/hello?name=TLS_Edge", route().Spec.Host)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello TLS_Edge", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Passthrough
+		// =============================
+
+		t.Run("Route passthrough https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				// the --resource mounts the certificates inside secret as files in the integration pod
+				"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+				// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+				"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+				"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+				"-t", "route.tls-termination=passthrough",

Review comment:
       Could the underlying HTTP endpoint used be inferred from the dependency set?
   
   That would simplify a lot the configuration in that case, at least for Quarkus HTTP, as the mounting of the secret could be done automatically and the corresponding properties set accordingly.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] astefanutti commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
astefanutti commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r701888927



##########
File path: deploy/traits.yaml
##########
@@ -833,19 +842,39 @@ traits:
   - name: tls-termination
     type: string
     description: The TLS termination type, like `edge`, `passthrough` or `reencrypt`.Refer
-      to the OpenShift documentation for additional information.
+      to the OpenShift route documentation for additional information.
   - name: tls-certificate
     type: string
-    description: The TLS certificate contents.Refer to the OpenShift documentation
+    description: The TLS certificate contents.Refer to the OpenShift route documentation
       for additional information.
+  - name: tls-certificate-secret
+    type: string
+    description: The TLS certificate contents read from a secret. The format is "secret-name[/key-name]",

Review comment:
       The way it is put, we may understand that the property must be the content of the TLS certificate, while it must be the secret name and key containing the certificate. I find the later a lot more descriptive as to what is expected for the end user. 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] astefanutti commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
astefanutti commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r701886551



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,382 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+	waitBeforeHttpRequest = 6 * time.Second
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+// self-signed certificate used when making the https request
+var certPem []byte
+
+// the e2e tests run on openshift3 in CI and there is no object to retrieve the base domain name
+// to create a valid hostname to later have it validate when doing the https request
+// as this a e2e test to validate the route object and not the certificate itself 
+// if the base domain name cannot be retrieved from dns/cluster we can safely skip TLS verification
+// if running on openshift4, there is the dns/cluster object to retrieve the base domain name, 
+// then in this case the http client validates the TLS certificate
+var skipClientTLSVerification = false
+
+func TestRunRoutes(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object across diferent tests
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		// they refer to the certificates create in the secret and are reused the different tests
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+
+		// =============================
+		// Insecure Route / No TLS
+		// =============================
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(waitBeforeHttpRequest)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		})
+
+		// =============================
+		// TLS Route Edge
+		// =============================
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+				"-t", "route.tls-termination=edge",
+				"-t", "route.tls-certificate-secret=" + refCert,
+				"-t", "route.tls-key-secret=" + refKey,

Review comment:
       My understanding is that a certificate is not require for `edge` termination. The router’s default certificate is used for TLS termination, which is from my experience what users tend to rely on.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] claudio4j commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
claudio4j commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r699527320



##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,444 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"strings"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	ctrl "sigs.k8s.io/controller-runtime/pkg/client"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+var certPem []byte
+
+// this test uses a route with no TLS
+func TestRunRouteNoTLS(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())

Review comment:
       Done.

##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,444 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"strings"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	ctrl "sigs.k8s.io/controller-runtime/pkg/client"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+var certPem []byte
+
+// this test uses a route with no TLS
+func TestRunRouteNoTLS(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+		// Cleanup all integrations when the test finishes
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(4 * time.Second)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+		})
+	})
+}
+
+func TestRunRouteTLS_Edge(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+		// delete secret when the test finishes
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		// they refer to the secret/certificates previsouly created
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			"-t", "route.tls-termination=edge",
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+		).Execute()).To(Succeed())
+		// Cleanup all integrations when the test finishes
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			url := fmt.Sprintf("https://%s/hello?name=TLS_Edge", route().Spec.Host)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello TLS_Edge", response)
+		})
+	})
+}
+
+func TestRunRouteTLS_Passthrough(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+			"-t", "route.tls-termination=passthrough",
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route passthrough https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_Passthrough"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+// This test uses a self-signed certificate to create a TLS route
+func TestRunRouteTLS_Reencrypt(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+			"-t", "route.tls-termination=reencrypt",
+			// the destination CA certificate which the route service uses to validate the HTTP endpoint TLS certificate
+			"-t", "route.tls-destination-ca-certificate-secret=" + refCert,
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route Reencrypt https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_Reencrypt"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+// This test uses a certificate provided by openshift "service serving certificates" to create a TLS route
+func TestRunRouteTLS_ReencryptWithServiceCA(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		// they refer to the secret previsouly created
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			// they are used only for the pod exposing the HTTP endpoint, not the router
+			"--resource", "secret:" + servingCertificateSecret + "@/etc/ssl/" + servingCertificateSecret,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			// these certificates are used only in the pod, not the router
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + servingCertificateSecret + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + servingCertificateSecret + "/tls.key",
+			"-t", "route.tls-termination=reencrypt",
+			// these certificates are used only in the router to encrypt the connection from the client to the router
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		time.Sleep(2 * time.Second)
+		Eventually(Service(ns, integrationName)()).ShouldNot(BeNil())
+		annotations := make(map[string]string)
+		annotations["service.beta.openshift.io/serving-cert-secret-name"] = servingCertificateSecret
+		err = addAnnotation(ns, integrationName, annotations)
+		assert.Nil(t, err)
+
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+		t.Run("Route reencrypt (with openshift service CA) https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_ReencryptWithServiceCAWithServiceCA"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+func httpRequest(t *testing.T, url string, tlsEnabled bool) (string, error) {
+	var client http.Client
+	if tlsEnabled {
+		certPool := x509.NewCertPool()
+		certPool.AppendCertsFromPEM(certPem)
+		transCfg := &http.Transport{
+			TLSClientConfig: &tls.Config {
+				RootCAs: certPool,
+			},
+		}
+		client = http.Client{Transport: transCfg}	
+	} else {
+		client = http.Client{}
+	}
+	response, err := client.Get(url)
+	defer func() {
+		if response != nil {
+			_ = response.Body.Close()
+		}
+	}()
+	if err != nil {
+		return "", err
+	}
+	assert.Nil(t, err)
+	buf := new(bytes.Buffer)
+	_, err = buf.ReadFrom(response.Body)
+	if err != nil {
+		return "", err
+	}
+	assert.Nil(t, err)
+	return buf.String(), nil
+}
+
+func createSecret(ns string) (corev1.Secret, error) {
+	keyCertPair := generateSampleKeyAndCertificate(ns)
+	sec := corev1.Secret{
+		TypeMeta: metav1.TypeMeta{
+			Kind:       "Secret",
+			APIVersion: corev1.SchemeGroupVersion.String(),
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: ns,
+			Name:      secretName,
+		},
+		Type: corev1.SecretTypeTLS,
+		Data: map[string][]byte{
+			corev1.TLSPrivateKeyKey: keyCertPair.Key,
+			corev1.TLSCertKey: keyCertPair.Certificate,
+		},
+	}
+	return sec, TestClient().Create(TestContext, &sec)
+}
+
+func generateSampleKeyAndCertificate(ns string) keyCertificatePair {
+	// Generate the TLS certificate
+	serialNumber := big.NewInt(rand2.Int63())
+	dnsHostname := integrationName + "-" + ns + "." + domainName()
+	x509Certificate := x509.Certificate{
+		SerialNumber: serialNumber,
+		Subject: pkix.Name{
+			Organization: []string{"Camel K test"},
+		},
+		IsCA: 				   true,
+		DNSNames:              []string{dnsHostname},
+		NotBefore:             time.Now(),
+		NotAfter:              time.Now().AddDate(1, 0, 0),
+		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
+		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
+		BasicConstraintsValid: true,
+	}
+
+	// generate the private key
+	certPrivateKey, err := rsa.GenerateKey(rand.Reader, 2048)
+	if err != nil {
+		fmt.Printf("Error generating private key: %s\n", err)
+	}
+
+	privateKeyBytes := x509.MarshalPKCS1PrivateKey(certPrivateKey)
+	// encode for storing into secret
+	privateKeyPem := pem.EncodeToMemory(
+		&pem.Block{
+			Type:  "RSA PRIVATE KEY",
+			Bytes: privateKeyBytes,
+		},
+	)
+	certBytes, err := x509.CreateCertificate(rand.Reader, &x509Certificate, &x509Certificate, &certPrivateKey.PublicKey, certPrivateKey)
+	if err != nil {
+		fmt.Printf("Error generating certificate: %s\n", err)
+	}
+
+	// encode for storing into secret
+	certPem = pem.EncodeToMemory(&pem.Block{
+		Type:  "CERTIFICATE",
+		Bytes: certBytes,
+	})
+
+	return keyCertificatePair {
+		Key: privateKeyPem,
+		Certificate: certPem,
+	}
+}
+
+func domainName() string {
+	consoleroute := Route("openshift-console", "console")()
+	return strings.ReplaceAll(consoleroute.Spec.Host, "console-openshift-console.", "")
+}
+
+func getService(ns string, name string) (*corev1.Service, error) {

Review comment:
       Dropped this `getService` in favor of using `Service` from test_support.go.

##########
File path: e2e/common/traits/route_test.go
##########
@@ -0,0 +1,444 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative"
+
+/*
+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 traits
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"math/big"
+	"net/http"
+	"strings"
+	"testing"
+	"time"
+
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+
+	rand2 "math/rand"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	ctrl "sigs.k8s.io/controller-runtime/pkg/client"
+
+	. "github.com/apache/camel-k/e2e/support"
+	"github.com/apache/camel-k/pkg/util/openshift"
+)
+
+const(
+	secretName = "test-certificate"
+	servingCertificateSecret = "serving-certificate"
+	integrationName = "platform-http-server"
+)
+
+type keyCertificatePair struct {
+	Key []byte
+	Certificate []byte
+}
+
+var certPem []byte
+
+// this test uses a route with no TLS
+func TestRunRouteNoTLS(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java").Execute()).To(Succeed())
+		// Cleanup all integrations when the test finishes
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route unsecure http works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before doing an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(4 * time.Second)
+			url := fmt.Sprintf("http://%s/hello?name=Simple", route().Spec.Host)
+			response, err := httpRequest(t, url, false)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello Simple", response)
+		})
+	})
+}
+
+func TestRunRouteTLS_Edge(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+		// delete secret when the test finishes
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		// they refer to the secret/certificates previsouly created
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			"-t", "route.tls-termination=edge",
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+		).Execute()).To(Succeed())
+		// Cleanup all integrations when the test finishes
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route Edge https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			url := fmt.Sprintf("https://%s/hello?name=TLS_Edge", route().Spec.Host)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello TLS_Edge", response)
+		})
+	})
+}
+
+func TestRunRouteTLS_Passthrough(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+			"-t", "route.tls-termination=passthrough",
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route passthrough https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_Passthrough"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+// This test uses a self-signed certificate to create a TLS route
+func TestRunRouteTLS_Reencrypt(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls with certificates
+		// this secret is used to setupt the route TLS object
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			"--resource", "secret:" + secretName + "@/etc/ssl/" + secretName,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + secretName + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + secretName + "/tls.key",
+			"-t", "route.tls-termination=reencrypt",
+			// the destination CA certificate which the route service uses to validate the HTTP endpoint TLS certificate
+			"-t", "route.tls-destination-ca-certificate-secret=" + refCert,
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+
+		t.Run("Route Reencrypt https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_Reencrypt"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+// This test uses a certificate provided by openshift "service serving certificates" to create a TLS route
+func TestRunRouteTLS_ReencryptWithServiceCA(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		ocp, err := openshift.IsOpenShift(TestClient())
+		if !ocp {
+			t.Skip("This test requires route object which is available on OpenShift only.")
+			return
+		}
+		assert.Nil(t, err)
+
+		// create a test secret of type tls
+		secret, err := createSecret(ns)
+		assert.Nil(t, err)
+
+		defer func() {
+			Expect(TestClient().Delete(TestContext, &secret)).To(Succeed())
+		}()
+
+		// they refer to the secret previsouly created
+		refKey := secretName + "/" + corev1.TLSPrivateKeyKey
+		refCert := secretName + "/" + corev1.TLSCertKey
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("run", "-n", ns, "files/PlatformHttpServer.java",
+			// the --resource mounts the certificates inside secret as files in the integration pod
+			// they are used only for the pod exposing the HTTP endpoint, not the router
+			"--resource", "secret:" + servingCertificateSecret + "@/etc/ssl/" + servingCertificateSecret,
+			// quarkus platform-http uses these two properties to setup the HTTP endpoint with TLS support
+			// these certificates are used only in the pod, not the router
+			"-p", "quarkus.http.ssl.certificate.file=/etc/ssl/" + servingCertificateSecret + "/tls.crt",
+			"-p", "quarkus.http.ssl.certificate.key-file=/etc/ssl/" + servingCertificateSecret + "/tls.key",
+			"-t", "route.tls-termination=reencrypt",
+			// these certificates are used only in the router to encrypt the connection from the client to the router
+			"-t", "route.tls-certificate-secret=" + refCert,
+			"-t", "route.tls-key-secret=" + refKey,
+			"-t", "container.port=8443",
+		).Execute()).To(Succeed())
+		// Cleanup all integrations
+		defer func() {
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+		}()
+		time.Sleep(2 * time.Second)
+		Eventually(Service(ns, integrationName)()).ShouldNot(BeNil())
+		annotations := make(map[string]string)
+		annotations["service.beta.openshift.io/serving-cert-secret-name"] = servingCertificateSecret
+		err = addAnnotation(ns, integrationName, annotations)
+		assert.Nil(t, err)
+
+		Eventually(IntegrationPodPhase(ns, integrationName), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+		t.Run("Route reencrypt (with openshift service CA) https works", func(t *testing.T) {
+			route := Route(ns, integrationName)
+			Eventually(route, TestTimeoutMedium).ShouldNot(BeNil())
+			// must wait a little time after route is created, before an http request, 
+			// otherwise the route is unavailable and the http request will fail
+			time.Sleep(6 * time.Second)
+			code := "TLS_ReencryptWithServiceCAWithServiceCA"
+			url := fmt.Sprintf("https://%s/hello?name=%s", route().Spec.Host, code)
+			response, err := httpRequest(t, url, true)
+			assert.Nil(t, err)
+			assert.Equal(t, "Hello " + code, response)
+		})
+	})
+}
+
+func httpRequest(t *testing.T, url string, tlsEnabled bool) (string, error) {
+	var client http.Client
+	if tlsEnabled {
+		certPool := x509.NewCertPool()
+		certPool.AppendCertsFromPEM(certPem)
+		transCfg := &http.Transport{
+			TLSClientConfig: &tls.Config {
+				RootCAs: certPool,
+			},
+		}
+		client = http.Client{Transport: transCfg}	
+	} else {
+		client = http.Client{}
+	}
+	response, err := client.Get(url)
+	defer func() {
+		if response != nil {
+			_ = response.Body.Close()
+		}
+	}()
+	if err != nil {
+		return "", err
+	}
+	assert.Nil(t, err)
+	buf := new(bytes.Buffer)
+	_, err = buf.ReadFrom(response.Body)
+	if err != nil {
+		return "", err
+	}
+	assert.Nil(t, err)
+	return buf.String(), nil
+}
+
+func createSecret(ns string) (corev1.Secret, error) {
+	keyCertPair := generateSampleKeyAndCertificate(ns)
+	sec := corev1.Secret{
+		TypeMeta: metav1.TypeMeta{
+			Kind:       "Secret",
+			APIVersion: corev1.SchemeGroupVersion.String(),
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: ns,
+			Name:      secretName,
+		},
+		Type: corev1.SecretTypeTLS,
+		Data: map[string][]byte{
+			corev1.TLSPrivateKeyKey: keyCertPair.Key,
+			corev1.TLSCertKey: keyCertPair.Certificate,
+		},
+	}
+	return sec, TestClient().Create(TestContext, &sec)
+}
+
+func generateSampleKeyAndCertificate(ns string) keyCertificatePair {
+	// Generate the TLS certificate
+	serialNumber := big.NewInt(rand2.Int63())
+	dnsHostname := integrationName + "-" + ns + "." + domainName()
+	x509Certificate := x509.Certificate{
+		SerialNumber: serialNumber,
+		Subject: pkix.Name{
+			Organization: []string{"Camel K test"},
+		},
+		IsCA: 				   true,
+		DNSNames:              []string{dnsHostname},
+		NotBefore:             time.Now(),
+		NotAfter:              time.Now().AddDate(1, 0, 0),
+		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
+		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
+		BasicConstraintsValid: true,
+	}
+
+	// generate the private key
+	certPrivateKey, err := rsa.GenerateKey(rand.Reader, 2048)
+	if err != nil {
+		fmt.Printf("Error generating private key: %s\n", err)
+	}
+
+	privateKeyBytes := x509.MarshalPKCS1PrivateKey(certPrivateKey)
+	// encode for storing into secret
+	privateKeyPem := pem.EncodeToMemory(
+		&pem.Block{
+			Type:  "RSA PRIVATE KEY",
+			Bytes: privateKeyBytes,
+		},
+	)
+	certBytes, err := x509.CreateCertificate(rand.Reader, &x509Certificate, &x509Certificate, &certPrivateKey.PublicKey, certPrivateKey)
+	if err != nil {
+		fmt.Printf("Error generating certificate: %s\n", err)
+	}
+
+	// encode for storing into secret
+	certPem = pem.EncodeToMemory(&pem.Block{
+		Type:  "CERTIFICATE",
+		Bytes: certBytes,
+	})
+
+	return keyCertificatePair {
+		Key: privateKeyPem,
+		Certificate: certPem,
+	}
+}
+
+func domainName() string {
+	consoleroute := Route("openshift-console", "console")()

Review comment:
       Changed to use `dns/cluster` object instead.

##########
File path: pkg/trait/route.go
##########
@@ -174,19 +196,83 @@ func (t *routeTrait) Apply(e *Environment) error {
 	return nil
 }
 
-func (t *routeTrait) getTLSConfig() *routev1.TLSConfig {
+func (t *routeTrait) getTLSConfig() (*routev1.TLSConfig, error) {
+	// a certificate is a multiline text, but to set it as value in a single line in CLI, the user must escape the new line character as \\n
+	// but in the TLS configuration, the certificates should be a multiline string
+	// then we need to replace the incoming escaped new lines \\n for a real new line \n
+	key := strings.ReplaceAll(t.TLSKey, "\\n", "\n")

Review comment:
       The parameters ending in`secret` have higher priority and are used. I added a documentation about reading keys and certificates from local filesystem or `secret`. 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [camel-k] astefanutti commented on a change in pull request #2577: trait: Add tests for route trait and read certificate from secrets

Posted by GitBox <gi...@apache.org>.
astefanutti commented on a change in pull request #2577:
URL: https://github.com/apache/camel-k/pull/2577#discussion_r701888927



##########
File path: deploy/traits.yaml
##########
@@ -833,19 +842,39 @@ traits:
   - name: tls-termination
     type: string
     description: The TLS termination type, like `edge`, `passthrough` or `reencrypt`.Refer
-      to the OpenShift documentation for additional information.
+      to the OpenShift route documentation for additional information.
   - name: tls-certificate
     type: string
-    description: The TLS certificate contents.Refer to the OpenShift documentation
+    description: The TLS certificate contents.Refer to the OpenShift route documentation
       for additional information.
+  - name: tls-certificate-secret
+    type: string
+    description: The TLS certificate contents read from a secret. The format is "secret-name[/key-name]",

Review comment:
       The way it is put, we may understand that the property must be the content of the TLS certificate, while it must be the secret containing the certificate. I find the later a lot more descriptive as to what is expected for the end user. 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org