Spend many hours to try to sort this out.
I have a table and want to create a read-only SAS and give to client components to read access. But never succeed.
If just use connection string and hook up table directly like this:
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(SliStorageConnection);
// Create the table client.
CloudTableClient tableClient = storageAccount.CreateCloudTableClient();
var table = tableClient.GetTableReference(GlobalFilterTable);
TableOperation tableOperation = TableOperation.Retrieve<TableEntity>(FilterTablePartition, "filter1");
TableResult tableResult = table.Execute(tableOperation);
It works fine. But with SAS like below, always returns 501 Not Implemented
var policy = new SharedAccessTablePolicy
{
SharedAccessExpiryTime = DateTime.Now.AddMinutes(30),
Permissions = SharedAccessTablePermissions.Query
};
string sas = table.GetSharedAccessSignature(
policy,
null,
FilterTablePartition,
String.Empty,
FilterTablePartition,
String.Empty);
Uri tableSasUri = new Uri(table.Uri, sas);
AccessTable(tableSasUri.AbsoluteUri.ToString());
private static void AccessTable(string tableSas)
{
string filterTableBaseUrl = tableSas.Substring(0, tableSas.IndexOf('?'));
var filterTableSasCredentials = new StorageCredentials(tableSas.Substring(filterTableBaseUrl.Length));
CloudTableClient tableClient = new CloudTableClient(new Uri(filterTableBaseUrl), filterTableSasCredentials);
var _manifestFilterCloudTable = tableClient.GetTableReference(GlobalFilterTable);
TableOperation tableOperation = TableOperation.Retrieve<TableEntity>(FilterTablePartition, "filter1");
TableResult tableResult = _manifestFilterCloudTable.Execute(tableOperation);
}
Tried different ways, give less than 1 hour time, named or anonymous policy identifier, use signature only ("sig") to create StorageCredentials
. All failed with different errors. Mostly 501 not implemented
, sometime resource not found
, sometimes 403 Forbidden
.
Couldn't find useful info online. I am using Microsoft.WindowsAzure.Storage
version 3.1 SDK.
Any help is highly appreciated
I believe the problem is in the following two lines of code:
CloudTableClient tableClient = new CloudTableClient(new Uri(filterTableBaseUrl), filterTableSasCredentials);
var _manifestFilterCloudTable = tableClient.GetTableReference(GlobalFilterTable);
Basically what is happening is that the table name is repeated twice in the table URL in manifestFilterCloudTable
. When you're creating CloudTableClient
, the URI should not include the table name. It should only be something like https://[youraccountname].table.core.windows.net
.
Please use the following code in your AccessTable
method:
string filterTableBaseUrl = tableSas.Substring(0, tableSas.IndexOf('?'));
var filterTableSasCredentials = new StorageCredentials(tableSas.Substring(filterTableBaseUrl.Length));
filterTableBaseUrl = filterTableBaseUrl.Substring(0, filterTableBaseUrl.LastIndexOf("/"));
tableClient = new CloudTableClient(new Uri(filterTableBaseUrl), filterTableSasCredentials);
var _manifestFilterCloudTable = tableClient.GetTableReference("Address");
TableOperation tableOperation = TableOperation.Retrieve<TableEntity>(FilterTablePartition, "filter1");
TableResult tableResult = _manifestFilterCloudTable.Execute(tableOperation);
Another thing I noticed that for SharedAccessPolicy, you're using DateTime.Now
. Depending on the timezone where the code is executed, you may run into 403 errors because date/time in Azure is in UTC. Please use DateTime.UtcNow
instead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With