83 lines
2.5 KiB
C#
83 lines
2.5 KiB
C#
|
using System.Security.Cryptography;
|
||
|
using Flurl;
|
||
|
using Flurl.Http;
|
||
|
using InnovEnergy.Lib.Utils;
|
||
|
using static System.Text.Encoding;
|
||
|
using Convert = System.Convert;
|
||
|
|
||
|
namespace InnovEnergy.Lib.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}";
|
||
|
}
|
||
|
|
||
|
}
|