add basic auth using username and password 02/117302/3
authorBartosz Gardziejewski <bartosz.gardziejewski@nokia.com>
Fri, 29 Jan 2021 09:43:17 +0000 (10:43 +0100)
committerBartosz Gardziejewski <bartosz.gardziejewski@nokia.com>
Tue, 2 Feb 2021 08:32:13 +0000 (09:32 +0100)
Signed-off-by: Bartosz Gardziejewski <bartosz.gardziejewski@nokia.com>
Change-Id: I67bc2c25149c8e2d4943f23cfa8d726cdb95995f
Issue-ID: INT-1805

pnfsimulator/README.md
pnfsimulator/docker-compose.yml
pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/BasicAvailabilityTest.java
pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/OptionalTemplatesTest.java
pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/SingleEventTest.java [new file with mode: 0644]
pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/TestUtils.java [new file with mode: 0644]
pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/VariablesReplacement.java
pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/suites/DockerBasedTestsSuite.java
pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapterImpl.java
pnfsimulator/src/main/resources/application.properties
pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapterImplTest.java

index 1ab9c3d..844fdf5 100644 (file)
@@ -375,8 +375,14 @@ CA certificates are incorporated into simulator docker image, thus no additional
 
 Certificates can be found in docker container under path: */usr/local/share/ca-certificates/*
 
-Simulator works with VES that uses both self-signed certificate (already present in keystore) and VES integrated to AAF. 
+Simulator works with VES that uses both self-signed certificate (already present in keystore) and VES integrated to AAF.
+
+Certification loading can be disabled by setting environment variable ```USE_CERTIFICATE_FOR_AUTHORIZATION``` to false. 
+Once certificate are not used for authorization, user can set up VES url using username and password.
+
+    {
+        "vesServerUrl": "http://<user>:<password>@<ves_url>:<port>/eventListener/v7"
+    }
 
 ## Developers Guide
 
index 54e4699..c7a19eb 100644 (file)
@@ -27,6 +27,8 @@ services:
     image: onap/org.onap.integration.simulators.pnfsimulator
     ports:
       - "5000:5000"
+    environment:
+      USE_CERTIFICATE_FOR_AUTHORIZATION: "true"
     volumes:
       - ./logs:/var/log
       - ./templates:/app/templates
index fffc447..323243c 100644 (file)
@@ -24,6 +24,7 @@ import static io.restassured.RestAssured.given;
 import static io.restassured.RestAssured.when;
 import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
 import static org.hamcrest.Matchers.equalTo;
+import static org.onap.pnfsimulator.integration.TestUtils.getCurrentIpAddress;
 
 import com.google.gson.JsonObject;
 
@@ -230,13 +231,4 @@ public class BasicAvailabilityTest {
         return "http://0.0.0.0:5000/simulator/" + action;
     }
 
-    private String getCurrentIpAddress() throws SocketException {
-        return Collections.list(NetworkInterface.getNetworkInterfaces()).stream()
-            .flatMap(i -> Collections.list(i.getInetAddresses()).stream())
-            .filter(ip -> ip instanceof Inet4Address)
-            .map(e -> (Inet4Address) e)
-            .findFirst()
-            .orElseThrow(RuntimeException::new)
-            .getHostAddress();
-    }
 }
index 8c8767d..50ad1cd 100644 (file)
@@ -23,24 +23,15 @@ package org.onap.pnfsimulator.integration;
 import static io.restassured.RestAssured.given;
 import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
 import static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.stringContainsInOrder;
+import static org.onap.pnfsimulator.integration.TestUtils.COMMON_EVENT_HEADER;
+import static org.onap.pnfsimulator.integration.TestUtils.PATCHED;
+import static org.onap.pnfsimulator.integration.TestUtils.SINGLE_EVENT_URL;
+import static org.onap.pnfsimulator.integration.TestUtils.findSourceNameInMongoDB;
+import static org.onap.pnfsimulator.integration.TestUtils.getCurrentIpAddress;
 
 import com.google.gson.JsonObject;
-import com.mongodb.MongoClient;
-import com.mongodb.MongoClientOptions;
-import com.mongodb.MongoCredential;
-import com.mongodb.ServerAddress;
-import com.mongodb.client.FindIterable;
-import com.mongodb.client.MongoCollection;
-import com.mongodb.client.MongoCursor;
-import com.mongodb.client.MongoDatabase;
 import java.time.Instant;
-import java.net.Inet4Address;
-import java.net.NetworkInterface;
-import java.net.SocketException;
 import java.net.UnknownHostException;
-import java.util.Collections;
-import java.util.List;
 
 import org.assertj.core.api.Assertions;
 import org.bson.Document;
@@ -60,16 +51,6 @@ import org.springframework.test.context.junit4.SpringRunner;
 @SpringBootTest(classes = {Main.class, TestConfiguration.class}, webEnvironment = WebEnvironment.DEFINED_PORT)
 public class OptionalTemplatesTest {
 
-    private static final String PNF_SIMULATOR_DB = "pnf_simulator";
-    private static final String COMMON_EVENT_HEADER = "commonEventHeader";
-    private static final String PNF_SIMULATOR_DB_PSWD = "zXcVbN123!";
-    private static final String PNF_SIMULATOR_DB_USER = "pnf_simulator_user";
-    private static final String PATCHED = "patched";
-    private static final String SINGLE_EVENT_URL = "http://0.0.0.0:5000/simulator/event";
-
-    @Autowired
-    VesSimulatorController vesSimulatorController;
-
     @Autowired
     private VesSimulatorService vesSimulatorService;
 
@@ -177,83 +158,4 @@ public class OptionalTemplatesTest {
             .isEqualTo("{\"commonEventHeader\":{\"sourceName\":\"HistoricalEvent\",\"version\":3}}");
     }
 
-    @Test
-    public void whenTriggeredSimulatorWithWrongVesIpInformationShouldBeReturned() {
-        //given
-        String body = "{\n"
-            + "\"vesServerUrl\": \"https://" + currentVesSimulatorIp + ":8080/ves-simulator/eventListener/v5\",\n"
-            + "\"event\": { \n"
-            + "\"commonEventHeader\": {\n"
-            + "\"sourceName\": \"HistoricalEvent\",\n"
-            + "\"version\": 3"
-            + "}\n"
-            + "}\n"
-            + "}";
-
-        //when
-        given()
-            .contentType("application/json")
-            .body(body)
-            .when()
-            .post(SINGLE_EVENT_URL)
-            .then()
-            .statusCode(421)
-            .body("message",
-                equalTo(
-                    "Fail to connect with ves: Connect to "+currentVesSimulatorIp+":8080 " +
-                    "[/"+currentVesSimulatorIp+"] " +
-                    "failed: Connection refused (Connection refused)"));
-    }
-
-    @Test
-    public void whenTriggeredSimulatorWithWrongEventShouldReturnedError() {
-        //given
-        String body = "{\n"
-            + "\"vesServerUrl\": \"https://" + currentVesSimulatorIp + ":9443/ves-simulator/eventListener/v5\",\n"
-            + "\"event\": { \n"
-            + "this is not JSON {}"
-            + "}\n"
-            + "}";
-
-        //when
-        given()
-            .contentType("application/json")
-            .body(body)
-            .when()
-            .post(SINGLE_EVENT_URL)
-            .then()
-            .statusCode(HttpStatus.BAD_REQUEST.value())
-            .body("message",
-                stringContainsInOrder(List.of("JSON parse error:","Unexpected character ('t' (code 116)):"))
-            );
-    }
-
-    private Document findSourceNameInMongoDB() throws UnknownHostException {
-        MongoCredential credential = MongoCredential
-            .createCredential(PNF_SIMULATOR_DB_USER, PNF_SIMULATOR_DB, PNF_SIMULATOR_DB_PSWD.toCharArray());
-        MongoClient mongoClient = new MongoClient(new ServerAddress(Inet4Address.getLocalHost(), 27017),
-            credential, MongoClientOptions.builder().build());
-        MongoDatabase pnfSimulatorDb = mongoClient.getDatabase(PNF_SIMULATOR_DB);
-        MongoCollection<Document> table = pnfSimulatorDb.getCollection("eventData");
-        Document searchQuery = new Document();
-        searchQuery.put(PATCHED, new Document("$regex", ".*" + "HistoricalEvent" + ".*"));
-        FindIterable<Document> findOfPatched = table.find(searchQuery);
-        Document dbObject = null;
-        MongoCursor<Document> cursor = findOfPatched.iterator();
-        if (cursor.hasNext()) {
-            dbObject = cursor.next();
-        }
-        return dbObject;
-    }
-
-    private String getCurrentIpAddress() throws SocketException {
-        return Collections.list(NetworkInterface.getNetworkInterfaces()).stream()
-            .flatMap(i -> Collections.list(i.getInetAddresses()).stream())
-            .filter(ip -> ip instanceof Inet4Address)
-            .map(e -> (Inet4Address) e)
-            .findFirst()
-            .orElseThrow(RuntimeException::new)
-            .getHostAddress();
-    }
-
 }
diff --git a/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/SingleEventTest.java b/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/SingleEventTest.java
new file mode 100644 (file)
index 0000000..3ad1385
--- /dev/null
@@ -0,0 +1,151 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2020 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.pnfsimulator.integration;
+
+import com.google.gson.JsonObject;
+import org.assertj.core.api.Assertions;
+import org.bson.Document;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.http.HttpStatus;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.net.UnknownHostException;
+import java.util.List;
+
+import static io.restassured.RestAssured.given;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.stringContainsInOrder;
+import static org.onap.pnfsimulator.integration.TestUtils.PATCHED;
+import static org.onap.pnfsimulator.integration.TestUtils.SINGLE_EVENT_URL;
+import static org.onap.pnfsimulator.integration.TestUtils.findSourceNameInMongoDB;
+import static org.onap.pnfsimulator.integration.TestUtils.getCurrentIpAddress;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = {Main.class, TestConfiguration.class}, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
+public class SingleEventTest {
+
+    @Autowired
+    private VesSimulatorService vesSimulatorService;
+
+    private String currentVesSimulatorIp;
+
+    @Before
+    public void setUp() throws Exception {
+        currentVesSimulatorIp = getCurrentIpAddress();
+    }
+
+    @After
+    public void tearDown() {
+        Mockito.reset(vesSimulatorService);
+    }
+
+    @Test
+    public void whenTriggeredSimulatorWithWrongVesAddressInformationShouldBeReturned() {
+        //given
+        String body = "{\n"
+            + "\"vesServerUrl\": \"https://" + currentVesSimulatorIp + ":8080/ves-simulator/eventListener/v5\",\n"
+            + "\"event\": { \n"
+            + "\"commonEventHeader\": {\n"
+            + "\"sourceName\": \"HistoricalEvent\",\n"
+            + "\"version\": 3"
+            + "}\n"
+            + "}\n"
+            + "}";
+
+        //when
+        given()
+            .contentType("application/json")
+            .body(body)
+            .when()
+            .post(SINGLE_EVENT_URL)
+            .then()
+            .statusCode(421)
+            .body("message",
+                equalTo(
+                    "Fail to connect with ves: Connect to "+currentVesSimulatorIp+":8080 " +
+                        "[/"+currentVesSimulatorIp+"] " +
+                        "failed: Connection refused (Connection refused)"));
+    }
+
+    @Test
+    public void whenTriggeredSimulatorWithWrongEventShouldReturnedError() {
+        //given
+        String body = "{\n"
+            + "\"vesServerUrl\": \"https://" + currentVesSimulatorIp + ":9443/ves-simulator/eventListener/v5\",\n"
+            + "\"event\": { \n"
+            + "this is not JSON {}"
+            + "}\n"
+            + "}";
+
+        //when
+        given()
+            .contentType("application/json")
+            .body(body)
+            .when()
+            .post(SINGLE_EVENT_URL)
+            .then()
+            .statusCode(HttpStatus.BAD_REQUEST.value())
+            .body("message",
+                stringContainsInOrder(List.of("JSON parse error:","Unexpected character ('t' (code 116)):"))
+            );
+    }
+
+    @Test
+    public void whenTriggeredSimulatorWithUsernameAndPasswordInUrlVesShouldAcceptRequest() throws UnknownHostException {
+        //given
+        String body = "{\n"
+            + "\"vesServerUrl\": \"https://user1:pass1@" + currentVesSimulatorIp + ":9443/ves-simulator/eventListener/v5\",\n"
+            + "\"event\": { \n"
+            + "\"commonEventHeader\": {\n"
+            + "\"sourceName\": \"HistoricalEvent\",\n"
+            + "\"version\": 3"
+            + "}\n"
+            + "}\n"
+            + "}";
+        ArgumentCaptor<JsonObject> parameterCaptor = ArgumentCaptor.forClass(JsonObject.class);
+
+        //when
+        given()
+            .contentType("application/json")
+            .body(body)
+            .when()
+            .post(SINGLE_EVENT_URL)
+            .then()
+            .statusCode(HttpStatus.ACCEPTED.value())
+            .body("message", equalTo("Accepted"));
+
+        //then
+        Mockito.verify(vesSimulatorService,
+            Mockito.timeout(3000))
+            .sendEventToDmaapV5(parameterCaptor.capture());
+
+        Document sourceNameInMongoDB = findSourceNameInMongoDB();
+        Assertions.assertThat(sourceNameInMongoDB.get(PATCHED))
+            .isEqualTo("{\"commonEventHeader\":{\"sourceName\":\"HistoricalEvent\",\"version\":3}}");
+    }
+}
diff --git a/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/TestUtils.java b/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/TestUtils.java
new file mode 100644 (file)
index 0000000..f7df5e9
--- /dev/null
@@ -0,0 +1,57 @@
+package org.onap.pnfsimulator.integration;
+
+import com.mongodb.MongoClient;
+import com.mongodb.MongoClientOptions;
+import com.mongodb.MongoCredential;
+import com.mongodb.ServerAddress;
+import com.mongodb.client.FindIterable;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.MongoCursor;
+import com.mongodb.client.MongoDatabase;
+import org.bson.Document;
+
+import java.net.Inet4Address;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.util.Collections;
+
+public class TestUtils {
+
+    private TestUtils() {}
+
+    public static final String PNF_SIMULATOR_DB = "pnf_simulator";
+    public static final String COMMON_EVENT_HEADER = "commonEventHeader";
+    public static final String PNF_SIMULATOR_DB_PSWD = "zXcVbN123!";
+    public static final String PNF_SIMULATOR_DB_USER = "pnf_simulator_user";
+    public static final String PATCHED = "patched";
+    public static final String SINGLE_EVENT_URL = "http://0.0.0.0:5000/simulator/event";
+
+    public static Document findSourceNameInMongoDB() throws UnknownHostException {
+        MongoCredential credential = MongoCredential
+            .createCredential(PNF_SIMULATOR_DB_USER, PNF_SIMULATOR_DB, PNF_SIMULATOR_DB_PSWD.toCharArray());
+        MongoClient mongoClient = new MongoClient(new ServerAddress(Inet4Address.getLocalHost(), 27017),
+            credential, MongoClientOptions.builder().build());
+        MongoDatabase pnfSimulatorDb = mongoClient.getDatabase(PNF_SIMULATOR_DB);
+        MongoCollection<Document> table = pnfSimulatorDb.getCollection("eventData");
+        Document searchQuery = new Document();
+        searchQuery.put(PATCHED, new Document("$regex", ".*" + "HistoricalEvent" + ".*"));
+        FindIterable<Document> findOfPatched = table.find(searchQuery);
+        Document dbObject = null;
+        MongoCursor<Document> cursor = findOfPatched.iterator();
+        if (cursor.hasNext()) {
+            dbObject = cursor.next();
+        }
+        return dbObject;
+    }
+
+    public static String getCurrentIpAddress() throws SocketException {
+        return Collections.list(NetworkInterface.getNetworkInterfaces()).stream()
+            .flatMap(i -> Collections.list(i.getInetAddresses()).stream())
+            .filter(ip -> ip instanceof Inet4Address)
+            .map(e -> (Inet4Address) e)
+            .findFirst()
+            .orElseThrow(RuntimeException::new)
+            .getHostAddress();
+    }
+}
index c0bd989..ae7970c 100644 (file)
@@ -3,6 +3,7 @@ package org.onap.pnfsimulator.integration;
 import static io.restassured.RestAssured.given;
 import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
 import static org.hamcrest.Matchers.equalTo;
+import static org.onap.pnfsimulator.integration.TestUtils.getCurrentIpAddress;
 
 import com.google.gson.JsonObject;
 import java.net.Inet4Address;
@@ -76,11 +77,4 @@ public class VariablesReplacement {
         return "http://0.0.0.0:5000/simulator/start";
     }
 
-    private String getCurrentIpAddress() throws SocketException {
-        return Collections.list(NetworkInterface.getNetworkInterfaces()).stream()
-                       .flatMap(i -> Collections.list(i.getInetAddresses()).stream())
-                       .filter(ip -> ip instanceof Inet4Address).map(e -> (Inet4Address) e).findFirst()
-                       .orElseThrow(RuntimeException::new).getHostAddress();
-    }
-
 }
index 3de06c3..f6a4c24 100644 (file)
@@ -30,6 +30,7 @@ import org.junit.runners.Suite.SuiteClasses;
 import org.onap.pnfsimulator.integration.BasicAvailabilityTest;
 import org.onap.pnfsimulator.integration.OptionalTemplatesTest;
 import org.onap.pnfsimulator.integration.SearchInTemplatesTest;
+import org.onap.pnfsimulator.integration.SingleEventTest;
 import org.onap.pnfsimulator.integration.TemplatesManagementTest;
 import org.onap.pnfsimulator.integration.VariablesReplacement;
 import org.slf4j.Logger;
@@ -40,7 +41,7 @@ import static io.restassured.RestAssured.given;
 
 @RunWith(Suite.class)
 @SuiteClasses({BasicAvailabilityTest.class, TemplatesManagementTest.class, OptionalTemplatesTest.class,
-    SearchInTemplatesTest.class, VariablesReplacement.class})
+    SearchInTemplatesTest.class, VariablesReplacement.class, SingleEventTest.class})
 public class DockerBasedTestsSuite {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(DockerBasedTestsSuite.class);
index 4f249b9..ba668fc 100644 (file)
@@ -20,6 +20,8 @@
 
 package org.onap.pnfsimulator.simulator.client;
 
+import org.apache.commons.codec.binary.Base64;
+import org.apache.http.HttpHeaders;
 import org.apache.http.HttpResponse;
 import org.apache.http.client.HttpClient;
 import org.apache.http.client.methods.HttpPost;
@@ -35,6 +37,9 @@ import org.slf4j.MarkerFactory;
 
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.charset.StandardCharsets;
 import java.security.GeneralSecurityException;
 import java.util.UUID;
 
@@ -71,22 +76,27 @@ public class HttpClientAdapterImpl implements HttpClientAdapter {
             LOGGER.info(INVOKE, "Message sent, ves response code: {}", response.getStatusLine());
             vesResponse = responseFactory.create(response);
             EntityUtils.consumeQuietly(response.getEntity()); //response has to be fully consumed otherwise apache won't release connection
-        } catch (IOException e) {
+        } catch (IOException | URISyntaxException e) {
             LOGGER.warn("Error sending message to ves: {}", e.getMessage(), e.getCause());
             vesResponse = new HttpResponseAdapter(421, String.format("Fail to connect with ves: %s", e.getMessage()));
         }
         return vesResponse;
     }
 
-    private HttpResponse sendAndRetrieve(String content) throws IOException {
+    private HttpResponse sendAndRetrieve(String content) throws IOException, URISyntaxException {
         HttpPost request = createRequest(content);
         HttpResponse httpResponse = client.execute(request);
         request.releaseConnection();
         return httpResponse;
     }
 
-    private HttpPost createRequest(String content) throws UnsupportedEncodingException {
-        HttpPost request = new HttpPost(this.targetUrl);
+    private HttpPost createRequest(String content) throws UnsupportedEncodingException, URISyntaxException {
+        LOGGER.info("sending request using address: {}", this.targetUrl);
+        URI targetAddress = new URI(this.targetUrl);
+        HttpPost request = new HttpPost(targetAddress);
+        if(urlContainsUserInfo(targetAddress)) {
+            request.addHeader(HttpHeaders.AUTHORIZATION, getAuthenticationHeaderForUser(targetAddress.getUserInfo()));
+        }
         StringEntity stringEntity = new StringEntity(content);
         request.addHeader(CONTENT_TYPE, APPLICATION_JSON);
         request.addHeader(X_ONAP_REQUEST_ID, MDC.get(REQUEST_ID));
@@ -95,4 +105,15 @@ public class HttpClientAdapterImpl implements HttpClientAdapter {
         return request;
     }
 
+    private boolean urlContainsUserInfo(URI targetAddress) {
+        return targetAddress.getUserInfo() != null && !targetAddress.getUserInfo().isEmpty();
+    }
+
+    private String getAuthenticationHeaderForUser(String userInfo) {
+        final byte[] encodedUserInfo = Base64.encodeBase64(
+            userInfo.getBytes(StandardCharsets.ISO_8859_1)
+        );
+        return String.format("Basic %s", new String(encodedUserInfo));
+    }
+
 }
index 1253e52..fddcec0 100644 (file)
@@ -10,7 +10,7 @@ management.endpoint.configprops.enabled=true
 management.endpoints.web.base-path=/
 management.endpoints.web.exposure.include=refresh,health
 
-ssl.clientCertificateEnabled=true
+ssl.clientCertificateEnabled=${USE_CERTIFICATE_FOR_AUTHORIZATION:true}
 ssl.strictHostnameVerification=${STRICT_HOSTNAME_VERIFICATION:false}
 ssl.clientCertificatePath=/app/store/cert.p12
 ssl.clientCertificatePasswordPath=/app/store/p12.pass
index cfb03d0..cfbc8c1 100644 (file)
 
 package org.onap.pnfsimulator.simulator.client;
 
+import org.apache.http.Header;
+import org.apache.http.HttpHeaders;
 import org.apache.http.HttpResponse;
 import org.apache.http.HttpStatus;
 import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpPost;
 import org.apache.http.conn.socket.PlainConnectionSocketFactory;
 import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.message.BasicHeader;
+import org.apache.tomcat.util.codec.binary.Base64;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
 import org.onap.pnfsimulator.simulator.client.utils.ssl.SslAuthenticationHelper;
 
 import java.io.IOException;
 import java.net.MalformedURLException;
+import java.nio.charset.StandardCharsets;
 import java.security.GeneralSecurityException;
+import java.util.List;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -60,12 +68,23 @@ class HttpClientAdapterImplTest {
 
     @Test
     void sendShouldSuccessfullySendRequestGivenValidUrl() throws IOException {
-        assertAdapterSentRequest("http://valid-url:8080", HttpStatus.SC_FORBIDDEN, HttpTestUtils.HTTP_MESSAGE_FORBIDDEN);
+        assertAdapterSentRequest("http://valid-url:8080",
+            HttpStatus.SC_FORBIDDEN, HttpTestUtils.HTTP_MESSAGE_FORBIDDEN);
     }
 
     @Test
     void sendShouldSuccessfullySendRequestGivenValidUrlUsingHttps() throws IOException {
-        assertAdapterSentRequest("https://valid-url:8443", HttpStatus.SC_ACCEPTED, HttpTestUtils.HTTP_MESSAGE_ACCEPTER);
+        assertAdapterSentRequest("https://valid-url:8443",
+            HttpStatus.SC_ACCEPTED, HttpTestUtils.HTTP_MESSAGE_ACCEPTER);
+    }
+
+    @Test
+    void sendShouldSuccessfullySendRequestUsingBasicAuth() throws IOException {
+        String testUserInfo = "user1:pass1";
+        Header authorizationHeader = createAuthorizationHeader(testUserInfo);
+        assertAdapterSentRequest("https://" + testUserInfo + "@valid-url:8443",
+            HttpStatus.SC_ACCEPTED, HttpTestUtils.HTTP_MESSAGE_ACCEPTER,
+            List.of(authorizationHeader));
     }
 
     @Test
@@ -98,7 +117,16 @@ class HttpClientAdapterImplTest {
         }
     }
 
+    private Header createAuthorizationHeader(String testUserInfo) {
+        String encodedUserInfo = new String(Base64.encodeBase64(testUserInfo.getBytes(StandardCharsets.UTF_8)));
+        return new BasicHeader(HttpHeaders.AUTHORIZATION, "Basic " + encodedUserInfo);
+    }
+
     private void assertAdapterSentRequest(String targetUrl, int responseCode, String responseMessage) throws IOException {
+        assertAdapterSentRequest(targetUrl, responseCode, responseMessage, List.of());
+    }
+
+    private void assertAdapterSentRequest(String targetUrl, int responseCode, String responseMessage, List<Header> expectedHeaders) throws IOException {
         HttpClientAdapter adapter = new HttpClientAdapterImpl(httpClient, targetUrl);
         doReturn(httpResponse).when(httpClient).execute(any());
         doReturn(createStatusLine(responseCode)).when(httpResponse).getStatusLine();
@@ -106,9 +134,12 @@ class HttpClientAdapterImplTest {
 
         HttpResponseAdapter response = adapter.send("test-msg");
 
-        verify(httpClient).execute(any());
+        ArgumentCaptor<HttpPost> httpPostCaptor = ArgumentCaptor.forClass(HttpPost.class);
+        verify(httpClient).execute(httpPostCaptor.capture());
+        Header[] headers = httpPostCaptor.getValue().getAllHeaders();
         assertEquals(responseCode, response.getCode());
         assertEquals(responseMessage, response.getMessage());
+        assertThat(headers).usingFieldByFieldElementComparator().containsAll(expectedHeaders);
     }
 
     private void assertAdapterInformsUserWhenServiceIsUnavailable(String targetUrl) throws IOException {