Skip to content

Commit c9ccfa5

Browse files
SNOW-3643369: Always set explicit GCS credentials to prevent ADC probe in SPCS
Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 4993be9 commit c9ccfa5

4 files changed

Lines changed: 15 additions & 11 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
# Changelog
44
- v4.3.1-SNAPSHOT
5+
- Fixed GCS-backed internal stage PUT failing with opaque `invalid_gcs_credentials` in SPCS pods on GCP: the GCS SDK's Application Default Credentials (ADC) probe was reaching out to `metadata.google.internal` which is unreachable inside SPCS; explicit credentials are now always set when a `GCS_ACCESS_TOKEN` is present, suppressing the ADC probe entirely. Also fixed `GCSAccessStrategyAwsSdk` rejecting custom GCS endpoints that lack an `https://` scheme prefix (e.g. bare `storage.me-central2.rep.googleapis.com`), mirroring the existing handling in `GCSDefaultAccessStrategy`. The catch-all in `setupGCSClient` now chains and logs the original exception instead of swallowing it (snowflakedb/snowflake-jdbc#2664).
56
- Fixed Azure PUT memory leak where each PUT instantiated a fresh `BlobServiceClient` whose underlying reactor-netty stack the SDK exposes no API to release; the Azure SDK `HttpClient` and its `ConnectionProvider` are now shared across all PUTs in a session and disposed at session close, mirroring the existing S3 pattern (snowflakedb/snowflake-jdbc#2658).
67
- Fixed `SFResultJsonParser2Failed: invalid escaped unicode character` when a chunked JSON result contained UTF-16 surrogate-pair `\u` escapes (e.g. emoji) and the read buffer happened to split exactly 9 bytes after `\u`; the off-by-one boundary guard in `ResultJsonParserV2` now reserves the full 10 bytes a surrogate pair requires (snowflakedb/snowflake-jdbc#2660).
78

src/main/java/net/snowflake/client/internal/jdbc/cloud/storage/GCSAccessStrategyAwsSdk.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ class GCSAccessStrategyAwsSdk implements GCSAccessStrategy {
6060
Optional<String> oEndpoint = stage.gcsCustomEndpoint();
6161
String endpoint = "https://storage.googleapis.com";
6262
if (oEndpoint.isPresent()) {
63-
endpoint = oEndpoint.get();
63+
String custom = oEndpoint.get();
64+
endpoint = custom.startsWith("https://") ? custom : "https://" + custom;
6465
}
6566
if (stage.getStorageAccount() != null && endpoint.startsWith(stage.getStorageAccount())) {
6667
endpoint = endpoint.replaceFirst(stage.getStorageAccount() + ".", "");

src/main/java/net/snowflake/client/internal/jdbc/cloud/storage/GCSDefaultAccessStrategy.java

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,20 +51,18 @@ class GCSDefaultAccessStrategy implements GCSAccessStrategy {
5151
StorageOptions.Builder builder = StorageOptions.newBuilder();
5252
overrideHost(stage, builder);
5353

54-
if (SnowflakeGCSClient.areDisabledGcsDefaultCredentials(session)) {
55-
logger.debug(
56-
"Adding explicit credentials to avoid default credential lookup by the GCS client");
57-
builder.setCredentials(GoogleCredentials.create(new AccessToken(accessToken, null)));
58-
}
54+
// Always set explicit credentials to prevent Application Default Credentials (ADC) lookup.
55+
// Without this, StorageOptions.build().getService() probes metadata.google.internal which
56+
// is unreachable in environments like SPCS, causing an opaque "invalid_gcs_credentials"
57+
// error.
58+
// Actual API authentication is handled by the Authorization header below, not this credential
59+
// object — it exists solely to suppress the ADC probe.
60+
builder.setCredentials(GoogleCredentials.create(new AccessToken(accessToken, null)));
5961

6062
if (transportFactory != null) {
6163
builder.setTransportOptions(
6264
HttpTransportOptions.newBuilder().setHttpTransportFactory(transportFactory).build());
6365
}
64-
65-
// Using GoogleCredential with access token will cause IllegalStateException when the token
66-
// is expired and trying to refresh, which cause error cannot be caught. Instead, set a
67-
// header so we can caught the error code.
6866
this.gcsClient =
6967
builder
7068
.setHeaderProvider(

src/main/java/net/snowflake/client/internal/jdbc/cloud/storage/SnowflakeGCSClient.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1262,8 +1262,12 @@ private void setupGCSClient(
12621262
encryptionKeySize);
12631263
}
12641264
}
1265+
} catch (SnowflakeSQLException ex) {
1266+
logger.debug("Failed to initialize GCS client", ex);
1267+
throw ex;
12651268
} catch (Exception ex) {
1266-
throw new IllegalArgumentException("invalid_gcs_credentials");
1269+
logger.debug("Failed to initialize GCS client", ex);
1270+
throw new IllegalArgumentException("invalid_gcs_credentials", ex);
12671271
}
12681272
}
12691273

0 commit comments

Comments
 (0)