Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
/*
* Copyright (c) 2025, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you 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.
*/
package org.wso2.micro.gateway.tests.common;

import com.sun.net.httpserver.HttpsConfigurator;
import com.sun.net.httpserver.HttpsParameters;
import com.sun.net.httpserver.HttpsServer;
import io.netty.handler.codec.http.HttpHeaderNames;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wso2.apimgt.gateway.cli.constants.TokenManagementConstants;

import javax.net.ssl.*;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.io.FileInputStream;

/**
* Mock HTTP server for testing Open API tests.
*/
public class MockBackEndServerForMultiSSLProfiles extends Thread {

private static final Logger log = LoggerFactory.getLogger(MockHttpServer.class);
private HttpsServer httpServer;
private HttpsServer incorrectHttpServer;
private static int backEndServerPort;

public static void main(String[] args) {

MockBackEndServerForMultiSSLProfiles mockBackEndServer = new MockBackEndServerForMultiSSLProfiles(backEndServerPort);
mockBackEndServer.start();
}

public MockBackEndServerForMultiSSLProfiles(int port) {

backEndServerPort = port;
}

public void run() {

if (backEndServerPort < 0) {
throw new RuntimeException("Server port is not defined");
}
try {
httpServer = HttpsServer.create(new InetSocketAddress(backEndServerPort), 0);
incorrectHttpServer = HttpsServer.create(new InetSocketAddress(backEndServerPort + 1), 0);

httpServer.setHttpsConfigurator(new HttpsConfigurator(
getSslContext("keyStores/dynamicSSL/KS.p12", "keyStores/dynamicSSL/TS.p12")) {
public void configure(HttpsParameters params) {

try {
// initialise the SSL context
SSLContext sslContext = SSLContext.getDefault();
SSLEngine engine = sslContext.createSSLEngine();
params.setNeedClientAuth(false);
params.setCipherSuites(engine.getEnabledCipherSuites());
params.setProtocols(engine.getEnabledProtocols());
// get the default parameters
SSLParameters defaultSSLParameters = sslContext
.getDefaultSSLParameters();
params.setSSLParameters(defaultSSLParameters);
} catch (Exception ex) {
log.error("Failed to create HTTPS port");
}
}
});

incorrectHttpServer.setHttpsConfigurator(new HttpsConfigurator(
getSslContext("keyStores/dynamicSSL/keystore.p12", "keyStores/dynamicSSL/truststore.p12")) {
public void configure(HttpsParameters params) {

try {
// initialise the SSL context
SSLContext sslContext = SSLContext.getDefault();
SSLEngine engine = sslContext.createSSLEngine();
params.setNeedClientAuth(false);
params.setCipherSuites(engine.getEnabledCipherSuites());
params.setProtocols(engine.getEnabledProtocols());
// get the default parameters
SSLParameters defaultSSLParameters = sslContext
.getDefaultSSLParameters();
params.setSSLParameters(defaultSSLParameters);
} catch (Exception ex) {
log.error("Failed to create HTTPS port");
}
}
});
String base = "/v1";
httpServer.createContext(base + "/pet/findByStatus", exchange -> {

byte[] response = ResponseConstants.responseBodyV1.getBytes();
exchange.getResponseHeaders().set(HttpHeaderNames.CONTENT_TYPE.toString(),
TokenManagementConstants.CONTENT_TYPE_APPLICATION_JSON);
exchange.sendResponseHeaders(HttpURLConnection.HTTP_OK, response.length);
exchange.getResponseBody().write(response);
exchange.close();
});
incorrectHttpServer.createContext(base + "/pet/2", exchange -> {
byte[] response = ResponseConstants.getPetResponse.getBytes();
exchange.getResponseHeaders().set(HttpHeaderNames.CONTENT_TYPE.toString(),
TokenManagementConstants.CONTENT_TYPE_APPLICATION_JSON);
exchange.sendResponseHeaders(HttpURLConnection.HTTP_OK, response.length);
exchange.getResponseBody().write(response);
exchange.close();
});
incorrectHttpServer.createContext(base + "/pet/", exchange -> {
byte[] response = ResponseConstants.getPetResponse.getBytes();
exchange.getResponseHeaders().set(HttpHeaderNames.CONTENT_TYPE.toString(),
TokenManagementConstants.CONTENT_TYPE_APPLICATION_JSON);
exchange.sendResponseHeaders(HttpURLConnection.HTTP_OK, response.length);
exchange.getResponseBody().write(response);
exchange.close();
});

httpServer.start();
incorrectHttpServer.start();
} catch (Exception e) {
log.error("Error occurred while setting up mock server", e);
}
}

public void stopIt() {

httpServer.stop(0);
incorrectHttpServer.stop(0);
}

private SSLContext getSslContext(String keystorePath, String truststorePath) throws Exception {
final char[] password = "ballerina".toCharArray();

KeyStore keyStore = KeyStore.getInstance("PKCS12");
String keyPath = getClass().getClassLoader()
.getResource(keystorePath).getPath();
final InputStream is = new FileInputStream(keyPath);
keyStore.load(is, password);

KeyStore trustStore = KeyStore.getInstance("PKCS12");
String trustPath = getClass().getClassLoader()
.getResource(truststorePath).getPath();
final InputStream tsIn = new FileInputStream(trustPath);
trustStore.load(tsIn, password);

String kmAlg = KeyManagerFactory.getDefaultAlgorithm();
String tmAlg = TrustManagerFactory.getDefaultAlgorithm();

KeyManagerFactory kmf = KeyManagerFactory.getInstance(kmAlg);
kmf.init(keyStore, password);

TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmAlg);
tmf.init(trustStore);

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
return sslContext;
}

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright (c) 2025, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you 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.
*/
package org.wso2.micro.gateway.tests.multiSSLProfiles;

