Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: fixed critical sonar issues #40

Merged
merged 7 commits into from
Oct 18, 2024
Merged
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
7 changes: 7 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # SonarCloud: Shallow clones should be disabled for a better relevancy of analysis

# Setting up both JDK 11 and 17
# 11 is used for compiling and running tests
# 17 is required by sonar
- name: Set up JDK 11
uses: actions/setup-java@v4
with:
Expand Down Expand Up @@ -70,3 +74,6 @@ jobs:
reporter: java-junit
list-suites: 'failed'
list-tests: 'failed'
- name: Build example-adapter
working-directory: ./example-adapter
run: ./gradlew --include-build ../src build
6 changes: 6 additions & 0 deletions example-adapter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ X-Road Example Adapter can be built using the provided Gradle wrapper. The follo
./gradlew clean build
```

To build the project with locally built XRd4J library, the following command can be used:

```bash
./gradlew --include-build ../src build
```

When successfully built, the following artifacts are produced in the `build/libs` directory:

* `example-adapter-x.x.x.war` : a deployable WAR file
Expand Down
1 change: 1 addition & 0 deletions src/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ tasks.withType<Javadoc>() {
outputs.dirs(file("$projectDir/../javadoc"))
options.encoding = "UTF-8"
options.destinationDirectory = file("$projectDir/../javadoc")
(options as StandardJavadocDocletOptions).addBooleanOption("Xdoclint:none", true)
}

dependencyCheck {
Expand Down
3 changes: 3 additions & 0 deletions src/client/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ dependencies {
api(project(":rest"))

testImplementation(libs.bundles.testImplementation)
testImplementation(libs.org.wiremock.wiremock)
testImplementation(libs.org.assertj.assertjCore)
testImplementation(libs.org.mockito.mockitoCore)
}


Expand Down
28 changes: 19 additions & 9 deletions src/client/src/main/java/org/niis/xrd4j/client/SOAPClientImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,16 @@ public class SOAPClientImpl implements SOAPClient {
* @throws SOAPException if there's a SOAP error
*/
public SOAPClientImpl() throws SOAPException {
this.connectionFactory = SOAPConnectionFactory.newInstance();
this(SOAPConnectionFactory.newInstance());
}

/**
* Constructs and initializes a new SOAPClientImpl.
*
* @param connectionFactory SOAPConnectionFactory object
*/
SOAPClientImpl(SOAPConnectionFactory connectionFactory) {
this.connectionFactory = connectionFactory;
}

/**
Expand All @@ -93,14 +102,15 @@ public SOAPMessage send(final SOAPMessage request, final String url) throws SOAP
LOGGER.error(ex.getMessage(), ex);
throw new XRd4JRuntimeException(ex.getMessage());
}
SOAPConnection connection = connectionFactory.createConnection();
LOGGER.debug(SEND_SOAP_TO, url);
LOGGER.trace("Outgoing SOAP request : \"{}\".", SOAPHelper.toString(request));
SOAPMessage response = connection.call(request, client);
LOGGER.debug("SOAP response received.");
LOGGER.trace("Incoming SOAP response : \"{}\".", SOAPHelper.toString(response));
connection.close();
return response;

try (SOAPConnection connection = connectionFactory.createConnection()) {
LOGGER.debug(SEND_SOAP_TO, url);
LOGGER.trace("Outgoing SOAP request : \"{}\".", SOAPHelper.toString(request));
SOAPMessage response = connection.call(request, client);
LOGGER.debug("SOAP response received.");
LOGGER.trace("Incoming SOAP response : \"{}\".", SOAPHelper.toString(response));
return response;
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ private ClientUtil() {
*/
public static void doTrustToCertificates() throws XRd4JException {
// Create a trust manager that does not validate certificate chains
@SuppressWarnings("java:S4830") // Sonar rule: "Server certificates should be verified during SSL/TLS connections"
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {

Expand All @@ -91,7 +92,7 @@ public void checkClientTrusted(X509Certificate[] certs, String authType) throws

try {
// Install the all-trusting trust manager
SSLContext sc = SSLContext.getInstance("SSL");
SSLContext sc = SSLContext.getInstance("TLSv1.2");
sc.init(null, trustAllCerts, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HostnameVerifier hv = (String urlHostName, SSLSession session) -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,23 @@
import org.niis.xrd4j.common.member.ConsumerMember;
import org.niis.xrd4j.common.member.ProducerMember;
import org.niis.xrd4j.common.message.ServiceRequest;
import org.niis.xrd4j.common.util.SOAPHelper;

import jakarta.xml.soap.Node;
import jakarta.xml.soap.SOAPConnection;
import jakarta.xml.soap.SOAPConnectionFactory;
import jakarta.xml.soap.SOAPElement;
import jakarta.xml.soap.SOAPEnvelope;
import jakarta.xml.soap.SOAPException;
import jakarta.xml.soap.SOAPMessage;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

/**
* Test cases for SOAPClientImpl class. Test cases cover only cases where SOAP
Expand All @@ -63,7 +70,7 @@ void setUp() throws Exception {
ProducerMember producer = new ProducerMember("FI", "COM", "MEMBER2", "subsystem", "getRandom", "v1");
producer.setNamespacePrefix("ns1");
producer.setNamespaceUrl("http://consumer.x-road.ee");
this.request = new ServiceRequest<String>(consumer, producer, "1234567890");
this.request = new ServiceRequest<>(consumer, producer, "1234567890");
this.request.setUserId("EE1234567890");
this.request.setRequestData("1234567890");

Expand Down Expand Up @@ -198,6 +205,28 @@ void testException4() throws SOAPException {
// OK
}
}*/


@Test
void testSendRequest() throws SOAPException {
var connectionFactory = mock(SOAPConnectionFactory.class);
var connection = mock(SOAPConnection.class);
when(connectionFactory.createConnection()).thenReturn(connection);
var response = SOAPHelper.toSOAP(
"<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
+ " <SOAP-ENV:Body>\n"
+ " <data>1234567890</data>\n"
+ " </SOAP-ENV:Body>\n"
+ "</SOAP-ENV:Envelope>");
when(connection.call(any(), any())).thenReturn(response);

var client = new SOAPClientImpl(connectionFactory);
var receivedResponse = client.send(request.getSoapMessage(), "http://localhost:8080");

Assertions.assertThat(receivedResponse).isEqualTo(response);
}


private final class TestRequestSerializer extends AbstractServiceRequestSerializer {

protected void serializeRequest(ServiceRequest serviceRequest, SOAPElement soapRequest, SOAPEnvelope envelope) throws SOAPException {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* The MIT License
* Copyright © 2018 Nordic Institute for Interoperability Solutions (NIIS)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.niis.xrd4j.client.util;

import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
import com.github.tomakehurst.wiremock.junit5.WireMockTest;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLSocketFactory;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;

import static com.github.tomakehurst.wiremock.client.WireMock.get;
import static com.github.tomakehurst.wiremock.client.WireMock.ok;
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
import static org.assertj.core.api.Assertions.assertThat;

@WireMockTest(httpsEnabled = true)
class ClientUtilTest {

private SSLSocketFactory defaultSSLSocketFactory;
private HostnameVerifier defaultHostnameVerifier;

@BeforeEach
void setUp() {
defaultSSLSocketFactory = HttpsURLConnection.getDefaultSSLSocketFactory();
defaultHostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier();
}

@AfterEach
void tearDown() {
HttpsURLConnection.setDefaultSSLSocketFactory(defaultSSLSocketFactory);
HttpsURLConnection.setDefaultHostnameVerifier(defaultHostnameVerifier);
}


@Test
void certificateNotTrusted(WireMockRuntimeInfo wm) throws Exception {
stubFor(get("/").willReturn(ok()));

URL url = new URL(wm.getHttpsBaseUrl());
var connection = (HttpURLConnection) url.openConnection();

Assertions.assertThatThrownBy(connection::getResponseCode)
.isInstanceOf(SSLHandshakeException.class)
.hasMessageStartingWith("PKIX path building failed");

}

@Test
void doTrustToCertificates(WireMockRuntimeInfo wm) throws Exception {
stubFor(get("/").willReturn(ok()));

ClientUtil.doTrustToCertificates();

var responseCode = getResponseCode(wm.getHttpsBaseUrl());

assertThat(responseCode).isEqualTo(SC_OK);
}

private int getResponseCode(String url) throws IOException {
var connection = (HttpURLConnection) new URL(url).openConnection();
return connection.getResponseCode();
}

}
3 changes: 3 additions & 0 deletions src/client/src/test/resources/log4j2-test.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,8 @@
<Logger name="org.niis.xrd4j.client" level="debug" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
<Logger name="org.niis.xrd4j.client.SOAPClientImpl" level="trace" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
</Loggers>
</Configuration>
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ public SymmetricEncrypter(Key key, byte[] iv, String transformation) {
* @throws BadPaddingException if there's an error
*/
@Override
@SuppressWarnings("java:S3329")
protected byte[] encrypt(byte[] plaintext) throws NoSuchAlgorithmException, InvalidKeyException,
InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
Cipher cipher = Cipher.getInstance(this.transformation);
Expand Down
48 changes: 16 additions & 32 deletions src/common/src/main/java/org/niis/xrd4j/common/util/SOAPHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,15 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.w3c.dom.Node.ELEMENT_NODE;
import static org.w3c.dom.Node.TEXT_NODE;

Expand All @@ -67,8 +69,7 @@
* @author Petteri Kivimäki
*/
public final class SOAPHelper {

private static final String CHARSET = "UTF-8";
private static final Charset CHARSET = UTF_8;
private static final Logger LOGGER = LoggerFactory.getLogger(SOAPHelper.class);
private static final MessageFactory MSG_FACTORY;

Expand Down Expand Up @@ -132,7 +133,7 @@ public static String toString(SOAPMessage message) {
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
message.writeTo(out);
return new String(out.toByteArray(), CHARSET);
return out.toString(CHARSET);
} catch (Exception ex) {
LOGGER.error(ex.getMessage(), ex);
return "";
Expand All @@ -150,8 +151,10 @@ public static String toString(Node node) {
try {
TransformerFactory factory = TransformerFactory.newInstance();
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
Transformer t = factory.newTransformer();
t.setOutputProperty(OutputKeys.ENCODING, CHARSET);
t.setOutputProperty(OutputKeys.ENCODING, CHARSET.toString());
t.transform(new DOMSource(node), new StreamResult(sw));
return sw.toString();
} catch (Exception ex) {
Expand Down Expand Up @@ -410,7 +413,7 @@ public static void removeNamespace(Node node) {
* @param attachments list of attachments to be searched
* @return string value of the attachment or null
*/
public static String getStringAttachment(String contentId, Iterator attachments) {
public static String getStringAttachment(String contentId, Iterator<?> attachments) {
if (attachments == null) {
return null;
}
Expand Down Expand Up @@ -454,10 +457,7 @@ public static boolean hasAttachments(SOAPMessage message) {
if (message == null) {
return false;
}
if (message.countAttachments() == 0) {
return false;
}
return true;
return message.countAttachments() != 0;
}

/**
Expand Down Expand Up @@ -507,35 +507,19 @@ public static SOAPElement xmlStrToSOAPElement(String xml) {
public static Document xmlStrToDoc(String xml) {
LOGGER.debug("Convert XML string to XML document.");
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
builderFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
builderFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
builderFactory.setNamespaceAware(true);
InputStream stream = null;
Document doc = null;
InputStream stream;
Document doc;
try {
stream = new ByteArrayInputStream(xml.getBytes());
doc = builderFactory.newDocumentBuilder().parse(stream);
LOGGER.debug("Converting XML string to XML document succeeded.");
} catch (Exception e) {
// If exception starts with "Invalid byte", it means that ISO-8859-1
// character set is probably used. Try to convert the string to
// UTF-8.
if (e.getLocalizedMessage().startsWith("Invalid byte")) {
LOGGER.warn("Invalid characters detected.");
try {
LOGGER.debug("Try to convert XML string from ISO-8859-1 to UTF-8.");
stream = new ByteArrayInputStream(new String(xml.getBytes(), "ISO-8859-1").getBytes(CHARSET));
doc = builderFactory.newDocumentBuilder().parse(stream);
LOGGER.debug("Converting XML string from ISO-8859-1 to UTF-8 succeeded.");
} catch (Exception ex) {
LOGGER.error(ex.getMessage());
LOGGER.warn("Converting XML string to XML document failed.");
LOGGER.warn("Converting XML string from ISO-8859-1 to UTF-8 failed.");
return null;
}
} else {
LOGGER.error(e.getMessage());
LOGGER.warn("Converting XML string to XML document failed.");
return null;
}
LOGGER.error(e.getMessage());
LOGGER.warn("Converting XML string to XML document failed.");
return null;
}
return doc;
}
Expand Down
Loading
Loading