Add support for HTTPS 85/83385/7
authordfarrelly <david.farrelly@est.tech>
Wed, 3 Apr 2019 14:40:31 +0000 (14:40 +0000)
committerdfarrelly <david.farrelly@est.tech>
Wed, 3 Apr 2019 14:40:31 +0000 (14:40 +0000)
*Add AAF certificates
*Switch PM Mapper endpoints to HTTPS
*Make external API calls secure if applicable

Issue-ID: DCAEGEN2-1296
Change-Id: I63aef8a93cfe6d6a37dcd32496b35ed0841cec4b
Signed-off-by: dfarrelly <david.farrelly@est.tech>
18 files changed:
dpo/blueprints/k8s-pm-mapper.yaml
src/main/java/org/onap/dcaegen2/services/pmmapper/App.java
src/main/java/org/onap/dcaegen2/services/pmmapper/datarouter/DataRouterSubscriber.java
src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/CreateContextException.java [new file with mode: 0644]
src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/KeyManagerException.java [new file with mode: 0644]
src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/LoadKeyStoreException.java [new file with mode: 0644]
src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/ServerResponseException.java [new file with mode: 0644]
src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/TrustManagerException.java [new file with mode: 0644]
src/main/java/org/onap/dcaegen2/services/pmmapper/model/MapperConfig.java
src/main/java/org/onap/dcaegen2/services/pmmapper/ssl/SSLContextFactory.java [new file with mode: 0644]
src/main/java/org/onap/dcaegen2/services/pmmapper/utils/DataRouterUtils.java
src/main/java/org/onap/dcaegen2/services/pmmapper/utils/RequestSender.java
src/test/java/org/onap/dcaegen2/pmmapper/config/util/RequestSenderTests.java
src/test/java/org/onap/dcaegen2/services/pmmapper/ssl/SSLContextFactoryTest.java [new file with mode: 0644]
src/test/java/org/onap/dcaegen2/services/pmmapper/utils/DataRouterUtilsTest.java
src/test/resources/password [new file with mode: 0644]
src/test/resources/testkeystore.jks.b64 [new file with mode: 0644]
src/test/resources/valid_mapper_config.json

index 88fb44a..0944da3 100644 (file)
@@ -22,17 +22,17 @@ tosca_definitions_version: cloudify_dsl_1_3
 
 imports:
   - "http://www.getcloudify.org/spec/cloudify/3.4/types.yaml"
-  - "https://nexus.onap.org/service/local/repositories/raw/content/org.onap.dcaegen2.platform.plugins/R3/k8splugin/1.4.4/k8splugin_types.yaml"
+  - "https://nexus.onap.org/service/local/repositories/raw/content/org.onap.dcaegen2.platform.plugins/R4/k8splugin/1.4.5/k8splugin_types.yaml"
 
 inputs:
   service_name:
     type: string
     description: Name of the serice
-    default: "pm-mapper"
+    default: "dcae-pm-mapper"
   tag_version:
     type: string
     description: Docker image to be used
-    default: "nexus3.onap.org:10001/onap/org.onap.dcaegen2.services.pm-mapper:1.0-SNAPSHOT"
+    default: "nexus3.onap.org:10001/onap/org.onap.dcaegen2.services.pm-mapper:latest"
   replicas:
     type: integer
     description: Number of instances
@@ -55,11 +55,11 @@ inputs:
     default: "ves-pub-1"
   dmaap_dr_username:
     type: string
-    description: dmaap datarouter user name
+    description: DMAAP Data Router user name
     default: "username"
   dmaap_dr_password:
     type: string
-    description: dmaap datarouter password
+    description: DMAAP Data Router password
     default: "password"
   dcae_location:
     type: string
@@ -69,42 +69,54 @@ inputs:
     type: string
     description: Subscriber id in Data Router
     default: ""
+  pm_mapper_service_protocol:
+    type: string
+    description: PM Mapper protocol
+    default: "https"
+  pm_mapper_service_port:
+    type: string
+    description: PM Mapper host port
+    default: "8443"
   dmaap_buscontroller_service_host:
     type: string
     description: DMAAP Bus Controller host address
     default: "dmaap-bc.onap.svc.cluster.local"
   dmaap_buscontroller_service_port:
     type: string
-    description: DMAAP bus Controller host port
+    description: DMAAP Bus Controller host port
     default: "8080"
   dmaap_dr_feed_id:
     type: string
-    description: ID of the data router feed that the PM Mapper will subscribe to
+    description: ID of the Data Router feed that the PM Mapper will subscribe to
     default: "1"
   dmaap_dr_service_host:
     type: string
     description: DMAAP Data Router host address
-    default: "dmaap-dr-node.onap.svc.cluster.local"
+    default: "dmaap-dr-node"
   dmaap_dr_service_port:
     type: string
     description: DMAAP Data Router host port
     default: "8443"
   dmaap_mr_service_host:
     type: string
-    description: DMAAP Data Router host address
-    default: "message-router.onap.svc.cluster.local"
+    description: DMAAP Message Router host address
+    default: "dmaap-mr"
   dmaap_mr_service_port:
     type: string
-    description: DMAAP Data Router host port
-    default: "3904"
+    description: DMAAP Message Router host port
+    default: "3905"
   dmaap_mr_topic_name:
     type: string
-    description: Name of MR topic events will be published to
+    description: Name of Message Router topic events will be published to
     default: "pm-mapper-ves"
   filter:
     type: string
-    description: PM mapper filter on measInfo, measInfoId, measType, instanceId
+    description: PM Mapper filter on measInfo, measInfoId, measType, instanceId
     default: "{ \"filters\":[]}"
+  enable_http:
+    type: boolean
+    description: Option to turn on HTTP connections
+    default: false
 
 node_templates:
   pm-mapper:
@@ -113,18 +125,25 @@ node_templates:
         start:
           inputs:
             ports:
