partial void PrepareRequest(Transaction body, HttpClient client, HttpRequestMessage request, string url) { var uriBuilder = new UriBuilder(request.RequestUri); var query = HttpUtility.ParseQueryString(uriBuilder.Query); if (conn is LocalConnection) { query["dbname"] = conn.DbName; if (!_isEmpty(body.Source_dbname)) { query["source_dbname"] = body.Source_dbname; } } query["open_mode"] = body.Mode.ToString(); if (conn is ManagementConnection || conn is CloudConnection) { query["region"] = EnumString.GetDescription(conn.Region); } if (conn is CloudConnection) { query["compute_name"] = conn.ComputeName; } uriBuilder.Query = query.ToString(); request.RequestUri = uriBuilder.Uri; // populate headers request.Headers.Host = request.RequestUri.Host; request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json; charset=utf-8"); // sign request here var raiRequest = new RAIRequest(request, conn); raiRequest.Sign(debugLevel: DebugLevel); DelveClient.AddExtraHeaders(request); // use HTTP 2.0 (to handle keep-alive) request.Version = System.Net.HttpVersion.Version20; // have a separate keep-alive task (per thread) if (!isStatusRequest(body)) { var tokenSource = new CancellationTokenSource(); AsyncLocalKeepAliveCancellationTokenSource.Value = tokenSource; CancellationToken ct = tokenSource.Token; /** * TODO: currently we swallo exceptions in KeepClientAlive. * If we want to throw, then we need to change this to asynchronously handle the throw * e.g. * try { * await this.KeepClientAlive(client, url, ct).ConfigureAwait(false); * } catch (Exception e) { * // Handle here * } **/ var keep_alive_task = this.KeepClientAlive(client, url, ct).ConfigureAwait(false); } }
public ComputeInfoProtocol CreateCompute(string name, RAIComputeSize size = RAIComputeSize.XS, string region = null, bool dryRun = false) { if (region == null) { region = EnumString.GetDescription(this.conn.Region); } CreateComputeRequestProtocol request = new CreateComputeRequestProtocol(); request.Region = region; request.Name = name; request.Size = EnumString.GetDescription(size); request.Dryrun = dryRun; return(this.ComputePutAsync(request).Result.Compute); }
public void Sign(DateTime t, string[] includeHeaders = null, int debugLevel = 1) { if (includeHeaders == null) { includeHeaders = new string[] { "host", "content-type", "x-rai-date" }; } if (this.Creds == null) { return; } // ISO8601 date/time strings for time of request string signatureDate = String.Format("{0:yyyyMMddTHHmmssZ}", t); string scopeDate = String.Format("{0:yyyyMMdd}", t); // Authentication scope string scope = string.Join("/", new string[] { scopeDate, EnumString.GetDescription(this.Region), this.Service, "rai01_request" }); // SHA256 hash of content Sha256 shaw256HashAlgo = new Sha256(); byte[] reqContent = InnerReq.Content.ReadAsByteArrayAsync().Result; byte[] sha256Hash = shaw256HashAlgo.Hash(reqContent); string contentHash = sha256Hash.ToHex(); // HTTP headers InnerReq.Headers.Authorization = null; // Include "x-rai-date" in signed headers if (!InnerReq.Headers.Contains("x-rai-date")) { InnerReq.Headers.TryAddWithoutValidation("x-rai-date", signatureDate); } var allHeaders = InnerReq.Headers.Union(InnerReq.Content.Headers); // Sort and lowercase() Headers to produce canonical form string canonicalHeaders = string.Join( "\n", from header in allHeaders orderby header.Key.ToLower() where includeHeaders.Contains(header.Key.ToLower()) select string.Format( "{0}:{1}", header.Key.ToLower(), string.Join(",", header.Value).Trim() ) ); string signedHeaders = string.Join( ";", from header in allHeaders orderby header.Key.ToLower() where includeHeaders.Contains(header.Key.ToLower()) select header.Key.ToLower() ); // Sort Query String var parsedQuery = HttpUtility.ParseQueryString(InnerReq.RequestUri.Query); var parsedQueryDict = parsedQuery.AllKeys.SelectMany( parsedQuery.GetValues, (k, v) => new { key = k, value = v } ); string query = string.Join( "&", from qparam in parsedQueryDict orderby qparam.key, qparam.value select string.Format( "{0}={1}", HttpUtility.UrlEncode(qparam.key), HttpUtility.UrlEncode(qparam.value)) ); // Create hash of canonical request string canonicalForm = string.Format( "{0}\n{1}\n{2}\n{3}\n\n{4}\n{5}", InnerReq.Method, HttpUtility.UrlPathEncode(InnerReq.RequestUri.AbsolutePath), query, canonicalHeaders, signedHeaders, contentHash ); if (debugLevel > 2) { Console.WriteLine("reqContent:"); Console.WriteLine(System.Text.Encoding.Default.GetString(reqContent)); Console.WriteLine("canonical_form:"); Console.WriteLine(canonicalForm); Console.WriteLine(); } sha256Hash = shaw256HashAlgo.Hash(Encoding.UTF8.GetBytes(canonicalForm)); string canonicalHash = sha256Hash.ToHex(); // Create and sign "String to Sign" string stringToSign = string.Format( "RAI01-ED25519-SHA256\n{0}\n{1}\n{2}", signatureDate, scope, canonicalHash ); byte[] seed = Convert.FromBase64String(Creds.PrivateKey); // select the Ed25519 signature algorithm var algorithm = SignatureAlgorithm.Ed25519; // create a new key pair using var key = Key.Import(algorithm, seed, KeyBlobFormat.RawPrivateKey); // sign the data using the private key byte[] signature = algorithm.Sign(key, Encoding.UTF8.GetBytes(stringToSign)); string sig = signature.ToHex(); if (debugLevel > 2) { Console.WriteLine("string_to_sign:"); Console.WriteLine(stringToSign); Console.WriteLine(); Console.WriteLine("signature:"); Console.WriteLine(sig); Console.WriteLine(); } var authHeader = string.Format( "RAI01-ED25519-SHA256 Credential={0}/{1}, SignedHeaders={2}, Signature={3}", Creds.AccessKey, scope, signedHeaders, sig ); InnerReq.Headers.TryAddWithoutValidation("Authorization", authHeader); }