Skip to content

Commit 3bfffa5

Browse files
authored
SNOW-2021533 Fix OCSP cache server URL when using proxy (#2149)
1 parent 083fd85 commit 3bfffa5

4 files changed

Lines changed: 102 additions & 12 deletions

File tree

src/main/java/net/snowflake/client/core/SFTrustManager.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,8 @@ public class SFTrustManager extends X509ExtendedTrustManager {
165165
private static final int DEFAULT_OCSP_RESPONDER_CONNECTION_TIMEOUT = 10000;
166166
/** Default OCSP Cache server host name prefix */
167167
private static final String DEFAULT_OCSP_CACHE_HOST_PREFIX = "http://ocsp.snowflakecomputing.";
168-
/** Default OCSP Cache server host name */
169-
private static final String DEFAULT_OCSP_CACHE_HOST = DEFAULT_OCSP_CACHE_HOST_PREFIX + "com";
168+
/** Default domain for OCSP cache host */
169+
private static final String DEFAULT_OCSP_CACHE_HOST_DOMAIN = "com";
170170

171171
/** OCSP response file cache directory */
172172
private static final FileCacheManager fileCacheManager;
@@ -329,7 +329,7 @@ static void resetOCSPResponseCacherServerURL(String ocspCacheServerUrl) throws I
329329
}
330330
}
331331

332-
private static void setOCSPResponseCacheServerURL(String topLevelDomain) {
332+
static void setOCSPResponseCacheServerURL(String serverURL) {
333333
String ocspCacheUrl = systemGetProperty(SF_OCSP_RESPONSE_CACHE_SERVER_URL);
334334
if (ocspCacheUrl != null) {
335335
SF_OCSP_RESPONSE_CACHE_SERVER_URL_VALUE = ocspCacheUrl;
@@ -345,6 +345,14 @@ private static void setOCSPResponseCacheServerURL(String topLevelDomain) {
345345
true);
346346
}
347347
if (SF_OCSP_RESPONSE_CACHE_SERVER_URL_VALUE == null) {
348+
String topLevelDomain = DEFAULT_OCSP_CACHE_HOST_DOMAIN;
349+
try {
350+
URL url = new URL(serverURL);
351+
int domainIndex = url.getHost().lastIndexOf(".") + 1;
352+
topLevelDomain = url.getHost().substring(domainIndex);
353+
} catch (Exception e) {
354+
logger.debug("Exception while setting top level domain (for OCSP)", e);
355+
}
348356
SF_OCSP_RESPONSE_CACHE_SERVER_URL_VALUE =
349357
String.format("%s%s/%s", DEFAULT_OCSP_CACHE_HOST_PREFIX, topLevelDomain, CACHE_FILE_NAME);
350358
}
@@ -772,8 +780,6 @@ void validateRevocationStatus(X509Certificate[] chain, String peerHost)
772780
ocspCacheServer.resetOCSPResponseCacheServer(peerHost);
773781
}
774782

775-
String topLevelDomain = peerHost.substring(peerHost.lastIndexOf(".") + 1);
776-
setOCSPResponseCacheServerURL(topLevelDomain);
777783
boolean isCached = isCached(pairIssuerSubjectList);
778784
if (useOCSPResponseCacheServer() && !isCached) {
779785
if (!ocspCacheServer.new_endpoint_enabled) {

src/main/java/net/snowflake/client/core/SessionUtil.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package net.snowflake.client.core;
22

33
import static net.snowflake.client.core.SFTrustManager.resetOCSPResponseCacherServerURL;
4+
import static net.snowflake.client.core.SFTrustManager.setOCSPResponseCacheServerURL;
45
import static net.snowflake.client.jdbc.SnowflakeUtil.isNullOrEmpty;
56
import static net.snowflake.client.jdbc.SnowflakeUtil.systemGetEnv;
67
import static net.snowflake.client.jdbc.SnowflakeUtil.systemGetProperty;
@@ -514,6 +515,13 @@ static SFLoginOutput newSession(
514515
Map<SFSessionProperty, Object> connectionPropertiesMap,
515516
String tracingLevel)
516517
throws SFException, SnowflakeSQLException {
518+
try {
519+
// Adjust OCSP cache server if it is private link
520+
resetOCSPUrlIfNecessary(loginInput.getServerUrl());
521+
} catch (IOException ex) {
522+
throw new SFException(ex, ErrorCode.IO_ERROR, "unexpected URL syntax exception");
523+
}
524+
517525
Stopwatch stopwatch = new Stopwatch();
518526
stopwatch.start();
519527
// build URL for login request
@@ -612,13 +620,6 @@ static SFLoginOutput newSession(
612620
throw new SFException(ex, ErrorCode.INTERNAL_ERROR, "unexpected URI syntax exception:1");
613621
}
614622

615-
try {
616-
// Adjust OCSP cache server if it is private link
617-
resetOCSPUrlIfNecessary(loginInput.getServerUrl());
618-
} catch (IOException ex) {
619-
throw new SFException(ex, ErrorCode.IO_ERROR, "unexpected URL syntax exception");
620-
}
621-
622623
HttpPost postRequest = null;
623624

624625
try {
@@ -1931,6 +1932,7 @@ enum TokenRequestType {
19311932
* @throws IOException If exception encountered
19321933
*/
19331934
public static void resetOCSPUrlIfNecessary(String serverUrl) throws IOException {
1935+
setOCSPResponseCacheServerURL(serverUrl);
19341936
if (PrivateLinkDetector.isPrivateLink(serverUrl)) {
19351937
// Privatelink uses special OCSP Cache server
19361938
URL url = new URL(serverUrl);
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package net.snowflake.client;
2+
3+
public class SystemPropertyOverrider {
4+
private final String propertyName;
5+
private final String oldValue;
6+
7+
public SystemPropertyOverrider(String propertyName, String newValue) {
8+
this.propertyName = propertyName;
9+
this.oldValue = System.getProperty(propertyName);
10+
System.setProperty(propertyName, newValue);
11+
}
12+
13+
public void rollback() {
14+
if (oldValue != null) {
15+
System.setProperty(propertyName, oldValue);
16+
} else {
17+
System.clearProperty(propertyName);
18+
}
19+
}
20+
}

src/test/java/net/snowflake/client/core/SFTrustManagerIT.java

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package net.snowflake.client.core;
22

3+
import static net.snowflake.client.core.SFTrustManager.SF_OCSP_RESPONSE_CACHE_SERVER_URL_VALUE;
34
import static org.awaitility.Awaitility.await;
45
import static org.hamcrest.CoreMatchers.equalTo;
56
import static org.hamcrest.CoreMatchers.not;
67
import static org.hamcrest.MatcherAssert.assertThat;
78
import static org.hamcrest.core.AnyOf.anyOf;
9+
import static org.junit.jupiter.api.Assertions.assertEquals;
810

911
import java.io.File;
1012
import java.io.IOException;
@@ -15,12 +17,16 @@
1517
import java.security.cert.X509Certificate;
1618
import java.time.Duration;
1719
import java.util.ArrayList;
20+
import java.util.Arrays;
1821
import java.util.List;
22+
import java.util.Properties;
1923
import java.util.concurrent.TimeUnit;
2024
import java.util.stream.Stream;
2125
import javax.net.ssl.SSLHandshakeException;
26+
import net.snowflake.client.SystemPropertyOverrider;
2227
import net.snowflake.client.category.TestTags;
2328
import net.snowflake.client.jdbc.BaseJDBCTest;
29+
import net.snowflake.client.jdbc.SnowflakeConnectionV1;
2430
import net.snowflake.client.jdbc.telemetryOOB.TelemetryService;
2531
import net.snowflake.client.log.SFLogger;
2632
import net.snowflake.client.log.SFLoggerFactory;
@@ -36,6 +42,7 @@
3642
import org.junit.jupiter.params.provider.Arguments;
3743
import org.junit.jupiter.params.provider.ArgumentsProvider;
3844
import org.junit.jupiter.params.provider.ArgumentsSource;
45+
import org.junit.jupiter.params.provider.CsvSource;
3946

4047
@Tag(TestTags.CORE)
4148
public class SFTrustManagerIT extends BaseJDBCTest {
@@ -96,6 +103,8 @@ public void tearDown() throws InterruptedException {
96103
public void testOcsp(String host) throws Throwable {
97104
System.setProperty(
98105
SFTrustManager.SF_OCSP_RESPONSE_CACHE_SERVER_ENABLED, Boolean.TRUE.toString());
106+
// this initialization normally happens on first call
107+
SFTrustManager.setOCSPResponseCacheServerURL(String.format("http://%s", host));
99108
HttpClient client =
100109
HttpUtil.buildHttpClient(
101110
new HttpClientSettingsKey(OCSPMode.FAIL_CLOSED),
@@ -259,4 +268,57 @@ private InputStream getFile(String fileName) throws Throwable {
259268
URL url = classLoader.getResource(fileName);
260269
return url != null ? url.openStream() : null;
261270
}
271+
272+
@ParameterizedTest
273+
@CsvSource({
274+
"jdbc:snowflake://someaccount.snowflakecomputing.com:443,http://ocsp.snowflakecomputing.com/ocsp_response_cache.json",
275+
"jdbc:snowflake://someaccount.snowflakecomputing.cn:443,http://ocsp.snowflakecomputing.cn/ocsp_response_cache.json",
276+
})
277+
void testOCSPCacheServerUrlWithoutProxy(String sfHost, String ocspHost) throws Exception {
278+
Properties props = new Properties();
279+
props.setProperty(SFSessionProperty.USER.getPropertyKey(), "testUser");
280+
props.setProperty(SFSessionProperty.PASSWORD.getPropertyKey(), "testPassword");
281+
props.setProperty(SFSessionProperty.LOGIN_TIMEOUT.getPropertyKey(), "1");
282+
try {
283+
new SnowflakeConnectionV1(sfHost, props);
284+
} catch (Exception e) {
285+
// do nothing, we don't want to connect, just check the value below
286+
}
287+
assertEquals(SF_OCSP_RESPONSE_CACHE_SERVER_URL_VALUE, ocspHost);
288+
}
289+
290+
@ParameterizedTest
291+
@CsvSource({
292+
"jdbc:snowflake://someaccount.snowflakecomputing.com:443,http://ocsp.snowflakecomputing.com/ocsp_response_cache.json",
293+
"jdbc:snowflake://someaccount.snowflakecomputing.cn:443,http://ocsp.snowflakecomputing.cn/ocsp_response_cache.json",
294+
})
295+
void testOCSPCacheServerUrlWithProxy(String sfHost, String ocspHost) {
296+
SystemPropertyOverrider useProxyOverrider =
297+
new SystemPropertyOverrider("http.useProxy", "true");
298+
SystemPropertyOverrider proxyHostOverrider =
299+
new SystemPropertyOverrider("http.proxyHost", "localhost");
300+
SystemPropertyOverrider proxyPortOverrider =
301+
new SystemPropertyOverrider("http.proxyPort", "8080");
302+
try {
303+
Properties props = new Properties();
304+
props.setProperty(SFSessionProperty.USER.getPropertyKey(), "testUser");
305+
props.setProperty(SFSessionProperty.PASSWORD.getPropertyKey(), "testPassword");
306+
props.setProperty(SFSessionProperty.LOGIN_TIMEOUT.getPropertyKey(), "1");
307+
try {
308+
new SnowflakeConnectionV1(sfHost, props);
309+
} catch (Exception e) {
310+
// do nothing, we don't want to connect, just check the value below
311+
}
312+
assertEquals(SF_OCSP_RESPONSE_CACHE_SERVER_URL_VALUE, ocspHost);
313+
} finally {
314+
Arrays.asList(useProxyOverrider, proxyHostOverrider, proxyPortOverrider)
315+
.forEach(SystemPropertyOverrider::rollback);
316+
}
317+
}
318+
319+
@BeforeEach
320+
@AfterEach
321+
void cleanup() {
322+
SF_OCSP_RESPONSE_CACHE_SERVER_URL_VALUE = null;
323+
}
262324
}

0 commit comments

Comments
 (0)