-              - '8080:0'
+              - '8443:0'
+              - '8081:0'
     properties:
       application_config:
+        enable_http:
+          { get_input: enable_http }
+        trust_store_path: "/opt/app/pm-mapper/etc/cert/trust.jks.b64"
+        trust_store_pass_path: "/opt/app/pm-mapper/etc/cert/trust.pass"
+        key_store_path: "/opt/app/pm-mapper/etc/cert/cert.jks.b64"
+        key_store_pass_path: "/opt/app/pm-mapper/etc/cert/cert.pass"
         buscontroller_feed_subscription_endpoint:
           { concat: ["http://", { get_input: dmaap_buscontroller_service_host },
                      ":", { get_input: dmaap_buscontroller_service_port}, "/webapi/dr_subs"]}
         dmaap_dr_feed_id:
           get_input: dmaap_dr_feed_id
         dmaap_dr_delete_endpoint:
-          { concat: ["http://", { get_input: dmaap_dr_service_host },
+          { concat: ["https://", { get_input: dmaap_dr_service_host },
                      ":", { get_input: dmaap_dr_service_port}, "/delete"]}
-        filters:
+        pm-mapper-filter:
           get_input: filter
         streams_subscribes:
           dmaap_subscriber:
@@ -140,8 +159,8 @@ node_templates:
               subscriber_id:
                 get_input: subscriber_id
               delivery_url:
-                { concat: ["http://", { get_input: service_name }, ".onap.svc.cluster.local",
-                           ":8081/delivery"]}
+                { concat: [{ get_input: pm_mapper_service_protocol },"://", { get_input: service_name }, ".onap.svc.cluster.local",
+                           ":", { get_input: pm_mapper_service_port }, "/delivery"]}
         streams_publishes:
           dmaap_publisher:
             aaf_username:
@@ -156,7 +175,7 @@ node_templates:
               client_id:
                 get_input: client_id
               topic_url:
-                { concat: ["http://", { get_input: dmaap_mr_service_host },
+                { concat: ["https://", { get_input: dmaap_mr_service_host },
                            ":", { get_input: dmaap_mr_service_port }, "/events/", { get_input: dmaap_mr_topic_name }]}
               location:
                 get_input: dcae_location
@@ -165,7 +184,7 @@ node_templates:
           endpoint: /healthcheck
           interval: 15s
           timeout: 1s
-          type: http
+          type: https
       image:
         get_input: tag_version
       replicas: { get_input: replicas }
@@ -173,4 +192,7 @@ node_templates:
       dns_name: { get_input: service_name }
       log_info:
         log_directory: "/var/log/ONAP/dcaegen2/services/pm-mapper"
+      tls_info:
+        cert_directory: "/opt/app/pm-mapper/etc/cert/"
+        use_tls: true
     type: dcae.nodes.ContainerizedPlatformComponent
\ No newline at end of file
index b52a5f1..25e3918 100644 (file)
@@ -42,6 +42,7 @@ import org.onap.dcaegen2.services.pmmapper.messagerouter.VESPublisher;
 import org.onap.dcaegen2.services.pmmapper.model.Event;
 import org.onap.dcaegen2.services.pmmapper.model.MapperConfig;
 import org.onap.dcaegen2.services.pmmapper.healthcheck.HealthCheckHandler;
+import org.onap.dcaegen2.services.pmmapper.ssl.SSLContextFactory;
 import org.onap.dcaegen2.services.pmmapper.utils.DataRouterUtils;
 import org.onap.dcaegen2.services.pmmapper.utils.MeasConverter;
 import org.onap.dcaegen2.services.pmmapper.utils.MeasSplitter;
@@ -53,6 +54,8 @@ import reactor.core.publisher.Flux;
 import reactor.core.publisher.FluxSink;
 import reactor.core.scheduler.Schedulers;
 
+import javax.net.ssl.SSLContext;
+import java.io.IOException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.ArrayList;
@@ -64,7 +67,7 @@ public class App {
     private static Path xmlSchema = Paths.get("/opt/app/pm-mapper/etc/measCollec_plusString.xsd");
     private static FluxSink<Event> fluxSink;
 
-    public static void main(String[] args) throws InterruptedException, TooManyTriesException, CBSConfigException, EnvironmentConfigException, CBSServerError, MapperConfigException {
+    public static void main(String[] args) throws InterruptedException, TooManyTriesException, CBSConfigException, EnvironmentConfigException, CBSServerError, MapperConfigException, IOException {
         Flux<Event> flux = Flux.create(eventFluxSink -> fluxSink = eventFluxSink);
         HealthCheckHandler healthCheckHandler = new HealthCheckHandler();
         MapperConfig mapperConfig = new ConfigHandler().getMapperConfig();
@@ -89,7 +92,7 @@ public class App {
                 .filter(events -> App.filter(filterHandler, events, mapperConfig))
                 .concatMap(events -> App.map(mapper, events, mapperConfig))
                 .concatMap(vesPublisher::publish)
-                .subscribe(events -> logger.unwrap().info("Event Processed"));
+                .subscribe(event -> App.sendEventProcessed(mapperConfig, event));
 
         DataRouterSubscriber dataRouterSubscriber = new DataRouterSubscriber(fluxSink::next, mapperConfig);
         dataRouterSubscriber.start();
@@ -98,8 +101,17 @@ public class App {
         configurables.add(mapperConfig);
         DynamicConfiguration dynamicConfiguration = new DynamicConfiguration(configurables, mapperConfig);
 
-        Undertow.builder()
-                .addHttpListener(8081, "0.0.0.0")
+        Undertow.Builder builder = Undertow.builder();
+
+        SSLContextFactory sslContextFactory = new SSLContextFactory(mapperConfig);
+        SSLContext sslContext = sslContextFactory.createSSLContext(mapperConfig);
+        SSLContext.setDefault(sslContext);
+
+        if(mapperConfig.getEnableHttp()) {
+            builder.addHttpListener(8081, "0.0.0.0");
+        }
+
+        builder.addHttpsListener(8443, "0.0.0.0", sslContext)
                 .setHandler(Handlers.routing()
                         .add("put", "/delivery/{filename}", dataRouterSubscriber)
                         .add("get", "/healthcheck", healthCheckHandler)
index 19a4750..a0a8eaf 100644 (file)
@@ -85,7 +85,7 @@ public class DataRouterSubscriber implements HttpHandler, Configurable {
     private Random jitterGenerator;
     private Gson metadataBuilder;
     private MapperConfig config;
-    private String subscriberId;
+    public static String subscriberId;
     @NonNull
     private EventReceiver eventReceiver;
 
diff --git a/src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/CreateContextException.java b/src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/CreateContextException.java
new file mode 100644 (file)
index 0000000..a5a230c
--- /dev/null
@@ -0,0 +1,27 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * Licensed 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcaegen2.services.pmmapper.exceptions;
+
+public class CreateContextException extends RuntimeException {
+    public CreateContextException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/KeyManagerException.java b/src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/KeyManagerException.java
new file mode 100644 (file)
index 0000000..d123991
--- /dev/null
@@ -0,0 +1,27 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * Licensed 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcaegen2.services.pmmapper.exceptions;
+
+public class KeyManagerException extends RuntimeException {
+    public KeyManagerException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/LoadKeyStoreException.java b/src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/LoadKeyStoreException.java
new file mode 100644 (file)
index 0000000..96bfad5
--- /dev/null
@@ -0,0 +1,27 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * Licensed 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcaegen2.services.pmmapper.exceptions;
+
+public class LoadKeyStoreException extends RuntimeException {
+    public LoadKeyStoreException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/ServerResponseException.java b/src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/ServerResponseException.java
new file mode 100644 (file)
index 0000000..b52e2d4
--- /dev/null
@@ -0,0 +1,27 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * Licensed 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcaegen2.services.pmmapper.exceptions;
+
+public class ServerResponseException extends Exception {
+    public ServerResponseException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/TrustManagerException.java b/src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/TrustManagerException.java
new file mode 100644 (file)
index 0000000..75ce61d
--- /dev/null
@@ -0,0 +1,27 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * Licensed 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcaegen2.services.pmmapper.exceptions;
+
+public class TrustManagerException extends RuntimeException {
+    public TrustManagerException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
\ No newline at end of file
index bd4eafb..b9d58ee 100644 (file)
-/*-\r
- * ============LICENSE_START=======================================================\r
- *  Copyright (C) 2019 Nordix Foundation.\r
- * ================================================================================\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- *\r
- * SPDX-License-Identifier: Apache-2.0\r
- * ============LICENSE_END=========================================================\r
- */\r
-package org.onap.dcaegen2.services.pmmapper.model;\r
-\r
-import java.net.MalformedURLException;\r
-import java.net.URL;\r
-\r
-import org.onap.dcaegen2.services.pmmapper.config.Configurable;\r
-import org.onap.dcaegen2.services.pmmapper.utils.GSONRequired;\r
-import com.google.gson.annotations.SerializedName;\r
-import lombok.Getter;\r
-import lombok.AccessLevel;\r
-import lombok.EqualsAndHashCode;\r
-import lombok.NoArgsConstructor;\r
-\r
-@Getter\r
-@EqualsAndHashCode\r
-@NoArgsConstructor\r
-public class MapperConfig implements Configurable{\r
-\r
-    public static final String CLIENT_NAME = "pm-mapper";\r
-\r
-    @GSONRequired\r
-    @Getter(AccessLevel.PRIVATE)\r
-    @SerializedName("streams_subscribes")\r
-    private StreamsSubscribes streamsSubscribes;\r
-\r
-    @GSONRequired\r
-    @Getter(AccessLevel.PRIVATE)\r
-    @SerializedName("streams_publishes")\r
-    private StreamsPublishes streamsPublishes;\r
-\r
-    @GSONRequired\r
-    @SerializedName("buscontroller_feed_subscription_endpoint")\r
-    private String busControllerSubscriptionEndpoint;\r
-\r
-    @GSONRequired\r
-    @SerializedName("dmaap_dr_feed_id")\r
-    private String dmaapDRFeedId;\r
-\r
-    @GSONRequired\r
-    @SerializedName("dmaap_dr_delete_endpoint")\r
-    private String dmaapDRDeleteEndpoint;\r
-\r
-    public String getBusControllerDeliveryUrl() {\r
-        return this.getStreamsSubscribes().getDmaapSubscriber().getDmaapInfo().getDeliveryUrl();\r
-    }\r
-\r
-    public String getDcaeLocation() {\r
-        return this.getStreamsSubscribes().getDmaapSubscriber().getDmaapInfo().getLocation();\r
-    }\r
-\r
-    public String getBusControllerUserName() {\r
-        return this.getStreamsSubscribes().getDmaapSubscriber().getDmaapInfo().getUsername();\r
-    }\r
-\r
-    public String getBusControllerPassword() {\r
-        return this.getStreamsSubscribes().getDmaapSubscriber().getDmaapInfo().getPassword();\r
-    }\r
-\r
-    public URL getBusControllerSubscriptionUrl() throws MalformedURLException {\r
-        return new URL(this.getBusControllerSubscriptionEndpoint());\r
-    }\r
-\r
-    public String getSubscriberIdentity(){\r
-        return this.getStreamsSubscribes().getDmaapSubscriber().getDmaapInfo().getSubscriberId();\r
-    }\r
-\r
-    public String getSubscriberDcaeLocation() {\r
-        return this.getStreamsSubscribes().getDmaapSubscriber().getDmaapInfo().getLocation();\r
-    }\r
-\r
-    public String getPublisherTopicUrl() {\r
-        return this.getStreamsPublishes().getDmaapPublisher().getDmaapInfo().getTopicUrl();\r
-    }\r
-\r
-    public boolean dmaapInfoEquals(MapperConfig mapperConfig){\r
-        return this\r
-                .getStreamsSubscribes()\r
-                .getDmaapSubscriber()\r
-                .getDmaapInfo()\r
-                .equals(mapperConfig.getStreamsSubscribes().getDmaapSubscriber().getDmaapInfo());\r
-    }\r
-\r
-    @Getter\r
-    @EqualsAndHashCode\r
-    private class StreamsSubscribes {\r
-        @GSONRequired\r
-        @SerializedName("dmaap_subscriber")\r
-        DmaapSubscriber dmaapSubscriber;\r
-    }\r
-\r
-    @Getter\r
-    @EqualsAndHashCode\r
-    class DmaapSubscriber {\r
-        @GSONRequired\r
-        @SerializedName("dmaap_info")\r
-        DmaapInfo dmaapInfo;\r
-    }\r
-\r
-    @Getter\r
-    @EqualsAndHashCode\r
-    private class StreamsPublishes {\r
-        @GSONRequired\r
-        @SerializedName("dmaap_publisher")\r
-        DmaapPublisher dmaapPublisher;\r
-    }\r
-\r
-    @Getter\r
-    @EqualsAndHashCode\r
-    class DmaapPublisher {\r
-        @GSONRequired\r
-        @SerializedName("dmaap_info")\r
-        DmaapInfo dmaapInfo;\r
-    }\r
-\r
-    @Getter\r
-    @EqualsAndHashCode\r
-    class DmaapInfo {\r
-        private String location;\r
-        private String username;\r
-        private String password;\r
-\r
-        @SerializedName("delivery_url")\r
-        private String deliveryUrl;\r
-\r
-        @SerializedName("subscriber_id")\r
-        private String subscriberId;\r
-\r
-        @SerializedName("aaf_username")\r
-        private String aafUsername;\r
-\r
-        @SerializedName("aaf_password")\r
-        private String aafPassword;\r
-\r
-        @SerializedName("client_role")\r
-        private String clientRole;\r
-\r
-        @SerializedName("client_id")\r
-        private String clientId;\r
-\r
-        @SerializedName("topic_url")\r
-        private String topicUrl;\r
-    }\r
-\r
-    @SerializedName("pm-mapper-filter")\r
-    MeasFilterConfig filterConfig;\r
-\r
-    @Override\r
-    public void reconfigure(MapperConfig mapperConfig) {\r
-        if(!this.equals(mapperConfig)) {\r
-            this.streamsSubscribes = mapperConfig.getStreamsSubscribes();\r
-            this.streamsPublishes = mapperConfig.getStreamsPublishes();\r
-            this.busControllerSubscriptionEndpoint = mapperConfig.getBusControllerSubscriptionEndpoint();\r
-            this.dmaapDRFeedId = mapperConfig.getDmaapDRFeedId();\r
-            this.dmaapDRDeleteEndpoint = mapperConfig.getDmaapDRDeleteEndpoint();\r
-        }\r
-    }\r
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * Licensed 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dcaegen2.services.pmmapper.model;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.onap.dcaegen2.services.pmmapper.config.Configurable;
+import org.onap.dcaegen2.services.pmmapper.utils.GSONRequired;
+import com.google.gson.annotations.SerializedName;
+import lombok.Getter;
+import lombok.AccessLevel;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+@Getter
+@EqualsAndHashCode
+@NoArgsConstructor
+public class MapperConfig implements Configurable{
+
+    public static final String CLIENT_NAME = "pm-mapper";
+
+    @GSONRequired
+    @SerializedName("enable_http")
+    private Boolean enableHttp;
+
+    @GSONRequired
+    @SerializedName("key_store_path")
+    private String keyStorePath;
+
+    @GSONRequired
+    @SerializedName("key_store_pass_path")
+    private String keyStorePassPath;
+
+    @GSONRequired
+    @SerializedName("trust_store_path")
+    private String trustStorePath;
+
+    @GSONRequired
+    @SerializedName("trust_store_pass_path")
+    private String trustStorePassPath;
+
+    @GSONRequired
+    @Getter(AccessLevel.PRIVATE)
+    @SerializedName("streams_subscribes")
+    private StreamsSubscribes streamsSubscribes;
+
+    @GSONRequired
+    @Getter(AccessLevel.PRIVATE)
+    @SerializedName("streams_publishes")
+    private StreamsPublishes streamsPublishes;
+
+    @GSONRequired
+    @SerializedName("buscontroller_feed_subscription_endpoint")
+    private String busControllerSubscriptionEndpoint;
+
+    @GSONRequired
+    @SerializedName("dmaap_dr_feed_id")
+    private String dmaapDRFeedId;
+
+    @GSONRequired
+    @SerializedName("dmaap_dr_delete_endpoint")
+    private String dmaapDRDeleteEndpoint;
+
+    @GSONRequired
+    @SerializedName("pm-mapper-filter")
+    private MeasFilterConfig filterConfig;
+
+    public String getBusControllerDeliveryUrl() {
+        return this.getStreamsSubscribes().getDmaapSubscriber().getDmaapInfo().getDeliveryUrl();
+    }
+
+    public String getDcaeLocation() {
+        return this.getStreamsSubscribes().getDmaapSubscriber().getDmaapInfo().getLocation();
+    }
+
+    public String getBusControllerUserName() {
+        return this.getStreamsSubscribes().getDmaapSubscriber().getDmaapInfo().getUsername();
+    }
+
+    public String getBusControllerPassword() {
+        return this.getStreamsSubscribes().getDmaapSubscriber().getDmaapInfo().getPassword();
+    }
+
+    public URL getBusControllerSubscriptionUrl() throws MalformedURLException {
+        return new URL(this.getBusControllerSubscriptionEndpoint());
+    }
+
+    public String getSubscriberIdentity(){
+        return this.getStreamsSubscribes().getDmaapSubscriber().getDmaapInfo().getSubscriberId();
+    }
+
+    public String getSubscriberDcaeLocation() {
+        return this.getStreamsSubscribes().getDmaapSubscriber().getDmaapInfo().getLocation();
+    }
+
+    public String getPublisherTopicUrl() {
+        return this.getStreamsPublishes().getDmaapPublisher().getDmaapInfo().getTopicUrl();
+    }
+
+    public boolean dmaapInfoEquals(MapperConfig mapperConfig){
+        return this
+                .getStreamsSubscribes()
+                .getDmaapSubscriber()
+                .getDmaapInfo()
+                .equals(mapperConfig.getStreamsSubscribes().getDmaapSubscriber().getDmaapInfo());
+    }
+
+    @Getter
+    @EqualsAndHashCode
+    private class StreamsSubscribes {
+        @GSONRequired
+        @SerializedName("dmaap_subscriber")
+        DmaapSubscriber dmaapSubscriber;
+    }
+
+    @Getter
+    @EqualsAndHashCode
+    class DmaapSubscriber {
+        @GSONRequired
+        @SerializedName("dmaap_info")
+        DmaapInfo dmaapInfo;
+    }
+
+    @Getter
+    @EqualsAndHashCode
+    private class StreamsPublishes {
+        @GSONRequired
+        @SerializedName("dmaap_publisher")
+        DmaapPublisher dmaapPublisher;
+    }
+
+    @Getter
+    @EqualsAndHashCode
+    class DmaapPublisher {
+        @GSONRequired
+        @SerializedName("dmaap_info")
+        DmaapInfo dmaapInfo;
+    }
+
+    @Getter
+    @EqualsAndHashCode
+    class DmaapInfo {
+        private String location;
+        private String username;
+        private String password;
+
+        @SerializedName("delivery_url")
+        private String deliveryUrl;
+
+        @SerializedName("subscriber_id")
+        private String subscriberId;
+
+        @SerializedName("aaf_username")
+        private String aafUsername;
+
+        @SerializedName("aaf_password")
+        private String aafPassword;
+
+        @SerializedName("client_role")
+        private String clientRole;
+
+        @SerializedName("client_id")
+        private String clientId;
+
+        @SerializedName("topic_url")
+        private String topicUrl;
+    }
+
+    @Override
+    public void reconfigure(MapperConfig mapperConfig) {
+        if(!this.equals(mapperConfig)) {
+            this.streamsSubscribes = mapperConfig.getStreamsSubscribes();
+            this.streamsPublishes = mapperConfig.getStreamsPublishes();
+            this.busControllerSubscriptionEndpoint = mapperConfig.getBusControllerSubscriptionEndpoint();
+            this.dmaapDRFeedId = mapperConfig.getDmaapDRFeedId();
+            this.dmaapDRDeleteEndpoint = mapperConfig.getDmaapDRDeleteEndpoint();
+        }
+    }
 }
\ No newline at end of file
diff --git a/src/main/java/org/onap/dcaegen2/services/pmmapper/ssl/SSLContextFactory.java b/src/main/java/org/onap/dcaegen2/services/pmmapper/ssl/SSLContextFactory.java
new file mode 100644 (file)
index 0000000..68e63f5
--- /dev/null
@@ -0,0 +1,133 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * Licensed 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dcaegen2.services.pmmapper.ssl;
+
+import org.onap.dcaegen2.services.pmmapper.exceptions.CreateContextException;
+import org.onap.dcaegen2.services.pmmapper.exceptions.KeyManagerException;
+import org.onap.dcaegen2.services.pmmapper.exceptions.LoadKeyStoreException;
+import org.onap.dcaegen2.services.pmmapper.exceptions.TrustManagerException;
+import org.onap.dcaegen2.services.pmmapper.model.MapperConfig;
+import org.onap.logging.ref.slf4j.ONAPLogAdapter;
+import org.slf4j.LoggerFactory;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Paths;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.util.Base64;
+
+import static java.nio.file.Files.readAllBytes;
+
+public class SSLContextFactory {
+    private static final ONAPLogAdapter logger = new ONAPLogAdapter(LoggerFactory.getLogger(SSLContextFactory.class));
+    private static MapperConfig mapperConfig;
+
+    public SSLContextFactory(MapperConfig config) {
+        mapperConfig = config;
+    }
+
+    public SSLContext createSSLContext(MapperConfig mapperConfig) throws IOException {
+        SSLContext sslContext = null;
+
+        try {
+            KeyStore keyStore = loadKeyStore(mapperConfig.getKeyStorePath(), mapperConfig.getKeyStorePassPath());
+            KeyManager[] keyManagers = createKeyManager(keyStore);
+
+            KeyStore trustStore = loadKeyStore(mapperConfig.getTrustStorePath(), mapperConfig.getTrustStorePassPath());
+            TrustManager[] trustManagers = createTrustManager(trustStore);
+
+            sslContext = SSLContext.getInstance("TLSv1.2");
+            sslContext.init(keyManagers, trustManagers, null);
+        } catch(KeyManagementException | NoSuchAlgorithmException e) {
+            logger.unwrap().error("Failed to create SSL Context.", e);
+            throw new CreateContextException("Failed to create SSL Context", e);
+        }
+        return sslContext;
+    }
+
+    private KeyManager[] createKeyManager(KeyStore keyStore) throws NoSuchAlgorithmException, IOException {
+        KeyManager[] keyManager;
+        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+
+        try {
+            keyManagerFactory.init(keyStore, getPassword(mapperConfig.getKeyStorePassPath()).toCharArray());
+        } catch (KeyStoreException | UnrecoverableKeyException e) {
+            logger.unwrap().error("Failed to initialize keystore.", e);
+            throw new KeyManagerException("Failed to create KeyManager from Keystore", e);
+        }
+        keyManager = keyManagerFactory.getKeyManagers();
+
+        return keyManager;
+    }
+
+    private TrustManager[] createTrustManager(KeyStore trustStore) throws NoSuchAlgorithmException {
+        TrustManager[] trustManagers;
+        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+        try {
+            trustManagerFactory.init(trustStore);
+        } catch (KeyStoreException e) {
+            throw new TrustManagerException("Failed to create TrustManager from Truststore", e);
+        }
+        trustManagers = trustManagerFactory.getTrustManagers();
+
+        return trustManagers;
+    }
+
+    private KeyStore loadKeyStore(String path, String passwordPath) throws IOException, NoSuchAlgorithmException {
+        String type = "JKS";
+        String encodedKeystore = new String(readAllBytes(Paths.get(path)));
+        String password = getPassword(passwordPath);
+
+        KeyStore keyStore = null;
+
+        try {
+            keyStore = KeyStore.getInstance(type);
+            byte[] decodedKeystore = Base64.getMimeDecoder().decode(encodedKeystore);
+            InputStream stream = new ByteArrayInputStream(decodedKeystore);
+            keyStore.load(stream, password.toCharArray());
+        } catch(KeyStoreException | CertificateException e) {
+            logger.unwrap().error("Failed to load Keystore from given configuration.", e);
+            throw new LoadKeyStoreException("Failed to load Keystore from given configuration", e);
+        }
+        return keyStore;
+    }
+
+    private String getPassword(String passwordPath) throws IOException {
+        try {
+            String password = new String(readAllBytes(Paths.get(passwordPath)));
+            password = password.replace("\n", "").replace("\r", "");
+            return password;
+        } catch (IOException e) {
+            logger.unwrap().error("Could not read password from: {}.", passwordPath, e);
+            throw new IOException("Password not found");
+        }
+    }
+}
index f30fb96..5147863 100644 (file)
@@ -20,6 +20,7 @@
 
 package org.onap.dcaegen2.services.pmmapper.utils;
 
+import org.onap.dcaegen2.services.pmmapper.datarouter.DataRouterSubscriber;
 import org.onap.dcaegen2.services.pmmapper.exceptions.ProcessEventException;
 import org.onap.dcaegen2.services.pmmapper.model.Event;
 import org.onap.dcaegen2.services.pmmapper.model.MapperConfig;
@@ -41,7 +42,7 @@ public class DataRouterUtils {
     public static String processEvent(MapperConfig config, Event event){
         logger.unwrap().info("Sending processed to DataRouter");
         String baseDelete = config.getDmaapDRDeleteEndpoint();
-        String subscriberIdentity = config.getSubscriberIdentity();
+        String subscriberIdentity = DataRouterSubscriber.subscriberId;
         String delete = String.format("%s/%s/%s", baseDelete, subscriberIdentity, event.getPublishIdentity());
         try {
             return new RequestSender().send("DELETE", delete);
@@ -50,4 +51,4 @@ public class DataRouterUtils {
             throw new ProcessEventException("Process event failure", exception);
         }
     }
-}
+}
\ No newline at end of file
index 658f820..fdbae59 100644 (file)
@@ -30,11 +30,15 @@ import java.nio.charset.StandardCharsets;
 import java.util.UUID;\r
 import java.util.stream.Collectors;\r
 \r
+import org.onap.dcaegen2.services.pmmapper.exceptions.ServerResponseException;\r
 import org.onap.dcaegen2.services.pmmapper.model.MapperConfig;\r
 import org.onap.logging.ref.slf4j.ONAPLogAdapter;\r
 import org.onap.logging.ref.slf4j.ONAPLogConstants;\r
 import org.slf4j.LoggerFactory;\r
 \r
+import javax.net.ssl.HttpsURLConnection;\r
+import javax.net.ssl.SSLContext;\r
+\r
 public class RequestSender {\r
     private static final int MAX_RETRIES = 5;\r
     private static final int RETRY_INTERVAL = 1000;\r
@@ -79,9 +83,16 @@ public class RequestSender {
         for (int i = 1; i <= MAX_RETRIES; i++) {\r
             final URL url = new URL(urlString);\r
             final HttpURLConnection connection = getHttpURLConnection(method, url, invocationID, requestID);\r
+\r
+\r
+            if("https".equalsIgnoreCase(url.getProtocol())) {\r
+                HttpsURLConnection.setDefaultSSLSocketFactory(SSLContext.getDefault().getSocketFactory());\r
+            }\r
+\r
             if(!body.isEmpty()) {\r
                 setMessageBody(connection, body);\r
             }\r
+\r
             logger.unwrap().info("Sending {} request to {}.", method, urlString);\r
 \r
             try (InputStream is = connection.getInputStream();\r
@@ -90,13 +101,13 @@ public class RequestSender {
                         .collect(Collectors.joining("\n"));\r
                 int responseCode = connection.getResponseCode();\r
                 if (!(isWithinErrorRange(responseCode))) {\r
-                    logger.unwrap().info("Server Response Received:\n{}", result);\r
+                    logger.unwrap().info("Response code: {}, Server Response Received:\n{}",responseCode, result);\r
                     break;\r
                 }\r
             } catch (Exception e) {\r
                 if (retryLimitReached(i)) {\r
-                    logger.unwrap().error("Execution error: "+connection.getResponseMessage(), e);\r
-                    throw new Exception(SERVER_ERROR_MESSAGE + ": " + connection.getResponseMessage(), e);\r
+                    logger.unwrap().error("Execution error: {}", connection.getResponseMessage(), e);\r
+                    throw new ServerResponseException(SERVER_ERROR_MESSAGE + ": " + connection.getResponseMessage(), e);\r
                 }\r
             }\r
 \r
@@ -105,7 +116,7 @@ public class RequestSender {
         return result;\r
     }\r
 \r
-    private HttpURLConnection getHttpURLConnection(String method, URL url, UUID invocationID, UUID requestID) throws Exception {\r
+    private HttpURLConnection getHttpURLConnection(String method, URL url, UUID invocationID, UUID requestID) throws IOException {\r
         HttpURLConnection connection = (HttpURLConnection) url.openConnection();\r
         connection.setReadTimeout(DEFAULT_READ_TIMEOUT);\r
         connection.setRequestProperty(ONAPLogConstants.Headers.REQUEST_ID, requestID.toString());\r
index 770ae43..b349b80 100644 (file)
@@ -26,7 +26,6 @@ import static org.mockserver.integration.ClientAndServer.startClientAndServer;
 import static org.mockserver.model.HttpRequest.request;\r
 import static org.mockserver.model.HttpResponse.response;\r
 \r
-import java.io.IOException;\r
 import java.net.URL;\r
 import java.net.UnknownHostException;\r
 \r
diff --git a/src/test/java/org/onap/dcaegen2/services/pmmapper/ssl/SSLContextFactoryTest.java b/src/test/java/org/onap/dcaegen2/services/pmmapper/ssl/SSLContextFactoryTest.java
new file mode 100644 (file)
index 0000000..6f5cee9
--- /dev/null
@@ -0,0 +1,84 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * Licensed 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcaegen2.services.pmmapper.ssl;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import org.junit.Rule;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.rules.ExpectedException;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.onap.dcaegen2.services.pmmapper.model.MapperConfig;
+
+import javax.net.ssl.*;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import static org.junit.Assert.assertNotNull;
+
+@ExtendWith(MockitoExtension.class)
+
+public class SSLContextFactoryTest {
+
+    @Rule
+    public ExpectedException exception = ExpectedException.none();
+
+    private static String validConfigFileContents;
+    private static MapperConfig validConfig;
+    private static MapperConfig inValidConfig;
+
+
+    private static final Path validConfigPath = Paths.get("src/test/resources/valid_mapper_config.json");
+
+    private SSLContextFactory objUnderTest;
+
+    @BeforeEach
+    void setUp() throws Exception {
+        validConfigFileContents = new String(Files.readAllBytes(validConfigPath));
+        JsonObject configObject = new JsonParser().parse(validConfigFileContents).getAsJsonObject();
+        validConfig = new Gson().fromJson(configObject, MapperConfig.class);
+
+        objUnderTest = new SSLContextFactory(validConfig);
+    }
+
+    @Test
+    void testCreateSSLContext() throws IOException {
+        SSLContext sslContext = objUnderTest.createSSLContext(validConfig);
+
+        assertNotNull(sslContext);
+    }
+
+    @Test
+    void testCreateSSLContextInvalidPassword() {
+        JsonObject configObject = new JsonParser().parse(validConfigFileContents).getAsJsonObject();
+        configObject.addProperty("key_store_pass_path", "src/test/resources/nopassword");
+        inValidConfig = new Gson().fromJson(configObject, MapperConfig.class);
+
+        assertThrows(IOException.class, () -> objUnderTest.createSSLContext(inValidConfig));
+    }
+}
\ No newline at end of file
index 73967c2..9975849 100644 (file)
@@ -31,25 +31,74 @@ import static org.mockito.Mockito.when;
 import java.io.ByteArrayInputStream;
 import java.net.HttpURLConnection;
 import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.onap.dcaegen2.services.pmmapper.datarouter.DataRouterSubscriber;
 import org.onap.dcaegen2.services.pmmapper.exceptions.ProcessEventException;
 import org.onap.dcaegen2.services.pmmapper.model.Event;
 import org.onap.dcaegen2.services.pmmapper.model.EventMetadata;
 import org.onap.dcaegen2.services.pmmapper.model.MapperConfig;
+import org.onap.dcaegen2.services.pmmapper.ssl.SSLContextFactory;
 import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PowerMockIgnore;
 import org.powermock.core.classloader.annotations.PrepareForTest;
 import org.powermock.modules.junit4.PowerMockRunner;
 import org.powermock.reflect.Whitebox;
 import utils.EventUtils;
 
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
 
+@PowerMockIgnore({"org.apache.http.conn.ssl.*", "javax.net.ssl.*" , "javax.crypto.*"})
+@PrepareForTest({RequestSender.class,DataRouterSubscriber.class})
 @RunWith(PowerMockRunner.class)
-@PrepareForTest(RequestSender.class)
 public class DataRouterUtilsTest {
 
+    private static String validConfigFileContents;
+    private static MapperConfig validConfig;
+    private SSLContextFactory sslContextFactory;
+    private static final Path validConfigPath = Paths.get("src/test/resources/valid_mapper_config.json");
+
     @Test
     public void processEventSuccessful() throws Exception {
+        validConfigFileContents = new String(Files.readAllBytes(validConfigPath));
+        JsonObject configObject = new JsonParser().parse(validConfigFileContents).getAsJsonObject();
+        validConfig = new Gson().fromJson(configObject, MapperConfig.class);
+        sslContextFactory = new SSLContextFactory(validConfig);
+
+        SSLContext sslContext = sslContextFactory.createSSLContext(validConfig);
+        SSLContext.setDefault(sslContext);
+
+        String serviceResponse = "I'm a service response ;)";
+        String publishIdentity = "12";
+        PowerMockito.mockStatic(Thread.class);
+        MapperConfig mockMapperConfig = mock(MapperConfig.class);
+        URL mockURL = mock(URL.class);
+        HttpsURLConnection mockConnection = mock(HttpsURLConnection.class, RETURNS_DEEP_STUBS);
+        when(mockConnection.getResponseCode()).thenReturn(200);
+        when(mockConnection.getInputStream()).thenReturn(new ByteArrayInputStream(serviceResponse.getBytes()));
+
+        when(mockURL.openConnection()).thenReturn(mockConnection);
+        when(mockURL.getProtocol()).thenReturn("https");
+        when(mockMapperConfig.getDmaapDRDeleteEndpoint()).thenReturn("https://dmaap-dr-node/delete/");
+        when(mockMapperConfig.getSubscriberIdentity()).thenReturn("12");
+
+        PowerMockito.whenNew(URL.class).withAnyArguments().thenReturn(mockURL);
+
+        Event testEvent = EventUtils.makeMockEvent("", mock(EventMetadata.class), publishIdentity);
+        assertEquals(serviceResponse,  DataRouterUtils.processEvent(mockMapperConfig, testEvent));
+        verify(mockConnection, times(1)).setRequestMethod(RequestSender.DELETE);
+    }
+
+    @Test
+    public void processEventSuccessfulHttp() throws Exception {
         String serviceResponse = "I'm a service response ;)";
         String publishIdentity = "12";
         PowerMockito.mockStatic(Thread.class);
@@ -60,7 +109,8 @@ public class DataRouterUtilsTest {
         when(mockConnection.getInputStream()).thenReturn(new ByteArrayInputStream(serviceResponse.getBytes()));
 
         when(mockURL.openConnection()).thenReturn(mockConnection);
-        when(mockMapperConfig.getDmaapDRDeleteEndpoint()).thenReturn("dmaap-dr-node/delete/");
+        when(mockURL.getProtocol()).thenReturn("http");
+        when(mockMapperConfig.getDmaapDRDeleteEndpoint()).thenReturn("http://dmaap-dr-node/delete/");
         when(mockMapperConfig.getSubscriberIdentity()).thenReturn("12");
 
         PowerMockito.whenNew(URL.class).withAnyArguments().thenReturn(mockURL);
@@ -72,17 +122,26 @@ public class DataRouterUtilsTest {
 
     @Test
     public void testNegativeResponse() throws Exception {
+        validConfigFileContents = new String(Files.readAllBytes(validConfigPath));
+        JsonObject configObject = new JsonParser().parse(validConfigFileContents).getAsJsonObject();
+        validConfig = new Gson().fromJson(configObject, MapperConfig.class);
+        sslContextFactory = new SSLContextFactory(validConfig);
+
+        SSLContext sslContext = sslContextFactory.createSSLContext(validConfig);
+        SSLContext.setDefault(sslContext);
+
         String serviceResponse = "I'm a negative service response ;)";
         String publishIdentity = "12";
         PowerMockito.mockStatic(Thread.class);
         MapperConfig mockMapperConfig = mock(MapperConfig.class);
         URL mockURL = mock(URL.class);
-        HttpURLConnection mockConnection = mock(HttpURLConnection.class, RETURNS_DEEP_STUBS);
+        HttpsURLConnection mockConnection = mock(HttpsURLConnection.class, RETURNS_DEEP_STUBS);
         when(mockConnection.getResponseCode()).thenReturn(503);
         when(mockConnection.getInputStream())
                 .thenAnswer(invocationOnMock -> new ByteArrayInputStream(serviceResponse.getBytes()));
 
         when(mockURL.openConnection()).thenReturn(mockConnection);
+        when(mockURL.getProtocol()).thenReturn("https");
         when(mockMapperConfig.getDmaapDRDeleteEndpoint()).thenReturn("dmaap-dr-node/delete/");
         when(mockMapperConfig.getSubscriberIdentity()).thenReturn("12");
 
@@ -102,10 +161,11 @@ public class DataRouterUtilsTest {
         PowerMockito.mockStatic(Thread.class);
         MapperConfig mockMapperConfig = mock(MapperConfig.class);
         URL mockURL = mock(URL.class);
-        HttpURLConnection mockConnection = mock(HttpURLConnection.class, RETURNS_DEEP_STUBS);
+        HttpsURLConnection mockConnection = mock(HttpsURLConnection.class, RETURNS_DEEP_STUBS);
         when(mockConnection.getResponseCode()).thenReturn(503);
 
         when(mockURL.openConnection()).thenReturn(mockConnection);
+        when(mockURL.getProtocol()).thenReturn("https");
         when(mockMapperConfig.getDmaapDRDeleteEndpoint()).thenReturn("dmaap-dr-node/delete/");
         when(mockMapperConfig.getSubscriberIdentity()).thenReturn("12");
 
diff --git a/src/test/resources/password b/src/test/resources/password
new file mode 100644 (file)
index 0000000..547d6c7
--- /dev/null
@@ -0,0 +1 @@
+pmmapper
\ No newline at end of file
diff --git a/src/test/resources/testkeystore.jks.b64 b/src/test/resources/testkeystore.jks.b64
new file mode 100644 (file)
index 0000000..f466fce
--- /dev/null
@@ -0,0 +1,35 @@
+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
index 040406f..e37b77e 100644 (file)
     "dmaap_dr_feed_id": "2",\r
     "buscontroller_feed_subscription_endpoint": "http://dmaap-bc.onap.svc.cluster.local:8080/webapi/dr_subs",\r
     "dmaap_dr_delete_endpoint": "http://dmaap-dr-node.onap.svc.cluster.local:8443/delete",\r
-    "services_calls": {}\r
+    "services_calls": {},\r
+    "key_store_path": "src/test/resources/testkeystore.jks.b64",\r
+    "key_store_pass_path": "src/test/resources/password",\r
+    "trust_store_path": "src/test/resources/testkeystore.jks.b64",\r
+    "trust_store_pass_path": "src/test/resources/password",\r
+    "enable_http": false\r
 }
\ No newline at end of file