Skip to content

Commit

Permalink
Added AzureBlobStorageWithSasToken
Browse files Browse the repository at this point in the history
  • Loading branch information
stevehansen authored and aloneguid committed Jun 11, 2024
1 parent 75464e1 commit f8e1b36
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 11 deletions.
6 changes: 6 additions & 0 deletions src/Stowage.Test/ITestSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ public interface ITestSettings {

#endregion

#region [ Azure Sas Token Auth ]

string AzureStorageSasToken { get; }

#endregion

string AwsBucket { get; }

string AwsKey { get; }
Expand Down
7 changes: 7 additions & 0 deletions src/Stowage.Test/Integration/Impl/AzureBlobTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,12 @@ public async Task Auth_ClientCredentials() {

await storage.Ls();
}

[Fact]
public async Task Auth_WithSasToken() {
IFileStorage storage = Files.Of.AzureBlobStorageWithSasToken(_settings.AzureStorageAccount, _settings.AzureStorageSasToken);

await storage.Ls("/" +_settings.AzureContainerName + "/");
}
}
}
24 changes: 23 additions & 1 deletion src/Stowage/Files.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
Expand Down Expand Up @@ -150,6 +150,28 @@ public static IFileStorage AzureBlobStorageWithLocalEmulator(this IFilesFactory
return new AzureBlobFileStorage(endpoint, new SharedKeyAuthHandler(accountName, sharedKey));
}

/// <summary>
/// Create Azure Blob Storage connection with Sas Token authentication.
/// </summary>
/// <param name="_"></param>
/// <param name="accountName"></param>
/// <param name="sasToken"></param>
/// <returns></returns>
public static IFileStorage AzureBlobStorageWithSasToken(this IFilesFactory _, string accountName, string sasToken) {
return new AzureBlobFileStorage(accountName, new SasAuthHandler(sasToken));
}

/// <summary>
/// Create Azure Blob Storage connection with Sas Token authentication and custom endpoint.
/// </summary>
/// <param name="_"></param>
/// <param name="endpoint"></param>
/// <param name="sasToken"></param>
/// <returns></returns>
public static IFileStorage AzureBlobStorageWithSasToken(this IFilesFactory _, Uri endpoint, string sasToken) {
return new AzureBlobFileStorage(endpoint, new SasAuthHandler(sasToken));
}

/// <summary>
/// Creates Amazon S3 provider
/// </summary>
Expand Down
34 changes: 24 additions & 10 deletions src/Stowage/Impl/Microsoft/SasAuthHandler.cs
Original file line number Diff line number Diff line change
@@ -1,30 +1,44 @@
using System.Collections.Specialized;
using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Web;

namespace Stowage.Impl.Microsoft {
class SasAuthHandler : DelegatingHandler {
private readonly string _signedStart;
private readonly string _signedExpiry;
private readonly string _signedResource;
private readonly string _signedPermissions;

private readonly string _sasToken;

/// <summary>
/// Examples: https://docs.microsoft.com/en-us/rest/api/storageservices/service-sas-examples#blob-examples
/// </summary>
/// <param name="sasToken">See https://docs.microsoft.com/en-us/azure/storage/common/storage-sas-overview#sas-token</param>
public SasAuthHandler(string sasToken) {
// parse SAS token into parts to sign later
NameValueCollection qs = HttpUtility.ParseQueryString(sasToken);
public SasAuthHandler(string sasToken) : base(new HttpClientHandler()) {
// make sure they didn't include the leading ?, we should strip it
if(sasToken.StartsWith('?')) {
sasToken = sasToken.Substring(1);
}

_sasToken = sasToken;
}

protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
//?sv=2019-12-12&ss=b&srt=sco&sp=r&se=2021-01-09T19:55:19Z&st=2020-12-07T11:55:19Z&spr=https&sig=ubKzO2g6eWX4pELoKk3XzmptRBi5P34AJj6i42%2Bm5%2FA%3D

Authenticate(request);

return base.SendAsync(request, cancellationToken);
}

#if NET5_0_OR_GREATER
protected override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken) {
Authenticate(request);

return base.Send(request, cancellationToken);
}
#endif

private void Authenticate(HttpRequestMessage request) {
// azure just requires us to append the sasToken to the url, we just need to check if we already have query arguments or not
request.RequestUri = new Uri(request.RequestUri + (request.RequestUri.Query.Length > 0 ? "&" : "?") + _sasToken);
}
}
}

0 comments on commit f8e1b36

Please sign in to comment.