diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/pom.xml b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/pom.xml index 7a36a6f36ad..bf1e7018e61 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/pom.xml +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/pom.xml @@ -55,6 +55,11 @@ org.json.wso2 json + + org.slf4j + slf4j-simple + test + @@ -97,6 +102,15 @@ + + org.apache.maven.plugins + maven-surefire-plugin + + + src/test/resources/testng.xml + + + org.jacoco jacoco-maven-plugin diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/AuthenticationHandler.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/AuthenticationHandler.java index 276380ce863..b851ee4f8cc 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/AuthenticationHandler.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/AuthenticationHandler.java @@ -52,7 +52,7 @@ public class AuthenticationHandler extends AbstractHandler { private static final Log log = LogFactory.getLog(AuthenticationHandler.class); private RESTInvoker restInvoker; - private static final String X_JWT_ASSERTION = "X-JWT-Assertion"; + private static final String X_JWT_ASSERTION = "X-JWT-Assertion"; private static final String JWTTOKEN = "JWTToken"; private static final String AUTHORIZATION = "Authorization"; private static final String BEARER = "Bearer "; @@ -72,8 +72,8 @@ public class AuthenticationHandler extends AbstractHandler { /** * Handling the message and checking the security. * - * @param messageContext - * @return + * @param messageContext Request message context. + * @return Boolean value of the result of the processing the request. */ @Override public boolean handleRequest(org.apache.synapse.MessageContext messageContext) { @@ -87,7 +87,7 @@ public class AuthenticationHandler extends AbstractHandler { Map headers = (Map) axisMC.getProperty(MessageContext.TRANSPORT_HEADERS); try { int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); - RESTResponse response; + RESTResponse response = null; if (headers.containsKey(AuthConstants.MDM_SIGNATURE)) { String mdmSignature = headers.get(AuthConstants.MDM_SIGNATURE); @@ -95,7 +95,7 @@ public class AuthenticationHandler extends AbstractHandler { log.debug("Verify Cert:\n" + mdmSignature); } String deviceType = this.getDeviceType(messageContext.getTo().getAddress().trim()); - if (deviceType == null){ + if (deviceType == null) { return false; } URI certVerifyUrl = new URI(iotServerConfiguration.getVerificationEndpoint() + deviceType); @@ -108,8 +108,7 @@ public class AuthenticationHandler extends AbstractHandler { Gson gson = new Gson(); String certVerifyContent = gson.toJson(certificate); - response = restInvoker.invokePOST(certVerifyUrl, certVerifyHeaders, null, - null, certVerifyContent); + response = restInvoker.invokePOST(certVerifyUrl, certVerifyHeaders, certVerifyContent); String str = response.getContent(); if (log.isDebugEnabled()) { @@ -140,8 +139,7 @@ public class AuthenticationHandler extends AbstractHandler { Gson gson = new Gson(); String certVerifyContent = gson.toJson(certificate); - response = restInvoker.invokePOST(certVerifyUrl, certVerifyHeaders, null, - null, certVerifyContent); + response = restInvoker.invokePOST(certVerifyUrl, certVerifyHeaders, certVerifyContent); if (log.isDebugEnabled()) { log.debug("Verify response:" + response.getContent()); } @@ -155,8 +153,6 @@ public class AuthenticationHandler extends AbstractHandler { if (x509 != null) { headers.put(AuthConstants.PROXY_MUTUAL_AUTH_HEADER, CertificateGenerator.getCommonName(x509)); return true; - } else { - response = null; } } else if (headers.containsKey(AuthConstants.ENCODED_PEM)) { String encodedPem = headers.get(AuthConstants.ENCODED_PEM); @@ -173,8 +169,7 @@ public class AuthenticationHandler extends AbstractHandler { certificate.setSerial(""); Gson gson = new Gson(); String certVerifyContent = gson.toJson(certificate); - response = restInvoker.invokePOST(certVerifyUrl, certVerifyHeaders, null, - null, certVerifyContent); + response = restInvoker.invokePOST(certVerifyUrl, certVerifyHeaders, certVerifyContent); if (log.isDebugEnabled()) { log.debug("Verify response:" + response.getContent()); } diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/invoker/RESTInvoker.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/invoker/RESTInvoker.java index da182e325b7..bd59e03dc14 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/invoker/RESTInvoker.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/invoker/RESTInvoker.java @@ -17,11 +17,9 @@ */ package org.wso2.carbon.apimgt.handlers.invoker; -import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.http.Header; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.*; import org.apache.http.entity.StringEntity; @@ -32,7 +30,6 @@ import org.apache.http.util.EntityUtils; import java.io.IOException; import java.net.URI; -import java.nio.charset.StandardCharsets; import java.util.Map; import java.util.Set; @@ -63,7 +60,7 @@ public class RESTInvoker { .setConnectionManager(connectionManager) .setDefaultRequestConfig(defaultRequestConfig) .build(); - if(log.isDebugEnabled()){ + if (log.isDebugEnabled()) { log.debug("REST client initialized with " + "maxTotalConnection = " + maxTotalConnections + "maxConnectionsPerRoute = " + maxTotalConnectionsPerRoute + @@ -72,14 +69,11 @@ public class RESTInvoker { } - public RESTResponse invokePOST(URI uri, Map requestHeaders, String username, - String password, String payload) throws IOException { + public RESTResponse invokePOST(URI uri, Map requestHeaders, String payload) throws IOException { HttpPost httpPost = null; CloseableHttpResponse response = null; - Header[] headers; int httpStatus; - String contentType; String output; try { httpPost = new HttpPost(uri); @@ -90,11 +84,9 @@ public class RESTInvoker { httpPost.setHeader(header, requestHeaders.get(header)); } } - response = sendReceiveRequest(httpPost, username, password); + response = sendReceiveRequest(httpPost); output = IOUtils.toString(response.getEntity().getContent()); - headers = response.getAllHeaders(); httpStatus = response.getStatusLine().getStatusCode(); - contentType = response.getEntity().getContentType().getValue(); if (log.isDebugEnabled()) { log.debug("Invoked POST " + uri.toString() + " - Input payload: " + payload + " - Response message: " + output); @@ -108,21 +100,11 @@ public class RESTInvoker { httpPost.releaseConnection(); } } - return new RESTResponse(contentType, output, headers, httpStatus); + return new RESTResponse(output, httpStatus); } - private CloseableHttpResponse sendReceiveRequest(HttpRequestBase requestBase, String username, String password) + private CloseableHttpResponse sendReceiveRequest(HttpRequestBase requestBase) throws IOException { - CloseableHttpResponse response; - if (username != null && !username.equals("") && password != null) { - String combinedCredentials = username + ":" + password; - byte[] encodedCredentials = Base64.encodeBase64(combinedCredentials.getBytes(StandardCharsets.UTF_8)); - requestBase.addHeader("Authorization", "Basic " + new String(encodedCredentials)); - - response = client.execute(requestBase); - } else { - response = client.execute(requestBase); - } - return response; + return client.execute(requestBase); } } diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/invoker/RESTResponse.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/invoker/RESTResponse.java index 57b4d58f940..205130b30e3 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/invoker/RESTResponse.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/invoker/RESTResponse.java @@ -17,40 +17,25 @@ */ package org.wso2.carbon.apimgt.handlers.invoker; -import org.apache.http.Header; /** * RESTResponse class holds the data retrieved from the HTTP invoke response. */ public class RESTResponse { - private String contentType; private String content; - private Header[] headers; private int httpStatus; /** * Constructor * - * @param contentType from the REST invoke response * @param content from the REST invoke response - * @param headers from the REST invoke response * @param httpStatus from the REST invoke response */ - RESTResponse(String contentType, String content, Header[] headers, int httpStatus) { - this.contentType = contentType; + RESTResponse(String content, int httpStatus) { this.content = content; - this.headers = headers; this.httpStatus = httpStatus; } - /** - * Get the content type of the EST invoke response - * - * @return String content type of the response - */ - public String getContentType() { - return contentType; - } /** * Get contents of the REST invoke response @@ -61,15 +46,6 @@ public class RESTResponse { return content; } - /** - * Get headers of the REST invoke response - * - * @return headers of the REST invoke response - */ - public Header[] getHeaders() { - return headers; - } - /** * Get the HTTP Status code from REST invoke response * diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/utils/Utils.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/utils/Utils.java index 1a2d7e58596..a36dc0f647e 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/utils/Utils.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/utils/Utils.java @@ -59,6 +59,7 @@ public class Utils { /** * This method initializes the iot-api-config.xml file. + * * @return IoTServerConfiguration Object based on the configuration file. */ public static IOTServerConfiguration initConfig() { @@ -67,10 +68,11 @@ public class Utils { /** * This methods initialized the iot-api-config.xml from provided path. + * * @param path The actual file path of iot-api-config.xml * @return The instance of the IOTServerConfiguration based on the configuration. */ - public static IOTServerConfiguration initConfig(String path){ + public static IOTServerConfiguration initConfig(String path) { try { File file = new File(path); Document doc = Utils.convertToDocument(file); @@ -145,15 +147,15 @@ public class Utils { getClientSecretes(iotServerConfiguration, restInvoker); } URI tokenUrl = new URI(iotServerConfiguration.getOauthTokenEndpoint()); - String tokenContent = "grant_type=password&username=" + iotServerConfiguration.getUsername()+ "&password=" + + String tokenContent = "grant_type=password&username=" + iotServerConfiguration.getUsername() + "&password=" + iotServerConfiguration.getPassword() + "&scope=activity-view"; String tokenBasicAuth = "Basic " + Base64.encode((clientId + ":" + clientSecret).getBytes()); Map tokenHeaders = new HashMap<>(); tokenHeaders.put("Authorization", tokenBasicAuth); tokenHeaders.put("Content-Type", "application/x-www-form-urlencoded"); - RESTResponse response = restInvoker.invokePOST(tokenUrl, tokenHeaders, null, null, tokenContent); - if(log.isDebugEnabled()) { + RESTResponse response = restInvoker.invokePOST(tokenUrl, tokenHeaders, tokenContent); + if (log.isDebugEnabled()) { log.debug("Token response:" + response.getContent()); } JSONObject jsonResponse = new JSONObject(response.getContent()); @@ -168,6 +170,7 @@ public class Utils { /** * This method register an application to get the client key and secret. + * * @param iotServerConfiguration Instance of the IoTServerConfiguration. * @throws APIMCertificateMGTException */ @@ -189,7 +192,7 @@ public class Utils { dcrHeaders.put(AuthConstants.CONTENT_TYPE_HEADER, AuthConstants.CONTENT_TYPE); dcrHeaders.put(AuthConstants.AUTHORIZATION_HEADER, AuthConstants.BASIC_AUTH_PREFIX + basicAuth); URI dcrUrl = new URI(iotServerConfiguration.getDynamicClientRegistrationEndpoint()); - RESTResponse response = restInvoker.invokePOST(dcrUrl, dcrHeaders, null, null, dcrContent); + RESTResponse response = restInvoker.invokePOST(dcrUrl, dcrHeaders, dcrContent); if (log.isDebugEnabled()) { log.debug("DCR response :" + response.getContent()); } diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/test/java/org/wso2/carbon/apimgt/handlers/AuthenticationHandlerTest.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/test/java/org/wso2/carbon/apimgt/handlers/AuthenticationHandlerTest.java index f68a9bd9733..f42505409af 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/test/java/org/wso2/carbon/apimgt/handlers/AuthenticationHandlerTest.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/test/java/org/wso2/carbon/apimgt/handlers/AuthenticationHandlerTest.java @@ -78,7 +78,7 @@ public class AuthenticationHandlerTest extends BaseAPIHandlerTest { @Test(description = "Handle request with without device type", dependsOnMethods = "testHandleRequestWithEmptyTransportHeader") - public void testHandleRequestWithURISyntaxError() throws Exception { + public void testHandleRequestWithoutDeviceType() throws Exception { HashMap transportHeaders = new HashMap<>(); transportHeaders.put(AuthConstants.MDM_SIGNATURE, "some cert"); boolean response = this.handler.handleRequest(createSynapseMessageContext("", this.synapseConfiguration, @@ -87,7 +87,7 @@ public class AuthenticationHandlerTest extends BaseAPIHandlerTest { } @Test(description = "Handle request with device type URI with MDM ceritificate", - dependsOnMethods = "testHandleRequestWithURISyntaxError") + dependsOnMethods = "testHandleRequestWithoutDeviceType") public void testHandleSuccessfulRequestMDMCertificate() throws Exception { HashMap transportHeaders = new HashMap<>(); transportHeaders.put(AuthConstants.MDM_SIGNATURE, "some cert"); @@ -150,6 +150,70 @@ public class AuthenticationHandlerTest extends BaseAPIHandlerTest { this.mockClient.reset(); } + @Test(description = "Handle request with device type URI with Encoded Pem with invalid response", + dependsOnMethods = "testHandleSuccessRequestEncodedPem") + public void testHandleSuccessRequestEncodedPemInvalidResponse() throws Exception { + HashMap transportHeaders = new HashMap<>(); + transportHeaders.put(AuthConstants.ENCODED_PEM, "encoded pem"); + setMockClient(); + this.mockClient.setResponse(getAccessTokenReponse()); + this.mockClient.setResponse(getInvalidResponse()); + MessageContext messageContext = createSynapseMessageContext("", this.synapseConfiguration, + transportHeaders, "https://test.com/testservice/api/testdevice"); + boolean response = this.handler.handleRequest(messageContext); + Assert.assertFalse(response); + this.mockClient.reset(); + } + + @Test(description = "Handle request with cert management exception ", + dependsOnMethods = "testHandleSuccessRequestEncodedPem") + public void testHandleRequestWithCertMgmtException() throws Exception { + HashMap transportHeaders = new HashMap<>(); + transportHeaders.put(AuthConstants.ENCODED_PEM, "encoded pem"); + setMockClient(); + this.mockClient.setResponse(null); + MessageContext messageContext = createSynapseMessageContext("", this.synapseConfiguration, + transportHeaders, "https://test.com/testservice/api/testdevice"); + boolean response = this.handler.handleRequest(messageContext); + Assert.assertFalse(response); + this.mockClient.reset(); + } + + @Test(description = "Handle request with IO exception", + dependsOnMethods = "testHandleRequestWithCertMgmtException") + public void testHandleRequestWithIOException() throws Exception { + HashMap transportHeaders = new HashMap<>(); + transportHeaders.put(AuthConstants.ENCODED_PEM, "encoded pem"); + setMockClient(); + this.mockClient.setResponse(getAccessTokenReponse()); + this.mockClient.setResponse(null); + MessageContext messageContext = createSynapseMessageContext("", this.synapseConfiguration, + transportHeaders, "https://test.com/testservice/api/testdevice"); + boolean response = this.handler.handleRequest(messageContext); + Assert.assertFalse(response); + this.mockClient.reset(); + } + + @Test(description = "Handle request with URI exception", + dependsOnMethods = "testHandleRequestWithIOException") + public void testHandleRequestWithURIException() throws Exception { + TestUtils.resetSystemProperties(); + HashMap transportHeaders = new HashMap<>(); + transportHeaders.put(AuthConstants.MDM_SIGNATURE, "some cert"); + AuthenticationHandler handler = new AuthenticationHandler(); + boolean response = handler.handleRequest(createSynapseMessageContext("", this.synapseConfiguration, + transportHeaders, "https://test.com/testservice/api/testdevice")); + Assert.assertFalse(response); + TestUtils.setSystemProperties(); + } + + @Test(description = "Handle response") + public void testHandleResponse() throws Exception { + boolean response = this.handler.handleResponse(null); + Assert.assertTrue(response); + } + + private static MessageContext createSynapseMessageContext( String payload, SynapseConfiguration config, HashMap transportHeaders, String address) throws Exception { @@ -228,6 +292,16 @@ public class AuthenticationHandlerTest extends BaseAPIHandlerTest { return mockDCRResponse; } + private CloseableHttpResponse getInvalidResponse() throws UnsupportedEncodingException { + CloseableHttpResponse mockDCRResponse = new MockHttpResponse(); + BasicHttpEntity responseEntity = new BasicHttpEntity(); + responseEntity.setContent(new ByteArrayInputStream("invalid response".getBytes(StandardCharsets.UTF_8.name()))); + responseEntity.setContentType(TestUtils.CONTENT_TYPE); + mockDCRResponse.setEntity(responseEntity); + mockDCRResponse.setStatusLine(new BasicStatusLine(new ProtocolVersion("http", 1, 0), 400, "Bad Request")); + return mockDCRResponse; + } + private String getContent(String filePath) throws IOException { FileReader fileReader = new FileReader(filePath); BufferedReader bufferedReader = new BufferedReader(fileReader); diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/test/java/org/wso2/carbon/apimgt/handlers/mock/MockClient.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/test/java/org/wso2/carbon/apimgt/handlers/mock/MockClient.java index 6c369690260..0c8ab4f6bd9 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/test/java/org/wso2/carbon/apimgt/handlers/mock/MockClient.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/test/java/org/wso2/carbon/apimgt/handlers/mock/MockClient.java @@ -41,7 +41,11 @@ public class MockClient extends CloseableHttpClient { throws IOException { if (this.responseCount < this.responses.size()) { this.responseCount++; - return this.responses.get(this.responseCount - 1); + CloseableHttpResponse response = this.responses.get(this.responseCount - 1); + if (response == null) { + throw new IOException("test exception"); + } + return response; } else { return new MockHttpResponse(); }