Skip to content

Commit 74a4533

Browse files
authored
Merge pull request #574 from splitio/FME-4283-proxy-auth-config
Updated SplitClientConfig
2 parents 193f3c4 + 3cca5ea commit 74a4533

File tree

3 files changed

+228
-2
lines changed

3 files changed

+228
-2
lines changed

client/src/main/java/io/split/client/SplitClientConfig.java

Lines changed: 94 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.split.client;
22

3+
import io.split.client.dtos.ProxyMTLSAuth;
34
import io.split.client.impressions.ImpressionListener;
45
import io.split.client.impressions.ImpressionsManager;
56
import io.split.client.utils.FileTypeEnum;
@@ -34,6 +35,11 @@ public class SplitClientConfig {
3435
public static final String STREAMING_ENDPOINT = "https://streaming.split.io/sse";
3536
public static final String TELEMETRY_ENDPOINT = "https://telemetry.split.io/api/v1";
3637

38+
public static class HttpScheme {
39+
public static final String HTTP = "http";
40+
public static final String HTTPS = "https";
41+
}
42+
3743
private final String _endpoint;
3844
private final String _eventsEndpoint;
3945

@@ -85,6 +91,8 @@ public class SplitClientConfig {
8591
private final HttpHost _proxy;
8692
private final String _proxyUsername;
8793
private final String _proxyPassword;
94+
private final String _proxyToken;
95+
private final ProxyMTLSAuth _proxyMtlsAuth;
8896

8997
// To be set during startup
9098
public static String splitSdkVersion;
@@ -118,6 +126,8 @@ private SplitClientConfig(String endpoint,
118126
HttpHost proxy,
119127
String proxyUsername,
120128
String proxyPassword,
129+
String proxyToken,
130+
ProxyMTLSAuth proxyMtlsAuth,
121131
int eventsQueueSize,
122132
long eventSendIntervalInMillis,
123133
int maxStringLength,
@@ -171,6 +181,8 @@ private SplitClientConfig(String endpoint,
171181
_proxy = proxy;
172182
_proxyUsername = proxyUsername;
173183
_proxyPassword = proxyPassword;
184+
_proxyToken = proxyToken;
185+
_proxyMtlsAuth = proxyMtlsAuth;
174186
_eventsQueueSize = eventsQueueSize;
175187
_eventSendIntervalInMillis = eventSendIntervalInMillis;
176188
_maxStringLength = maxStringLength;
@@ -302,6 +314,14 @@ public String proxyPassword() {
302314
return _proxyPassword;
303315
}
304316

317+
public String proxyToken() {
318+
return _proxyToken;
319+
}
320+
321+
public ProxyMTLSAuth proxyMTLSAuth() {
322+
return _proxyMtlsAuth;
323+
}
324+
305325
public long eventSendIntervalInMillis() {
306326
return _eventSendIntervalInMillis;
307327
}
@@ -417,8 +437,8 @@ public boolean isSdkEndpointOverridden() {
417437
}
418438

419439
public CustomHttpModule alternativeHTTPModule() { return _alternativeHTTPModule; }
420-
public static final class Builder {
421440

441+
public static final class Builder {
422442
private String _endpoint = SDK_ENDPOINT;
423443
private boolean _endpointSet = false;
424444
private String _eventsEndpoint = EVENTS_ENDPOINT;
@@ -440,8 +460,11 @@ public static final class Builder {
440460
private int _waitBeforeShutdown = 5000;
441461
private String _proxyHost = "localhost";
442462
private int _proxyPort = -1;
463+
private String _proxyScheme = HttpScheme.HTTP;
443464
private String _proxyUsername;
444465
private String _proxyPassword;
466+
private String _proxyToken;
467+
private ProxyMTLSAuth _proxyMtlsAuth;
445468
private int _eventsQueueSize = 500;
446469
private long _eventSendIntervalInMillis = 30 * (long)1000;
447470
private int _maxStringLength = 250;
@@ -754,6 +777,17 @@ public Builder proxyPort(int proxyPort) {
754777
return this;
755778
}
756779

780+
/**
781+
* The http scheme of the proxy. Default is http.
782+
*
783+
* @param proxyScheme protocol for the proxy
784+
* @return this builder
785+
*/
786+
public Builder proxyScheme(String proxyScheme) {
787+
_proxyScheme = proxyScheme;
788+
return this;
789+
}
790+
757791
/**
758792
* Set the username for authentication against the proxy (if proxy settings are enabled). (Optional).
759793
*
@@ -776,6 +810,28 @@ public Builder proxyPassword(String proxyPassword) {
776810
return this;
777811
}
778812

813+
/**
814+
* Set the token for authentication against the proxy (if proxy settings are enabled). (Optional).
815+
*
816+
* @param proxyToken
817+
* @return this builder
818+
*/
819+
public Builder proxyToken(String proxyToken) {
820+
_proxyToken = proxyToken;
821+
return this;
822+
}
823+
824+
/**
825+
* Set the mtls authentication against the proxy (if proxy settings are enabled). (Optional).
826+
*
827+
* @param proxyMtlsAuth
828+
* @return this builder
829+
*/
830+
public Builder proxyMtlsAuth(ProxyMTLSAuth proxyMtlsAuth) {
831+
_proxyMtlsAuth = proxyMtlsAuth;
832+
return this;
833+
}
834+
779835
/**
780836
* Disables running destroy() on shutdown by default.
781837
*
@@ -788,7 +844,7 @@ public Builder disableDestroyOnShutDown() {
788844

789845
HttpHost proxy() {
790846
if (_proxyPort != -1) {
791-
return new HttpHost(_proxyHost, _proxyPort);
847+
return new HttpHost(_proxyScheme, _proxyHost, _proxyPort);
792848
}
793849
// Default is no proxy.
794850
return null;
@@ -1096,6 +1152,38 @@ private void verifyAlternativeClient() {
10961152
}
10971153
}
10981154

1155+
private void verifyProxy() {
1156+
if (_proxyPort == -1) {
1157+
return;
1158+
}
1159+
1160+
if (!(_proxyScheme.equals(HttpScheme.HTTP) || _proxyScheme.equals(HttpScheme.HTTPS))) {
1161+
throw new IllegalArgumentException("Proxy scheme must be either http or https.");
1162+
}
1163+
1164+
if (_proxyUsername == null && _proxyToken == null && _proxyMtlsAuth == null) {
1165+
return;
1166+
}
1167+
1168+
if (_proxyUsername != null && _proxyToken != null) {
1169+
throw new IllegalArgumentException("Proxy user and Proxy token params are updated, set only one param.");
1170+
}
1171+
1172+
if (_proxyUsername != null && _proxyMtlsAuth != null) {
1173+
throw new IllegalArgumentException("Proxy user and Proxy mTLS params are updated, set only one param.");
1174+
}
1175+
1176+
if (_proxyToken != null && _proxyMtlsAuth != null) {
1177+
throw new IllegalArgumentException("Proxy token and Proxy mTLS params are updated, set only one param.");
1178+
}
1179+
1180+
if (_proxyMtlsAuth != null) {
1181+
if (_proxyMtlsAuth.getP12File() == null || _proxyMtlsAuth.getP12FilePassKey() == null) {
1182+
throw new IllegalArgumentException("Proxy mTLS must have p12 file path and name, and pass phrase.");
1183+
}
1184+
}
1185+
}
1186+
10991187
public SplitClientConfig build() {
11001188

11011189
verifyRates();
@@ -1108,6 +1196,8 @@ public SplitClientConfig build() {
11081196

11091197
verifyAlternativeClient();
11101198

1199+
verifyProxy();
1200+
11111201
if (_numThreadsForSegmentFetch <= 0) {
11121202
throw new IllegalArgumentException("Number of threads for fetching segments MUST be greater than zero");
11131203
}
@@ -1133,6 +1223,8 @@ public SplitClientConfig build() {
11331223
proxy(),
11341224
_proxyUsername,
11351225
_proxyPassword,
1226+
_proxyToken,
1227+
_proxyMtlsAuth,
11361228
_eventsQueueSize,
11371229
_eventSendIntervalInMillis,
11381230
_maxStringLength,
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package io.split.client.dtos;
2+
3+
public class ProxyMTLSAuth {
4+
private final String _proxyP12File;
5+
private final String _proxyP12FilePassKey;
6+
7+
private ProxyMTLSAuth(String proxyP12File, String proxyP12FilePassKey) {
8+
_proxyP12File = proxyP12File;
9+
_proxyP12FilePassKey = proxyP12FilePassKey;
10+
}
11+
12+
public String getP12File() { return _proxyP12File; }
13+
14+
public String getP12FilePassKey() { return _proxyP12FilePassKey; }
15+
16+
public static ProxyMTLSAuth.Builder builder() {
17+
return new ProxyMTLSAuth.Builder();
18+
}
19+
20+
public static class Builder {
21+
private String _p12File;
22+
private String _p12FilePassKey;
23+
24+
public Builder() {
25+
}
26+
27+
public ProxyMTLSAuth.Builder proxyP12File(String p12File) {
28+
_p12File = p12File;
29+
return this;
30+
}
31+
32+
public ProxyMTLSAuth.Builder proxyP12FilePassKey(String p12FilePassKey) {
33+
_p12FilePassKey = p12FilePassKey;
34+
return this;
35+
}
36+
37+
public ProxyMTLSAuth build() {
38+
return new ProxyMTLSAuth(_p12File, _p12FilePassKey);
39+
}
40+
}
41+
}

client/src/test/java/io/split/client/SplitClientConfigTest.java

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.split.client;
22

33
import com.google.common.util.concurrent.ThreadFactoryBuilder;
4+
import io.split.client.dtos.ProxyMTLSAuth;
45
import io.split.client.impressions.Impression;
56
import io.split.client.impressions.ImpressionListener;
67
import io.split.client.impressions.ImpressionsManager;
@@ -252,6 +253,98 @@ public Map<String, List<String>> getHeaderOverrides(RequestContext context) {
252253

253254
SplitClientConfig config2 = SplitClientConfig.builder().build();
254255
Assert.assertNull(config2.customHeaderDecorator());
256+
}
257+
258+
@Test
259+
public void checkProxyParams() {
260+
SplitClientConfig config = SplitClientConfig.builder()
261+
.proxyHost("proxy-host")
262+
.proxyPort(8888).build();
263+
Assert.assertEquals("proxy-host", config.proxy().getHostName());
264+
Assert.assertEquals(8888, config.proxy().getPort());
265+
266+
config = SplitClientConfig.builder()
267+
.proxyHost("proxy-host")
268+
.proxyPort(8888)
269+
.proxyScheme(SplitClientConfig.HttpScheme.HTTPS)
270+
.proxyUsername("user")
271+
.proxyPassword("pass")
272+
.build();
273+
Assert.assertEquals("user", config.proxyUsername());
274+
Assert.assertEquals("pass", config.proxyPassword());
275+
276+
config = SplitClientConfig.builder()
277+
.proxyHost("proxy-host")
278+
.proxyPort(8888)
279+
.proxyToken("my-token")
280+
.build();
281+
Assert.assertEquals("my-token", config.proxyToken());
282+
283+
config = SplitClientConfig.builder()
284+
.proxyHost("proxy-host")
285+
.proxyPort(8888)
286+
.proxyMtlsAuth(new ProxyMTLSAuth.Builder().proxyP12File("path/to/file").proxyP12FilePassKey("pass-key").build())
287+
.build();
288+
Assert.assertEquals("path/to/file", config.proxyMTLSAuth().getP12File());
289+
Assert.assertEquals("pass-key", config.proxyMTLSAuth().getP12FilePassKey());
290+
}
291+
292+
@Test(expected = IllegalArgumentException.class)
293+
public void cannotUseInvalidHttpScheme() {
294+
SplitClientConfig.builder()
295+
.proxyHost("proxy-host")
296+
.proxyPort(8888)
297+
.proxyScheme("ftp")
298+
.build();
299+
}
300+
301+
@Test(expected = IllegalArgumentException.class)
302+
public void cannotUseProxyTokenAndProxyUsername() {
303+
SplitClientConfig.builder()
304+
.proxyHost("proxy-host")
305+
.proxyPort(8888)
306+
.proxyUsername("user")
307+
.proxyPassword("pass")
308+
.proxyToken("my-token")
309+
.build();
310+
}
311+
312+
@Test(expected = IllegalArgumentException.class)
313+
public void cannotUseProxyUserAndProxyMtls() {
314+
SplitClientConfig.builder()
315+
.proxyHost("proxy-host")
316+
.proxyPort(8888)
317+
.proxyUsername("user")
318+
.proxyPassword("pass")
319+
.proxyMtlsAuth(new ProxyMTLSAuth.Builder().proxyP12File("path/to/file").proxyP12FilePassKey("pass-key").build())
320+
.build();
321+
}
255322

323+
@Test(expected = IllegalArgumentException.class)
324+
public void cannotUseProxyTokenAndProxyMtls() {
325+
SplitClientConfig.builder()
326+
.proxyHost("proxy-host")
327+
.proxyPort(8888)
328+
.proxyToken("my-token")
329+
.proxyMtlsAuth(new ProxyMTLSAuth.Builder().proxyP12File("path/to/file").proxyP12FilePassKey("pass-key").build())
330+
.build();
331+
}
332+
333+
@Test(expected = IllegalArgumentException.class)
334+
public void mustUseP12FileWithProxyMtls() {
335+
SplitClientConfig.builder()
336+
.proxyHost("proxy-host")
337+
.proxyPort(8888)
338+
.proxyMtlsAuth(new ProxyMTLSAuth.Builder().proxyP12FilePassKey("pass-key").build())
339+
.build();
340+
}
341+
342+
@Test(expected = IllegalArgumentException.class)
343+
public void mustUseP12PassKeyWithProxyMtls() {
344+
SplitClientConfig.builder()
345+
.proxyHost("proxy-host")
346+
.proxyPort(8888)
347+
.proxyMtlsAuth(new ProxyMTLSAuth.Builder().proxyP12File("path/to/file").build())
348+
.build();
256349
}
257350
}

0 commit comments

Comments
 (0)