import io.netty.handler.codec.http.HttpHeaderNames;
import org.json.JSONObject;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.wso2.micro.gateway.tests.common.BaseTestCase;
import org.wso2.micro.gateway.tests.common.model.ApplicationDTO;
import org.wso2.micro.gateway.tests.util.HttpClientRequest;
import org.wso2.micro.gateway.tests.util.TestConstant;
import org.wso2.micro.gateway.tests.util.TokenUtil;

import java.util.HashMap;
import java.util.Map;

public class MultiSSLProfilesTestCase extends BaseTestCase {
protected String jwtTokenProd;
protected String context = "v1";
@BeforeClass()
public void start() throws Exception {

String project = "MultiSSLProfileProject";
//Define application info

ApplicationDTO application = new ApplicationDTO();
application.setName("jwtApp");
application.setTier("Unlimited");
application.setId((int) (Math.random() * 1000));
jwtTokenProd = TokenUtil.getBasicJWT(application, new JSONObject(), TestConstant.KEY_TYPE_PRODUCTION, 3600);

//generate apis with CLI and start the micro gateway server
super.init(project, new String[] { "multiSSLProfiles/multi_ssl_profiles.yaml"}, null,
"confs/multi-ssl-profiles.conf");
}

@Test(description = "Test invoking a backend with a correct truststore and keystore")
public void testCorrectTrustStoreAndKeyStore() throws Exception {
Map<String, String> headers = new HashMap<>();
headers.put(HttpHeaderNames.AUTHORIZATION.toString(), "Bearer " + jwtTokenProd);
// invokes the 2381, which contains the correct truststore and keystore
org.wso2.micro.gateway.tests.util.HttpResponse response = HttpClientRequest
.doGet(getServiceURLHttp("petstore/v1/pet/findByStatus"), headers);
Assert.assertNotNull(response);
Assert.assertEquals(response.getResponseCode(), 200);
}

@Test(description = "Test invoking a backend with an incorrect truststore and keystore")
public void testIncorrectTrustStoreAndKeyStore() throws Exception {
Map<String, String> headers = new HashMap<>();
headers.put(HttpHeaderNames.AUTHORIZATION.toString(), "Bearer " + jwtTokenProd);
// invokes the backend at port 2382, which contains an incorrect truststore and keystore
org.wso2.micro.gateway.tests.util.HttpResponse response = HttpClientRequest
.doGet(getServiceURLHttp("/petstore/v1/pet/10"), headers);
Assert.assertNull(response);
}

@AfterClass
public void stop() throws Exception {
//Stop all the mock servers
super.finalize();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
import org.testng.Assert;
import org.wso2.micro.gateway.tests.common.JMSPublisher;
import org.wso2.micro.gateway.tests.common.MockBackEndServer;
import org.wso2.micro.gateway.tests.common.MockBackEndServerForMultiSSLProfiles;
import org.wso2.micro.gateway.tests.context.Utils;

import java.io.File;

public class PreRequisites {
private MockBackEndServer mockBackEndServer;
private MockBackEndServerForMultiSSLProfiles mockBackEndServerForMultiSSL;
@BeforeSuite
private void initializeMessageBroker() throws Exception {
JMSPublisher jmsPublisher = new JMSPublisher();
Expand All @@ -27,10 +29,20 @@ public void startMockBackendServer() {
mockBackEndServer.start();
}

@BeforeSuite
public void startMockBackendServerForMultiSSL() {
int port = 2381;
boolean isOpen = Utils.isPortOpen(port);
Assert.assertFalse(isOpen, "Port: " + port + " already in use.");
mockBackEndServerForMultiSSL = new MockBackEndServerForMultiSSLProfiles(port);
mockBackEndServerForMultiSSL.start();
}

@AfterSuite
public void stop() throws Exception {
//Stop all the mock servers
mockBackEndServer.stopIt();
mockBackEndServerForMultiSSL.stopIt();
}

@BeforeSuite
Expand Down
34 changes: 34 additions & 0 deletions tests/src/test/resources/confs/multi-ssl-profiles.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[listenerConfig]
httpPort=9590
httpsPort=9595
tokenListenerPort=9596

[[httpClients.sslConfig]]
hostname = "localhost"
port = 2380
# SSL Protocol to be used
protocolName = "TLS"
# List of ciphers to be used
ciphers=""
# SSL/TLS protocols to be enabled
protocolVersions = "TLSv1.2,TLSv1.1"
# Internal keystore
keyStorePath = "${mgw-runtime.home}/runtime/bre/security/ballerinaKeystore.p12"
keyStorePassword = "ballerina"
# Truststore
trustStorePath = "${mgw-runtime.home}/runtime/bre/security/ballerinaTruststore.p12"
trustStorePassword = "ballerina"

[[httpClients.sslConfig]]
# SSL Protocol to be used
protocolName = "TLS"
# List of ciphers to be used
ciphers=""
# SSL/TLS protocols to be enabled
protocolVersions = "TLSv1.2,TLSv1.1"
# Internal keystore
keyStorePath = "${mgw-runtime.home}/runtime/bre/security/ballerinaKeystore.p12"
keyStorePassword = "ballerina"
# Truststore
trustStorePath = "${mgw-runtime.home}/runtime/bre/security/ballerinaTruststore.p12"
trustStorePassword = "ballerina"
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading