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

Changed behavior of java api client to avoid 401 problems #2553 #2560

Merged
merged 2 commits into from
Sep 27, 2023
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
1 change: 1 addition & 0 deletions sechub-api-java/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ dependencies {
testImplementation spring_boot_dependency.junit_jupiter
testImplementation library.apache_commons_io
testImplementation library.mockito_inline
testImplementation library.wiremock
}

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,14 @@ public abstract class AbstractSecHubClient implements SecHubClient {

private Set<SecHubClientListener> secHubClientListeners;

public AbstractSecHubClient() {
secHubClientListeners = new LinkedHashSet<>();
public AbstractSecHubClient(URI serverUri, String username, String apiToken, boolean trustAll) {
this.serverUri = serverUri;
this.trustAll = trustAll;

this.secHubClientListeners = new LinkedHashSet<>();

setUsername(username);
setApiToken(apiToken);
}

public void setUsername(String username) {
Expand All @@ -30,14 +36,6 @@ public void setApiToken(String apiToken) {
this.sealedApiToken = apiTokenAccess.seal(apiToken);
}

public void setServerUri(URI serverUri) {
this.serverUri = serverUri;
}

public void setTrustAll(boolean trustAll) {
this.trustAll = trustAll;
}

@Override
public boolean isTrustAll() {
return trustAll;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,7 @@ public DefaultSecHubClient(URI serverUri, String username, String apiToken) {
}

public DefaultSecHubClient(URI serverUri, String username, String apiToken, boolean trustAll) {
setUsername(username);
setApiToken(apiToken);
setServerUri(serverUri);
setTrustAll(trustAll);
super(serverUri, username, apiToken, trustAll);

apiClient = new ApiClientBuilder().createApiClient(this, mapper);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.mercedesbenz.sechub.api;

import java.net.URI;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
Expand Down Expand Up @@ -33,6 +34,7 @@ public class MockedSecHubClient extends AbstractSecHubClient {
private Set<String> userToProjectAssignments = new HashSet<>();

public MockedSecHubClient() {
super(URI.create("https://localhost/mocked-sechub"), "mockuser", "pseudo-token", true);
mockDataAccess = new MockDataAccess();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
// SPDX-License-Identifier: MIT
package com.mercedesbenz.sechub.api.internal;

import java.net.Socket;
import java.net.http.HttpClient;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Base64;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.net.ssl.X509ExtendedTrustManager;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.mercedesbenz.sechub.api.SecHubClient;
Expand All @@ -18,36 +21,30 @@
public class ApiClientBuilder {

public ApiClient createApiClient(SecHubClient client, ObjectMapper mapper) {
HttpClient.Builder builder = HttpClient.newBuilder().authenticator(new SecHubClientAuthenticator(client));
HttpClient.Builder builder = HttpClient.newBuilder();
if (client.isTrustAll()) {
builder.sslContext(createTrustAllSSLContext());
}

ApiClient apiClient = new ApiClient(builder, mapper, client.getServerUri().toString());
apiClient.setRequestInterceptor((request) -> {
request.setHeader("Authorization", createBasicAuthenticationHeader(client));
});
return apiClient;

}

private static final String createBasicAuthenticationHeader(SecHubClient client) {
String valueToEncode = client.getUsername() + ":" + client.getSealedApiToken();
return "Basic " + Base64.getEncoder().encodeToString(valueToEncode.getBytes());
}

private SSLContext createTrustAllSSLContext() {
SSLContext sslContext = null;
try {
sslContext = SSLContext.getInstance("TLS");

TrustManager trustManager = new X509TrustManager() {

private X509Certificate[] emptyCertificatesArray = new X509Certificate[] {};

public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
/* we do not check the client - we trust all */
}

public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
/* we do not check the server - we trust all */
}

public X509Certificate[] getAcceptedIssuers() {
return emptyCertificatesArray;
}
};
TrustManager trustManager = new TrustAllManager();

sslContext.init(null, new TrustManager[] { trustManager }, null);

Expand All @@ -57,4 +54,42 @@ public X509Certificate[] getAcceptedIssuers() {
}

}

private class TrustAllManager extends X509ExtendedTrustManager {

private X509Certificate[] emptyCertificatesArray = new X509Certificate[] {};

public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
/* we do not check - we trust all */
}

public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
/* we do not check - we trust all */
}

public X509Certificate[] getAcceptedIssuers() {
return emptyCertificatesArray;
}

@Override
public void checkClientTrusted(X509Certificate[] chain, String authType, Socket socket) throws CertificateException {
/* we do not check - we trust all */
}

@Override
public void checkServerTrusted(X509Certificate[] chain, String authType, Socket socket) throws CertificateException {
/* we do not check - we trust all */
}

@Override
public void checkClientTrusted(X509Certificate[] chain, String authType, SSLEngine engine) throws CertificateException {
/* we do not check - we trust all */

}

@Override
public void checkServerTrusted(X509Certificate[] chain, String authType, SSLEngine engine) throws CertificateException {
/* we do not check - we trust all */
}
};
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package com.mercedesbenz.sechub.api;

import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.*;
import static org.junit.Assert.*;

import java.net.URI;

import org.junit.Rule;
import org.junit.Test;

import com.github.tomakehurst.wiremock.junit.WireMockRule;
import com.mercedesbenz.sechub.test.TestPortProvider;

import wiremock.org.apache.http.HttpStatus;

/**
* Junit 4 test because of missing official WireMock Junit5 extension - so we
* use WireMock Rule and Junit4.
*
* @author Albert Tregnaghi
*
*/
public class DefaultSechubClientWireMockTest {

private static final String EXAMPLE_TOKEN = "example-token";

private static final String EXAMPLE_USER = "example-user";
private static final String APPLICATION_JSON = "application/json";

private static final int HTTPS_PORT = TestPortProvider.DEFAULT_INSTANCE.getWireMockTestHTTPSPort();

private static final int HTTP_PORT = TestPortProvider.DEFAULT_INSTANCE.getWireMockTestHTTPPort();

@Rule
public WireMockRule wireMockRule = new WireMockRule(wireMockConfig().port(HTTP_PORT).httpsPort(HTTPS_PORT));

@Test
public void fetch_sechub_status_with_basic_auth() throws Exception {

/* prepare */
String statusBody = """
[ {
"key" : "status.scheduler.enabled",
"value" : "true"
}, {
"key" : "status.scheduler.jobs.all",
"value" : "2"
} ]
""";
stubFor(get(urlEqualTo("/api/admin/status")).withBasicAuth(EXAMPLE_USER, EXAMPLE_TOKEN)
.willReturn(aResponse().withStatus(HttpStatus.SC_OK).withHeader("Content-Type", APPLICATION_JSON).withBody(statusBody)));

DefaultSecHubClient client = createTestClientWithExampleCredentials();

/* execute */
SecHubStatus status = client.fetchSecHubStatus();

/* test */
verify(getRequestedFor(urlEqualTo("/api/admin/status")));
assertNotNull(status);
assertEquals("true", status.getStatusInformationMap().get("status.scheduler.enabled"));
assertEquals("2", status.getStatusInformationMap().get("status.scheduler.jobs.all"));

}

@Test
public void credential_changes_on_client_after_creation_are_possible() throws Exception {

/* prepare */
String statusBody = """
[ {
"key" : "status.scheduler.enabled",
"value" : "false"
}, {
"key" : "status.scheduler.jobs.all",
"value" : "0"
} ]
""";
stubFor(get(urlEqualTo("/api/admin/status")).withBasicAuth("other-user", "other-token")
.willReturn(aResponse().withStatus(HttpStatus.SC_OK).withHeader("Content-Type", APPLICATION_JSON).withBody(statusBody)));

DefaultSecHubClient client = createTestClientWithExampleCredentials();

/* execute */
client.setApiToken("other-token");
client.setUsername("other-user");

/* test */
SecHubStatus status = client.fetchSecHubStatus();
verify(getRequestedFor(urlEqualTo("/api/admin/status")));

assertEquals("false", status.getStatusInformationMap().get("status.scheduler.enabled"));
assertEquals("0", status.getStatusInformationMap().get("status.scheduler.jobs.all"));
}

private DefaultSecHubClient createTestClientWithExampleCredentials() {
DefaultSecHubClient client = new DefaultSecHubClient(URI.create(wireMockRule.baseUrl()), EXAMPLE_USER, EXAMPLE_TOKEN, true);
return client;
}
}
Loading