From 3eced2927621fc1a4260e802b06164fafcda57cf Mon Sep 17 00:00:00 2001 From: Krzysztof Gajewski Date: Wed, 13 Jan 2021 12:47:27 +0100 Subject: Add HTTPS to collect files from xNFs - plus small refactoring related to above - update to version 1.5.3 Issue-ID: DCAEGEN2-2528 Signed-off-by: Krzysztof Gajewski Change-Id: I2531c85967964f1359bafd5b694afbf662edf54e --- .../datafile/configuration/AppConfigTest.java | 23 +-- .../datafile/http/DfcHttpClientTest.java | 34 ++-- .../datafile/http/DfcHttpsClientTest.java | 164 +++++++++++++++++++ .../datafile/http/HttpClientResponseHelper.java | 176 ++++++++++++++++++++- .../http/HttpsClientConnectionManagerUtilTest.java | 52 ++++++ .../collectors/datafile/scheme/SchemeTest.java | 1 + .../datafile/tasks/FileCollectorTest.java | 102 ++++++++++-- .../datafile/tasks/ScheduledTasksTest.java | 1 + .../datafile/utils/SecurityUtilTest.java | 120 ++++++++++++++ 9 files changed, 635 insertions(+), 38 deletions(-) create mode 100644 datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/http/DfcHttpsClientTest.java create mode 100644 datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/http/HttpsClientConnectionManagerUtilTest.java create mode 100644 datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/utils/SecurityUtilTest.java (limited to 'datafile-app-server/src/test/java/org') diff --git a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/configuration/AppConfigTest.java b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/configuration/AppConfigTest.java index 7f0c6422..bcbe7f82 100644 --- a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/configuration/AppConfigTest.java +++ b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/configuration/AppConfigTest.java @@ -1,6 +1,7 @@ /*- * ============LICENSE_START====================================================================== - * Copyright (C) 2018, 2020 NOKIA Intellectual Property, 2018-2019 Nordix Foundation. All rights reserved. + * Copyright (C) 2018, 2020-2021 NOKIA Intellectual Property, 2018-2019 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 @@ -83,12 +84,12 @@ public class AppConfigTest { .password("izBJD8nLjawq0HMG") // .build(); - private static final ImmutableFtpesConfig CORRECT_FTPES_CONFIGURATION = // - new ImmutableFtpesConfig.Builder() // + private static final ImmutableCertificateConfig CORRECT_CERTIFICATE_CONFIGURATION = // + new ImmutableCertificateConfig.Builder() // .keyCert("/src/test/resources/dfc.jks") // .keyPasswordPath("/src/test/resources/dfc.jks.pass") // - .trustedCa("/src/test/resources/ftp.jks") // - .trustedCaPasswordPath("/src/test/resources/ftp.jks.pass") // + .trustedCa("/src/test/resources/cert.jks") // + .trustedCaPasswordPath("/src/test/resources/cert.jks.pass") // .build(); private AppConfig appConfigUnderTest; @@ -120,9 +121,9 @@ public class AppConfigTest { Assertions.assertNotNull(publisherCfg); assertThat(publisherCfg).isEqualToComparingFieldByField(CORRECT_PUBLISHER_CONFIG); - FtpesConfig ftpesConfig = appConfigUnderTest.getFtpesConfiguration(); - assertThat(ftpesConfig).isNotNull(); - assertThat(ftpesConfig).isEqualToComparingFieldByField(CORRECT_FTPES_CONFIGURATION); + CertificateConfig certificateConfig = appConfigUnderTest.getCertificateConfiguration(); + assertThat(certificateConfig).isNotNull(); + assertThat(certificateConfig).isEqualToComparingFieldByField(CORRECT_CERTIFICATE_CONFIGURATION); } @Test @@ -157,7 +158,7 @@ public class AppConfigTest { assertThatThrownBy(() -> appConfigUnderTest.getPublisherConfiguration(CHANGE_IDENTIFIER)) .hasMessageContaining("No PublishingConfiguration loaded, changeIdentifier: PM_MEAS_FILES"); - Assertions.assertNull(appConfigUnderTest.getFtpesConfiguration()); + Assertions.assertNull(appConfigUnderTest.getCertificateConfiguration()); } @Test @@ -172,7 +173,7 @@ public class AppConfigTest { Assertions.assertNull(appConfigUnderTest.getDmaapConsumerConfiguration()); assertThatThrownBy(() -> appConfigUnderTest.getPublisherConfiguration(CHANGE_IDENTIFIER)) .hasMessageContaining(CHANGE_IDENTIFIER); - Assertions.assertNull(appConfigUnderTest.getFtpesConfiguration()); + Assertions.assertNull(appConfigUnderTest.getCertificateConfiguration()); } @Test @@ -190,7 +191,7 @@ public class AppConfigTest { Assertions.assertNull(appConfigUnderTest.getDmaapConsumerConfiguration()); assertThatThrownBy(() -> appConfigUnderTest.getPublisherConfiguration(CHANGE_IDENTIFIER)) .hasMessageContaining(CHANGE_IDENTIFIER); - Assertions.assertNull(appConfigUnderTest.getFtpesConfiguration()); + Assertions.assertNull(appConfigUnderTest.getCertificateConfiguration()); } @Test diff --git a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/http/DfcHttpClientTest.java b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/http/DfcHttpClientTest.java index f49cd391..2013950a 100644 --- a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/http/DfcHttpClientTest.java +++ b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/http/DfcHttpClientTest.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START====================================================================== - * Copyright (C) 2020 Nokia. All rights reserved. + * Copyright (C) 2020-2021 Nokia. 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 @@ -43,7 +43,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) -public class DfcHttpClientTest { +class DfcHttpClientTest { private static final String USERNAME = "bob"; private static final String PASSWORD = "123"; @@ -55,28 +55,20 @@ public class DfcHttpClientTest { DfcHttpClient dfcHttpClientSpy; - private ImmutableFileServerData createFileServerData() { - return ImmutableFileServerData.builder() - .serverAddress(XNF_ADDRESS) - .userId(USERNAME).password(PASSWORD) - .port(PORT) - .build(); - } - @BeforeEach public void setup() { dfcHttpClientSpy = spy(new DfcHttpClient(createFileServerData())); } @Test - public void openConnection_successAuthSetup() throws DatafileTaskException { + void openConnection_successAuthSetup() throws DatafileTaskException { dfcHttpClientSpy.open(); HttpClientConfig config = dfcHttpClientSpy.client.configuration(); assertEquals(HttpUtils.basicAuth(USERNAME, PASSWORD), config.headers().get("Authorization")); } @Test - public void openConnection_failedBasicAuthSetupThrowException() { + void openConnection_failedBasicAuthSetupThrowException() { ImmutableFileServerData serverData = ImmutableFileServerData.builder() .serverAddress(XNF_ADDRESS) .userId(USERNAME).password("") @@ -90,7 +82,7 @@ public class DfcHttpClientTest { } @Test - public void prepareUri_UriWithoutPort() { + void prepareUri_UriWithoutPort() { ImmutableFileServerData serverData = ImmutableFileServerData.builder() .serverAddress(XNF_ADDRESS) .userId(USERNAME).password(PASSWORD) @@ -103,7 +95,7 @@ public class DfcHttpClientTest { } @Test - public void collectFile_AllOk() throws Exception { + void collectFile_AllOk() throws Exception { String REMOTE_FILE = "any"; Flux fis = Flux.just(new ByteArrayInputStream("ReturnedString".getBytes())); @@ -121,7 +113,7 @@ public class DfcHttpClientTest { } @Test - public void collectFile_No200ResponseWriteToErrorMessage() throws DatafileTaskException { + void collectFile_No200ResponseWriteToErrorMessage() throws DatafileTaskException { String ERROR_RESPONSE = "This is unexpected message"; String REMOTE_FILE = "any"; Flux fis = Flux.error(new Throwable(ERROR_RESPONSE)); @@ -138,8 +130,16 @@ public class DfcHttpClientTest { } @Test - public void isResponseOk_validateResponse() { - assertTrue(dfcHttpClientSpy.isResponseOk(HttpClientResponseHelper.RESPONSE_OK)); + void isResponseOk_validateResponse() { + assertTrue(dfcHttpClientSpy.isResponseOk(HttpClientResponseHelper.NETTY_RESPONSE_OK)); assertFalse(dfcHttpClientSpy.isResponseOk(HttpClientResponseHelper.RESPONSE_ANY_NO_OK)); } + + private ImmutableFileServerData createFileServerData() { + return ImmutableFileServerData.builder() + .serverAddress(XNF_ADDRESS) + .userId(USERNAME).password(PASSWORD) + .port(PORT) + .build(); + } } diff --git a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/http/DfcHttpsClientTest.java b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/http/DfcHttpsClientTest.java new file mode 100644 index 00000000..8df91d3a --- /dev/null +++ b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/http/DfcHttpsClientTest.java @@ -0,0 +1,164 @@ +/*- + * ============LICENSE_START====================================================================== + * Copyright (C) 2021 Nokia. 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.http; + + +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.conn.ConnectTimeoutException; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.onap.dcaegen2.collectors.datafile.commons.ImmutableFileServerData; +import org.onap.dcaegen2.collectors.datafile.exceptions.DatafileTaskException; +import org.onap.dcaegen2.collectors.datafile.exceptions.NonRetryableDatafileTaskException; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Path; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +@ExtendWith(MockitoExtension.class) +class DfcHttpsClientTest { + + private static final String USERNAME = "bob"; + private static final String PASSWORD = "123"; + private static final String XNF_ADDRESS = "127.0.0.1"; + private static final int PORT = 443; + private static String remoteFile = "remoteFile"; + + @Mock + private PoolingHttpClientConnectionManager connectionManager; + @Mock + private Path localFile; + + DfcHttpsClient dfcHttpsClientSpy; + + @BeforeEach + public void setup() { + dfcHttpsClientSpy = spy(new DfcHttpsClient(createFileServerData(), connectionManager)); + } + + @Test + void fileServerData_properLocationBasicAuth() throws Exception { + boolean result = dfcHttpsClientSpy.basicAuthValidNotPresentOrThrow(); + assertEquals(true, result); + } + + @Test + void fileServerData_properLocationNoBasicAuth() throws Exception { + dfcHttpsClientSpy = spy(new DfcHttpsClient(emptyUserInFileServerData(), connectionManager)); + + boolean result = dfcHttpsClientSpy.basicAuthValidNotPresentOrThrow(); + assertEquals(false, result); + } + + @Test + void fileServerData_improperAuthDataExceptionOccurred() throws Exception { + dfcHttpsClientSpy = spy(new DfcHttpsClient(invalidUserInFileServerData(), connectionManager)); + + assertThrows(DatafileTaskException.class, () -> dfcHttpsClientSpy.basicAuthValidNotPresentOrThrow()); + } + + @Test + void dfcHttpsClient_flow_successfulCallAndResponseProcessing() throws Exception { + doReturn(HttpClientResponseHelper.APACHE_RESPONSE_OK).when(dfcHttpsClientSpy) + .executeHttpClient(any(HttpGet.class)); + doReturn((long)3).when(dfcHttpsClientSpy).writeFile(eq(localFile), any(InputStream.class)); + + dfcHttpsClientSpy.open(); + dfcHttpsClientSpy.collectFile(remoteFile, localFile); + dfcHttpsClientSpy.close(); + + verify(dfcHttpsClientSpy, times(1)).makeCall(any(HttpGet.class)); + verify(dfcHttpsClientSpy, times(1)) + .executeHttpClient(any(HttpGet.class)); + verify(dfcHttpsClientSpy, times(1)) + .processResponse(HttpClientResponseHelper.APACHE_RESPONSE_OK, localFile); + verify(dfcHttpsClientSpy, times(1)) + .writeFile(eq(localFile), any(InputStream.class)); + } + + @Test + void dfcHttpsClient_flow_failedCallUnexpectedResponseCode() throws Exception { + doReturn(HttpClientResponseHelper.APACHE_RESPONSE_OK).when(dfcHttpsClientSpy) + .executeHttpClient(any(HttpGet.class)); + doReturn(false).when(dfcHttpsClientSpy).isResponseOk(any(HttpResponse.class)); + + dfcHttpsClientSpy.open(); + + assertThrows(NonRetryableDatafileTaskException.class, + () -> dfcHttpsClientSpy.collectFile(remoteFile, localFile)); + } + + @Test + void dfcHttpsClient_flow_failedCallConnectionTimeout() throws Exception { + doThrow(ConnectTimeoutException.class).when(dfcHttpsClientSpy) + .executeHttpClient(any(HttpGet.class)); + + dfcHttpsClientSpy.open(); + + assertThrows(NonRetryableDatafileTaskException.class, + () -> dfcHttpsClientSpy.collectFile(remoteFile, localFile)); + } + + @Test + void dfcHttpsClient_flow_failedCallIOExceptionForExecuteHttpClient() throws Exception { + doThrow(IOException.class).when(dfcHttpsClientSpy) + .executeHttpClient(any(HttpGet.class)); + + dfcHttpsClientSpy.open(); + + assertThrows(DatafileTaskException.class, + () -> dfcHttpsClientSpy.collectFile(remoteFile, localFile)); + } + + private ImmutableFileServerData createFileServerData() { + return ImmutableFileServerData.builder() + .serverAddress(XNF_ADDRESS) + .userId(USERNAME).password(PASSWORD) + .port(PORT) + .build(); + } + + private ImmutableFileServerData emptyUserInFileServerData() { + return ImmutableFileServerData.builder() + .serverAddress(XNF_ADDRESS) + .userId("").password("") + .port(PORT) + .build(); + } + + private ImmutableFileServerData invalidUserInFileServerData() { + return ImmutableFileServerData.builder() + .serverAddress(XNF_ADDRESS) + .userId("demo").password("") + .port(PORT) + .build(); + } +} diff --git a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/http/HttpClientResponseHelper.java b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/http/HttpClientResponseHelper.java index 42ab4b3a..0d52858d 100644 --- a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/http/HttpClientResponseHelper.java +++ b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/http/HttpClientResponseHelper.java @@ -20,16 +20,28 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.handler.codec.http.cookie.Cookie; +import org.apache.http.Header; +import org.apache.http.HeaderIterator; +import org.apache.http.HttpEntity; +import org.apache.http.ProtocolVersion; +import org.apache.http.StatusLine; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.params.HttpParams; import reactor.netty.http.client.HttpClientResponse; import reactor.util.context.Context; import reactor.util.context.ContextView; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Locale; import java.util.Map; import java.util.Set; public class HttpClientResponseHelper { - public static final HttpClientResponse RESPONSE_OK = new HttpClientResponse() { + public static final HttpClientResponse NETTY_RESPONSE_OK = new HttpClientResponse() { @Override public Map> cookies() { @@ -167,4 +179,166 @@ public class HttpClientResponseHelper { return HttpResponseStatus.NOT_IMPLEMENTED; } }; + + public static final CloseableHttpResponse APACHE_RESPONSE_OK = new CloseableHttpResponse() { + @Override public void close() throws IOException { + getEntity().getContent().close(); + } + + @Override public StatusLine getStatusLine() { + return new StatusLine() { + @Override public ProtocolVersion getProtocolVersion() { + return null; + } + + @Override public int getStatusCode() { + return 200; + } + + @Override public String getReasonPhrase() { + return null; + } + }; + } + + @Override public void setStatusLine(StatusLine statusLine) { + + } + + @Override public void setStatusLine(ProtocolVersion protocolVersion, int i) { + + } + + @Override public void setStatusLine(ProtocolVersion protocolVersion, int i, String s) { + + } + + @Override public void setStatusCode(int i) throws IllegalStateException { + + } + + @Override public void setReasonPhrase(String s) throws IllegalStateException { + + } + + @Override public HttpEntity getEntity() { + return new HttpEntity() { + @Override public boolean isRepeatable() { + return false; + } + + @Override public boolean isChunked() { + return false; + } + + @Override public long getContentLength() { + return 0; + } + + @Override public Header getContentType() { + return null; + } + + @Override public Header getContentEncoding() { + return null; + } + + @Override public InputStream getContent() throws IOException, UnsupportedOperationException { + return new ByteArrayInputStream("abc".getBytes()); + } + + @Override public void writeTo(OutputStream outputStream) throws IOException { + + } + + @Override public boolean isStreaming() { + return false; + } + + @Override public void consumeContent() throws IOException { + + } + }; + } + + @Override public void setEntity(HttpEntity httpEntity) { + + } + + @Override public Locale getLocale() { + return null; + } + + @Override public void setLocale(Locale locale) { + + } + + @Override public ProtocolVersion getProtocolVersion() { + return null; + } + + @Override public boolean containsHeader(String s) { + return false; + } + + @Override public Header[] getHeaders(String s) { + return new Header[0]; + } + + @Override public Header getFirstHeader(String s) { + return null; + } + + @Override public Header getLastHeader(String s) { + return null; + } + + @Override public Header[] getAllHeaders() { + return new Header[0]; + } + + @Override public void addHeader(Header header) { + + } + + @Override public void addHeader(String s, String s1) { + + } + + @Override public void setHeader(Header header) { + + } + + @Override public void setHeader(String s, String s1) { + + } + + @Override public void setHeaders(Header[] headers) { + + } + + @Override public void removeHeader(Header header) { + + } + + @Override public void removeHeaders(String s) { + + } + + @Override public HeaderIterator headerIterator() { + return null; + } + + @Override public HeaderIterator headerIterator(String s) { + return null; + } + + @Override public HttpParams getParams() { + return null; + } + + @Override public void setParams(HttpParams httpParams) { + + } + }; } diff --git a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/http/HttpsClientConnectionManagerUtilTest.java b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/http/HttpsClientConnectionManagerUtilTest.java new file mode 100644 index 00000000..fa4473a6 --- /dev/null +++ b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/http/HttpsClientConnectionManagerUtilTest.java @@ -0,0 +1,52 @@ +/*- + * ============LICENSE_START====================================================================== + * Copyright (C) 2021 Nokia. 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.http; + +import org.junit.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; +import org.onap.dcaegen2.collectors.datafile.exceptions.DatafileTaskException; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; + +@ExtendWith(MockitoExtension.class) +public class HttpsClientConnectionManagerUtilTest { + + private static final String KEY_PATH = "src/test/resources/keystore.p12"; + private static final String KEY_PASSWORD = "src/test/resources/keystore.pass"; + private static final String KEY_IMPROPER_PASSWORD = "src/test/resources/dfc.jks.pass"; + private static final String TRUSTED_CA_PATH = "src/test/resources/trust.jks"; + private static final String TRUSTED_CA_PASSWORD = "src/test/resources/trust.pass"; + + @Test + public void emptyManager_shouldThrowException() { + assertThrows(DatafileTaskException.class, () -> HttpsClientConnectionManagerUtil.instance()); + } + + @Test + public void creatingManager_successfulCase() throws Exception { + HttpsClientConnectionManagerUtil.setupOrUpdate(KEY_PATH, KEY_PASSWORD, TRUSTED_CA_PATH, TRUSTED_CA_PASSWORD); + assertNotNull(HttpsClientConnectionManagerUtil.instance()); + } + + @Test + public void creatingManager_improperSecretShouldThrowException() { + assertThrows(DatafileTaskException.class, () -> HttpsClientConnectionManagerUtil.setupOrUpdate(KEY_PATH, KEY_IMPROPER_PASSWORD, TRUSTED_CA_PATH, TRUSTED_CA_PASSWORD)); + assertThrows(DatafileTaskException.class, () -> HttpsClientConnectionManagerUtil.instance()); + } + +} diff --git a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/scheme/SchemeTest.java b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/scheme/SchemeTest.java index fb475791..61adef9a 100644 --- a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/scheme/SchemeTest.java +++ b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/scheme/SchemeTest.java @@ -34,6 +34,7 @@ public class SchemeTest { assertEquals(Scheme.FTPES, Scheme.getSchemeFromString("FTPES")); assertEquals(Scheme.SFTP, Scheme.getSchemeFromString("SFTP")); assertEquals(Scheme.HTTP, Scheme.getSchemeFromString("HTTP")); + assertEquals(Scheme.HTTPS, Scheme.getSchemeFromString("HTTPS")); } @Test diff --git a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/FileCollectorTest.java b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/FileCollectorTest.java index 1146cf26..ceb8a989 100644 --- a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/FileCollectorTest.java +++ b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/FileCollectorTest.java @@ -38,12 +38,14 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; 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.configuration.CertificateConfig; import org.onap.dcaegen2.collectors.datafile.exceptions.DatafileTaskException; import org.onap.dcaegen2.collectors.datafile.exceptions.NonRetryableDatafileTaskException; import org.onap.dcaegen2.collectors.datafile.ftp.FtpesClient; import org.onap.dcaegen2.collectors.datafile.commons.Scheme; import org.onap.dcaegen2.collectors.datafile.ftp.SftpClient; +import org.onap.dcaegen2.collectors.datafile.http.DfcHttpClient; +import org.onap.dcaegen2.collectors.datafile.http.DfcHttpsClient; import org.onap.dcaegen2.collectors.datafile.model.Counters; import org.onap.dcaegen2.collectors.datafile.model.FileData; import org.onap.dcaegen2.collectors.datafile.model.FilePublishInformation; @@ -64,6 +66,8 @@ public class FileCollectorTest { private static final String FILE_READY_CHANGE_TYPE = "FileReady"; private static final String FTPES_SCHEME = "ftpes://"; private static final String SFTP_SCHEME = "sftp://"; + private static final String HTTP_SCHEME = "http://"; + private static final String HTTPS_SCHEME = "https://"; private static final String SERVER_ADDRESS = "192.168.0.101"; private static final int PORT_22 = 22; private static final String PM_FILE_NAME = "A20161224.1030-1045.bin.gz"; @@ -79,24 +83,36 @@ public class FileCollectorTest { private static final String SFTP_LOCATION = SFTP_SCHEME + SERVER_ADDRESS + ":" + PORT_22 + REMOTE_FILE_LOCATION; private static final String SFTP_LOCATION_NO_PORT = SFTP_SCHEME + SERVER_ADDRESS + REMOTE_FILE_LOCATION; + private static final String HTTP_LOCATION = + HTTP_SCHEME + USER + ":" + PWD + "@" + SERVER_ADDRESS + ":" + PORT_22 + REMOTE_FILE_LOCATION; + private static final String HTTP_LOCATION_NO_PORT = + HTTP_SCHEME + USER + ":" + PWD + "@" + SERVER_ADDRESS + REMOTE_FILE_LOCATION; + private static final String HTTPS_LOCATION = + HTTP_SCHEME + USER + ":" + PWD + "@" + SERVER_ADDRESS + ":" + PORT_22 + REMOTE_FILE_LOCATION; + private static final String HTTPS_LOCATION_NO_PORT = + HTTP_SCHEME + USER + ":" + PWD + "@" + SERVER_ADDRESS + REMOTE_FILE_LOCATION; + private static final String GZIP_COMPRESSION = "gzip"; 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_PATH = "ftpKeyPassword"; + private static final String CERTIFICATE_KEY_PATH = "certificateKeyPath"; + private static final String CERTIFICATE_KEY_PASSWORD_PATH = "certificateKeyPassword"; private static final String TRUSTED_CA_PATH = "trustedCAPath"; private static final String TRUSTED_CA_PASSWORD_PATH = "trustedCAPassword"; private static final String CHANGE_IDENTIFIER = "PM_MEAS_FILES"; private static AppConfig appConfigMock = mock(AppConfig.class); - private static FtpesConfig ftpesConfigMock = mock(FtpesConfig.class); + private static CertificateConfig certificateConfigMock = mock(CertificateConfig.class); private FtpesClient ftpesClientMock = mock(FtpesClient.class); private SftpClient sftpClientMock = mock(SftpClient.class); private final Map contextMap = new HashMap<>(); + private DfcHttpClient dfcHttpClientMock = mock(DfcHttpClient.class); + private DfcHttpsClient dfcHttpsClientMock = mock(DfcHttpsClient.class); + private Counters counters; private MessageMetaData createMessageMetaData() { @@ -145,11 +161,11 @@ public class FileCollectorTest { @BeforeAll static void setUpConfiguration() { - when(appConfigMock.getFtpesConfiguration()).thenReturn(ftpesConfigMock); - when(ftpesConfigMock.keyCert()).thenReturn(FTP_KEY_PATH); - when(ftpesConfigMock.keyPasswordPath()).thenReturn(FTP_KEY_PASSWORD_PATH); - when(ftpesConfigMock.trustedCa()).thenReturn(TRUSTED_CA_PATH); - when(ftpesConfigMock.trustedCaPasswordPath()).thenReturn(TRUSTED_CA_PASSWORD_PATH); + when(appConfigMock.getCertificateConfiguration()).thenReturn(certificateConfigMock); + when(certificateConfigMock.keyCert()).thenReturn(CERTIFICATE_KEY_PATH); + when(certificateConfigMock.keyPasswordPath()).thenReturn(CERTIFICATE_KEY_PASSWORD_PATH); + when(certificateConfigMock.trustedCa()).thenReturn(TRUSTED_CA_PATH); + when(certificateConfigMock.trustedCaPasswordPath()).thenReturn(TRUSTED_CA_PASSWORD_PATH); } @BeforeEach @@ -178,6 +194,7 @@ public class FileCollectorTest { assertEquals(1, counters.getNoOfCollectedFiles(),"collectedFiles should have been 1"); assertEquals(0, counters.getNoOfFailedFtpAttempts(),"failedFtpAttempts should have been 0"); + assertEquals(0, counters.getNoOfFailedHttpAttempts(),"failedHttpAttempts should have been 0"); } @Test @@ -209,6 +226,70 @@ public class FileCollectorTest { assertEquals(2, counters.getNoOfCollectedFiles(),"collectedFiles should have been 2"); } + @Test + public void whenHttpFile_returnCorrectResponse() throws Exception { + FileCollector collectorUndetTest = spy(new FileCollector(appConfigMock, counters)); + doReturn(dfcHttpClientMock).when(collectorUndetTest).createHttpClient(any()); + + FileData fileData = createFileData(HTTP_LOCATION_NO_PORT, Scheme.HTTP); + + FilePublishInformation expectedfilePublishInformation = + createExpectedFilePublishInformation(HTTP_LOCATION_NO_PORT); + + StepVerifier.create(collectorUndetTest.collectFile(fileData, 3, Duration.ofSeconds(0), contextMap)) + .expectNext(expectedfilePublishInformation) // + .verifyComplete(); + + // The same again, but with port + fileData = createFileData(HTTP_LOCATION, Scheme.HTTP); + expectedfilePublishInformation = createExpectedFilePublishInformation(HTTP_LOCATION); + + StepVerifier.create(collectorUndetTest.collectFile(fileData, 3, Duration.ofSeconds(0), contextMap)) + .expectNext(expectedfilePublishInformation) // + .verifyComplete(); + + verify(dfcHttpClientMock, times(2)).open(); + verify(dfcHttpClientMock, times(2)).collectFile(REMOTE_FILE_LOCATION, LOCAL_FILE_LOCATION); + verify(dfcHttpClientMock, times(2)).close(); + verifyNoMoreInteractions(dfcHttpClientMock); + + assertEquals(2, counters.getNoOfCollectedFiles(),"collectedFiles should have been 1"); + assertEquals(0, counters.getNoOfFailedFtpAttempts(),"failedFtpAttempts should have been 0"); + assertEquals(0, counters.getNoOfFailedHttpAttempts(),"failedHttpAttempts should have been 0"); + } + + @Test + public void whenHttpsFile_returnCorrectResponse() throws Exception { + FileCollector collectorUndetTest = spy(new FileCollector(appConfigMock, counters)); + doReturn(dfcHttpsClientMock).when(collectorUndetTest).createHttpsClient(any()); + + FileData fileData = createFileData(HTTPS_LOCATION_NO_PORT, Scheme.HTTPS); + + FilePublishInformation expectedfilePublishInformation = + createExpectedFilePublishInformation(HTTPS_LOCATION_NO_PORT); + + StepVerifier.create(collectorUndetTest.collectFile(fileData, 3, Duration.ofSeconds(0), contextMap)) + .expectNext(expectedfilePublishInformation) // + .verifyComplete(); + + // The same again, but with port + fileData = createFileData(HTTPS_LOCATION, Scheme.HTTPS); + expectedfilePublishInformation = createExpectedFilePublishInformation(HTTPS_LOCATION); + + StepVerifier.create(collectorUndetTest.collectFile(fileData, 3, Duration.ofSeconds(0), contextMap)) + .expectNext(expectedfilePublishInformation) // + .verifyComplete(); + + verify(dfcHttpsClientMock, times(2)).open(); + verify(dfcHttpsClientMock, times(2)).collectFile(REMOTE_FILE_LOCATION, LOCAL_FILE_LOCATION); + verify(dfcHttpsClientMock, times(2)).close(); + verifyNoMoreInteractions(dfcHttpsClientMock); + + assertEquals(2, counters.getNoOfCollectedFiles(),"collectedFiles should have been 1"); + assertEquals(0, counters.getNoOfFailedFtpAttempts(),"failedFtpAttempts should have been 0"); + assertEquals(0, counters.getNoOfFailedHttpAttempts(),"failedHttpAttempts should have been 0"); + } + @Test public void whenFtpesFileAlwaysFail_retryAndFail() throws Exception { FileCollector collectorUndetTest = spy(new FileCollector(appConfigMock, counters)); @@ -226,6 +307,7 @@ public class FileCollectorTest { assertEquals(0, counters.getNoOfCollectedFiles(),"collectedFiles should have been 0"); assertEquals(4, counters.getNoOfFailedFtpAttempts(),"failedFtpAttempts should have been 4"); + assertEquals(0, counters.getNoOfFailedHttpAttempts(),"failedHttpAttempts should have been 0"); } @Test @@ -245,6 +327,7 @@ public class FileCollectorTest { assertEquals(0, counters.getNoOfCollectedFiles(),"collectedFiles should have been 0"); assertEquals(1, counters.getNoOfFailedFtpAttempts(),"failedFtpAttempts should have been 1"); + assertEquals(0, counters.getNoOfFailedHttpAttempts(),"failedHttpAttempts should have been 0"); } @Test @@ -267,5 +350,6 @@ public class FileCollectorTest { assertEquals(1, counters.getNoOfCollectedFiles(),"collectedFiles should have been 1"); assertEquals(1, counters.getNoOfFailedFtpAttempts(),"failedFtpAttempts should have been 1"); + assertEquals(0, counters.getNoOfFailedHttpAttempts(),"failedHttpAttempts should have been 0"); } } diff --git a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/ScheduledTasksTest.java b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/ScheduledTasksTest.java index 09d7627e..85f52ff8 100644 --- a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/ScheduledTasksTest.java +++ b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/ScheduledTasksTest.java @@ -392,6 +392,7 @@ public class ScheduledTasksTest { assertEquals(2, testedObject.getCounters().getTotalReceivedEvents(),"totalReceivedEvents should have been 2"); assertEquals(1, testedObject.getCounters().getNoOfFailedFtp(),"failedFtp should have been 1"); + assertEquals(0, testedObject.getCounters().getNoOfFailedHttp(),"failedHttp should have been 0"); } @Test diff --git a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/utils/SecurityUtilTest.java b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/utils/SecurityUtilTest.java new file mode 100644 index 00000000..75ad8a48 --- /dev/null +++ b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/utils/SecurityUtilTest.java @@ -0,0 +1,120 @@ +/*- + * ============LICENSE_START====================================================================== + * Copyright (C) 2021 Nokia. 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.utils; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.onap.dcaegen2.collectors.datafile.commons.SecurityUtil; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.InvalidPathException; +import java.nio.file.Path; +import java.nio.file.Paths; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.powermock.api.mockito.PowerMockito.mockStatic; +import static org.powermock.api.mockito.PowerMockito.when; + +/** + * Tests the SecurityUtil. + * + * @author Krzysztof Gajewski + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest(SecurityUtil.class) +@PowerMockIgnore({"com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "javax.management.*"}) +public class SecurityUtilTest { + + @Mock + Path path; + + private static final String expectedPassword = "password"; + private static final String validPath = "/validPath"; + private static final String invalidPath = "/invalidPath"; + + @Test + public void whenGetKeystorePasswordFromFile_passwordSuccessfullyReturned() throws Exception { + mockStatic(Paths.class); + mockStatic(Files.class); + when(Paths.get(validPath)).thenReturn(path); + when(Files.readAllBytes(path)).thenReturn("password".getBytes()); + + String result = SecurityUtil.getKeystorePasswordFromFile(validPath); + assertEquals(expectedPassword, result); + + } + + @Test + public void whenGetKeystorePasswordFromFile_IOExceptionForValidPath() throws Exception { + mockStatic(Paths.class); + mockStatic(Files.class); + when(Paths.get(validPath)).thenReturn(path); + when(Files.readAllBytes(path)).thenThrow(IOException.class); + + assertEquals("", SecurityUtil.getKeystorePasswordFromFile(validPath)); + + } + + @Test + public void whenGetKeystorePasswordFromFile_InvalidPathExceptionForInvalidPath() { + mockStatic(Paths.class); + mockStatic(Files.class); + when(Paths.get(invalidPath)).thenThrow(InvalidPathException.class); + + assertThrows(InvalidPathException.class, () -> SecurityUtil.getKeystorePasswordFromFile(invalidPath)); + + } + + @Test + public void whenGetTruststorePasswordFromFile_passwordSuccessfullyReturned() throws Exception { + mockStatic(Paths.class); + mockStatic(Files.class); + when(Paths.get(validPath)).thenReturn(path); + when(Files.readAllBytes(path)).thenReturn("password".getBytes()); + + String result = SecurityUtil.getTruststorePasswordFromFile(validPath); + assertEquals(expectedPassword, result); + + } + + @Test + public void whenGetTruststorePasswordFromFile_IOExceptionForValidPath() throws Exception { + mockStatic(Paths.class); + mockStatic(Files.class); + when(Paths.get(validPath)).thenReturn(path); + when(Files.readAllBytes(path)).thenThrow(IOException.class); + + assertEquals("", SecurityUtil.getTruststorePasswordFromFile(validPath)); + + } + + @Test + public void whenGetTruststorePasswordFromFile_InvalidPathExceptionForInvalidPath() { + mockStatic(Paths.class); + mockStatic(Files.class); + when(Paths.get(invalidPath)).thenThrow(InvalidPathException.class); + + assertThrows(InvalidPathException.class, () -> SecurityUtil.getTruststorePasswordFromFile(invalidPath)); + + } + +} -- cgit 1.2.3-korg