using System.Security.Cryptography; using Flurl; using Flurl.Http; using InnovEnergy.Lib.Utils; using static System.Text.Encoding; using Convert = System.Convert; namespace InnovEnergy.S3.Drivers; public record S3Config { public String Bucket { get; init; } = ""; public String Region { get; init; } = ""; public String Provider { get; init; } = ""; public String Key { get; init; } = ""; public String Secret { get; init; } = ""; public String ContentType { get; init; } = ""; public String Host => $"{Bucket}.{Region}.{Provider}"; public String Url => $"https://{Host}"; public IFlurlRequest CreatePutRequest(String s3Path) => CreateRequest("PUT", s3Path); public IFlurlRequest CreateGetRequest(String s3Path) => CreateRequest("GET", s3Path); private IFlurlRequest CreateRequest(String method, String s3Path) { var date = DateTime.UtcNow.ToString("r"); var auth = CreateAuthorization(method, s3Path, date); return Url .AppendPathSegment(s3Path) .WithHeader("Host", Host) .WithHeader("Date", date) .WithHeader("Authorization", auth) .AllowAnyHttpStatus(); } private String CreateAuthorization(String method, String s3Path, String date) { return CreateAuthorization ( method : method, bucket : Bucket, s3Path : s3Path, date : date, s3Key : Key, s3Secret : Secret, contentType: ContentType ); } private static String CreateAuthorization(String method, String bucket, String s3Path, String date, String s3Key, String s3Secret, String contentType = "", String md5Hash = "") { // StringToSign = HTTP-Verb + "\n" + // Content-MD5 + "\n" + // Content-Type + "\n" + // Date + "\n" + // CanonicalizedAmzHeaders + // CanonicalizedResource; var payload = $"{method}\n{md5Hash}\n{contentType}\n{date}\n/{bucket.Trim('/')}/{s3Path.Trim('/')}"; using var hmacSha1 = new HMACSHA1(UTF8.GetBytes(s3Secret)); var signature = UTF8 .GetBytes(payload) .Apply(hmacSha1.ComputeHash) .Apply(Convert.ToBase64String); return $"AWS {s3Key}:{signature}"; } }