public override bool Equals(object obj) { if (obj == null) { return(false); } try { SFSessionProperties prop = (SFSessionProperties)obj; foreach (SFSessionProperty sessionProperty in Enum.GetValues(typeof(SFSessionProperty))) { if (this.ContainsKey(sessionProperty) ^ prop.ContainsKey(sessionProperty)) { return(false); } if (!this.ContainsKey(sessionProperty)) { continue; } if (!this[sessionProperty].Equals(prop[sessionProperty])) { return(false); } } return(true); } catch (InvalidCastException) { logger.Warn("Invalid casting to SFSessionProperties"); return(false); } }
/// <see cref="IAuthenticator"/> async Task IAuthenticator.AuthenticateAsync(CancellationToken cancellationToken) { logger.Info("External Browser Authentication"); int localPort = GetRandomUnusedPort(); string proofKey; string samlResponseToken; using (var httpListener = GetHttpListener(localPort)) { httpListener.Start(); logger.Debug("Get IdpUrl and ProofKey"); var authenticatorRestRequest = BuildAuthenticatorRestRequest(localPort); var authenticatorRestResponse = await session.restRequester.PostAsync <AuthenticatorResponse>( authenticatorRestRequest, cancellationToken ).ConfigureAwait(false); authenticatorRestResponse.FilterFailedResponse(); var idpUrl = authenticatorRestResponse.data.ssoUrl; proofKey = authenticatorRestResponse.data.proofKey; logger.Debug("Open browser"); StartBrowser(idpUrl); logger.Debug("Get the redirect SAML request"); var context = await httpListener.GetContextAsync().ConfigureAwait(false); var request = context.Request; samlResponseToken = ValidateAndExtractToken(request); HttpListenerResponse response = context.Response; try { using (var output = response.OutputStream) { await output.WriteAsync(SUCCESS_RESPONSE, 0, SUCCESS_RESPONSE.Length).ConfigureAwait(false); } } catch (Exception e) { // Ignore the exception as it does not affect the overall authentication flow logger.Warn("External browser response not sent out"); } httpListener.Stop(); } logger.Debug("Send login request"); var loginResponse = await session.restRequester.PostAsync <LoginResponse>( BuildExternalBrowserLoginRequest(samlResponseToken, proofKey), cancellationToken ).ConfigureAwait(false); session.ProcessLoginResponse(loginResponse); }
internal static SFSessionProperties parseConnectionString(String connectionString, SecureString password) { logger.Info("Start parsing connection string."); SFSessionProperties properties = new SFSessionProperties(); string[] propertyEntry = connectionString.Split(';'); foreach (string keyVal in propertyEntry) { if (keyVal.Length > 0) { string[] token = keyVal.Split(new string[] { "=" }, StringSplitOptions.None); if (token.Length == 2) { try { SFSessionProperty p = (SFSessionProperty)Enum.Parse( typeof(SFSessionProperty), token[0].ToUpper()); properties.Add(p, token[1]); logger.Info($"Connection property: {p}, value: {(p == SFSessionProperty.PASSWORD ? "XXXXXXXX" : token[1])}"); } catch (ArgumentException e) { logger.Warn($"Property {token[0]} not found ignored."); } } else { string invalidStringDetail = String.Format("Invalid kay value pair {0}", keyVal); SnowflakeDbException e = new SnowflakeDbException(SFError.INVALID_CONNECTION_STRING, new object[] { invalidStringDetail }); logger.Error("Invalid string.", e); throw e; } } } if (password != null) { properties[SFSessionProperty.PASSWORD] = new NetworkCredential(string.Empty, password).Password; } checkSessionProperties(properties); // compose host value if not specified if (!properties.ContainsKey(SFSessionProperty.HOST)) { string hostName = String.Format("%s.snowflakecomputing.com", properties[SFSessionProperty.ACCOUNT]); properties.Add(SFSessionProperty.HOST, hostName); logger.Info($"Compose host name: {hostName}"); } return(properties); }
internal SFSession(String connectionString, SecureString password, IRestRequester restRequester) { this.restRequester = restRequester; properties = SFSessionProperties.parseConnectionString(connectionString, password); ParameterMap = new Dictionary <SFSessionParameter, object>(); int recommendedMinTimeoutSec = BaseRestRequest.DEFAULT_REST_RETRY_SECONDS_TIMEOUT; int timeoutInSec = recommendedMinTimeoutSec; try { ParameterMap[SFSessionParameter.CLIENT_VALIDATE_DEFAULT_PARAMETERS] = Boolean.Parse(properties[SFSessionProperty.VALIDATE_DEFAULT_PARAMETERS]); timeoutInSec = int.Parse(properties[SFSessionProperty.CONNECTION_TIMEOUT]); InsecureMode = Boolean.Parse(properties[SFSessionProperty.INSECUREMODE]); } catch (Exception e) { logger.Error(e.Message); throw new SnowflakeDbException(e.InnerException, SFError.INVALID_CONNECTION_STRING, "Unable to connect"); } if (timeoutInSec < recommendedMinTimeoutSec) { logger.Warn($"Connection timeout provided is less than recommended minimum value of" + $" {recommendedMinTimeoutSec}"); } if (timeoutInSec < 0) { logger.Warn($"Connection timeout provided is negative. Timeout will be infinite."); } connectionTimeout = timeoutInSec > 0 ? TimeSpan.FromSeconds(timeoutInSec) : Timeout.InfiniteTimeSpan; }
internal void close() { var queryParams = new Dictionary <string, string>(); queryParams[SF_QUERY_SESSION_DELETE] = "true"; queryParams[SF_QUERY_REQUEST_ID] = Guid.NewGuid().ToString(); SFRestRequest closeSessionRequest = new SFRestRequest { uri = BuildUri(SF_SESSION_PATH, queryParams), authorizationToken = string.Format(SF_AUTHORIZATION_SNOWFLAKE_FMT, sessionToken) }; var response = restRequest.Post <NullDataResponse>(closeSessionRequest); if (!response.success) { logger.Warn($"Failed to delete session, error ignored. Code: {response.code} Message: {response.message}"); } }
internal void Cancel() { SFRestRequest request = BuildCancelQueryRequest(); if (request == null) { return; } var response = _restRequester.Post <NullDataResponse>(request); if (response.success) { logger.Info("Query cancellation succeed"); } else { logger.Warn("Query cancellation failed."); } }
protected override async Task <HttpResponseMessage> SendAsync(HttpRequestMessage requestMessage, CancellationToken cancellationToken) { HttpResponseMessage response = null; int backOffInSec = 1; TimeSpan httpTimeout = (TimeSpan)requestMessage.Properties["TIMEOUT_PER_HTTP_REQUEST"]; CancellationTokenSource childCts = null; while (true) { try { childCts = null; if (!httpTimeout.Equals(Timeout.InfiniteTimeSpan)) { childCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); childCts.CancelAfter(httpTimeout); } response = await base.SendAsync(requestMessage, childCts == null? cancellationToken : childCts.Token); } catch (Exception e) { if (cancellationToken.IsCancellationRequested) { logger.Debug("SF rest request timeout."); cancellationToken.ThrowIfCancellationRequested(); } else if (childCts != null && childCts.Token.IsCancellationRequested) { logger.Warn("Http request timeout. Retry the request"); } else { //TODO: Should probably check to see if the error is recoverable or transient. logger.Warn("Error occurred during request, retrying...", e); } } if (response != null) { if (response.IsSuccessStatusCode) { logger.Debug($"Success Response: {response.ToString()}"); return(response); } logger.Debug($"Failed Response: {response.ToString()}"); } else { logger.Info("Response returned was null."); } logger.Debug($"Sleep {backOffInSec} seconds and then retry the request"); Thread.Sleep(backOffInSec * 1000); backOffInSec = backOffInSec >= 16 ? 16 : backOffInSec * 2; } }
protected override async Task <HttpResponseMessage> SendAsync(HttpRequestMessage requestMessage, CancellationToken cancellationToken) { HttpResponseMessage response = null; int backOffInSec = 1; int totalRetryTime = 0; int maxDefaultBackoff = 16; ServicePoint p = ServicePointManager.FindServicePoint(requestMessage.RequestUri); p.Expect100Continue = false; // Saves about 100 ms per request p.UseNagleAlgorithm = false; // Saves about 200 ms per request p.ConnectionLimit = 20; // Default value is 2, we need more connections for performing multiple parallel queries TimeSpan httpTimeout = (TimeSpan)requestMessage.Properties[SFRestRequest.HTTP_REQUEST_TIMEOUT_KEY]; TimeSpan restTimeout = (TimeSpan)requestMessage.Properties[SFRestRequest.REST_REQUEST_TIMEOUT_KEY]; if (logger.IsDebugEnabled()) { logger.Debug("Http request timeout : " + httpTimeout); logger.Debug("Rest request timeout : " + restTimeout); } CancellationTokenSource childCts = null; UriUpdater updater = new UriUpdater(requestMessage.RequestUri); while (true) { try { childCts = null; if (!httpTimeout.Equals(Timeout.InfiniteTimeSpan)) { childCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); childCts.CancelAfter(httpTimeout); } response = await base.SendAsync(requestMessage, childCts == null? cancellationToken : childCts.Token).ConfigureAwait(false); } catch (Exception e) { if (cancellationToken.IsCancellationRequested) { logger.Debug("SF rest request timeout or explicit cancel called."); cancellationToken.ThrowIfCancellationRequested(); } else if (childCts != null && childCts.Token.IsCancellationRequested) { logger.Warn("Http request timeout. Retry the request"); totalRetryTime += (int)httpTimeout.TotalSeconds; } else { //TODO: Should probably check to see if the error is recoverable or transient. logger.Warn("Error occurred during request, retrying...", e); } } if (response != null) { if (response.IsSuccessStatusCode) { return(response); } else { logger.Debug($"Failed Response: {response.ToString()}"); bool isRetryable = isRetryableHTTPCode((int)response.StatusCode); if (!isRetryable) { // No need to keep retrying, stop here return(response); } } } else { logger.Info("Response returned was null."); } requestMessage.RequestUri = updater.Update(); logger.Debug($"Sleep {backOffInSec} seconds and then retry the request"); Thread.Sleep(backOffInSec * 1000); totalRetryTime += backOffInSec; backOffInSec = backOffInSec >= maxDefaultBackoff ? maxDefaultBackoff : backOffInSec * 2; if (totalRetryTime + backOffInSec > restTimeout.TotalSeconds) { // No need to wait more than necessary if it can be avoided. // If the rest timeout will be reached before the next back-off, // use a smaller one to give the Rest request a chance to timeout early backOffInSec = Math.Max(1, (int)restTimeout.TotalSeconds - totalRetryTime - 1); } } }
protected override async Task <HttpResponseMessage> SendAsync(HttpRequestMessage requestMessage, CancellationToken cancellationToken) { HttpResponseMessage response = null; int backOffInSec = 1; ServicePoint p = ServicePointManager.FindServicePoint(requestMessage.RequestUri); p.Expect100Continue = false; // Saves about 100 ms per request p.UseNagleAlgorithm = false; // Saves about 200 ms per request p.ConnectionLimit = 20; // Default value is 2, we need more connections for performing multiple parallel queries TimeSpan httpTimeout = (TimeSpan)requestMessage.Properties["TIMEOUT_PER_HTTP_REQUEST"]; CancellationTokenSource childCts = null; UriUpdater updater = new UriUpdater(requestMessage.RequestUri); while (true) { try { childCts = null; if (!httpTimeout.Equals(Timeout.InfiniteTimeSpan)) { childCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); childCts.CancelAfter(httpTimeout); } response = await base.SendAsync(requestMessage, childCts == null? cancellationToken : childCts.Token).ConfigureAwait(false); } catch (Exception e) { if (cancellationToken.IsCancellationRequested) { logger.Debug("SF rest request timeout."); cancellationToken.ThrowIfCancellationRequested(); } else if (childCts != null && childCts.Token.IsCancellationRequested) { logger.Warn("Http request timeout. Retry the request"); } else { //TODO: Should probably check to see if the error is recoverable or transient. logger.Warn("Error occurred during request, retrying...", e); } } if (response != null) { if (response.IsSuccessStatusCode) { return(response); } logger.Debug($"Failed Response: {response.ToString()}"); } else { logger.Info("Response returned was null."); } requestMessage.RequestUri = updater.Update(); logger.Debug($"Sleep {backOffInSec} seconds and then retry the request"); Thread.Sleep(backOffInSec * 1000); backOffInSec = backOffInSec >= 16 ? 16 : backOffInSec * 2; } }