diff --git a/CHANGES.txt b/CHANGES.txt index 072fab1f..fe88db4a 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,6 @@ +4.13.0 (Sep 6, 2024) +- Added support for Kerberos Proxy authentication. + 4.12.1 (Jun 10, 2024) - Fixed deadlock for virtual thread in Push Manager and SSE Client. diff --git a/client/pom.xml b/client/pom.xml index 8e7ac11c..0fb3f854 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -181,11 +181,13 @@ 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 6f8db64c..0a6b0fbd 100644 --- a/client/src/main/java/io/split/client/SplitClientConfig.java +++ b/client/src/main/java/io/split/client/SplitClientConfig.java @@ -4,9 +4,9 @@ import io.split.client.impressions.ImpressionsManager; import io.split.client.utils.FileTypeEnum; import io.split.integrations.IntegrationsConfig; +import io.split.service.ProxyAuthScheme; import io.split.storages.enums.OperationMode; import io.split.storages.enums.StorageMode; -import io.split.service.HttpAuthScheme; import org.apache.hc.core5.http.HttpHost; import pluggable.CustomStorageWrapper; @@ -92,9 +92,8 @@ public class SplitClientConfig { private final HashSet _flagSetsFilter; private final int _invalidSets; private final CustomHeaderDecorator _customHeaderDecorator; - private final HttpAuthScheme _authScheme; - private final String _kerberosPrincipalName; - + private final ProxyAuthScheme _proxyAuthScheme; + private final String _proxyKerberosPrincipalName; public static Builder builder() { return new Builder(); @@ -152,8 +151,8 @@ private SplitClientConfig(String endpoint, HashSet flagSetsFilter, int invalidSets, CustomHeaderDecorator customHeaderDecorator, - HttpAuthScheme authScheme, - String kerberosPrincipalName) { + ProxyAuthScheme proxyAuthScheme, + String proxyKerberosPrincipalName) { _endpoint = endpoint; _eventsEndpoint = eventsEndpoint; _featuresRefreshRate = pollForFeatureChangesEveryNSeconds; @@ -206,8 +205,8 @@ private SplitClientConfig(String endpoint, _flagSetsFilter = flagSetsFilter; _invalidSets = invalidSets; _customHeaderDecorator = customHeaderDecorator; - _authScheme = authScheme; - _kerberosPrincipalName = kerberosPrincipalName; + _proxyAuthScheme = proxyAuthScheme; + _proxyKerberosPrincipalName = proxyKerberosPrincipalName; Properties props = new Properties(); try { @@ -415,10 +414,10 @@ public int getInvalidSets() { public CustomHeaderDecorator customHeaderDecorator() { return _customHeaderDecorator; } - public HttpAuthScheme authScheme() { - return _authScheme; + public ProxyAuthScheme proxyAuthScheme() { + return _proxyAuthScheme; } - public String kerberosPrincipalName() { return _kerberosPrincipalName; } + public String proxyKerberosPrincipalName() { return _proxyKerberosPrincipalName; } public static final class Builder { @@ -477,8 +476,8 @@ public static final class Builder { private HashSet _flagSetsFilter = new HashSet<>(); private int _invalidSetsCount = 0; private CustomHeaderDecorator _customHeaderDecorator = null; - private HttpAuthScheme _authScheme = null; - private String _kerberosPrincipalName = null; + private ProxyAuthScheme _proxyAuthScheme = null; + private String _proxyKerberosPrincipalName = null; public Builder() { } @@ -976,22 +975,22 @@ public Builder customHeaderDecorator(CustomHeaderDecorator customHeaderDecorator /** * Authentication Scheme * - * @param authScheme + * @param proxyAuthScheme * @return this builder */ - public Builder authScheme(HttpAuthScheme authScheme) { - _authScheme = authScheme; + public Builder proxyAuthScheme(ProxyAuthScheme proxyAuthScheme) { + _proxyAuthScheme = proxyAuthScheme; return this; } /** * Kerberos Principal Account Name * - * @param kerberosPrincipalName + * @param proxyKerberosPrincipalName * @return this builder */ - public Builder kerberosPrincipalName(String kerberosPrincipalName) { - _kerberosPrincipalName = kerberosPrincipalName; + public Builder proxyKerberosPrincipalName(String proxyKerberosPrincipalName) { + _proxyKerberosPrincipalName = proxyKerberosPrincipalName; return this; } @@ -1054,11 +1053,11 @@ private void verifyEndPoints() { } private void verifyAuthScheme() { - if (_authScheme == HttpAuthScheme.KERBEROS) { + if (_proxyAuthScheme == ProxyAuthScheme.KERBEROS) { if (proxy() == null) { throw new IllegalStateException("Kerberos mode require Proxy parameters."); } - if (_kerberosPrincipalName == null) { + if (_proxyKerberosPrincipalName == null) { throw new IllegalStateException("Kerberos mode require Kerberos Principal Name."); } } @@ -1184,8 +1183,8 @@ public SplitClientConfig build() { _flagSetsFilter, _invalidSetsCount, _customHeaderDecorator, - _authScheme, - _kerberosPrincipalName); + _proxyAuthScheme, + _proxyKerberosPrincipalName); } } } \ No newline at end of file diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java index e43d1404..32568342 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -57,10 +57,10 @@ import io.split.engine.segments.SegmentChangeFetcher; import io.split.engine.segments.SegmentSynchronizationTaskImp; import io.split.integrations.IntegrationsConfig; -import io.split.service.HttpAuthScheme; -import io.split.service.SplitHttpClient; -import io.split.service.SplitHttpClientImpl; +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; @@ -507,7 +507,7 @@ protected static SplitHttpClient buildSplitHttpClient(String apiToken, SplitClie SDKMetadata sdkMetadata, RequestDecorator requestDecorator) throws URISyntaxException, IOException { // setup Kerberos client - if (config.authScheme() == HttpAuthScheme.KERBEROS) { + 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(); @@ -583,7 +583,7 @@ protected static OkHttpClient buildOkHttpClient(Proxy proxy, SplitClientConfig c protected static HTTPKerberosAuthInterceptor getProxyAuthenticator(SplitClientConfig config, Map kerberosOptions) throws IOException { - return new HTTPKerberosAuthInterceptor(config.kerberosPrincipalName(), kerberosOptions); + return new HTTPKerberosAuthInterceptor(config.proxyKerberosPrincipalName(), kerberosOptions); } private static CloseableHttpClient buildSSEdHttpClient(String apiToken, SplitClientConfig config, SDKMetadata sdkMetadata) { diff --git a/client/src/main/java/io/split/service/HTTPKerberosAuthInterceptor.java b/client/src/main/java/io/split/service/HTTPKerberosAuthInterceptor.java index 34fe0eaa..038425c1 100644 --- a/client/src/main/java/io/split/service/HTTPKerberosAuthInterceptor.java +++ b/client/src/main/java/io/split/service/HTTPKerberosAuthInterceptor.java @@ -31,10 +31,25 @@ import okhttp3.Route; /** + * * An HTTP Request interceptor that modifies the request headers to enable * Kerberos authentication. It appends the Kerberos authentication token to the * 'Authorization' request header for Kerberos authentication * + * Copyright 2024 MarkLogic Corporation + * + * Licensed 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. + * */ public class HTTPKerberosAuthInterceptor implements Authenticator { String host; diff --git a/client/src/main/java/io/split/service/HttpAuthScheme.java b/client/src/main/java/io/split/service/ProxyAuthScheme.java similarity index 58% rename from client/src/main/java/io/split/service/HttpAuthScheme.java rename to client/src/main/java/io/split/service/ProxyAuthScheme.java index 1753f736..1d4c237b 100644 --- a/client/src/main/java/io/split/service/HttpAuthScheme.java +++ b/client/src/main/java/io/split/service/ProxyAuthScheme.java @@ -1,5 +1,5 @@ package io.split.service; -public enum HttpAuthScheme { +public enum ProxyAuthScheme { KERBEROS } diff --git a/client/src/test/java/io/split/client/SplitClientConfigTest.java b/client/src/test/java/io/split/client/SplitClientConfigTest.java index 760479d8..c79e6118 100644 --- a/client/src/test/java/io/split/client/SplitClientConfigTest.java +++ b/client/src/test/java/io/split/client/SplitClientConfigTest.java @@ -6,7 +6,7 @@ import io.split.client.impressions.ImpressionsManager; import io.split.client.dtos.RequestContext; import io.split.integrations.IntegrationsConfig; -import io.split.service.HttpAuthScheme; +import io.split.service.ProxyAuthScheme; import org.junit.Assert; import org.junit.Test; import org.mockito.Mockito; @@ -259,30 +259,30 @@ public Map> getHeaderOverrides(RequestContext context) { @Test public void checkExpectedAuthScheme() { SplitClientConfig cfg = SplitClientConfig.builder() - .authScheme(HttpAuthScheme.KERBEROS) - .kerberosPrincipalName("bilal@bilal") + .proxyAuthScheme(ProxyAuthScheme.KERBEROS) + .proxyKerberosPrincipalName("bilal@bilal") .proxyHost("local") .proxyPort(8080) .build(); - Assert.assertEquals(HttpAuthScheme.KERBEROS, cfg.authScheme()); + Assert.assertEquals(ProxyAuthScheme.KERBEROS, cfg.proxyAuthScheme()); cfg = SplitClientConfig.builder() .build(); - Assert.assertEquals(null, cfg.authScheme()); + Assert.assertEquals(null, cfg.proxyAuthScheme()); } @Test(expected = IllegalStateException.class) public void testAuthSchemeWithoutProxy() { SplitClientConfig.builder() - .authScheme(HttpAuthScheme.KERBEROS) - .kerberosPrincipalName("bilal") + .proxyAuthScheme(ProxyAuthScheme.KERBEROS) + .proxyKerberosPrincipalName("bilal") .build(); } @Test(expected = IllegalStateException.class) public void testAuthSchemeWithoutPrincipalName() { SplitClientConfig.builder() - .authScheme(HttpAuthScheme.KERBEROS) + .proxyAuthScheme(ProxyAuthScheme.KERBEROS) .proxyHost("local") .proxyPort(8080) .build(); diff --git a/client/src/test/java/io/split/client/SplitFactoryImplTest.java b/client/src/test/java/io/split/client/SplitFactoryImplTest.java index f5ae83d0..ab775553 100644 --- a/client/src/test/java/io/split/client/SplitFactoryImplTest.java +++ b/client/src/test/java/io/split/client/SplitFactoryImplTest.java @@ -4,7 +4,7 @@ import io.split.client.utils.FileTypeEnum; import io.split.client.utils.SDKMetadata; import io.split.integrations.IntegrationsConfig; -import io.split.service.HttpAuthScheme; +import io.split.service.ProxyAuthScheme; import io.split.service.SplitHttpClient; import io.split.service.SplitHttpClientKerberosImpl; import io.split.storages.enums.OperationMode; @@ -380,8 +380,8 @@ public void testBuildKerberosClientParams() throws URISyntaxException, IOExcepti SplitClientConfig splitClientConfig = SplitClientConfig.builder() .setBlockUntilReadyTimeout(10000) - .authScheme(HttpAuthScheme.KERBEROS) - .kerberosPrincipalName("bilal@localhost") + .proxyAuthScheme(ProxyAuthScheme.KERBEROS) + .proxyKerberosPrincipalName("bilal@localhost") .proxyPort(6060) .proxyHost(ENDPOINT) .build(); @@ -422,8 +422,8 @@ public void testFactoryKerberosInstance() throws URISyntaxException, IOException SplitClientConfig splitClientConfig = SplitClientConfig.builder() .setBlockUntilReadyTimeout(10000) - .authScheme(HttpAuthScheme.KERBEROS) - .kerberosPrincipalName("bilal@localhost") + .proxyAuthScheme(ProxyAuthScheme.KERBEROS) + .proxyKerberosPrincipalName("bilal@localhost") .proxyPort(6060) .proxyHost(ENDPOINT) .build(); @@ -447,8 +447,8 @@ public void testFactoryKerberosInstance() throws URISyntaxException, IOException public void testBuildOkHttpClient() { SplitClientConfig splitClientConfig = SplitClientConfig.builder() .setBlockUntilReadyTimeout(10000) - .authScheme(HttpAuthScheme.KERBEROS) - .kerberosPrincipalName("bilal@localhost") + .proxyAuthScheme(ProxyAuthScheme.KERBEROS) + .proxyKerberosPrincipalName("bilal@localhost") .proxyPort(6060) .proxyHost(ENDPOINT) .build(); diff --git a/client/src/test/java/io/split/service/HTTPKerberosAuthIntercepterTest.java b/client/src/test/java/io/split/service/HTTPKerberosAuthIntercepterTest.java index 62bc453e..b49eda75 100644 --- a/client/src/test/java/io/split/service/HTTPKerberosAuthIntercepterTest.java +++ b/client/src/test/java/io/split/service/HTTPKerberosAuthIntercepterTest.java @@ -25,7 +25,6 @@ import java.util.HashMap; import java.util.Map; - @RunWith(PowerMockRunner.class) @PrepareForTest(HTTPKerberosAuthInterceptor.class) public class HTTPKerberosAuthIntercepterTest {