Search in sources :

Example 1 with SnowflakeSQLException

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;
}
Also used : SnowflakeSQLException(net.snowflake.client.jdbc.SnowflakeSQLException) CloseableHttpResponse(org.apache.http.client.methods.CloseableHttpResponse)

Example 2 with SnowflakeSQLException

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;
}
Also used : ClientConfiguration(com.amazonaws.ClientConfiguration) SnowflakeSQLException(net.snowflake.client.jdbc.SnowflakeSQLException)

Example 3 with SnowflakeSQLException

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;
}
Also used : HttpPost(org.apache.http.client.methods.HttpPost) StringEntity(org.apache.http.entity.StringEntity) UnexpectedException(java.rmi.UnexpectedException) SnowflakeSQLException(net.snowflake.client.jdbc.SnowflakeSQLException) IOException(java.io.IOException)

Example 4 with SnowflakeSQLException

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");
}
Also used : SnowflakeSQLException(net.snowflake.client.jdbc.SnowflakeSQLException) Ignore(org.junit.Ignore) Test(org.junit.Test)

Example 5 with SnowflakeSQLException

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);
}
Also used : HttpPost(org.apache.http.client.methods.HttpPost) SnowflakeSQLException(net.snowflake.client.jdbc.SnowflakeSQLException) Connection(java.sql.Connection) JsonNode(com.fasterxml.jackson.databind.JsonNode) Properties(java.util.Properties) InvocationOnMock(org.mockito.invocation.InvocationOnMock) Test(org.junit.Test)

Aggregations

SnowflakeSQLException (net.snowflake.client.jdbc.SnowflakeSQLException)12 IOException (java.io.IOException)4 HttpPost (org.apache.http.client.methods.HttpPost)4 JsonNode (com.fasterxml.jackson.databind.JsonNode)3 Test (org.junit.Test)3 URISyntaxException (java.net.URISyntaxException)2 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)2 URIBuilder (org.apache.http.client.utils.URIBuilder)2 StringEntity (org.apache.http.entity.StringEntity)2 ClientConfiguration (com.amazonaws.ClientConfiguration)1 Protocol (com.amazonaws.Protocol)1 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 InetSocketAddress (java.net.InetSocketAddress)1 Proxy (java.net.Proxy)1 UnexpectedException (java.rmi.UnexpectedException)1 Connection (java.sql.Connection)1 SQLException (java.sql.SQLException)1 List (java.util.List)1 Properties (java.util.Properties)1 Collectors (java.util.stream.Collectors)1