rebus-org / Rebus.AzureBlobs

:bus: Azure Blobs-based databus storage for Rebus
https://mookid.dk/category/rebus
Other
3 stars 5 forks source link

Save method's ExistsAsync call throws exception with container SAS token #2

Closed eeskildsen closed 4 years ago

eeskildsen commented 4 years ago

Version: 0.3.0

Issue

I'm trying to give Rebus access to only one container in Azure storage. I'm using a container SAS token for this. I generate the token in PowerShell:

$context = New-AzStorageContext -StorageAccountName '...' -StorageAccountKey '...'
New-AzStorageContainerSASToken -Name '...' -Permission 'rwdl' -Context $context

Rebus connects okay, but when it comes time to write, the Save method throws an exception:

This request is not authorized to perform this operation.

From debugging, it seems the call to ExistsAsync is the problem. I guess that whole section is incompatible with a container SAS token, since it tries to create the container if it doesn't exist.

Questions

eeskildsen commented 4 years ago

So, looking in Rebus.AzureServiceBus, I see what looks like an equivalent setting in DoNotCreateQueues. I'm starting to implement this in the data bus settings in a fork. (Let me know if there's a better way I'm missing.)

mookid8000 commented 4 years ago

Hi @eeskildsen , I think that would be the way to handle it. Have you succeeded in making it work for you?

eeskildsen commented 4 years ago

Yes, thanks....I can get a PR ready if you're interested, although I'm not sure what the time frame will be.

mookid8000 commented 4 years ago

Definitely interested in PR 😃

mookid8000 commented 4 years ago

Hi @eeskildsen , how's it going with the PR? 😁

eeskildsen commented 4 years ago

@mookid8000 Haven't had time to come back to it yet, but it's on my to-do list! Hoping to come back to it soon...maybe over the holidays.

mookid8000 commented 4 years ago

it's ok... I had a customer waiting for this particular feature, so I've released Rebus.AzureBlobs 0.4.0 just now that may be what you were after...

With Rebus.AzureBlobs 0.4.0, you can skip container creation like this:

Configure.With(sender)
    .Transport(...)
    .DataBus(d => d.StoreInBlobStorage(storageAccount, "attachments")
                    .DoNotCreateContainer())
    .Start();

which should make it possible for this to run and create attachments with only WRITE access and no MANAGE access. Conversely, with this

Configure.With(sender)
    .Transport(...)
    .DataBus(d => d.StoreInBlobStorage(storageAccount, "attachments")
                    .DoNotUpdateLastReadTime())
    .Start();

should make it possible to run this and read attachments with only READ access.

Lastly, if one prefers fully qualified blob container URIs with SAS tokens, one can make Rebus run with it like this:

Configure.With(sender)
    .Transport(...)
    .DataBus(d => d.StoreInBlobStorage(new Uri(uriWithSasToken))
                    .DoNotCreateContainer()
                    .DoNotUpdateLastReadTime())
    .Start();

In the code sample above, uriWithSasToken can be generated like this:

// your ordinary storage account and stuff
var storageAccount = CloudStorageAccount.Parse(...);
var blobClient = storageAccount.CreateCloudBlobClient();
var container = blobClient.GetContainerReference("attachments");

// generate SAS token
var policy = new SharedAccessAccountPolicy
{
    Permissions = permissions,
    Services = SharedAccessAccountServices.Blob,
    ResourceTypes = SharedAccessAccountResourceTypes.Container | SharedAccessAccountResourceTypes.Object,
    SharedAccessExpiryTime = DateTimeOffset.Now.AddDays(1),
    Protocols = SharedAccessProtocol.HttpsOrHttp,
};

var sasToken = storageAccount.GetSharedAccessSignature(policy);

// this one has it all:
var uriWithSasToken = container.Uri + sasToken;

When you have time, maybe you can try and see if 0.4.0 works for you?