diff --git a/client/pom.xml b/client/pom.xml
index 0fb3f854..d9c1629a 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -177,18 +177,6 @@
snakeyaml
2.0
-
- com.squareup.okhttp3
- okhttp
- 4.12.0
- true
-
-
- com.squareup.okhttp3
- logging-interceptor
- 4.12.0
- true
-
diff --git a/client/src/main/java/io/split/client/SplitClientConfig.java b/client/src/main/java/io/split/client/SplitClientConfig.java
index 0a6b0fbd..effd2bb9 100644
--- a/client/src/main/java/io/split/client/SplitClientConfig.java
+++ b/client/src/main/java/io/split/client/SplitClientConfig.java
@@ -5,6 +5,7 @@
import io.split.client.utils.FileTypeEnum;
import io.split.integrations.IntegrationsConfig;
import io.split.service.ProxyAuthScheme;
+import io.split.service.SplitHttpClient;
import io.split.storages.enums.OperationMode;
import io.split.storages.enums.StorageMode;
import org.apache.hc.core5.http.HttpHost;
@@ -94,6 +95,7 @@ public class SplitClientConfig {
private final CustomHeaderDecorator _customHeaderDecorator;
private final ProxyAuthScheme _proxyAuthScheme;
private final String _proxyKerberosPrincipalName;
+ private final SplitHttpClient _proxyKerberosClient;
public static Builder builder() {
return new Builder();
@@ -152,7 +154,8 @@ private SplitClientConfig(String endpoint,
int invalidSets,
CustomHeaderDecorator customHeaderDecorator,
ProxyAuthScheme proxyAuthScheme,
- String proxyKerberosPrincipalName) {
+ String proxyKerberosPrincipalName,
+ SplitHttpClient proxyKerberosClient) {
_endpoint = endpoint;
_eventsEndpoint = eventsEndpoint;
_featuresRefreshRate = pollForFeatureChangesEveryNSeconds;
@@ -207,6 +210,7 @@ private SplitClientConfig(String endpoint,
_customHeaderDecorator = customHeaderDecorator;
_proxyAuthScheme = proxyAuthScheme;
_proxyKerberosPrincipalName = proxyKerberosPrincipalName;
+ _proxyKerberosClient = proxyKerberosClient;
Properties props = new Properties();
try {
@@ -419,6 +423,7 @@ public ProxyAuthScheme proxyAuthScheme() {
}
public String proxyKerberosPrincipalName() { return _proxyKerberosPrincipalName; }
+ public SplitHttpClient proxyKerberosClient() { return _proxyKerberosClient; }
public static final class Builder {
private String _endpoint = SDK_ENDPOINT;
@@ -478,6 +483,7 @@ public static final class Builder {
private CustomHeaderDecorator _customHeaderDecorator = null;
private ProxyAuthScheme _proxyAuthScheme = null;
private String _proxyKerberosPrincipalName = null;
+ private SplitHttpClient _proxyKerberosClient = null;
public Builder() {
}
@@ -994,6 +1000,17 @@ public Builder proxyKerberosPrincipalName(String proxyKerberosPrincipalName) {
return this;
}
+ /**
+ * Kerberos Http Client
+ *
+ * @param proxyKerberosClient
+ * @return this builder
+ */
+ public Builder proxyKerberosClient(SplitHttpClient proxyKerberosClient) {
+ _proxyKerberosClient = proxyKerberosClient;
+ return this;
+ }
+
/**
* Thread Factory
*
@@ -1060,6 +1077,9 @@ private void verifyAuthScheme() {
if (_proxyKerberosPrincipalName == null) {
throw new IllegalStateException("Kerberos mode require Kerberos Principal Name.");
}
+ if (_proxyKerberosClient == null) {
+ throw new IllegalStateException("Kerberos mode require Kerberos Http Client.");
+ }
}
}
@@ -1184,7 +1204,8 @@ public SplitClientConfig build() {
_invalidSetsCount,
_customHeaderDecorator,
_proxyAuthScheme,
- _proxyKerberosPrincipalName);
+ _proxyKerberosPrincipalName,
+ _proxyKerberosClient);
}
}
}
\ No newline at end of file
diff --git a/client/src/main/java/io/split/client/SplitFactoryBuilder.java b/client/src/main/java/io/split/client/SplitFactoryBuilder.java
index c2271ec4..2b48fb0d 100644
--- a/client/src/main/java/io/split/client/SplitFactoryBuilder.java
+++ b/client/src/main/java/io/split/client/SplitFactoryBuilder.java
@@ -2,6 +2,7 @@
import io.split.inputValidation.ApiKeyValidator;
import io.split.grammar.Treatments;
+import io.split.service.SplitHttpClient;
import io.split.storages.enums.StorageMode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java
index 32568342..7595768d 100644
--- a/client/src/main/java/io/split/client/SplitFactoryImpl.java
+++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java
@@ -58,10 +58,9 @@
import io.split.engine.segments.SegmentSynchronizationTaskImp;
import io.split.integrations.IntegrationsConfig;
import io.split.service.ProxyAuthScheme;
-import io.split.service.SplitHttpClientKerberosImpl;
import io.split.service.SplitHttpClientImpl;
import io.split.service.SplitHttpClient;
-import io.split.service.HTTPKerberosAuthInterceptor;
+
import io.split.storages.SegmentCache;
import io.split.storages.SegmentCacheConsumer;
import io.split.storages.SegmentCacheProducer;
@@ -86,6 +85,7 @@
import io.split.telemetry.synchronizer.TelemetryInMemorySubmitter;
import io.split.telemetry.synchronizer.TelemetrySyncTask;
import io.split.telemetry.synchronizer.TelemetrySynchronizer;
+
import org.apache.hc.client5.http.auth.AuthScope;
import org.apache.hc.client5.http.auth.Credentials;
import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
@@ -108,26 +108,16 @@
import org.slf4j.LoggerFactory;
import pluggable.CustomStorageWrapper;
-import okhttp3.Authenticator;
-import okhttp3.OkHttpClient;
-import okhttp3.OkHttpClient.Builder;
-import okhttp3.logging.HttpLoggingInterceptor;
-
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.URI;
import java.net.URISyntaxException;
-import java.net.InetSocketAddress;
-import java.net.Proxy;
-import java.util.Map;
-import java.util.HashMap;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;
import java.util.HashSet;
import java.util.List;
import java.util.ArrayList;
-import java.util.concurrent.TimeUnit;
import static io.split.client.utils.SplitExecutorFactory.buildExecutorService;
@@ -167,15 +157,16 @@ public class SplitFactoryImpl implements SplitFactory {
private final SplitSynchronizationTask _splitSynchronizationTask;
private final EventsTask _eventsTask;
private final SyncManager _syncManager;
- private final SplitHttpClient _splitHttpClient;
+ private SplitHttpClient _splitHttpClient;
private final UserStorageWrapper _userStorageWrapper;
private final ImpressionsSender _impressionsSender;
private final URI _rootTarget;
private final URI _eventsRootTarget;
private final UniqueKeysTracker _uniqueKeysTracker;
+ private RequestDecorator _requestDecorator;
// Constructor for standalone mode
- public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyntaxException, IOException {
+ public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyntaxException {
_userStorageWrapper = null;
_operationMode = config.operationMode();
_startTime = System.currentTimeMillis();
@@ -199,8 +190,14 @@ public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyn
_gates = new SDKReadinessGates();
// HttpClient
- RequestDecorator requestDecorator = new RequestDecorator(config.customHeaderDecorator());
- _splitHttpClient = buildSplitHttpClient(apiToken, config, _sdkMetadata, requestDecorator);
+ _requestDecorator = new RequestDecorator(config.customHeaderDecorator());
+ if (config.proxyAuthScheme() != ProxyAuthScheme.KERBEROS) {
+ _splitHttpClient = buildSplitHttpClient(apiToken, config, _sdkMetadata, _requestDecorator);
+ } else {
+ _splitHttpClient = config.proxyKerberosClient();
+ _splitHttpClient.setMetaData(_sdkMetadata);
+ _splitHttpClient.setRequestDecorator(_requestDecorator);
+ }
// Roots
_rootTarget = URI.create(config.endpoint());
@@ -269,7 +266,7 @@ public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyn
// SyncManager
SplitTasks splitTasks = SplitTasks.build(_splitSynchronizationTask, _segmentSynchronizationTaskImp,
_impressionsManager, _eventsTask, _telemetrySyncTask, _uniqueKeysTracker);
- SplitAPI splitAPI = SplitAPI.build(_splitHttpClient, buildSSEdHttpClient(apiToken, config, _sdkMetadata), requestDecorator);
+ SplitAPI splitAPI = SplitAPI.build(_splitHttpClient, buildSSEdHttpClient(apiToken, config, _sdkMetadata), _requestDecorator);
_syncManager = SyncManagerImp.build(splitTasks, _splitFetcher, splitCache, splitAPI,
segmentCache, _gates, _telemetryStorageProducer, _telemetrySynchronizer, config, splitParser,
@@ -287,6 +284,14 @@ public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyn
}
}
+ public RequestDecorator getRequestDecorator() {
+ return _requestDecorator;
+ }
+
+ public SDKMetadata getSDKMetaData() {
+ return _sdkMetadata;
+ }
+
// Constructor for consumer mode
protected SplitFactoryImpl(String apiToken, SplitClientConfig config, CustomStorageWrapper customStorageWrapper)
throws URISyntaxException {
@@ -503,36 +508,12 @@ public boolean isDestroyed() {
return isTerminated;
}
+ public void setSplitHttpClient(SplitHttpClient splitHttpClient) {
+ _splitHttpClient = splitHttpClient;
+ }
protected static SplitHttpClient buildSplitHttpClient(String apiToken, SplitClientConfig config,
SDKMetadata sdkMetadata, RequestDecorator requestDecorator)
- throws URISyntaxException, IOException {
- // setup Kerberos client
- if (config.proxyAuthScheme() == ProxyAuthScheme.KERBEROS) {
- _log.info("Using Kerberos-Proxy Authentication Scheme.");
- Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(config.proxy().getHostName(), config.proxy().getPort()));
- HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
- if (config.debugEnabled()) {
- logging.setLevel(HttpLoggingInterceptor.Level.HEADERS);
- } else {
- logging.setLevel(HttpLoggingInterceptor.Level.NONE);
- }
-
- Map kerberosOptions = new HashMap<>();
- kerberosOptions.put("com.sun.security.auth.module.Krb5LoginModule", "required");
- kerberosOptions.put("refreshKrb5Config", "false");
- kerberosOptions.put("doNotPrompt", "false");
- kerberosOptions.put("useTicketCache", "true");
-
- Authenticator proxyAuthenticator = getProxyAuthenticator(config, kerberosOptions);
- OkHttpClient client = buildOkHttpClient(proxy, config, logging, proxyAuthenticator);
-
- return SplitHttpClientKerberosImpl.create(
- client,
- requestDecorator,
- apiToken,
- sdkMetadata);
- }
-
+ throws URISyntaxException {
SSLConnectionSocketFactory sslSocketFactory = SSLConnectionSocketFactoryBuilder.create()
.setSslContext(SSLContexts.createSystemDefault())
.setTlsVersions(TLS.V_1_1, TLS.V_1_2)
@@ -570,21 +551,6 @@ protected static SplitHttpClient buildSplitHttpClient(String apiToken, SplitClie
sdkMetadata);
}
- protected static OkHttpClient buildOkHttpClient(Proxy proxy, SplitClientConfig config,
- HttpLoggingInterceptor logging, Authenticator proxyAuthenticator) {
- return new Builder()
- .proxy(proxy)
- .readTimeout(config.readTimeout(), TimeUnit.MILLISECONDS)
- .connectTimeout(config.connectionTimeout(), TimeUnit.MILLISECONDS)
- .addInterceptor(logging)
- .proxyAuthenticator(proxyAuthenticator)
- .build();
- }
-
- protected static HTTPKerberosAuthInterceptor getProxyAuthenticator(SplitClientConfig config,
- Map kerberosOptions) throws IOException {
- return new HTTPKerberosAuthInterceptor(config.proxyKerberosPrincipalName(), kerberosOptions);
- }
private static CloseableHttpClient buildSSEdHttpClient(String apiToken, SplitClientConfig config,
SDKMetadata sdkMetadata) {
RequestConfig requestConfig = RequestConfig.custom()
diff --git a/client/src/main/java/io/split/service/SplitHttpClient.java b/client/src/main/java/io/split/service/SplitHttpClient.java
index 1c88bcd4..52026aaa 100644
--- a/client/src/main/java/io/split/service/SplitHttpClient.java
+++ b/client/src/main/java/io/split/service/SplitHttpClient.java
@@ -1,5 +1,7 @@
package io.split.service;
+import io.split.client.RequestDecorator;
+import io.split.client.utils.SDKMetadata;
import io.split.engine.common.FetchOptions;
import io.split.client.dtos.SplitHttpResponse;
@@ -32,4 +34,8 @@ public interface SplitHttpClient extends Closeable {
public SplitHttpResponse post(URI uri,
HttpEntity entity,
Map> additionalHeaders) throws IOException;
-}
+
+ public void setMetaData(SDKMetadata metadata);
+
+ public void setRequestDecorator(RequestDecorator requestDecorator);
+}
\ No newline at end of file
diff --git a/client/src/main/java/io/split/service/SplitHttpClientImpl.java b/client/src/main/java/io/split/service/SplitHttpClientImpl.java
index 64ca3a55..af91400e 100644
--- a/client/src/main/java/io/split/service/SplitHttpClientImpl.java
+++ b/client/src/main/java/io/split/service/SplitHttpClientImpl.java
@@ -145,4 +145,15 @@ private void setBasicHeaders(HttpRequest request) {
public void close() throws IOException {
_client.close();
}
+
+ @Override
+ public void setMetaData(SDKMetadata metadata) {
+ // only implemented for Kerberos client
+ }
+
+ @Override
+ public void setRequestDecorator(RequestDecorator requestDecorator) {
+ // only implemented for Kerberos client
+ }
+
}
diff --git a/client/src/test/java/io/split/service/HTTPKerberosAuthIntercepterTest.java b/client/src/test/java/io/split/service/HTTPKerberosAuthIntercepterTest.java
deleted file mode 100644
index b49eda75..00000000
--- a/client/src/test/java/io/split/service/HTTPKerberosAuthIntercepterTest.java
+++ /dev/null
@@ -1,112 +0,0 @@
-package io.split.service;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.powermock.api.mockito.PowerMockito;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
-
-import javax.security.auth.Subject;
-import javax.security.auth.kerberos.KerberosPrincipal;
-import javax.security.auth.login.AppConfigurationEntry;
-import javax.security.auth.login.LoginContext;
-import javax.security.auth.login.LoginException;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.verify;
-import static org.mockito.internal.verification.VerificationModeFactory.times;
-import static org.powermock.api.mockito.PowerMockito.*;
-
-import java.security.PrivilegedActionException;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-
-@RunWith(PowerMockRunner.class)
-@PrepareForTest(HTTPKerberosAuthInterceptor.class)
-public class HTTPKerberosAuthIntercepterTest {
-
- @Test
- public void testBasicFlow() throws Exception {
- System.setProperty("java.security.krb5.conf", "src/test/resources/krb5.conf");
-
- HTTPKerberosAuthInterceptor kerberosAuthInterceptor = mock(HTTPKerberosAuthInterceptor.class);
- LoginContext loginContext = PowerMockito.mock(LoginContext.class);
- when(kerberosAuthInterceptor.getLoginContext(any())).thenReturn((loginContext));
-
- doCallRealMethod().when(kerberosAuthInterceptor).buildSubjectCredentials();
- kerberosAuthInterceptor.buildSubjectCredentials();
- verify(loginContext, times(1)).login();
-
- Subject subject = new Subject();
- when(loginContext.getSubject()).thenReturn(subject);
- doCallRealMethod().when(kerberosAuthInterceptor).getContextSubject();
- kerberosAuthInterceptor.getContextSubject();
- verify(loginContext, times(1)).getSubject();
-
- subject.getPrincipals().add(new KerberosPrincipal("bilal"));
- subject.getPublicCredentials().add(new KerberosPrincipal("name"));
- subject.getPrivateCredentials().add(new KerberosPrincipal("name"));
-
- doCallRealMethod().when(kerberosAuthInterceptor).getClientPrincipalName();
- assertThat(kerberosAuthInterceptor.getClientPrincipalName(), is(equalTo("bilal@ATHENA.MIT.EDU"))) ;
- verify(loginContext, times(2)).getSubject();
-
- when(kerberosAuthInterceptor.buildAuthorizationHeader(any())).thenReturn("secured-token");
- okhttp3.Request originalRequest = new okhttp3.Request.Builder().url("http://somthing").build();
- okhttp3.Response response = new okhttp3.Response.Builder().code(200).request(originalRequest).
- protocol(okhttp3.Protocol.HTTP_1_1).message("ok").build();
- doCallRealMethod().when(kerberosAuthInterceptor).authenticate(null, response);
- okhttp3.Request request = kerberosAuthInterceptor.authenticate(null, response);
- assertThat(request.headers("Proxy-authorization"), is(equalTo(Arrays.asList("Negotiate secured-token"))));
- }
-
- @Test
- public void testKerberosLoginConfiguration() {
- Map kerberosOptions = new HashMap();
- kerberosOptions.put("com.sun.security.auth.module.Krb5LoginModule", "required");
- kerberosOptions.put("refreshKrb5Config", "false");
- kerberosOptions.put("doNotPrompt", "false");
- kerberosOptions.put("useTicketCache", "true");
-
- HTTPKerberosAuthInterceptor.KerberosLoginConfiguration kerberosConfig = new HTTPKerberosAuthInterceptor.KerberosLoginConfiguration(kerberosOptions);
- AppConfigurationEntry[] appConfig = kerberosConfig.getAppConfigurationEntry("");
- assertThat("com.sun.security.auth.module.Krb5LoginModule", is(equalTo(appConfig[0].getLoginModuleName())));
- assertThat(AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, is(equalTo(appConfig[0].getControlFlag())));
- }
-
- @Test(expected = IllegalStateException.class)
- public void testKerberosLoginConfigurationException() {
- HTTPKerberosAuthInterceptor.KerberosLoginConfiguration kerberosConfig = new HTTPKerberosAuthInterceptor.KerberosLoginConfiguration();
- AppConfigurationEntry[] appConfig = kerberosConfig.getAppConfigurationEntry("");
- }
-
- @Test
- public void testBuildAuthorizationHeader() throws LoginException, PrivilegedActionException {
- System.setProperty("java.security.krb5.conf", "src/test/resources/krb5.conf");
-
- HTTPKerberosAuthInterceptor kerberosAuthInterceptor = mock(HTTPKerberosAuthInterceptor.class);
- HTTPKerberosAuthInterceptor.CreateAuthorizationHeaderAction ahh = mock(HTTPKerberosAuthInterceptor.CreateAuthorizationHeaderAction.class);
- when(ahh.getNegotiateToken()).thenReturn("secret-token");
- when(kerberosAuthInterceptor.getAuthorizationHeaderAction(any(), any())).thenReturn(ahh);
-
- LoginContext loginContext = PowerMockito.mock(LoginContext.class);
- doCallRealMethod().when(kerberosAuthInterceptor).buildAuthorizationHeader("bilal");
- Subject subject = new Subject();
- when(loginContext.getSubject()).thenReturn(subject);
- when(kerberosAuthInterceptor.getContextSubject()).thenReturn(subject);
- when(kerberosAuthInterceptor.getLoginContext(subject)).thenReturn((loginContext));
- doCallRealMethod().when(kerberosAuthInterceptor).buildSubjectCredentials();
- kerberosAuthInterceptor.buildSubjectCredentials();
-
- subject.getPrincipals().add(new KerberosPrincipal("bilal"));
- subject.getPublicCredentials().add(new KerberosPrincipal("name"));
- subject.getPrivateCredentials().add(new KerberosPrincipal("name"));
- doCallRealMethod().when(kerberosAuthInterceptor).getClientPrincipalName();
-
- assertThat("secret-token", is(equalTo(kerberosAuthInterceptor.buildAuthorizationHeader("bilal"))));
- }
-}
diff --git a/client/src/test/java/io/split/service/HttpSplitClientKerberosTest.java b/client/src/test/java/io/split/service/HttpSplitClientKerberosTest.java
deleted file mode 100644
index 3ddf5c68..00000000
--- a/client/src/test/java/io/split/service/HttpSplitClientKerberosTest.java
+++ /dev/null
@@ -1,303 +0,0 @@
-package io.split.service;
-
-import com.google.common.base.Charsets;
-import com.google.common.io.Files;
-
-import io.split.client.CustomHeaderDecorator;
-import io.split.client.RequestDecorator;
-import io.split.client.dtos.*;
-import io.split.client.impressions.Impression;
-import io.split.client.utils.Json;
-import io.split.client.utils.SDKMetadata;
-import io.split.client.utils.Utils;
-import io.split.engine.common.FetchOptions;
-
-import okhttp3.OkHttpClient;
-import okhttp3.OkHttpClient.*;
-import okhttp3.HttpUrl;
-import okhttp3.Headers;
-
-import okhttp3.mockwebserver.MockResponse;
-import okhttp3.mockwebserver.MockWebServer;
-import okhttp3.mockwebserver.RecordedRequest;
-import org.apache.hc.core5.http.*;
-import org.apache.hc.core5.http.io.entity.EntityUtils;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.io.*;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.HttpURLConnection;
-import java.net.Proxy;
-import java.net.InetSocketAddress;
-import java.util.List;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Map;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsEqual.equalTo;
-
-public class HttpSplitClientKerberosTest {
-
- @Test
- public void testGetWithSpecialCharacters() throws IOException, InterruptedException {
- MockWebServer server = new MockWebServer();
- BufferedReader br = new BufferedReader(new FileReader("src/test/resources/split-change-special-characters.json"));
- String body;
- try {
- StringBuilder sb = new StringBuilder();
- String line = br.readLine();
-
- while (line != null) {
- sb.append(line);
- sb.append(System.lineSeparator());
- line = br.readLine();
- }
- body = sb.toString();
- } finally {
- br.close();
- }
-
- server.enqueue(new MockResponse().setBody(body).addHeader(HttpHeaders.VIA, "HTTP/1.1 s_proxy_rio1"));
- server.start();
- HttpUrl baseUrl = server.url("/v1/");
- URI rootTarget = baseUrl.uri();
- RequestDecorator decorator = new RequestDecorator(null);
- OkHttpClient client = new Builder().build();
-
- SplitHttpClientKerberosImpl splitHttpClientKerberosImpl = new SplitHttpClientKerberosImpl(client, decorator, "qwerty", metadata());
-
- Map> additionalHeaders = Collections.singletonMap("AdditionalHeader",
- Collections.singletonList("add"));
-
- SplitHttpResponse splitHttpResponse = splitHttpClientKerberosImpl.get(rootTarget,
- new FetchOptions.Builder().cacheControlHeaders(true).build(), additionalHeaders);
-
-
- RecordedRequest request = server.takeRequest();
- server.shutdown();
- Headers requestHeaders = request.getHeaders();
-
- assertThat(splitHttpResponse.statusCode(), is(equalTo(HttpURLConnection.HTTP_OK)));
- Assert.assertEquals("/v1/", request.getPath());
- assertThat(requestHeaders.get("Authorization"), is(equalTo("Bearer qwerty"))) ;
- assertThat(requestHeaders.get("SplitSDKClientKey"), is(equalTo("erty")));
- assertThat(requestHeaders.get("SplitSDKVersion"), is(equalTo("java-1.2.3")));
- assertThat(requestHeaders.get("SplitSDKMachineIP"), is(equalTo("1.2.3.4")));
- assertThat(requestHeaders.get("SplitSDKMachineName"), is(equalTo("someIP")));
- assertThat(requestHeaders.get("AdditionalHeader"), is(equalTo("add")));
-
- SplitChange change = Json.fromJson(splitHttpResponse.body(), SplitChange.class);
- Header[] headers = splitHttpResponse.responseHeaders();
- assertThat(headers[1].getName(), is(equalTo("via")));
- assertThat(headers[1].getValue(), is(equalTo("[HTTP/1.1 s_proxy_rio1]")));
- assertThat(splitHttpResponse.statusCode(), is(equalTo(200)));
- Assert.assertNotNull(change);
- Assert.assertEquals(1, change.splits.size());
- Assert.assertNotNull(change.splits.get(0));
-
- Split split = change.splits.get(0);
- Map configs = split.configurations;
- Assert.assertEquals(2, configs.size());
- Assert.assertEquals("{\"test\": \"blue\",\"grüne Straße\": 13}", configs.get("on"));
- Assert.assertEquals("{\"test\": \"blue\",\"size\": 15}", configs.get("off"));
- Assert.assertEquals(2, split.sets.size());
- splitHttpClientKerberosImpl.close();
- }
-
- @Test
- public void testGetErrors() throws IOException, InterruptedException {
- MockWebServer server = new MockWebServer();
- server.enqueue(new MockResponse().setBody("").setResponseCode(HttpURLConnection.HTTP_INTERNAL_ERROR));
- server.start();
- HttpUrl baseUrl = server.url("/v1/");
- URI rootTarget = baseUrl.uri();
- RequestDecorator decorator = new RequestDecorator(null);
- OkHttpClient client = new Builder().build();
-
- SplitHttpClientKerberosImpl splitHttpClientKerberosImpl = new SplitHttpClientKerberosImpl(client, decorator, "qwerty", metadata());
-
- Map> additionalHeaders = Collections.singletonMap("AdditionalHeader",
- Collections.singletonList("add"));
-
- SplitHttpResponse splitHttpResponse = splitHttpClientKerberosImpl.get(rootTarget,
- new FetchOptions.Builder().cacheControlHeaders(true).build(), additionalHeaders);
-
-
- RecordedRequest request = server.takeRequest();
- server.shutdown();
- assertThat(splitHttpResponse.statusCode(), is(equalTo(HttpURLConnection.HTTP_INTERNAL_ERROR)));
- splitHttpClientKerberosImpl.close();
- }
-
-
- @Test
- public void testGetParameters() throws IOException, InterruptedException {
- class MyCustomHeaders implements CustomHeaderDecorator {
- public MyCustomHeaders() {}
- @Override
- public Map> getHeaderOverrides(RequestContext context) {
- Map> additionalHeaders = context.headers();
- additionalHeaders.put("first", Arrays.asList("1"));
- additionalHeaders.put("second", Arrays.asList("2.1", "2.2"));
- additionalHeaders.put("third", Arrays.asList("3"));
- return additionalHeaders;
- }
- }
-
- MockWebServer server = new MockWebServer();
- BufferedReader br = new BufferedReader(new FileReader("src/test/resources/split-change-special-characters.json"));
- String body;
- try {
- StringBuilder sb = new StringBuilder();
- String line = br.readLine();
-
- while (line != null) {
- sb.append(line);
- sb.append(System.lineSeparator());
- line = br.readLine();
- }
- body = sb.toString();
- } finally {
- br.close();
- }
-
- server.enqueue(new MockResponse().setBody(body).addHeader(HttpHeaders.VIA, "HTTP/1.1 s_proxy_rio1"));
- server.start();
- HttpUrl baseUrl = server.url("/splitChanges?since=1234567");
- URI rootTarget = baseUrl.uri();
- RequestDecorator decorator = new RequestDecorator(new MyCustomHeaders());
- OkHttpClient client = new Builder().build();
-
- SplitHttpClientKerberosImpl splitHttpClientKerberosImpl = new SplitHttpClientKerberosImpl(client, decorator, "qwerty", metadata());
-
- FetchOptions options = new FetchOptions.Builder().cacheControlHeaders(true).build();
- SplitHttpResponse splitHttpResponse = splitHttpClientKerberosImpl.get(rootTarget, options, null);
-
- RecordedRequest request = server.takeRequest();
- server.shutdown();
- Headers requestHeaders = request.getHeaders();
-
- assertThat(requestHeaders.get("Cache-Control"), is(equalTo("no-cache")));
- assertThat(requestHeaders.get("first"), is(equalTo("1")));
- assertThat(requestHeaders.values("second"), is(equalTo(Arrays.asList("2.1","2.2"))));
- assertThat(requestHeaders.get("third"), is(equalTo("3")));
- Assert.assertEquals("/splitChanges?since=1234567", request.getPath());
- assertThat(request.getMethod(), is(equalTo("GET")));
- }
-
- @Test(expected = IllegalStateException.class)
- public void testException() throws URISyntaxException, IOException {
- URI uri = new URI("https://api.split.io/splitChanges?since=1234567");
- RequestDecorator decorator = null;
-
- ByteArrayInputStream stubInputStream = new ByteArrayInputStream(Files.asCharSource(
- new File("src/test/resources/split-change-special-characters.json"), Charsets.UTF_8).read().getBytes(Charsets.UTF_8));
-
- Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("1.0.0.127", 8080));
- OkHttpClient client = new OkHttpClient.Builder()
- .proxy(proxy)
- .build();
-
- SplitHttpClientKerberosImpl splitHtpClientKerberos = SplitHttpClientKerberosImpl.create(client, decorator, "qwerty", metadata());
- SplitHttpResponse splitHttpResponse = splitHtpClientKerberos.get(uri,
- new FetchOptions.Builder().cacheControlHeaders(true).build(), null);
- }
-
- @Test
- public void testPost() throws IOException, ParseException, InterruptedException {
- MockWebServer server = new MockWebServer();
-
- server.enqueue(new MockResponse().addHeader(HttpHeaders.VIA, "HTTP/1.1 s_proxy_rio1"));
- server.start();
- HttpUrl baseUrl = server.url("/impressions");
- URI rootTarget = baseUrl.uri();
- RequestDecorator decorator = new RequestDecorator(null);
- OkHttpClient client = new Builder().build();
-
- SplitHttpClientKerberosImpl splitHttpClientKerberosImpl = new SplitHttpClientKerberosImpl(client, decorator, "qwerty", metadata());
-
- FetchOptions options = new FetchOptions.Builder().cacheControlHeaders(true).build();
- // Send impressions
- List toSend = Arrays.asList(new TestImpressions("t1", Arrays.asList(
- KeyImpression.fromImpression(new Impression("k1", null, "t1", "on", 123L, "r1", 456L, null)),
- KeyImpression.fromImpression(new Impression("k2", null, "t1", "on", 123L, "r1", 456L, null)),
- KeyImpression.fromImpression(new Impression("k3", null, "t1", "on", 123L, "r1", 456L, null)))),
- new TestImpressions("t2", Arrays.asList(
- KeyImpression.fromImpression(new Impression("k1", null, "t2", "on", 123L, "r1", 456L, null)),
- KeyImpression.fromImpression(new Impression("k2", null, "t2", "on", 123L, "r1", 456L, null)),
- KeyImpression.fromImpression(new Impression("k3", null, "t2", "on", 123L, "r1", 456L, null)))));
-
- Map> additionalHeaders = Collections.singletonMap("SplitSDKImpressionsMode",
- Collections.singletonList("OPTIMIZED"));
-
- SplitHttpResponse splitHttpResponse = splitHttpClientKerberosImpl.post(rootTarget, Utils.toJsonEntity(toSend),
- additionalHeaders);
-
- RecordedRequest request = server.takeRequest();
- server.shutdown();
- Headers requestHeaders = request.getHeaders();
- String postBody = EntityUtils.toString(Utils.toJsonEntity(toSend));
-
- Assert.assertEquals("POST /impressions HTTP/1.1", request.getRequestLine());
- Assert.assertEquals(postBody, request.getBody().readUtf8());
- assertThat(requestHeaders.get("Authorization"), is(equalTo("Bearer qwerty"))) ;
- assertThat(requestHeaders.get("SplitSDKClientKey"), is(equalTo("erty")));
- assertThat(requestHeaders.get("SplitSDKVersion"), is(equalTo("java-1.2.3")));
- assertThat(requestHeaders.get("SplitSDKMachineIP"), is(equalTo("1.2.3.4")));
- assertThat(requestHeaders.get("SplitSDKMachineName"), is(equalTo("someIP")));
- assertThat(requestHeaders.get("SplitSDKImpressionsMode"), is(equalTo("OPTIMIZED")));
-
- Header[] headers = splitHttpResponse.responseHeaders();
- assertThat(headers[1].getName(), is(equalTo("via")));
- assertThat(headers[1].getValue(), is(equalTo("[HTTP/1.1 s_proxy_rio1]")));
- assertThat(splitHttpResponse.statusCode(), is(equalTo(200)));
- }
-
- @Test
- public void testPostErrors() throws IOException, InterruptedException {
- MockWebServer server = new MockWebServer();
- server.enqueue(new MockResponse().setBody("").setResponseCode(HttpURLConnection.HTTP_INTERNAL_ERROR));
- server.start();
- HttpUrl baseUrl = server.url("/v1/");
- URI rootTarget = baseUrl.uri();
- RequestDecorator decorator = new RequestDecorator(null);
- OkHttpClient client = new Builder().build();
-
- SplitHttpClientKerberosImpl splitHttpClientKerberosImpl = new SplitHttpClientKerberosImpl(client, decorator, "qwerty", metadata());
-
- Map> additionalHeaders = Collections.singletonMap("AdditionalHeader",
- Collections.singletonList("add"));
-
- SplitHttpResponse splitHttpResponse = splitHttpClientKerberosImpl.post(rootTarget,
- Utils.toJsonEntity("<>"), additionalHeaders);
-
-
- RecordedRequest request = server.takeRequest();
- server.shutdown();
- assertThat(splitHttpResponse.statusCode(), is(equalTo(HttpURLConnection.HTTP_INTERNAL_ERROR)));
- splitHttpClientKerberosImpl.close();
- }
-
- @Test(expected = IllegalStateException.class)
- public void testPosttException() throws URISyntaxException {
- RequestDecorator decorator = null;
- URI uri = new URI("https://kubernetesturl.com/split/api/testImpressions/bulk");
-
- Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("1.0.0.127", 8080));
- OkHttpClient client = new OkHttpClient.Builder()
- .proxy(proxy)
- .build();
- SplitHttpClientKerberosImpl splitHtpClientKerberos = SplitHttpClientKerberosImpl.create(client, decorator, "qwerty", metadata());
- SplitHttpResponse splitHttpResponse = splitHtpClientKerberos.post(uri,
- Utils.toJsonEntity(Arrays.asList(new String[] { "A", "B", "C", "D" })), null);
- }
-
- private SDKMetadata metadata() {
- return new SDKMetadata("java-1.2.3", "1.2.3.4", "someIP");
- }
-
-}
diff --git a/client/src/test/resources/krb5.conf b/client/src/test/resources/krb5.conf
deleted file mode 100644
index 78d63ba8..00000000
--- a/client/src/test/resources/krb5.conf
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF 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.
-#
-
-[libdefaults]
- kdc_realm = ATHENA.MIT.EDU
- default_realm = ATHENA.MIT.EDU
- kdc_tcp_port = 88
- kdc_udp_port = 88
- dns_lookup_realm = false
- dns_lookup_kdc = false
- udp_preference_limit = 1
-
-[logging]
- default = FILE:/var/logs/krb5kdc.log
-
-[realms]
- ATHENA.MIT.EDU = {
-# kdc = 10.12.4.76:88
-# kdc = tcp/10.12.4.76:88
-# kdc = tcp/192.168.1.19:88
- kdc = 192.168.1.19:88
- }
\ No newline at end of file
diff --git a/kerberos/pom.xml b/kerberos/pom.xml
new file mode 100644
index 00000000..461ac046
--- /dev/null
+++ b/kerberos/pom.xml
@@ -0,0 +1,90 @@
+
+
+
+ java-client-parent
+ io.split.client
+ 4.13.0
+
+ 4.0.0
+
+ kerberos
+ jar
+ Kerberos
+ Kerberos Authentication
+
+
+
+ release
+
+
+
+ org.sonatype.plugins
+ nexus-staging-maven-plugin
+ 1.6.3
+ true
+
+ false
+
+
+
+
+
+
+
+
+ com.squareup.okhttp3
+ okhttp
+ 4.12.0
+
+
+ com.squareup.okhttp3
+ logging-interceptor
+ 4.12.0
+
+
+ org.apache.httpcomponents.client5
+ httpclient5
+ 5.0.3
+
+
+ io.split.client
+ java-client
+ 4.13.0
+ compile
+
+
+
+
+ junit
+ junit
+ test
+
+
+ org.mockito
+ mockito-core
+ 1.10.19
+ test
+
+
+ org.powermock
+ powermock-module-junit4
+ 1.7.4
+ test
+
+
+ org.powermock
+ powermock-api-mockito
+ 1.7.4
+ test
+
+
+ com.squareup.okhttp3
+ mockwebserver
+ 4.8.0
+ test
+
+
+
+
\ No newline at end of file
diff --git a/client/src/main/java/io/split/service/HTTPKerberosAuthInterceptor.java b/kerberos/src/main/java/io/split/kerberos/HTTPKerberosAuthInterceptor.java
similarity index 99%
rename from client/src/main/java/io/split/service/HTTPKerberosAuthInterceptor.java
rename to kerberos/src/main/java/io/split/kerberos/HTTPKerberosAuthInterceptor.java
index 038425c1..b72a8fef 100644
--- a/client/src/main/java/io/split/service/HTTPKerberosAuthInterceptor.java
+++ b/kerberos/src/main/java/io/split/kerberos/HTTPKerberosAuthInterceptor.java
@@ -1,6 +1,4 @@
-package io.split.service;
-
-import io.split.client.exceptions.KerberosAuthException;
+package io.split.kerberos;
import java.io.IOException;
import java.util.Map;
diff --git a/client/src/main/java/io/split/client/exceptions/KerberosAuthException.java b/kerberos/src/main/java/io/split/kerberos/KerberosAuthException.java
similarity index 87%
rename from client/src/main/java/io/split/client/exceptions/KerberosAuthException.java
rename to kerberos/src/main/java/io/split/kerberos/KerberosAuthException.java
index 462944d8..563bcf42 100644
--- a/client/src/main/java/io/split/client/exceptions/KerberosAuthException.java
+++ b/kerberos/src/main/java/io/split/kerberos/KerberosAuthException.java
@@ -1,4 +1,4 @@
-package io.split.client.exceptions;
+package io.split.kerberos;
public class KerberosAuthException extends Exception {
public KerberosAuthException(String message) {
diff --git a/kerberos/src/main/java/io/split/kerberos/SplitHttpClientKerberosBuilder.java b/kerberos/src/main/java/io/split/kerberos/SplitHttpClientKerberosBuilder.java
new file mode 100644
index 00000000..11283e3d
--- /dev/null
+++ b/kerberos/src/main/java/io/split/kerberos/SplitHttpClientKerberosBuilder.java
@@ -0,0 +1,56 @@
+package io.split.kerberos;
+
+import java.io.IOException;
+import java.net.Proxy;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import okhttp3.Authenticator;
+import okhttp3.OkHttpClient;
+import okhttp3.OkHttpClient.Builder;
+import okhttp3.logging.HttpLoggingInterceptor;
+
+public class SplitHttpClientKerberosBuilder {
+ private static final int DEFAULT_CONNECTION_TIMEOUT = 10000;
+ private static final int DEFAULT_READ_TIMEOUT = 10000;
+
+ public static OkHttpClient buildOkHttpClient(Proxy proxy, String proxyKerberosPrincipalName,
+ boolean debugEnabled, int readTimeout, int connectionTimeout) throws IOException {
+
+ HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
+ if (debugEnabled) {
+ logging.setLevel(HttpLoggingInterceptor.Level.HEADERS);
+ } else {
+ logging.setLevel(HttpLoggingInterceptor.Level.NONE);
+ }
+
+ if (connectionTimeout <= 0 || connectionTimeout > DEFAULT_CONNECTION_TIMEOUT) {
+ connectionTimeout = DEFAULT_CONNECTION_TIMEOUT;
+ }
+ if (readTimeout <= 0 || readTimeout > DEFAULT_READ_TIMEOUT) {
+ readTimeout = DEFAULT_READ_TIMEOUT;
+ }
+
+ Map kerberosOptions = new HashMap<>();
+ kerberosOptions.put("com.sun.security.auth.module.Krb5LoginModule", "required");
+ kerberosOptions.put("refreshKrb5Config", "false");
+ kerberosOptions.put("doNotPrompt", "false");
+ kerberosOptions.put("useTicketCache", "true");
+
+ Authenticator proxyAuthenticator = getProxyAuthenticator(proxyKerberosPrincipalName, kerberosOptions);
+
+ return new Builder()
+ .proxy(proxy)
+ .readTimeout(readTimeout, TimeUnit.MILLISECONDS)
+ .connectTimeout(connectionTimeout, TimeUnit.MILLISECONDS)
+ .addInterceptor(logging)
+ .proxyAuthenticator(proxyAuthenticator)
+ .build();
+ }
+
+ public static HTTPKerberosAuthInterceptor getProxyAuthenticator(String proxyKerberosPrincipalName,
+ Map kerberosOptions) throws IOException {
+ return new HTTPKerberosAuthInterceptor(proxyKerberosPrincipalName, kerberosOptions);
+ }
+}
diff --git a/client/src/main/java/io/split/service/SplitHttpClientKerberosImpl.java b/kerberos/src/main/java/io/split/kerberos/SplitHttpClientKerberosImpl.java
similarity index 87%
rename from client/src/main/java/io/split/service/SplitHttpClientKerberosImpl.java
rename to kerberos/src/main/java/io/split/kerberos/SplitHttpClientKerberosImpl.java
index ef5106e1..c29a84cb 100644
--- a/client/src/main/java/io/split/service/SplitHttpClientKerberosImpl.java
+++ b/kerberos/src/main/java/io/split/kerberos/SplitHttpClientKerberosImpl.java
@@ -1,16 +1,18 @@
-package io.split.service;
+package io.split.kerberos;
import io.split.client.RequestDecorator;
import io.split.client.dtos.SplitHttpResponse;
import io.split.client.utils.SDKMetadata;
import io.split.engine.common.FetchOptions;
+import io.split.service.SplitHttpClient;
+
+import split.org.apache.hc.client5.http.classic.methods.HttpGet;
+import split.org.apache.hc.core5.http.Header;
+import split.org.apache.hc.core5.http.HttpEntity;
+import split.org.apache.hc.core5.http.HttpRequest;
+import split.org.apache.hc.core5.http.io.entity.EntityUtils;
+import split.org.apache.hc.core5.http.message.BasicHeader;
-import org.apache.hc.client5.http.classic.methods.HttpGet;
-import org.apache.hc.core5.http.Header;
-import org.apache.hc.core5.http.HttpEntity;
-import org.apache.hc.core5.http.HttpRequest;
-import org.apache.hc.core5.http.io.entity.EntityUtils;
-import org.apache.hc.core5.http.message.BasicHeader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -38,26 +40,33 @@ public class SplitHttpClientKerberosImpl implements SplitHttpClient {
private static final String HEADER_CLIENT_MACHINE_IP = "SplitSDKMachineIP";
private static final String HEADER_CLIENT_VERSION = "SplitSDKVersion";
- private final RequestDecorator _requestDecorator;
+ private RequestDecorator _requestDecorator;
private final String _apikey;
- private final SDKMetadata _metadata;
+ private SDKMetadata _metadata;
private final OkHttpClient _client;
- public static SplitHttpClientKerberosImpl create(OkHttpClient client, RequestDecorator requestDecorator,
- String apikey,
- SDKMetadata metadata) {
- return new SplitHttpClientKerberosImpl(client, requestDecorator, apikey, metadata);
+ public static SplitHttpClientKerberosImpl create(OkHttpClient client,
+ String apikey) {
+ return new SplitHttpClientKerberosImpl(client, apikey);
}
- SplitHttpClientKerberosImpl(OkHttpClient client, RequestDecorator requestDecorator,
- String apikey,
- SDKMetadata metadata) {
- _requestDecorator = requestDecorator;
+ SplitHttpClientKerberosImpl(OkHttpClient client,
+ String apikey) {
_apikey = apikey;
- _metadata = metadata;
_client = client;
}
+ @Override
+ public void setMetaData(SDKMetadata metadata) {
+ _metadata = metadata;
+ }
+
+ @Override
+ public void setRequestDecorator(RequestDecorator requestDecorator) {
+ _requestDecorator = requestDecorator;
+ }
+
+ @Override
public SplitHttpResponse get(URI uri, FetchOptions options, Map> additionalHeaders) {
try {
Builder requestBuilder = new Builder();
@@ -98,6 +107,7 @@ public SplitHttpResponse get(URI uri, FetchOptions options, Map> additionalHeaders) {
try {
@@ -107,7 +117,7 @@ public SplitHttpResponse post(URI url, HttpEntity entity,
setAdditionalAndDecoratedHeaders(requestBuilder, additionalHeaders);
requestBuilder.addHeader("Accept-Encoding", "gzip");
requestBuilder.addHeader("Content-Type", "application/json");
- String post = EntityUtils.toString(entity);
+ String post = EntityUtils.toString((HttpEntity) entity);
RequestBody postBody = RequestBody.create(post.getBytes());
requestBuilder.post(postBody);
@@ -177,7 +187,7 @@ protected Header[] getResponseHeaders(Response response) {
responseHeaders.add(responseHeader);
}
}
- return responseHeaders.toArray(new Header[0]);
+ return responseHeaders.toArray(new split.org.apache.hc.core5.http.Header[0]);
}
@Override
public void close() throws IOException {
diff --git a/pom.xml b/pom.xml
index e99da05f..3f899b8e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -85,6 +85,7 @@
redis-wrapper
testing
client
+ kerberos