I am currently writing an Azure Function App that scans the data in Storage Account blobs and tables to delete data older than a given time period. I am utilising the Azure.Data.Tables v12.8.0 library for table access and Azure.Storage.Blobs v12.16.0 for Blob Access
The Storage Account has and ACL enabled to allow access from Private Endpoints and, for development purposes, my IP address. I am utilising the Storage Accounts Shared Key to access both blob and table storage.
The code I have for blob storage is working without issue and is able to return a list of containers and then delete blobs older than X days.
The code I have for table storage is not able to return a list of tables and results in a 403 response.
When building the TableServiceClient object I have used both teh shared key and DefaultAzureCredentials authorisation approach both result in a 403.
Shared Key
private void GetTableServiceClient()
{
log.LogInformation($"Initialising Tables Client");
TableSharedKeyCredential sharedKeyCredential = new TableSharedKeyCredential(storageAccountName, storageAccountAccessKey);
string tableUri = $"https://{storageAccountName}.table.core.windows.net";
tableServiceClient = new TableServiceClient(new Uri(tableUri), sharedKeyCredential);
}
DefaultAzureCredential
private void GetTableServiceClient()
{
log.LogInformation($"Initialising Tables Client");
string tableUri = $"https://{storageAccountName}.table.core.windows.net";
tableServiceClient = new TableServiceClient(new Uri(tableUri), new DefaultAzureCredential());
}
Here are my RBAC permissions on the storage account
If I use the tableServiceClient object rfom either auth schema it works getting the account properties.
var aaa = await tableServiceClient.GetPropertiesAsync();
However, when trying to get a list of tables it fails with a 403
var queryTableResults = tableServiceClient.QueryAsync().AsPages();
await foreach (Page<TableItem> tableItem in queryTableResults)
{
foreach (TableItem table in tableItem.Values)
{
tables.Add(table.Name);
}
}
Testing using the TableClient object on a specific existing table also results in a 403
TableClient table = tableServiceClient.GetTableClient("myTableName");
I also tested the code from the GitHub repo which again resulted in a 403.
var client = new TableClient(
new Uri(@"https://myAccount.table.core.windows.net"),
"PM_Test",
new TableSharedKeyCredential("myAccount", "myKey"));
// Create the table if it doesn't already exist to verify we've successfully authenticated.
await client.CreateIfNotExistsAsync();
Full error response
This request is not authorized to perform this operation.
RequestId:379f5ba3-8002-003c-5fa9-b0c385000000
Time:2023-07-07T08:00:32.2632228Z
Status: 403 (Forbidden)
ErrorCode: AuthorizationFailure
Content:
{"odata.error":{"code":"AuthorizationFailure","message":{"lang":"en-US","value":"This request is not authorized to perform this operation.\nRequestId:379f5ba3-8002-003c-5fa9-b0c385000000\nTime:2023-07-07T08:00:32.2632228Z"}}}
Headers:
Transfer-Encoding: chunked
Server: Windows-Azure-Table/1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: 379f5ba3-8002-003c-5fa9-b0c385000000
x-ms-client-request-id: 30b14cac-5008-45ce-a2d7-47a355f535e6
x-ms-version: REDACTED
X-Content-Type-Options: REDACTED
Date: Fri, 07 Jul 2023 08:00:31 GMT
Content-Type: application/json;odata=minimalmetadata;streaming=true;charset=utf-8
I have also tested the storage account tables list Rest API endpoints which works and me a valid list of existing tables.
My question here is why does accessing the Storage Account tables using the Access Key result in 403 responses while it works without issue when accessing Blob storage?
Edit
I have jsut run it again and noticed that the time is an our behind in the error response, it's GMT not BST. The Rest API response is also in GMT so not sure it matters.
This request is not authorized to perform this operation.
RequestId:86e25127-e002-0015-22be-b0fdf1000000
Time:2023-07-07T10:34:56.5908862Z
Status: 403 (Forbidden)
ErrorCode: AuthorizationFailure
Content:
{"odata.error":{"code":"AuthorizationFailure","message":{"lang":"en-US","value":"This request is not authorized to perform this operation.\nRequestId:86e25127-e002-0015-22be-b0fdf1000000\nTime:2023-07-07T10:34:56.5908862Z"}}}
Headers:
Transfer-Encoding: chunked
Server: Windows-Azure-Table/1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: 86e25127-e002-0015-22be-b0fdf1000000
x-ms-client-request-id: 7c221aff-03d7-4de6-a58d-94fb7d7a951d
x-ms-version: REDACTED
X-Content-Type-Options: REDACTED
Date: Fri, 07 Jul 2023 10:34:56 GMT
Content-Type: application/json;odata=minimalmetadata;streaming=true;charset=utf-8
We eventually found the solution to the problem. Using Table Storage on this storage account was a recent change and we had not implemented an on premise DNS entry for the Storage Accounts table. This resulted in the Private Endpoint not being used. Going to get that added but adding an additional IP on the ACL for the dev machine enabled access.