use of net.snowflake.client.jdbc.SnowflakeSQLException in project snowflake-jdbc by snowflakedb.
the class HttpUtil method executeRequestInternal.
/**
* Helper to execute a request with retry and check and throw exception if response is not
* success. This should be used only for small request has it execute the REST request and get
* back the result as a string.
*
* <p>Connection under the httpRequest is released.
*
* @param httpRequest request object contains all the information
* @param retryTimeout retry timeout (in seconds)
* @param authTimeout authenticator specific timeout (in seconds)
* @param socketTimeout socket timeout (in ms)
* @param retryCount retry count for the request
* @param injectSocketTimeout simulate socket timeout
* @param canceling canceling flag
* @param withoutCookies whether this request should ignore cookies
* @param includeRetryParameters whether to include retry parameters in retried requests
* @param includeRequestGuid whether to include request_guid
* @param retryOnHTTP403 whether to retry on HTTP 403
* @param httpClient client object used to communicate with other machine
* @return response in String
* @throws SnowflakeSQLException if Snowflake error occurs
* @throws IOException raises if a general IO error occurs
*/
private static String executeRequestInternal(HttpRequestBase httpRequest, int retryTimeout, int authTimeout, int socketTimeout, int retryCount, int injectSocketTimeout, AtomicBoolean canceling, boolean withoutCookies, boolean includeRetryParameters, boolean includeRequestGuid, boolean retryOnHTTP403, CloseableHttpClient httpClient) throws SnowflakeSQLException, IOException {
// HttpRequest.toString() contains request URI. Scrub any credentials, if
// present, before logging
String requestInfoScrubbed = SecretDetector.maskSASToken(httpRequest.toString());
logger.debug("Pool: {} Executing: {}", (ArgSupplier) HttpUtil::getHttpClientStats, requestInfoScrubbed);
String theString;
StringWriter writer = null;
CloseableHttpResponse response = null;
try {
response = RestRequest.execute(httpClient, httpRequest, retryTimeout, authTimeout, socketTimeout, retryCount, injectSocketTimeout, canceling, withoutCookies, includeRetryParameters, includeRequestGuid, retryOnHTTP403);
if (response == null || response.getStatusLine().getStatusCode() != 200) {
logger.error("Error executing request: {}", requestInfoScrubbed);
SnowflakeUtil.logResponseDetails(response, logger);
if (response != null) {
EntityUtils.consume(response.getEntity());
}
throw new SnowflakeSQLException(SqlState.IO_ERROR, ErrorCode.NETWORK_ERROR.getMessageCode(), "HTTP status=" + ((response != null) ? response.getStatusLine().getStatusCode() : "null response"));
}
writer = new StringWriter();
try (InputStream ins = response.getEntity().getContent()) {
IOUtils.copy(ins, writer, "UTF-8");
}
theString = writer.toString();
} finally {
IOUtils.closeQuietly(writer);
IOUtils.closeQuietly(response);
}
logger.debug("Pool: {} Request returned for: {}", (ArgSupplier) HttpUtil::getHttpClientStats, requestInfoScrubbed);
return theString;
}
use of net.snowflake.client.jdbc.SnowflakeSQLException in project snowflake-jdbc by snowflakedb.
the class StorageClientFactory method createS3Client.
/**
* Creates a SnowflakeS3ClientObject which encapsulates the Amazon S3 client
*
* @param stageCredentials Map of stage credential properties
* @param parallel degree of parallelism
* @param encMat encryption material for the client
* @param stageRegion the region where the stage is located
* @param stageEndPoint the FIPS endpoint for the stage, if needed
* @param isClientSideEncrypted whether client-side encryption should be used
* @param session the active session
* @param useS3RegionalUrl
* @return the SnowflakeS3Client instance created
* @throws SnowflakeSQLException failure to create the S3 client
*/
private SnowflakeS3Client createS3Client(Map<?, ?> stageCredentials, int parallel, RemoteStoreFileEncryptionMaterial encMat, Properties proxyProperties, String stageRegion, String stageEndPoint, boolean isClientSideEncrypted, SFBaseSession session, boolean useS3RegionalUrl) throws SnowflakeSQLException {
final int S3_TRANSFER_MAX_RETRIES = 3;
logger.debug("createS3Client encryption={}", (encMat == null ? "no" : "yes"));
SnowflakeS3Client s3Client;
ClientConfiguration clientConfig = new ClientConfiguration();
clientConfig.setMaxConnections(parallel + 1);
clientConfig.setMaxErrorRetry(S3_TRANSFER_MAX_RETRIES);
clientConfig.setDisableSocketProxy(HttpUtil.isSocksProxyDisabled());
logger.debug("s3 client configuration: maxConnection={}, connectionTimeout={}, " + "socketTimeout={}, maxErrorRetry={}", clientConfig.getMaxConnections(), clientConfig.getConnectionTimeout(), clientConfig.getSocketTimeout(), clientConfig.getMaxErrorRetry());
try {
s3Client = new SnowflakeS3Client(stageCredentials, clientConfig, encMat, proxyProperties, stageRegion, stageEndPoint, isClientSideEncrypted, session, useS3RegionalUrl);
} catch (Exception ex) {
logger.debug("Exception creating s3 client", ex);
throw ex;
}
logger.debug("s3 client created");
return s3Client;
}
use of net.snowflake.client.jdbc.SnowflakeSQLException in project snowflake-jdbc by snowflakedb.
the class TelemetryClient method sendBatch.
/**
* Send all cached logs to server
*
* @return whether the logs were sent successfully
* @throws IOException if closed or uploading batch fails
*/
private boolean sendBatch() throws IOException {
if (isClosed) {
throw new IOException("Telemetry connector is closed");
}
if (!isTelemetryEnabled()) {
return false;
}
LinkedList<TelemetryData> tmpList;
synchronized (locker) {
tmpList = this.logBatch;
this.logBatch = new LinkedList<>();
}
if (this.session != null && this.session.isClosed()) {
throw new UnexpectedException("Session is closed when sending log");
}
if (!tmpList.isEmpty()) {
// session shared with JDBC
String payload = logsToString(tmpList);
logger.debugNoMask("Payload of telemetry is : " + payload);
HttpPost post = new HttpPost(this.telemetryUrl);
post.setEntity(new StringEntity(payload));
post.setHeader("Content-type", "application/json");
if (this.session == null) {
post.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + this.token);
post.setHeader("X-Snowflake-Authorization-Token-Type", "KEYPAIR_JWT");
post.setHeader(HttpHeaders.ACCEPT, "application/json");
} else {
post.setHeader(HttpHeaders.AUTHORIZATION, "Snowflake Token=\"" + this.session.getSessionToken() + "\"");
}
String response = null;
try {
response = this.session == null ? HttpUtil.executeGeneralRequest(post, TELEMETRY_HTTP_RETRY_TIMEOUT_IN_SEC, this.session.getAuthTimeout(), this.session.getHttpClientSocketTimeout(), 0, this.httpClient) : HttpUtil.executeGeneralRequest(post, TELEMETRY_HTTP_RETRY_TIMEOUT_IN_SEC, this.session.getAuthTimeout(), this.session.getHttpClientSocketTimeout(), 0, this.session.getHttpClientKey());
} catch (SnowflakeSQLException e) {
// when got error like 404 or bad request, disable telemetry in this
disableTelemetry();
// telemetry instance
logger.error("Telemetry request failed, " + "response: {}, exception: {}", response, e.getMessage());
return false;
}
}
return true;
}
use of net.snowflake.client.jdbc.SnowflakeSQLException in project snowflake-jdbc by snowflakedb.
the class SessionUtilLatestIT method testJwtAuthTimeoutRetry.
/**
* Tests the JWT renew functionality when retrying login requests. To run, update environment
* variables to use connect with JWT authentication.
*
* @throws SFException
* @throws SnowflakeSQLException
*/
@Ignore
@Test
public void testJwtAuthTimeoutRetry() throws SFException, SnowflakeSQLException {
final SFLoginInput loginInput = initMockLoginInput();
Map<SFSessionProperty, Object> connectionPropertiesMap = initConnectionPropertiesMap();
MockedStatic<HttpUtil> mockedHttpUtil = mockStatic(HttpUtil.class);
SnowflakeSQLException ex = new SnowflakeSQLException(ErrorCode.AUTHENTICATOR_REQUEST_TIMEOUT, 0, true, 0);
mockedHttpUtil.when(() -> HttpUtil.executeGeneralRequest(Mockito.any(HttpRequestBase.class), Mockito.anyInt(), Mockito.anyInt(), Mockito.anyInt(), Mockito.anyInt(), Mockito.nullable(HttpClientSettingsKey.class))).thenThrow(// fail first
ex).thenReturn(// succeed on retry
"{\"data\":null,\"code\":null,\"message\":null,\"success\":true}");
SessionUtil.openSession(loginInput, connectionPropertiesMap, "ALL");
}
use of net.snowflake.client.jdbc.SnowflakeSQLException in project snowflake-jdbc by snowflakedb.
the class SnowflakeMFACacheTest method testMFAFunctionality.
@Test
public void testMFAFunctionality() throws SQLException {
SessionUtil.deleteMfaTokenCache(host, user);
try (MockedStatic<HttpUtil> mockedHttpUtil = Mockito.mockStatic(HttpUtil.class)) {
mockedHttpUtil.when(() -> HttpUtil.executeGeneralRequest(any(HttpPost.class), anyInt(), anyInt(), anyInt(), anyInt(), any(HttpClientSettingsKey.class))).thenAnswer(new Answer<String>() {
int callCount = 0;
@Override
public String answer(InvocationOnMock invocation) throws Throwable {
String res;
JsonNode jsonNode;
final Object[] args = invocation.getArguments();
if (callCount == 0) {
// First connection request
jsonNode = parseRequest((HttpPost) args[0]);
assertTrue(jsonNode.path("data").path("SESSION_PARAMETERS").path("CLIENT_REQUEST_MFA_TOKEN").asBoolean());
// return first mfa token
res = getNormalMockedHttpResponse(true, 0).toString();
} else if (callCount == 1) {
// First close() request
res = getNormalMockedHttpResponse(true, -1).toString();
} else if (callCount == 2) {
// Second connection request
jsonNode = parseRequest((HttpPost) args[0]);
assertTrue(jsonNode.path("data").path("SESSION_PARAMETERS").path("CLIENT_REQUEST_MFA_TOKEN").asBoolean());
assertEquals(mockedMfaToken[0], jsonNode.path("data").path("TOKEN").asText());
// Normally backend won't send a new mfa token in this case. For testing
// purpose, we issue a new token to test whether the mfa token can be refreshed
// when receiving a new one from server.
res = getNormalMockedHttpResponse(true, 1).toString();
} else if (callCount == 3) {
// Second close() request
res = getNormalMockedHttpResponse(true, -1).toString();
} else if (callCount == 4) {
// Third connection request
// Check for the new mfa token
jsonNode = parseRequest((HttpPost) args[0]);
assertTrue(jsonNode.path("data").path("SESSION_PARAMETERS").path("CLIENT_REQUEST_MFA_TOKEN").asBoolean());
assertEquals(mockedMfaToken[1], jsonNode.path("data").path("TOKEN").asText());
res = getNormalMockedHttpResponse(true, -1).toString();
} else if (callCount == 5) {
// Third close() request
res = getNormalMockedHttpResponse(true, -1).toString();
} else if (callCount == 6) {
// test if failed log in response can delete the cached mfa token
res = getNormalMockedHttpResponse(false, -1).toString();
} else if (callCount == 7) {
jsonNode = parseRequest((HttpPost) args[0]);
assertTrue(jsonNode.path("data").path("SESSION_PARAMETERS").path("CLIENT_REQUEST_MFA_TOKEN").asBoolean());
// no token should be included this time.
assertEquals("", jsonNode.path("data").path("TOKEN").asText());
res = getNormalMockedHttpResponse(true, -1).toString();
} else if (callCount == 8) {
// final close()
res = getNormalMockedHttpResponse(true, -1).toString();
} else {
// unexpected request
res = getNormalMockedHttpResponse(false, -1).toString();
}
// this will be incremented on both connecting and closing
callCount += 1;
return res;
}
});
Properties prop = getBaseProp();
// connect url
String url = "jdbc:snowflake://testaccount.snowflakecomputing.com";
// The first connection contains no mfa token. After the connection, a mfa token will be saved
Connection con = DriverManager.getConnection(url, prop);
con.close();
// The second connection is expected to include the mfa token issued for the first connection
// and a new mfa token is issued
Connection con1 = DriverManager.getConnection(url, prop);
con1.close();
// The third connection is expected to include the new mfa token.
Connection con2 = DriverManager.getConnection(url, prop);
con2.close();
// This connection would receive an exception and then should clean up the mfa cache
try {
Connection con3 = DriverManager.getConnection(url, prop);
Assert.fail();
} catch (SnowflakeSQLException ex) {
// An exception is forced to happen by mocking. Do nothing.
}
// This connect request should not contain mfa cached token
Connection con4 = DriverManager.getConnection(url, prop);
con4.close();
}
SessionUtil.deleteMfaTokenCache(host, user);
}
Aggregations