From 65624cf1aa6143dde0dd125bc847f74d8458b9c0 Mon Sep 17 00:00:00 2001 From: Kim Date: Thu, 9 Mar 2023 09:05:59 +0100 Subject: [PATCH] added dynamic s3 key generation --- csharp/App/Backend/Database/User.cs | 77 ++++++++++++++++++++++------- 1 file changed, 58 insertions(+), 19 deletions(-) diff --git a/csharp/App/Backend/Database/User.cs b/csharp/App/Backend/Database/User.cs index ea2344aaf..3f8fef76a 100644 --- a/csharp/App/Backend/Database/User.cs +++ b/csharp/App/Backend/Database/User.cs @@ -1,14 +1,17 @@ using System.Diagnostics.CodeAnalysis; +using System.Net.Http.Headers; using System.Net.Mail; using System.Security.Cryptography; using System.Text; using System.Text.Json; using System.Text.Json.Nodes; +using System.Text.RegularExpressions; using Flurl.Http; using Innovenergy.Backend.Model; using Innovenergy.Backend.Utils; using InnovEnergy.Lib.Utils; using SQLite; +using ResponseExtensions = Flurl.Http.ResponseExtensions; #pragma warning disable CS0472 #pragma warning disable CS8602 @@ -59,11 +62,42 @@ public partial class Db return Create(user); } - [UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "")] + + private static Byte[] HmacSha256Digest(String message, String secret) + { + var encoding = new UTF8Encoding(); + var keyBytes = encoding.GetBytes(secret); + var messageBytes = encoding.GetBytes(message); + var cryptographer = new HMACSHA256(keyBytes); + + var bytes = cryptographer.ComputeHash(messageBytes); + return bytes; + } + + public String BuildSignature(String method, String path, String data, Int64 time, String secret) + { + var messageToSign = ""; + messageToSign += method + " /v2/" + path + "\n"; + messageToSign += data + "\n"; + + // query strings + messageToSign += "\n"; + // headers + messageToSign += "\n"; + + messageToSign += time; + + Console.WriteLine("Message to sign:\n" + messageToSign); + + + var hmac = HmacSha256Digest(messageToSign, secret); + return Convert.ToBase64String(hmac); + } public Object CreateAndSaveUserS3ApiKey(User user) { //EXOSCALE API URL - const String url = "https://api-ch-dk-2.exoscale.com/v2/access-key"; + const String url = "https://api-ch-dk-2.exoscale.com/v2/"; + const String path = "access-key"; const String secret = "S2K1okphiCSNK4mzqr4swguFzngWAMb1OoSlZsJa9F0"; const String apiKey = "EXOb98ec9008e3ec16e19d7b593"; @@ -80,27 +114,32 @@ public partial class Db instList.Add(new JsonObject {["domain"] = "sos",["resource-name"] = installation.Name,["resource-type"] = "bucket"}); } - var jsonPayload = new JsonObject { ["name"] = user.Email, ["operations"] = new JsonArray{ "getObject", "listBucket" }, ["content"] = instList}; - var expiration = DateTime.Now.AddSeconds(60); + var jsonPayload = new JsonObject { ["name"] = user.Email, ["operations"] = new JsonArray{ "list-sos-bucket", "get-sos-object" }, ["content"] = instList}; + var stringPayload = jsonPayload.ToJsonString(); - var signature = $"POST /v2/access-key\n{jsonPayload}\n\n\n{((DateTimeOffset)expiration).ToUnixTimeSeconds()}"; - using var hmacSha256 = new HMACSHA256(Encoding.UTF8.GetBytes(secret)); - - signature = Encoding.UTF8 - .GetBytes(signature) - .Apply(hmacSha256.ComputeHash) - .Apply(Convert.ToBase64String); + var unixExpiration = DateTimeOffset.UtcNow.ToUnixTimeSeconds()+60; + var signature = BuildSignature("POST", path, stringPayload, unixExpiration , secret); - var keyJson = url - .WithHeader("Authorization", - $"EXO2-HMAC-SHA256 credential={apiKey},expires={((DateTimeOffset)expiration).ToUnixTimeSeconds()},signature={signature}"); + var authHeader = "credential="+apiKey+",expires="+unixExpiration+",signature="+signature; + var client = new HttpClient(); + client.DefaultRequestHeaders.Authorization = + new AuthenticationHeaderValue("EXO2-HMAC-SHA256", authHeader); + + var content = new StringContent(stringPayload, Encoding.UTF8, "application/json"); + + + var response = client.PostAsync(url+path, content).Result; + + if (response.StatusCode.ToString() != "OK") + { + return response; + } + + var responseString = response.Content.ReadAsStringAsync().Result; + var newKey = Enumerable.Last(Regex.Match(responseString, "key\\\":\\\"([A-Z])\\w+").ToString().Split('"')); + return SetUserS3ApiKey(user, newKey); - var result = keyJson.PostJsonAsync(jsonPayload.ToString()) - .ReceiveJson() - .Result; - return result; - // return SetUserS3ApiKey(user, keyJson.GetValue("key")); } public Result SetUserS3ApiKey(User user, String key)