You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2019/12/03 13:11:02 UTC

[camel] branch master updated: [CAMEL-13213] Cannot use rest-swagger component with swagger.json provided over HTTPS protocol (#3374)

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

davsclaus pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/master by this push:
     new 0c2aa42  [CAMEL-13213] Cannot use rest-swagger component with swagger.json provided over HTTPS protocol (#3374)
0c2aa42 is described below

commit 0c2aa42dcba4a1a02044622bdf474cb51c4e0629
Author: JiriOndrusek <jo...@redhat.com>
AuthorDate: Tue Dec 3 14:10:50 2019 +0100

    [CAMEL-13213] Cannot use rest-swagger component with swagger.json provided over HTTPS protocol (#3374)
---
 components/camel-rest-swagger/pom.xml              | 11 ++--
 .../src/main/docs/rest-swagger-component.adoc      |  3 +-
 .../rest/swagger/RestSwaggerEndpoint.java          | 76 ++++++++++++++++++----
 .../camel/component/rest/swagger/HttpsTest.java    | 19 +++++-
 .../rest/swagger/RestSwaggerEndpointTest.java      |  4 +-
 .../karaf/features/src/main/resources/features.xml |  1 +
 6 files changed, 91 insertions(+), 23 deletions(-)

diff --git a/components/camel-rest-swagger/pom.xml b/components/camel-rest-swagger/pom.xml
index f9ea6f5..cd2f0a5 100644
--- a/components/camel-rest-swagger/pom.xml
+++ b/components/camel-rest-swagger/pom.xml
@@ -71,6 +71,11 @@
             </exclusions>
         </dependency>
 
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-http</artifactId>
+        </dependency>
+
         <!-- test -->
         <dependency>
             <groupId>org.apache.camel</groupId>
@@ -123,12 +128,6 @@
 
         <dependency>
             <groupId>org.apache.camel</groupId>
-            <artifactId>camel-http</artifactId>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.camel</groupId>
             <artifactId>camel-netty-http</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/components/camel-rest-swagger/src/main/docs/rest-swagger-component.adoc b/components/camel-rest-swagger/src/main/docs/rest-swagger-component.adoc
index 844d9b6..fddde2a 100644
--- a/components/camel-rest-swagger/src/main/docs/rest-swagger-component.adoc
+++ b/components/camel-rest-swagger/src/main/docs/rest-swagger-component.adoc
@@ -126,7 +126,7 @@ with the following path and query parameters:
 |===
 
 
-=== Query Parameters (8 parameters):
+=== Query Parameters (9 parameters):
 
 
 [width="100%",cols="2,5,^1,2",options="header"]
@@ -140,6 +140,7 @@ with the following path and query parameters:
 | *produces* (producer) | What payload type this component is producing. For example application/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the Swagger specification. Overrides all other configuration. |  | String
 | *basicPropertyBinding* (advanced) | Whether the endpoint should use basic property binding (Camel 2.x) or the newer property binding with additional capabilities | false | boolean
 | *synchronous* (advanced) | Sets whether synchronous processing should be strictly used, or Camel is allowed to use asynchronous processing (if supported). | false | boolean
+| *sslContextParameters* (security) | To configure security using SSLContextParameters. |  | SSLContextParameters
 |===
 // endpoint options: END
 // spring-boot-auto-configure options: START
diff --git a/components/camel-rest-swagger/src/main/java/org/apache/camel/component/rest/swagger/RestSwaggerEndpoint.java b/components/camel-rest-swagger/src/main/java/org/apache/camel/component/rest/swagger/RestSwaggerEndpoint.java
index 8245b28..5e94d11 100644
--- a/components/camel-rest-swagger/src/main/java/org/apache/camel/component/rest/swagger/RestSwaggerEndpoint.java
+++ b/components/camel-rest-swagger/src/main/java/org/apache/camel/component/rest/swagger/RestSwaggerEndpoint.java
@@ -51,6 +51,9 @@ import org.apache.camel.Endpoint;
 import org.apache.camel.ExchangePattern;
 import org.apache.camel.Processor;
 import org.apache.camel.Producer;
+import org.apache.camel.component.http.HttpComponent;
+import org.apache.camel.component.http.HttpEndpoint;
+import org.apache.camel.component.http.HttpProducer;
 import org.apache.camel.spi.Metadata;
 import org.apache.camel.spi.RestConfiguration;
 import org.apache.camel.spi.UriEndpoint;
@@ -58,9 +61,11 @@ import org.apache.camel.spi.UriParam;
 import org.apache.camel.spi.UriPath;
 import org.apache.camel.support.DefaultEndpoint;
 import org.apache.camel.support.ResourceHelper;
+import org.apache.camel.support.jsse.SSLContextParameters;
 import org.apache.camel.util.ObjectHelper;
 import org.apache.camel.util.StringHelper;
 import org.apache.camel.util.UnsafeUriCharactersEncoder;
+import org.apache.http.client.methods.HttpGet;
 
 import static java.util.Optional.ofNullable;
 import static org.apache.camel.component.rest.swagger.RestSwaggerHelper.isHostParam;
@@ -123,6 +128,9 @@ public final class RestSwaggerEndpoint extends DefaultEndpoint {
         + " any value present in the Swagger specification. Overrides all other configuration.", label = "producer")
     private String produces;
 
+    @UriParam(label = "security", description = "To configure security using SSLContextParameters.")
+    private SSLContextParameters sslContextParameters;
+
     @UriPath(description = "Path to the Swagger specification file. The scheme, host base path are taken from this"
         + " specification, but these can be overridden with properties on the component or endpoint level. If not"
         + " given the component tries to load `swagger.json` resource from the classpath. Note that the `host` defined on the"
@@ -165,7 +173,8 @@ public final class RestSwaggerEndpoint extends DefaultEndpoint {
     @Override
     public Producer createProducer() throws Exception {
         final CamelContext camelContext = getCamelContext();
-        final Swagger swagger = loadSpecificationFrom(camelContext, specificationUri);
+
+        final Swagger swagger = loadSpecificationFrom(camelContext, specificationUri, resolveSslContextParameters());
 
         final Map<String, Path> paths = swagger.getPaths();
 
@@ -200,6 +209,16 @@ public final class RestSwaggerEndpoint extends DefaultEndpoint {
             + "`. Operations defined in the specification are: " + supportedOperations);
     }
 
+    private SSLContextParameters resolveSslContextParameters() {
+        if (sslContextParameters != null) {
+            return sslContextParameters;
+        }
+        if (component().getSslContextParameters() != null) {
+            return component().getSslContextParameters();
+        }
+        return component().retrieveGlobalSslContextParameters();
+    }
+
     public String getBasePath() {
         return basePath;
     }
@@ -212,6 +231,10 @@ public final class RestSwaggerEndpoint extends DefaultEndpoint {
         return consumes;
     }
 
+    public SSLContextParameters getSslContextParameters() {
+        return sslContextParameters;
+    }
+
     public String getHost() {
         return host;
     }
@@ -245,6 +268,10 @@ public final class RestSwaggerEndpoint extends DefaultEndpoint {
         this.consumes = isMediaRange(consumes, "consumes");
     }
 
+    public void setSslContextParameters(SSLContextParameters sslContextParameters) {
+        this.sslContextParameters = sslContextParameters;
+    }
+
     public void setHost(final String host) {
         this.host = isHostParam(host);
     }
@@ -592,31 +619,53 @@ public final class RestSwaggerEndpoint extends DefaultEndpoint {
      * @return the specification
      * @throws IOException
      */
-    static Swagger loadSpecificationFrom(final CamelContext camelContext, final URI uri) throws IOException {
+    static Swagger loadSpecificationFrom(final CamelContext camelContext, final URI uri, SSLContextParameters sslContextParameters) throws IOException {
         final ObjectMapper mapper = Json.mapper();
 
         final SwaggerParser swaggerParser = new SwaggerParser();
 
         final String uriAsString = uri.toString();
 
-        try (InputStream stream = ResourceHelper.resolveMandatoryResourceAsInputStream(camelContext, uriAsString)) {
-            final JsonNode node = mapper.readTree(stream);
+        if (sslContextParameters == null) {
+            try (InputStream stream = ResourceHelper.resolveMandatoryResourceAsInputStream(camelContext, uriAsString)) {
+                return parseInputStream(swaggerParser, mapper, stream);
+            } catch (final Exception e) {
+                return loadSpecificationFallback(swaggerParser, uriAsString, e);
+            }
+        }
 
-            return swaggerParser.read(node);
+        HttpComponent httpComponent = new HttpComponent();
+        httpComponent.setSslContextParameters(sslContextParameters);
+        httpComponent.setCamelContext(camelContext);
+        try (HttpEndpoint e = (HttpEndpoint)httpComponent.createEndpoint(uriAsString);
+             HttpProducer p = (HttpProducer)e.createProducer();
+             InputStream stream = p.getHttpClient().execute(new HttpGet(uri)).getEntity().getContent())  {
+
+            return parseInputStream(swaggerParser, mapper, stream);
         } catch (final Exception e) {
-            // try Swaggers loader
-            final Swagger swagger = swaggerParser.read(uriAsString);
+            return loadSpecificationFallback(swaggerParser, uriAsString, e);
+        }
+    }
 
-            if (swagger != null) {
-                return swagger;
-            }
+    static Swagger loadSpecificationFallback(SwaggerParser swaggerParser, String uriAsString, Exception originalException) {
+        // try Swaggers loader
+        final Swagger swagger = swaggerParser.read(uriAsString);
+
+        if (swagger != null) {
+            return swagger;
+        }
 
-            throw new IllegalArgumentException("The given Swagger specification could not be loaded from `" + uri
+        throw new IllegalArgumentException("The given Swagger specification could not be loaded from `" + uriAsString
                 + "`. Tried loading using Camel's resource resolution and using Swagger's own resource resolution."
                 + " Swagger tends to swallow exceptions while parsing, try specifying Java system property `debugParser`"
                 + " (e.g. `-DdebugParser=true`), the exception that occurred when loading using Camel's resource"
-                + " loader follows", e);
-        }
+                + " loader follows", originalException);
+    }
+
+    static Swagger parseInputStream(SwaggerParser swaggerParser, ObjectMapper mapper, InputStream stream) throws IOException {
+        final JsonNode node = mapper.readTree(stream);
+
+        return swaggerParser.read(node);
     }
 
     static String pickBestScheme(final String specificationScheme, final List<Scheme> schemes) {
@@ -651,4 +700,5 @@ public final class RestSwaggerEndpoint extends DefaultEndpoint {
         return expression.toString();
     }
 
+
 }
diff --git a/components/camel-rest-swagger/src/test/java/org/apache/camel/component/rest/swagger/HttpsTest.java b/components/camel-rest-swagger/src/test/java/org/apache/camel/component/rest/swagger/HttpsTest.java
index 4e53c40..33638a7 100644
--- a/components/camel-rest-swagger/src/test/java/org/apache/camel/component/rest/swagger/HttpsTest.java
+++ b/components/camel-rest-swagger/src/test/java/org/apache/camel/component/rest/swagger/HttpsTest.java
@@ -94,6 +94,20 @@ public abstract class HttpsTest extends CamelTestSupport {
             equalTo("application/xml, application/json")));
     }
 
+
+    @Test
+    public void swaggerJsonOverHttps() throws Exception {
+        final Pet pet = template.requestBodyAndHeader("direct:httpsJsonGetPetById", NO_BODY, "petId", 14, Pet.class);
+
+        assertNotNull(pet);
+
+        assertEquals(Integer.valueOf(14), pet.id);
+        assertEquals("Olafur Eliason Arnalds", pet.name);
+
+        petstore.verify(getRequestedFor(urlEqualTo("/v2/pet/14")).withHeader("Accept",
+                equalTo("application/xml, application/json")));
+    }
+
     @Override
     protected CamelContext createCamelContext() throws Exception {
         final CamelContext camelContext = super.createCamelContext();
@@ -101,9 +115,10 @@ public abstract class HttpsTest extends CamelTestSupport {
         final RestSwaggerComponent component = new RestSwaggerComponent();
         component.setComponentName(componentName);
         component.setHost("https://localhost:" + petstore.httpsPort());
+        component.setUseGlobalSslContextParameters(true);
 
         camelContext.addComponent("petStore", component);
-
+        camelContext.setSSLContextParameters(createHttpsParameters(camelContext));
         return camelContext;
     }
 
@@ -119,6 +134,8 @@ public abstract class HttpsTest extends CamelTestSupport {
                 jaxb.setJaxbProviderProperties(Collections.singletonMap(Marshaller.JAXB_FORMATTED_OUTPUT, false));
 
                 from("direct:getPetById").to("petStore:getPetById").unmarshal(jaxb);
+
+                from("direct:httpsJsonGetPetById").to("petStore:https://localhost:" + petstore.httpsPort() + "/swagger.json#getPetById").unmarshal(jaxb);
             }
         };
     }
diff --git a/components/camel-rest-swagger/src/test/java/org/apache/camel/component/rest/swagger/RestSwaggerEndpointTest.java b/components/camel-rest-swagger/src/test/java/org/apache/camel/component/rest/swagger/RestSwaggerEndpointTest.java
index 8b4b432..42c3cd6 100644
--- a/components/camel-rest-swagger/src/test/java/org/apache/camel/component/rest/swagger/RestSwaggerEndpointTest.java
+++ b/components/camel-rest-swagger/src/test/java/org/apache/camel/component/rest/swagger/RestSwaggerEndpointTest.java
@@ -338,7 +338,7 @@ public class RestSwaggerEndpointTest {
         when(camelContext.getClassResolver()).thenReturn(new DefaultClassResolver());
 
         assertThat(
-            RestSwaggerEndpoint.loadSpecificationFrom(camelContext, RestSwaggerComponent.DEFAULT_SPECIFICATION_URI))
+            RestSwaggerEndpoint.loadSpecificationFrom(camelContext, RestSwaggerComponent.DEFAULT_SPECIFICATION_URI, null))
                 .isNotNull();
     }
 
@@ -363,7 +363,7 @@ public class RestSwaggerEndpointTest {
         final CamelContext camelContext = mock(CamelContext.class);
         when(camelContext.getClassResolver()).thenReturn(new DefaultClassResolver());
 
-        RestSwaggerEndpoint.loadSpecificationFrom(camelContext, URI.create("non-existant.json"));
+        RestSwaggerEndpoint.loadSpecificationFrom(camelContext, URI.create("non-existant.json"), null);
     }
 
     @Test
diff --git a/platforms/karaf/features/src/main/resources/features.xml b/platforms/karaf/features/src/main/resources/features.xml
index 5b7d2ac..13cb2d4 100644
--- a/platforms/karaf/features/src/main/resources/features.xml
+++ b/platforms/karaf/features/src/main/resources/features.xml
@@ -2083,6 +2083,7 @@
   </feature> -->
   <feature name='camel-rest-swagger' version='${project.version}' start-level='50'>
     <feature version='${project.version}'>camel-core</feature>
+    <feature version='${project.version}'>camel-http</feature>
     <bundle dependency='true'>mvn:org.yaml/snakeyaml/${snakeyaml-version}</bundle>
     <bundle dependency='true'>mvn:javax.validation/validation-api/${validation-1-api-version}</bundle>
     <bundle dependency='true'>mvn:com.fasterxml.jackson.core/jackson-core/${jackson2-version}</bundle>