From 0ae7a7f6b40ff13a21f33e3e573d6b3ebde6bf90 Mon Sep 17 00:00:00 2001 From: Vijay Venkatesh Kumar Date: Fri, 5 Oct 2018 14:14:00 +0200 Subject: Fix mutual authentication Last version from demo. Change-Id: Ib41581bf6f9eb92a03edf8434261d3674b6e3e39 Issue-ID: DCAEGEN2-860 Signed-off-by: elinuxhenrik Signed-off-by: Vijay Venkatesh Kumar --- datafile-app-server/config/cacerts | Bin 0 -> 1403 bytes datafile-app-server/config/datafile_endpoints.json | 13 +- datafile-app-server/config/ftpKey.jks | Bin 0 -> 2579 bytes datafile-app-server/pom.xml | 23 +--- .../datafile/configuration/AppConfig.java | 29 +++++ .../datafile/configuration/CloudConfigParser.java | 10 ++ .../collectors/datafile/configuration/Config.java | 3 + .../datafile/configuration/DatafileAppConfig.java | 41 +++--- .../datafile/configuration/FtpesConfig.java | 52 ++++++++ .../datafile/controllers/HeartbeatController.java | 2 +- .../datafile/exceptions/DatafileTaskException.java | 2 + .../exceptions/DmaapEmptyResponseException.java | 2 + .../exceptions/DmaapNotFoundException.java | 2 + .../exceptions/EnvironmentLoaderException.java | 2 + .../collectors/datafile/ftp/FileServerData.java | 31 ----- .../collectors/datafile/ftp/FtpsClient.java | 119 ------------------ .../collectors/datafile/ftp/SftpClient.java | 98 --------------- .../datafile/service/DmaapConsumerJsonParser.java | 8 +- .../datafile/tasks/DmaapConsumerTaskImpl.java | 2 +- .../datafile/tasks/XnfCollectorTask.java | 2 + .../datafile/tasks/XnfCollectorTaskImpl.java | 36 +++++- .../configuration/CloudConfigParserTest.java | 139 ++++++++++----------- .../configuration/DatafileAppConfigTest.java | 85 +++++++++---- .../collectors/datafile/ftp/FtpClientTest.java | 57 --------- .../collectors/datafile/ftp/SftpClientTest.java | 103 --------------- .../datafile/tasks/XnfCollectorTaskImplTest.java | 38 +++++- .../src/test/resources/datafile_endpoints.json | 24 ++-- 27 files changed, 365 insertions(+), 558 deletions(-) create mode 100644 datafile-app-server/config/cacerts create mode 100644 datafile-app-server/config/ftpKey.jks create mode 100644 datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/FtpesConfig.java delete mode 100644 datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/ftp/FileServerData.java delete mode 100644 datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/ftp/FtpsClient.java delete mode 100644 datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/ftp/SftpClient.java delete mode 100644 datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/ftp/FtpClientTest.java delete mode 100644 datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/ftp/SftpClientTest.java (limited to 'datafile-app-server') diff --git a/datafile-app-server/config/cacerts b/datafile-app-server/config/cacerts new file mode 100644 index 00000000..0cd28a92 Binary files /dev/null and b/datafile-app-server/config/cacerts differ diff --git a/datafile-app-server/config/datafile_endpoints.json b/datafile-app-server/config/datafile_endpoints.json index 5664bdeb..9da01d7b 100644 --- a/datafile-app-server/config/datafile_endpoints.json +++ b/datafile-app-server/config/datafile_endpoints.json @@ -6,8 +6,8 @@ "dmaapPortNumber": 2222, "dmaapTopicName": "/events/unauthenticated.VES_NOTIFICATION_OUTPUT", "dmaapProtocol": "http", - "dmaapUserName": "admin", - "dmaapUserPassword": "admin", + "dmaapUserName": "", + "dmaapUserPassword": "", "dmaapContentType": "application/json", "consumerId": "C12", "consumerGroup": "OpenDcae-c12", @@ -23,6 +23,15 @@ "dmaapUserPassword": "dradmin", "dmaapContentType": "application/octet-stream" } + }, + "ftp": { + "ftpesConfiguration": { + "keyCert": "config/ftpKey.jks", + "keyPassword": "secret", + "trustedCA": "config/cacerts", + "trustedCAPassword": "secret" + } } } } + diff --git a/datafile-app-server/config/ftpKey.jks b/datafile-app-server/config/ftpKey.jks new file mode 100644 index 00000000..2587b719 Binary files /dev/null and b/datafile-app-server/config/ftpKey.jks differ diff --git a/datafile-app-server/pom.xml b/datafile-app-server/pom.xml index 88a7a6d1..f5626af7 100644 --- a/datafile-app-server/pom.xml +++ b/datafile-app-server/pom.xml @@ -19,15 +19,17 @@ + 4.0.0 + org.onap.dcaegen2.collectors datafile 1.0.0-SNAPSHOT - 4.0.0 org.onap.dcaegen2.collectors.datafile datafile-app-server + 1.0.1-SNAPSHOT jar @@ -149,10 +151,6 @@ org.springframework.boot spring-boot-starter-webflux - - commons-net - commons-net - commons-io commons-io @@ -204,21 +202,6 @@ testng test - - org.mockftpserver - MockFtpServer - test - - - com.github.stefanbirkner - fake-sftp-server-rule - test - - - com.jcraft - jsch - 0.1.53 - diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/AppConfig.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/AppConfig.java index 245e0959..0df6b1d1 100644 --- a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/AppConfig.java +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/AppConfig.java @@ -91,6 +91,18 @@ public class AppConfig extends DatafileAppConfig { @Value("${dmaap.dmaapProducerConfiguration.dmaapContentType:}") public String producerDmaapContentType; + @Value("${ftp.ftpesConfiguration.keyCert:}") + public String keyCert; + + @Value("${ftp.ftpesConfiguration.keyPassword:}") + public String keyPassword; + + @Value("${ftp.ftpesConfiguration.trustedCA:}") + public String trustedCA; + + @Value("${ftp.ftpesConfiguration.trustedCAPassword:}") + public String trustedCAPassword; + @Override public DmaapConsumerConfiguration getDmaapConsumerConfiguration() { return new ImmutableDmaapConsumerConfiguration.Builder() @@ -154,4 +166,21 @@ public class AppConfig extends DatafileAppConfig { .build(); } + @Override + public FtpesConfig getFtpesConfiguration() { + return new ImmutableFtpesConfig.Builder() + .keyCert( + Optional.ofNullable(keyCert).filter(p -> !p.isEmpty()) + .orElse(ftpesConfig.keyCert())) + .keyPassword( + Optional.ofNullable(keyPassword).filter(p -> !p.isEmpty()) + .orElse(ftpesConfig.keyPassword())) + .trustedCA( + Optional.ofNullable(trustedCA).filter(p -> !p.isEmpty()) + .orElse(ftpesConfig.trustedCA())) + .trustedCAPassword( + Optional.ofNullable(trustedCAPassword).filter(p -> !p.isEmpty()) + .orElse(ftpesConfig.trustedCAPassword())) + .build(); + } } diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/CloudConfigParser.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/CloudConfigParser.java index 7570d704..03ef70ab 100644 --- a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/CloudConfigParser.java +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/CloudConfigParser.java @@ -19,6 +19,7 @@ package org.onap.dcaegen2.collectors.datafile.configuration; import com.google.gson.JsonObject; + import org.onap.dcaegen2.collectors.datafile.config.DmaapConsumerConfiguration; import org.onap.dcaegen2.collectors.datafile.config.DmaapPublisherConfiguration; import org.onap.dcaegen2.collectors.datafile.config.ImmutableDmaapConsumerConfiguration; @@ -62,4 +63,13 @@ public class CloudConfigParser { .consumerGroup(jsonObject.get("dmaap.dmaapConsumerConfiguration.consumerGroup").getAsString()) .build(); } + + public FtpesConfig getFtpesConfig() { + return new ImmutableFtpesConfig.Builder() + .keyCert(jsonObject.get("dmaap.ftpesConfig.keyCert").getAsString()) + .keyPassword(jsonObject.get("dmaap.ftpesConfig.keyPassword").getAsString()) + .trustedCA(jsonObject.get("dmaap.ftpesConfig.trustedCA").getAsString()) + .trustedCAPassword(jsonObject.get("dmaap.ftpesConfig.trustedCAPassword").getAsString()) + .build(); + } } \ No newline at end of file diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/Config.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/Config.java index 5ab4358a..7cd65ea2 100644 --- a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/Config.java +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/Config.java @@ -31,5 +31,8 @@ public interface Config { DmaapPublisherConfiguration getDmaapPublisherConfiguration(); + FtpesConfig getFtpesConfiguration(); + void initFileStreamReader(); + } diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/DatafileAppConfig.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/DatafileAppConfig.java index b6525f0f..66480792 100644 --- a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/DatafileAppConfig.java +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/DatafileAppConfig.java @@ -2,17 +2,15 @@ * ============LICENSE_START====================================================================== * Copyright (C) 2018 NOKIA Intellectual Property, 2018 Nordix Foundation. All rights reserved. * =============================================================================================== - * 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 + * 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 + * 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. + * 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. * ============LICENSE_END======================================================================== */ @@ -56,6 +54,9 @@ public abstract class DatafileAppConfig implements Config { private static final String DMAAP = "dmaap"; private static final String DMAAP_PRODUCER = "dmaapProducerConfiguration"; private static final String DMAAP_CONSUMER = "dmaapConsumerConfiguration"; + private static final String FTP = "ftp"; + private static final String FTPES_CONFIGURATION = "ftpesConfiguration"; + private static final Logger logger = LoggerFactory.getLogger(DatafileAppConfig.class); @@ -63,6 +64,8 @@ public abstract class DatafileAppConfig implements Config { DmaapPublisherConfiguration dmaapPublisherConfiguration; + FtpesConfig ftpesConfig; + @NotEmpty private String filepath; @@ -77,6 +80,11 @@ public abstract class DatafileAppConfig implements Config { return dmaapPublisherConfiguration; } + @Override + public FtpesConfig getFtpesConfiguration() { + return ftpesConfig; + } + @Override public void initFileStreamReader() { @@ -88,13 +96,16 @@ public abstract class DatafileAppConfig implements Config { JsonElement rootElement = getJsonElement(parser, inputStream); if (rootElement.isJsonObject()) { jsonObject = rootElement.getAsJsonObject(); + ftpesConfig = deserializeType(gsonBuilder, + jsonObject.getAsJsonObject(CONFIG).getAsJsonObject(FTP).getAsJsonObject(FTPES_CONFIGURATION), + FtpesConfig.class); dmaapConsumerConfiguration = deserializeType(gsonBuilder, - jsonObject.getAsJsonObject(CONFIG).getAsJsonObject(DMAAP).getAsJsonObject(DMAAP_CONSUMER), - DmaapConsumerConfiguration.class); + jsonObject.getAsJsonObject(CONFIG).getAsJsonObject(DMAAP).getAsJsonObject(DMAAP_CONSUMER), + DmaapConsumerConfiguration.class); dmaapPublisherConfiguration = deserializeType(gsonBuilder, - jsonObject.getAsJsonObject(CONFIG).getAsJsonObject(DMAAP).getAsJsonObject(DMAAP_PRODUCER), - DmaapPublisherConfiguration.class); + jsonObject.getAsJsonObject(CONFIG).getAsJsonObject(DMAAP).getAsJsonObject(DMAAP_PRODUCER), + DmaapPublisherConfiguration.class); } } catch (IOException e) { logger.error("Problem with file loading, file: {}", filepath, e); @@ -108,7 +119,7 @@ public abstract class DatafileAppConfig implements Config { } private T deserializeType(@NotNull GsonBuilder gsonBuilder, @NotNull JsonObject jsonObject, - @NotNull Class type) { + @NotNull Class type) { return gsonBuilder.create().fromJson(jsonObject, type); } @@ -124,4 +135,4 @@ public abstract class DatafileAppConfig implements Config { this.filepath = filepath; } -} \ No newline at end of file +} diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/FtpesConfig.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/FtpesConfig.java new file mode 100644 index 00000000..5861bf4e --- /dev/null +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/FtpesConfig.java @@ -0,0 +1,52 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2018 NOKIA Intellectual Property, 2018 Nordix Foundation. All rights reserved. + * ================================================================================ + * 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.collectors.datafile.configuration; + +/** + * @author + * + */ +import java.io.Serializable; + +import org.immutables.gson.Gson; +import org.immutables.value.Value; +import org.springframework.stereotype.Component; + + +@Component +@Value.Immutable +@Value.Style(builder = "new") +@Gson.TypeAdapters +public abstract class FtpesConfig implements Serializable { + + private static final long serialVersionUID = 1L; + + @Value.Parameter + public abstract String keyCert(); + + @Value.Parameter + public abstract String keyPassword(); + + @Value.Parameter + public abstract String trustedCA(); + + @Value.Parameter + public abstract String trustedCAPassword(); +} \ No newline at end of file diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/controllers/HeartbeatController.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/controllers/HeartbeatController.java index 98dfdedc..d6c535f0 100644 --- a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/controllers/HeartbeatController.java +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/controllers/HeartbeatController.java @@ -37,7 +37,7 @@ import reactor.core.publisher.Mono; * @author Henrik Andersson */ @RestController -@Api(value = "HeartbeatController", description = "Check liveness of DATAFILE service") +@Api(value = "HeartbeatController") public class HeartbeatController { private static final Logger logger = LoggerFactory.getLogger(HeartbeatController.class); diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/exceptions/DatafileTaskException.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/exceptions/DatafileTaskException.java index 2d62871c..7a047107 100644 --- a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/exceptions/DatafileTaskException.java +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/exceptions/DatafileTaskException.java @@ -23,6 +23,8 @@ package org.onap.dcaegen2.collectors.datafile.exceptions; */ public class DatafileTaskException extends Exception { + private static final long serialVersionUID = 1L; + public DatafileTaskException() { super(); } diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/exceptions/DmaapEmptyResponseException.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/exceptions/DmaapEmptyResponseException.java index cf387296..a1758ea5 100644 --- a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/exceptions/DmaapEmptyResponseException.java +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/exceptions/DmaapEmptyResponseException.java @@ -23,6 +23,8 @@ package org.onap.dcaegen2.collectors.datafile.exceptions; */ public class DmaapEmptyResponseException extends DatafileTaskException { + private static final long serialVersionUID = 1L; + public DmaapEmptyResponseException() { super(); } diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/exceptions/DmaapNotFoundException.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/exceptions/DmaapNotFoundException.java index e27a2036..401889f8 100644 --- a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/exceptions/DmaapNotFoundException.java +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/exceptions/DmaapNotFoundException.java @@ -23,6 +23,8 @@ package org.onap.dcaegen2.collectors.datafile.exceptions; */ public class DmaapNotFoundException extends DatafileTaskException { + private static final long serialVersionUID = 1L; + public DmaapNotFoundException(String message) { super(message); } diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/exceptions/EnvironmentLoaderException.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/exceptions/EnvironmentLoaderException.java index 75c2e8a8..ebfe1902 100644 --- a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/exceptions/EnvironmentLoaderException.java +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/exceptions/EnvironmentLoaderException.java @@ -23,6 +23,8 @@ package org.onap.dcaegen2.collectors.datafile.exceptions; */ public class EnvironmentLoaderException extends Exception { + private static final long serialVersionUID = 1L; + public EnvironmentLoaderException(String message) { super(message); } diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/ftp/FileServerData.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/ftp/FileServerData.java deleted file mode 100644 index d4eca4d7..00000000 --- a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/ftp/FileServerData.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * ============LICENSE_START====================================================================== - * Copyright (C) 2018 Nordix Foundation. All rights reserved. - * =============================================================================================== - * 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. - * ============LICENSE_END======================================================================== - */ - -package org.onap.dcaegen2.collectors.datafile.ftp; - -import org.immutables.value.Value; - -/** - * @author Henrik Andersson - * - */ -@Value.Immutable -public interface FileServerData { - public String serverAddress(); - public String userId(); - public String password(); - public int port(); -} diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/ftp/FtpsClient.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/ftp/FtpsClient.java deleted file mode 100644 index 89f5bbf2..00000000 --- a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/ftp/FtpsClient.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * ============LICENSE_START====================================================================== - * Copyright (C) 2018 Nordix Foundation. All rights reserved. - * =============================================================================================== - * 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. - * ============LICENSE_END======================================================================== - */ - -package org.onap.dcaegen2.collectors.datafile.ftp; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -import org.apache.commons.net.ftp.FTPReply; -import org.apache.commons.net.ftp.FTPSClient; -import org.apache.commons.net.util.TrustManagerUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -/** - * Gets file from xNF with FTPS protocol. - * - * TODO: Refactor for better test. - * - * @author Martin Yan - * - */ -@Component -public class FtpsClient { // TODO: Should be final but needs PowerMock or Mockito 2.x to be able to - // mock then, so this will be done as an improvement after first version - // committed. - private static final Logger logger = LoggerFactory.getLogger(FtpsClient.class); - - public boolean collectFile(FileServerData fileServerData, String remoteFile, String localFile) { - logger.trace("collectFile called with fileServerData: {}, remoteFile: {}, localFile: {}", fileServerData, - remoteFile, localFile); - boolean result = true; - try { - FTPSClient ftps = new FTPSClient("TLS"); - - result = setUpConnection(fileServerData, ftps); - - if (result) { - getFile(remoteFile, localFile, ftps); - - closeDownConnection(ftps); - } - } catch (IOException ex) { - logger.error("Unable to collect file from xNF. Data: {}", fileServerData, ex); - result = false; - } - logger.trace("collectFile left with result: {}", result); - return result; - } - - private boolean setUpConnection(FileServerData fileServerData, FTPSClient ftps) { - boolean success = true; - ftps.setTrustManager(TrustManagerUtils.getAcceptAllTrustManager()); - - try { - ftps.connect(fileServerData.serverAddress(), fileServerData.port()); - - if (!ftps.login(fileServerData.userId(), fileServerData.password())) { - ftps.logout(); - logger.error("Unable to log in to xNF. {}", fileServerData); - success = false; - } - - if (success) { - int reply = ftps.getReplyCode(); - if (!FTPReply.isPositiveCompletion(reply)) { - ftps.disconnect(); - logger.error("Unable to connect in to xNF. {}", fileServerData); - success = false; - } - ftps.enterLocalPassiveMode(); - } - } catch (Exception ex) { - logger.error("Unable to connect to xNF. Data: {}", fileServerData, ex); - success = false; - } - - return success; - } - - private void getFile(String remoteFile, String localFile, FTPSClient ftps) - throws IOException { - OutputStream output; - File outfile = new File(localFile); - outfile.createNewFile(); - - output = new FileOutputStream(outfile); - - ftps.retrieveFile(remoteFile, output); - - output.close(); - logger.debug("File {} Download Successfull from xNF", outfile.getName()); - } - - private void closeDownConnection(FTPSClient ftps) { - try { - ftps.logout(); - ftps.disconnect(); - } catch (Exception e) { - // Do nothing, file has been collected. - } - } -} diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/ftp/SftpClient.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/ftp/SftpClient.java deleted file mode 100644 index e7c7c09b..00000000 --- a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/ftp/SftpClient.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * ============LICENSE_START====================================================================== - * Copyright (C) 2018 Nordix Foundation. All rights reserved. - * =============================================================================================== - * 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. - * ============LICENSE_END======================================================================== - */ - -package org.onap.dcaegen2.collectors.datafile.ftp; - -import com.jcraft.jsch.Channel; -import com.jcraft.jsch.ChannelSftp; -import com.jcraft.jsch.JSch; -import com.jcraft.jsch.JSchException; -import com.jcraft.jsch.Session; -import com.jcraft.jsch.SftpException; - -import org.apache.commons.io.FilenameUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -/** - * Gets file from xNF with SFTP protocol. - * - * TODO: Refactor for better test. - * - * @author Martin Yan - * - */ -@Component -public class SftpClient { // TODO: Should be final but needs PowerMock to be able to mock then, so - // this will be done as an improvement after first version committed. - private static final Logger logger = LoggerFactory.getLogger(SftpClient.class); - - public boolean collectFile(FileServerData fileServerData, String remoteFile, String localFile) { - boolean result = true; - Session session = setUpSession(fileServerData); - - if (session != null) { - ChannelSftp sftpChannel = getChannel(session, fileServerData); - if (sftpChannel != null) { - try { - sftpChannel.get(remoteFile, localFile); - logger.debug("File " + FilenameUtils.getName(localFile) + " Download Successfull from xNF"); - } catch (SftpException e) { - logger.error("Unable to get file from xNF. " + fileServerData, e); - result = false; - } - - sftpChannel.exit(); - } else { - result = false; - } - session.disconnect(); - } else { - result = false; - } - return result; - } - - private Session setUpSession(FileServerData fileServerData) { - JSch jsch = new JSch(); // TODO: Might be changed to use Spring as an improvement after - // first version committed. - - Session session = null; - try { - session = jsch.getSession(fileServerData.userId(), fileServerData.serverAddress(), fileServerData.port()); - session.setConfig("StrictHostKeyChecking", "no"); - session.setPassword(fileServerData.password()); - session.connect(); - } catch (JSchException e) { - logger.error("Unable to set up SFTP connection to xNF. " + fileServerData, e); - } - return session; - } - - private ChannelSftp getChannel(Session session, FileServerData fileServerData) { - ChannelSftp sftpChannel = null; - try { - Channel channel; - channel = session.openChannel("sftp"); - channel.connect(); - sftpChannel = (ChannelSftp) channel; - } catch (JSchException e) { - logger.error("Unable to get sftp channel to xNF. " + fileServerData, e); - } - return sftpChannel; - } -} diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/service/DmaapConsumerJsonParser.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/service/DmaapConsumerJsonParser.java index 619ccc11..cfd06db3 100644 --- a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/service/DmaapConsumerJsonParser.java +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/service/DmaapConsumerJsonParser.java @@ -44,7 +44,6 @@ import reactor.core.publisher.Mono; * @author Henrik Andersson */ public class DmaapConsumerJsonParser { - private static final Logger logger = LoggerFactory.getLogger(DmaapConsumerJsonParser.class); private static final String EVENT = "event"; @@ -72,6 +71,7 @@ public class DmaapConsumerJsonParser { } private Mono getJsonParserMessage(String message) { + logger.trace("original message from message router: {}", message); return StringUtils.isEmpty(message) ? Mono.error(new DmaapEmptyResponseException()) : Mono.fromSupplier(() -> new JsonParser().parse(message)); } @@ -87,6 +87,8 @@ public class DmaapConsumerJsonParser { } public Optional getJsonObjectFromAnArray(JsonElement element) { + logger.trace("starting to getJsonObjectFromAnArray!"); + return Optional.of(new JsonParser().parse(element.getAsString()).getAsJsonObject()); } @@ -103,7 +105,6 @@ public class DmaapConsumerJsonParser { String changeType = getValueFromJson(notificationFields, CHANGE_TYPE); String notificationFieldsVersion = getValueFromJson(notificationFields, NOTIFICATION_FIELDS_VERSION); JsonArray arrayOfNamedHashMap = notificationFields.getAsJsonArray(ARRAY_OF_NAMED_HASH_MAP); - if (isNotificationFieldsHeaderNotEmpty(changeIdentifier, changeType, notificationFieldsVersion) && arrayOfNamedHashMap != null) { return getAllFileDataFromJson(changeIdentifier, changeType, arrayOfNamedHashMap); @@ -121,7 +122,6 @@ public class DmaapConsumerJsonParser { } return Flux.error( new DmaapNotFoundException("FileReady event has incorrect JsonObject - missing header. " + jsonObject)); - } private Flux getAllFileDataFromJson(String changeIdentifier, String changeType, @@ -143,6 +143,8 @@ public class DmaapConsumerJsonParser { } private FileData getFileDataFromJson(JsonObject fileInfo, String changeIdentifier, String changeType) { + logger.trace("starting to getFileDataFromJson!"); + FileData fileData = null; String name = getValueFromJson(fileInfo, NAME); diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/DmaapConsumerTaskImpl.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/DmaapConsumerTaskImpl.java index 7ec474ca..f80db897 100644 --- a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/DmaapConsumerTaskImpl.java +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/DmaapConsumerTaskImpl.java @@ -59,7 +59,7 @@ public class DmaapConsumerTaskImpl extends DmaapConsumerTask { @Override Flux consume(Mono message) { - logger.trace("consume called with arg {}", message.toString()); + logger.trace("consume called with arg {}", message); return dmaapConsumerJsonParser.getJsonObject(message); } diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/XnfCollectorTask.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/XnfCollectorTask.java index 66d59ae8..b98d40d3 100644 --- a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/XnfCollectorTask.java +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/XnfCollectorTask.java @@ -18,6 +18,7 @@ package org.onap.dcaegen2.collectors.datafile.tasks; +import org.onap.dcaegen2.collectors.datafile.configuration.FtpesConfig; import org.onap.dcaegen2.collectors.datafile.model.ConsumerDmaapModel; import org.onap.dcaegen2.collectors.datafile.model.FileData; @@ -27,5 +28,6 @@ import reactor.core.publisher.Flux; * @author Henrik Andersson */ public interface XnfCollectorTask { + abstract FtpesConfig resolveConfiguration(); Flux execute(FileData fileData); } diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/XnfCollectorTaskImpl.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/XnfCollectorTaskImpl.java index a29fb092..be6ac9cc 100644 --- a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/XnfCollectorTaskImpl.java +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/XnfCollectorTaskImpl.java @@ -19,6 +19,9 @@ package org.onap.dcaegen2.collectors.datafile.tasks; import java.io.File; import java.net.URI; +import org.onap.dcaegen2.collectors.datafile.configuration.AppConfig; +import org.onap.dcaegen2.collectors.datafile.configuration.Config; +import org.onap.dcaegen2.collectors.datafile.configuration.FtpesConfig; import org.onap.dcaegen2.collectors.datafile.ftp.FileServerData; import org.onap.dcaegen2.collectors.datafile.ftp.FtpsClient; import org.onap.dcaegen2.collectors.datafile.ftp.ImmutableFileServerData; @@ -44,12 +47,14 @@ public class XnfCollectorTaskImpl implements XnfCollectorTask { private static final String SFTP = "sftp"; private static final Logger logger = LoggerFactory.getLogger(XnfCollectorTaskImpl.class); + private Config datafileAppConfig; private final FtpsClient ftpsClient; private final SftpClient sftpClient; @Autowired - protected XnfCollectorTaskImpl(FtpsClient ftpsCleint, SftpClient sftpClient) { + protected XnfCollectorTaskImpl(AppConfig datafileAppConfig, FtpsClient ftpsCleint, SftpClient sftpClient) { + this.datafileAppConfig = datafileAppConfig; this.ftpsClient = ftpsCleint; this.sftpClient = sftpClient; } @@ -57,6 +62,8 @@ public class XnfCollectorTaskImpl implements XnfCollectorTask { @Override public Flux execute(FileData fileData) { logger.trace("Entering execute with {}", fileData); + resolveKeyStore(); + String localFile = collectFile(fileData); if (localFile != null) { @@ -68,17 +75,27 @@ public class XnfCollectorTaskImpl implements XnfCollectorTask { return Flux.empty(); } + @Override + public FtpesConfig resolveConfiguration() { + return datafileAppConfig.getFtpesConfiguration(); + } + + private void resolveKeyStore() { + FtpesConfig ftpesConfig = resolveConfiguration(); + ftpsClient.setKeyCertPath(ftpesConfig.keyCert()); + ftpsClient.setKeyCertPassword(ftpesConfig.keyPassword()); + ftpsClient.setTrustedCAPath(ftpesConfig.trustedCA()); + ftpsClient.setTrustedCAPassword(ftpesConfig.trustedCAPassword()); + } + private String collectFile(FileData fileData) { + logger.trace("starting to collectFile"); String location = fileData.location(); URI uri = URI.create(location); - String[] userInfo = getUserNameAndPasswordIfGiven(uri.getUserInfo()); - FileServerData fileServerData = ImmutableFileServerData.builder().serverAddress(uri.getHost()) - .userId(userInfo != null ? userInfo[0] : "").password(userInfo != null ? userInfo[1] : "") - .port(uri.getPort()).build(); + FileServerData fileServerData = getFileServerData(uri); String remoteFile = uri.getPath(); String localFile = "target" + File.separator + fileData.name(); String scheme = uri.getScheme(); - boolean fileDownloaded = false; if (FTPES.equals(scheme) || FTPS.equals(scheme)) { fileDownloaded = ftpsClient.collectFile(fileServerData, remoteFile, localFile); @@ -96,6 +113,13 @@ public class XnfCollectorTaskImpl implements XnfCollectorTask { return localFile; } + private FileServerData getFileServerData(URI uri) { + String[] userInfo = getUserNameAndPasswordIfGiven(uri.getUserInfo()); + return ImmutableFileServerData.builder().serverAddress(uri.getHost()) + .userId(userInfo != null ? userInfo[0] : "").password(userInfo != null ? userInfo[1] : "") + .port(uri.getPort()).build(); + } + private String[] getUserNameAndPasswordIfGiven(String userInfoString) { String[] userInfo = null; if (userInfoString != null && !userInfoString.isEmpty()) { diff --git a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/configuration/CloudConfigParserTest.java b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/configuration/CloudConfigParserTest.java index 60968c05..119224b4 100644 --- a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/configuration/CloudConfigParserTest.java +++ b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/configuration/CloudConfigParserTest.java @@ -1,28 +1,25 @@ /* - * ============LICENSE_START======================================================= - * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. - * ================================================================================ - * 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 + * ============LICENSE_START====================================================================== + * Copyright (C) 2018 NOKIA Intellectual Property, 2018 Nordix Foundation. All rights reserved. + * =============================================================================================== + * 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 + * 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. - * ============LICENSE_END========================================================= + * 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. + * ============LICENSE_END======================================================================== */ package org.onap.dcaegen2.collectors.datafile.configuration; - import static org.assertj.core.api.Assertions.assertThat; -import com.google.gson.Gson; import com.google.gson.JsonObject; + import org.junit.jupiter.api.Test; import org.onap.dcaegen2.collectors.datafile.config.DmaapConsumerConfiguration; import org.onap.dcaegen2.collectors.datafile.config.DmaapPublisherConfiguration; @@ -31,74 +28,74 @@ import org.onap.dcaegen2.collectors.datafile.config.ImmutableDmaapPublisherConfi class CloudConfigParserTest { - private static final String CORRECT_JSON = - "{\"dmaap.dmaapProducerConfiguration.dmaapTopicName\": \"/events/unauthenticated.VES_NOTIFICATION_OUTPUT\", " - + "\"dmaap.dmaapConsumerConfiguration.timeoutMS\": -1," - + " \"dmaap.dmaapConsumerConfiguration.dmaapHostName\": \"message-router.onap.svc.cluster.local\"," - + "\"dmaap.dmaapConsumerConfiguration.dmaapUserName\": \"admin\", " - + "\"dmaap.dmaapProducerConfiguration.dmaapPortNumber\": 3904, " - + "\"dmaap.dmaapConsumerConfiguration.dmaapUserPassword\": \"admin\", " - + "\"dmaap.dmaapProducerConfiguration.dmaapProtocol\": \"http\", " - + "\"dmaap.dmaapProducerConfiguration.dmaapContentType\": \"application/json\", " - + "\"dmaap.dmaapConsumerConfiguration.dmaapTopicName\": \"/events/unauthenticated.VES_NOTIFICATION_OUTPUT\", " - + "\"dmaap.dmaapConsumerConfiguration.dmaapPortNumber\": 3904, " - + "\"dmaap.dmaapConsumerConfiguration.dmaapContentType\": \"application/json\", " - + "\"dmaap.dmaapConsumerConfiguration.messageLimit\": -1, " - + "\"dmaap.dmaapConsumerConfiguration.dmaapProtocol\": \"http\", " - + "\"dmaap.dmaapConsumerConfiguration.consumerId\": \"c12\"," - + "\"dmaap.dmaapProducerConfiguration.dmaapHostName\": \"message-router.onap.svc.cluster.local\", " - + "\"dmaap.dmaapConsumerConfiguration.consumerGroup\": \"OpenDCAE-c12\", " - + "\"dmaap.dmaapProducerConfiguration.dmaapUserName\": \"admin\", " - + "\"dmaap.dmaapProducerConfiguration.dmaapUserPassword\": \"admin\"}"; - - private static final ImmutableDmaapConsumerConfiguration correctDmaapConsumerConfig = - new ImmutableDmaapConsumerConfiguration.Builder() - .timeoutMS(-1) - .dmaapHostName("message-router.onap.svc.cluster.local") - .dmaapUserName("admin") - .dmaapUserPassword("admin") - .dmaapTopicName("/events/unauthenticated.VES_NOTIFICATION_OUTPUT") - .dmaapPortNumber(3904) - .dmaapContentType("application/json") - .messageLimit(-1) - .dmaapProtocol("http") - .consumerId("c12") - .consumerGroup("OpenDCAE-c12") - .build(); - - private static final ImmutableDmaapPublisherConfiguration correctDmaapPublisherConfig = - new ImmutableDmaapPublisherConfiguration.Builder() - .dmaapTopicName("/events/unauthenticated.VES_NOTIFICATION_OUTPUT") - .dmaapUserPassword("admin") - .dmaapPortNumber(3904) - .dmaapProtocol("http") - .dmaapContentType("application/json") - .dmaapHostName("message-router.onap.svc.cluster.local") - .dmaapUserName("admin") - .build(); - - private CloudConfigParser cloudConfigParser = new CloudConfigParser( - new Gson().fromJson(CORRECT_JSON, JsonObject.class)); + private static final ImmutableDmaapConsumerConfiguration CORRECT_DMAAP_CONSUMER_CONFIG = + new ImmutableDmaapConsumerConfiguration.Builder().timeoutMS(-1) + .dmaapHostName("message-router.onap.svc.cluster.local").dmaapUserName("admin") + .dmaapUserPassword("admin").dmaapTopicName("/events/unauthenticated.VES_NOTIFICATION_OUTPUT") + .dmaapPortNumber(2222).dmaapContentType("application/json").messageLimit(-1).dmaapProtocol("http") + .consumerId("C12").consumerGroup("OpenDCAE-c12").build(); + + private static final ImmutableDmaapPublisherConfiguration CORRECT_DMAAP_PUBLISHER_CONFIG = + new ImmutableDmaapPublisherConfiguration.Builder().dmaapTopicName("publish").dmaapUserPassword("dradmin") + .dmaapPortNumber(3907).dmaapProtocol("https").dmaapContentType("application/json") + .dmaapHostName("message-router.onap.svc.cluster.local").dmaapUserName("dradmin").build(); + private static final ImmutableFtpesConfig CORRECT_FTPES_CONFIGURATION = + new ImmutableFtpesConfig.Builder().keyCert("/config/ftpKey.jks").keyPassword("secret") + .trustedCA("config/cacerts").trustedCAPassword("secret").build(); + + private CloudConfigParser cloudConfigParser = new CloudConfigParser(getCloudConfigJsonObject()); @Test public void shouldCreateDmaapConsumerConfigurationCorrectly() { - // when DmaapConsumerConfiguration dmaapConsumerConfig = cloudConfigParser.getDmaapConsumerConfig(); - // then assertThat(dmaapConsumerConfig).isNotNull(); - assertThat(dmaapConsumerConfig).isEqualToComparingFieldByField(correctDmaapConsumerConfig); + assertThat(dmaapConsumerConfig).isEqualToComparingFieldByField(CORRECT_DMAAP_CONSUMER_CONFIG); } - @Test public void shouldCreateDmaapPublisherConfigurationCorrectly() { - // when DmaapPublisherConfiguration dmaapPublisherConfig = cloudConfigParser.getDmaapPublisherConfig(); - // then assertThat(dmaapPublisherConfig).isNotNull(); - assertThat(dmaapPublisherConfig).isEqualToComparingFieldByField(correctDmaapPublisherConfig); + assertThat(dmaapPublisherConfig).isEqualToComparingFieldByField(CORRECT_DMAAP_PUBLISHER_CONFIG); + } + + @Test + public void shouldCreateFtpesConfigurationCorrectly() { + FtpesConfig ftpesConfig = cloudConfigParser.getFtpesConfig(); + + assertThat(ftpesConfig).isNotNull(); + assertThat(ftpesConfig).isEqualToComparingFieldByField(CORRECT_FTPES_CONFIGURATION); + } + + public JsonObject getCloudConfigJsonObject() { + JsonObject config = new JsonObject(); + config.addProperty("dmaap.dmaapConsumerConfiguration.timeoutMS", -1); + config.addProperty("dmaap.dmaapConsumerConfiguration.dmaapHostName", "message-router.onap.svc.cluster.local"); + config.addProperty("dmaap.dmaapConsumerConfiguration.dmaapUserName", "admin"); + config.addProperty("dmaap.dmaapConsumerConfiguration.dmaapUserPassword", "admin"); + config.addProperty("dmaap.dmaapConsumerConfiguration.dmaapTopicName", + "/events/unauthenticated.VES_NOTIFICATION_OUTPUT"); + config.addProperty("dmaap.dmaapConsumerConfiguration.dmaapPortNumber", 2222); + config.addProperty("dmaap.dmaapConsumerConfiguration.dmaapContentType", "application/json"); + config.addProperty("dmaap.dmaapConsumerConfiguration.messageLimit", -1); + config.addProperty("dmaap.dmaapConsumerConfiguration.dmaapProtocol", "http"); + config.addProperty("dmaap.dmaapConsumerConfiguration.consumerId", "C12"); + config.addProperty("dmaap.dmaapConsumerConfiguration.consumerGroup", "OpenDCAE-c12"); + config.addProperty("dmaap.dmaapProducerConfiguration.dmaapTopicName", "publish"); + config.addProperty("dmaap.dmaapProducerConfiguration.dmaapProtocol", "https"); + config.addProperty("dmaap.dmaapProducerConfiguration.dmaapContentType", "application/json"); + config.addProperty("dmaap.dmaapProducerConfiguration.dmaapHostName", "message-router.onap.svc.cluster.local"); + config.addProperty("dmaap.dmaapProducerConfiguration.dmaapPortNumber", 3907); + config.addProperty("dmaap.dmaapProducerConfiguration.dmaapUserName", "dradmin"); + config.addProperty("dmaap.dmaapProducerConfiguration.dmaapUserPassword", "dradmin"); + config.addProperty("dmaap.ftpesConfig.keyCert", "/config/ftpKey.jks"); + config.addProperty("dmaap.ftpesConfig.keyPassword", "secret"); + config.addProperty("dmaap.ftpesConfig.trustedCA", "config/cacerts"); + config.addProperty("dmaap.ftpesConfig.trustedCAPassword", "secret"); + + return config; } -} \ No newline at end of file +} diff --git a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/configuration/DatafileAppConfigTest.java b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/configuration/DatafileAppConfigTest.java index 12c8c7e7..1238a472 100644 --- a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/configuration/DatafileAppConfigTest.java +++ b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/configuration/DatafileAppConfigTest.java @@ -26,6 +26,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import com.google.gson.JsonElement; +import com.google.gson.JsonObject; import com.google.gson.JsonParser; import java.io.ByteArrayInputStream; @@ -48,23 +49,8 @@ import org.onap.dcaegen2.collectors.datafile.integration.junit5.mockito.MockitoE class DatafileAppConfigTest { private static final String DATAFILE_ENDPOINTS = "datafile_endpoints.json"; - private static final String JSON_STRING = - "{\"configs\":{\"dmaap\":{\"dmaapConsumerConfiguration\":{\"consumerGroup\":\"other\",\"consumerId\":\"1\"," - + "\"dmaapContentType\":\"application/json\",\"dmaapHostName\":\"localhost\"," - + "\"dmaapPortNumber\":2222,\"dmaapProtocol\":\"http\",\"dmaapTopicName\":\"temp\"," - + "\"dmaapUserName\":\"admin\",\"dmaapUserPassword\":\"admin\",\"messageLimit\":1000," - + "\"timeoutMS\":1000},\"dmaapProducerConfiguration\":{\"dmaapContentType\":\"application/json\"," - + "\"dmaapHostName\":\"localhost\",\"dmaapPortNumber\":2223,\"dmaapProtocol\":\"http\"," - + "\"dmaapTopicName\":\"temp\",\"dmaapUserName\":\"admin\",\"dmaapUserPassword\":\"admin\"}}}}"; - private static final String INCORRECT_JSON_STRING = - "{\"configs\":{\"dmaap\":{\"dmaapConsumerConfiguration\":{\"consumerGroup\":\"other\",\"consumerId\":\"1\"," - + "\"dmaapContentType\":\"application/json\",\"dmaapHostName\":\"localhost\"," - + "\"dmaapPortNumber\":2222,\"dmaapProtocol\":\"http\",\"dmaapTopicName\":\"temp\"," - + "\"dmaapUserName\":\"admin\",\"dmaapUserPassword\":\"admin\",\"messageLimit\":1000," - + "\"timeoutMS\":1000},\"dmaapProducerConfiguration\":{\"dmaapContentType\":\"application/json\"," - + "\"dmaapHostName\":\"localhost\",\"dmaapPortNumber\":2223,\"dmaapProtocol\":\"http\"," - + "\"FAULTY_PARAMETER_NAME\":\"temp\"," - + "\"dmaapUserName\":\"admin\",\"dmaapUserPassword\":\"admin\"}}}}"; + private static final boolean CORRECT_JSON = true; + private static final boolean INCORRECT_JSON = false; private static DatafileAppConfig datafileAppConfig; private static AppConfig appConfig; @@ -90,9 +76,10 @@ class DatafileAppConfigTest { } @Test - public void whenTheConfigurationFits_GetAaiAndDmaapObjectRepresentationConfiguration() throws IOException { + public void whenTheConfigurationFits_GetFtpsAndDmaapObjectRepresentationConfiguration() throws IOException { // Given - InputStream inputStream = new ByteArrayInputStream((JSON_STRING.getBytes(StandardCharsets.UTF_8))); + InputStream inputStream = + new ByteArrayInputStream((getJsonConfig(CORRECT_JSON).getBytes(StandardCharsets.UTF_8))); // When datafileAppConfig.setFilepath(filePath); @@ -100,6 +87,7 @@ class DatafileAppConfigTest { datafileAppConfig.initFileStreamReader(); appConfig.dmaapConsumerConfiguration = datafileAppConfig.getDmaapConsumerConfiguration(); appConfig.dmaapPublisherConfiguration = datafileAppConfig.getDmaapPublisherConfiguration(); + appConfig.ftpesConfig = datafileAppConfig.getFtpesConfiguration(); // Then verify(datafileAppConfig, times(1)).setFilepath(anyString()); @@ -110,6 +98,7 @@ class DatafileAppConfigTest { datafileAppConfig.getDmaapPublisherConfiguration()); Assertions.assertEquals(appConfig.getDmaapConsumerConfiguration(), datafileAppConfig.getDmaapConsumerConfiguration()); + Assertions.assertEquals(appConfig.getFtpesConfiguration(), datafileAppConfig.getFtpesConfiguration()); } @@ -127,13 +116,15 @@ class DatafileAppConfigTest { verify(datafileAppConfig, times(1)).initFileStreamReader(); Assertions.assertNull(datafileAppConfig.getDmaapConsumerConfiguration()); Assertions.assertNull(datafileAppConfig.getDmaapPublisherConfiguration()); + Assertions.assertNull(datafileAppConfig.getFtpesConfiguration()); } @Test public void whenFileIsExistsButJsonIsIncorrect() throws IOException { // Given - InputStream inputStream = new ByteArrayInputStream((INCORRECT_JSON_STRING.getBytes(StandardCharsets.UTF_8))); + InputStream inputStream = + new ByteArrayInputStream((getJsonConfig(INCORRECT_JSON).getBytes(StandardCharsets.UTF_8))); // When datafileAppConfig.setFilepath(filePath); @@ -145,6 +136,7 @@ class DatafileAppConfigTest { verify(datafileAppConfig, times(1)).initFileStreamReader(); Assertions.assertNotNull(datafileAppConfig.getDmaapConsumerConfiguration()); Assertions.assertNull(datafileAppConfig.getDmaapPublisherConfiguration()); + Assertions.assertNotNull(datafileAppConfig.getFtpesConfiguration()); } @@ -152,7 +144,8 @@ class DatafileAppConfigTest { @Test public void whenTheConfigurationFits_ButRootElementIsNotAJsonObject() throws IOException { // Given - InputStream inputStream = new ByteArrayInputStream((JSON_STRING.getBytes(StandardCharsets.UTF_8))); + InputStream inputStream = + new ByteArrayInputStream((getJsonConfig(CORRECT_JSON).getBytes(StandardCharsets.UTF_8))); // When datafileAppConfig.setFilepath(filePath); doReturn(inputStream).when(datafileAppConfig).getInputStream(any()); @@ -162,11 +155,61 @@ class DatafileAppConfigTest { datafileAppConfig.initFileStreamReader(); appConfig.dmaapConsumerConfiguration = datafileAppConfig.getDmaapConsumerConfiguration(); appConfig.dmaapPublisherConfiguration = datafileAppConfig.getDmaapPublisherConfiguration(); + appConfig.ftpesConfig = datafileAppConfig.getFtpesConfiguration(); // Then verify(datafileAppConfig, times(1)).setFilepath(anyString()); verify(datafileAppConfig, times(1)).initFileStreamReader(); Assertions.assertNull(datafileAppConfig.getDmaapConsumerConfiguration()); Assertions.assertNull(datafileAppConfig.getDmaapPublisherConfiguration()); + Assertions.assertNull(datafileAppConfig.getFtpesConfiguration()); + } + + private String getJsonConfig(boolean correct) { + JsonObject dmaapConsumerConfigData = new JsonObject(); + dmaapConsumerConfigData.addProperty("dmaapHostName", "localhost"); + dmaapConsumerConfigData.addProperty("dmaapPortNumber", 2222); + dmaapConsumerConfigData.addProperty("dmaapTopicName", "/events/unauthenticated.VES_NOTIFICATION_OUTPUT"); + dmaapConsumerConfigData.addProperty("dmaapProtocol", "http"); + dmaapConsumerConfigData.addProperty("dmaapUserName", "admin"); + dmaapConsumerConfigData.addProperty("dmaapUserPassword", "admin"); + dmaapConsumerConfigData.addProperty("dmaapContentType", "application/json"); + dmaapConsumerConfigData.addProperty("consumerId", "C12"); + dmaapConsumerConfigData.addProperty("consumerGroup", "OpenDcae-c12"); + dmaapConsumerConfigData.addProperty("timeoutMS", -1); + dmaapConsumerConfigData.addProperty("messageLimit", 1); + + JsonObject dmaapProducerConfigData = new JsonObject(); + dmaapProducerConfigData.addProperty("dmaapHostName", "localhost"); + dmaapProducerConfigData.addProperty("dmaapPortNumber", 3907); + dmaapProducerConfigData.addProperty("dmaapTopicName", "publish"); + dmaapProducerConfigData.addProperty("dmaapProtocol", "https"); + if (correct) { + dmaapProducerConfigData.addProperty("dmaapUserName", "dradmin"); + dmaapProducerConfigData.addProperty("dmaapUserPassword", "dradmin"); + dmaapProducerConfigData.addProperty("dmaapContentType", "application/octet-stream"); + } + + JsonObject dmaapConfigs = new JsonObject(); + dmaapConfigs.add("dmaapConsumerConfiguration", dmaapConsumerConfigData); + dmaapConfigs.add("dmaapProducerConfiguration", dmaapProducerConfigData); + + JsonObject ftpesConfigData = new JsonObject(); + ftpesConfigData.addProperty("keyCert", "config/ftpKey.jks"); + ftpesConfigData.addProperty("keyPassword", "secret"); + ftpesConfigData.addProperty("trustedCA", "config/cacerts"); + ftpesConfigData.addProperty("trustedCAPassword", "secret"); + + JsonObject ftpesConfiguration = new JsonObject(); + ftpesConfiguration.add("ftpesConfiguration", ftpesConfigData); + + JsonObject configs = new JsonObject(); + configs.add("dmaap", dmaapConfigs); + configs.add("ftp", ftpesConfiguration); + + JsonObject completeJson = new JsonObject(); + completeJson.add("configs", configs); + + return completeJson.toString(); } } diff --git a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/ftp/FtpClientTest.java b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/ftp/FtpClientTest.java deleted file mode 100644 index a95b80ed..00000000 --- a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/ftp/FtpClientTest.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * ============LICENSE_START====================================================================== - * Copyright (C) 2018 Nordix Foundation. All rights reserved. - * =============================================================================================== - * 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. - * ============LICENSE_END======================================================================== - */ - -package org.onap.dcaegen2.collectors.datafile.ftp; - -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.mockftpserver.fake.FakeFtpServer; -import org.mockftpserver.fake.UserAccount; -import org.mockftpserver.fake.filesystem.FileEntry; -import org.mockftpserver.fake.filesystem.FileSystem; -import org.mockftpserver.fake.filesystem.UnixFakeFileSystem; - -public class FtpClientTest { - - private static final String HOME_DIR = "/"; - private static final String FILE = "/dir/sample.txt"; - private static final String CONTENTS = "abcdef 1234567890"; - private static final int PORT = 8021; - - private static final String USERNAME = "bob"; - private static final String PASSWORD = "123"; - - private FakeFtpServer fakeFtpServer; - - @BeforeAll - protected void setUp() throws Exception { - fakeFtpServer = new FakeFtpServer(); - fakeFtpServer.setServerControlPort(PORT); - - FileSystem fileSystem = new UnixFakeFileSystem(); - fileSystem.add(new FileEntry(FILE, CONTENTS)); - fakeFtpServer.setFileSystem(fileSystem); - UserAccount userAccount = new UserAccount(USERNAME, PASSWORD, HOME_DIR); - fakeFtpServer.addUserAccount(userAccount); - - fakeFtpServer.start(); - } - - @AfterAll - protected void tearDown() throws Exception { - fakeFtpServer.stop(); - } -} diff --git a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/ftp/SftpClientTest.java b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/ftp/SftpClientTest.java deleted file mode 100644 index 13f1fbb9..00000000 --- a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/ftp/SftpClientTest.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * ============LICENSE_START====================================================================== - * Copyright (C) 2018 Nordix Foundation. All rights reserved. - * =============================================================================================== - * 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. - * ============LICENSE_END======================================================================== - */ - -package org.onap.dcaegen2.collectors.datafile.ftp; - -import static java.nio.charset.StandardCharsets.UTF_8; -import static org.apache.commons.io.IOUtils.toByteArray; -import static org.assertj.core.api.Assertions.assertThat; - -import com.github.stefanbirkner.fakesftpserver.rule.FakeSftpServerRule; -import com.jcraft.jsch.ChannelSftp; -import com.jcraft.jsch.JSch; -import com.jcraft.jsch.JSchException; -import com.jcraft.jsch.Session; -import com.jcraft.jsch.SftpException; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; - -import org.junit.Rule; -import org.junit.Test; - -public class SftpClientTest { - private static final String USERNAME = "bob"; - private static final String PASSWORD = "123"; - private static final String DUMMY_CONTENT = "dummy content"; - private static final String LOCAL_DUMMY_FILE = "target/dummy.txt"; - private static final String REMOTE_DUMMY_FILE = "/dummy_directory/dummy_file.txt"; - private static final JSch JSCH = new JSch(); - private static final int TIMEOUT = 2000; - - @Rule - public final FakeSftpServerRule sftpServer = new FakeSftpServerRule().addUser(USERNAME, PASSWORD); - - @Test - public void collectFile_withOKresponse() throws IOException, JSchException, SftpException { - SftpClient sftpClient = new SftpClient(); - sftpServer.putFile(REMOTE_DUMMY_FILE, DUMMY_CONTENT, UTF_8); - byte[] file = downloadFile(sftpServer, REMOTE_DUMMY_FILE); - FileServerData expectedFileServerData = ImmutableFileServerData.builder().serverAddress("127.0.0.1") - .userId(USERNAME).password(PASSWORD).port(sftpServer.getPort()).build(); - sftpClient.collectFile(expectedFileServerData, REMOTE_DUMMY_FILE, - LOCAL_DUMMY_FILE); - byte[] localFile = Files.readAllBytes(new File(LOCAL_DUMMY_FILE).toPath()); - assertThat(new String(file, UTF_8)).isEqualTo(DUMMY_CONTENT); - assertThat(new String(localFile, UTF_8)).isEqualTo(DUMMY_CONTENT); - } - - private static Session connectToServer(FakeSftpServerRule sftpServer) throws JSchException { - return connectToServerAtPort(sftpServer.getPort()); - } - - private static Session connectToServerAtPort(int port) throws JSchException { - Session session = createSessionWithCredentials(USERNAME, PASSWORD, port); - session.connect(TIMEOUT); - return session; - } - - private static ChannelSftp connectSftpChannel(Session session) throws JSchException { - ChannelSftp channel = (ChannelSftp) session.openChannel("sftp"); - channel.connect(); - return channel; - } - - private static Session createSessionWithCredentials(String username, String password, int port) - throws JSchException { - Session session = JSCH.getSession(username, "127.0.0.1", port); - session.setConfig("StrictHostKeyChecking", "no"); - session.setPassword(password); - return session; - } - - private static byte[] downloadFile(FakeSftpServerRule server, String path) - throws JSchException, SftpException, IOException { - Session session = connectToServer(server); - ChannelSftp channel = connectSftpChannel(session); - try { - InputStream is = channel.get(path); - return toByteArray(is); - } finally { - channel.disconnect(); - session.disconnect(); - } - } - -} diff --git a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/XnfCollectorTaskImplTest.java b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/XnfCollectorTaskImplTest.java index 528a481c..3a3f16c0 100644 --- a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/XnfCollectorTaskImplTest.java +++ b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/XnfCollectorTaskImplTest.java @@ -24,7 +24,10 @@ import static org.mockito.Mockito.when; import java.io.File; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import org.onap.dcaegen2.collectors.datafile.configuration.AppConfig; +import org.onap.dcaegen2.collectors.datafile.configuration.FtpesConfig; import org.onap.dcaegen2.collectors.datafile.ftp.FileServerData; import org.onap.dcaegen2.collectors.datafile.ftp.FtpsClient; import org.onap.dcaegen2.collectors.datafile.ftp.ImmutableFileServerData; @@ -60,14 +63,31 @@ public class XnfCollectorTaskImplTest { private static final String MEAS_COLLECT_FILE_FORMAT_TYPE = "org.3GPP.32.435#measCollec"; private static final String FILE_FORMAT_VERSION = "V10"; + private static final String FTP_KEY_PATH = "ftpKeyPath"; + private static final String FTP_KEY_PASSWORD = "ftpKeyPassword"; + private static final String TRUSTED_CA_PATH = "trustedCAPath"; + private static final String TRUSTED_CA_PASSWORD = "trustedCAPassword"; + + private static AppConfig appConfigMock = mock(AppConfig.class); + private static FtpesConfig ftpesConfigMock = mock(FtpesConfig.class); + private FtpsClient ftpsClientMock = mock(FtpsClient.class); private SftpClient sftpClientMock = mock(SftpClient.class); - private XnfCollectorTask collectorUndetTest = new XnfCollectorTaskImpl(ftpsClientMock, sftpClientMock); + private XnfCollectorTask collectorUndetTest = new XnfCollectorTaskImpl(appConfigMock, ftpsClientMock, sftpClientMock); + + @BeforeAll + public static void setUpConfiguration() { + when(appConfigMock.getFtpesConfiguration()).thenReturn(ftpesConfigMock); + when(ftpesConfigMock.keyCert()).thenReturn(FTP_KEY_PATH); + when(ftpesConfigMock.keyPassword()).thenReturn(FTP_KEY_PASSWORD); + when(ftpesConfigMock.trustedCA()).thenReturn(TRUSTED_CA_PATH); + when(ftpesConfigMock.trustedCAPassword()).thenReturn(TRUSTED_CA_PASSWORD); + } @Test - public void whenSingleFtpesFile_returnCorrectResponse() { + public void whenFtpesFile_returnCorrectResponse() { FileData fileData = ImmutableFileData.builder().changeIdentifier(PM_MEAS_CHANGE_IDINTIFIER) .changeType(FILE_READY_CHANGE_TYPE).name(PM_FILE_NAME).location(FTPES_LOCATION) .compression(GZIP_COMPRESSION).fileFormatType(MEAS_COLLECT_FILE_FORMAT_TYPE) @@ -86,11 +106,15 @@ public class XnfCollectorTaskImplTest { .verifyComplete(); verify(ftpsClientMock, times(1)).collectFile(fileServerData, REMOTE_FILE_LOCATION, LOCAL_FILE_LOCATION); + verify(ftpsClientMock).setKeyCertPath(FTP_KEY_PATH); + verify(ftpsClientMock).setKeyCertPassword(FTP_KEY_PASSWORD); + verify(ftpsClientMock).setTrustedCAPath(TRUSTED_CA_PATH); + verify(ftpsClientMock).setTrustedCAPassword(TRUSTED_CA_PASSWORD); verifyNoMoreInteractions(ftpsClientMock); } @Test - public void whenSingleSftpFile_returnCorrectResponse() { + public void whenSftpFile_returnCorrectResponse() { FileData fileData = ImmutableFileData.builder().changeIdentifier(PM_MEAS_CHANGE_IDINTIFIER) .changeType(FILE_READY_CHANGE_TYPE).name(PM_FILE_NAME).location(SFTP_LOCATION) .compression(GZIP_COMPRESSION).fileFormatType(MEAS_COLLECT_FILE_FORMAT_TYPE) @@ -109,6 +133,10 @@ public class XnfCollectorTaskImplTest { .verifyComplete(); verify(sftpClientMock, times(1)).collectFile(fileServerData, REMOTE_FILE_LOCATION, LOCAL_FILE_LOCATION); + verify(ftpsClientMock).setKeyCertPath(FTP_KEY_PATH); + verify(ftpsClientMock).setKeyCertPassword(FTP_KEY_PASSWORD); + verify(ftpsClientMock).setTrustedCAPath(TRUSTED_CA_PATH); + verify(ftpsClientMock).setTrustedCAPassword(TRUSTED_CA_PASSWORD); verifyNoMoreInteractions(ftpsClientMock); } @@ -126,6 +154,10 @@ public class XnfCollectorTaskImplTest { StepVerifier.create(collectorUndetTest.execute(fileData)).expectNextCount(0).verifyComplete(); + verify(ftpsClientMock).setKeyCertPath(FTP_KEY_PATH); + verify(ftpsClientMock).setKeyCertPassword(FTP_KEY_PASSWORD); + verify(ftpsClientMock).setTrustedCAPath(TRUSTED_CA_PATH); + verify(ftpsClientMock).setTrustedCAPassword(TRUSTED_CA_PASSWORD); verifyNoMoreInteractions(ftpsClientMock); } } diff --git a/datafile-app-server/src/test/resources/datafile_endpoints.json b/datafile-app-server/src/test/resources/datafile_endpoints.json index dff77d2f..1b2ab1ec 100644 --- a/datafile-app-server/src/test/resources/datafile_endpoints.json +++ b/datafile-app-server/src/test/resources/datafile_endpoints.json @@ -2,27 +2,37 @@ "configs": { "dmaap": { "dmaapConsumerConfiguration": { - "consumerGroup": "notification", "consumerId": "C12", - "dmaapContentType": "application/json", "dmaapHostName": "localhost", "dmaapPortNumber": 2222, - "dmaapProtocol": "http", "dmaapTopicName": "/events/unauthenticated.VES_NOTIFICATION_OUTPUT", + "dmaapProtocol": "http", "dmaapUserName": "admin", "dmaapUserPassword": "admin", - "messageLimit": 1000, - "timeoutMS": 1000 + "dmaapContentType": "application/json", + "consumerId": "C12", + "consumerGroup": "OpenDcae-c12", + "timeoutMS": -1, + "messageLimit": 1 }, "dmaapProducerConfiguration": { - "dmaapContentType": "application/octet-stream", "dmaapHostName": "localhost", "dmaapPortNumber": 3907, "dmaapProtocol": "https", "dmaapTopicName": "publish", "dmaapUserName": "dradmin", - "dmaapUserPassword": "dradmin" + "dmaapUserPassword": "dradmin", + "dmaapContentType": "application/octet-stream" + } + }, + "ftp": { + "ftpesConfiguration": { + "keyCert": "/config/ftpKey.jks", + "keyPassword": "secret", + "trustedCA": "/config/ftpKey.jks", + "trustedCAPassword": "secret" } } } } + -- cgit 1.2.3-korg