403 Fehler in der Produktion von WindowsAzure.Storage
Ich habe eine WebForms-App, die die WindowsAzure.Storage-API v3 verwendet. In der Entwicklung und in einer Produktionsumgebung funktioniert es einwandfrei, aber ich rolle eine neue Instanz aus und jeder Code, der Azure Blob Storage aufruft, gibt einen 403-Fehler aus.
Ich habe eine Weile damit herumgespielt und es schlägt bei jedem Aufruf von Blob Storage fehl. Anstatt meinen Code anzuzeigen, zeige ich meinen Stack-Trace:
[WebException: The remote server returned an error: (403) Forbidden.],
System.Net.HttpWebRequest.GetResponse() +8525404
Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteSync(RESTCommand`1 cmd, IRetryPolicy policy, OperationContext operationContext) +1541
[StorageException: The remote server returned an error: (403) Forbidden.]
Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteSync(RESTCommand`1 cmd, IRetryPolicy policy, OperationContext operationContext) +2996
Microsoft.WindowsAzure.Storage.Blob.CloudBlobContainer.CreateIfNotExists(BlobContainerPublicAccessType accessType, BlobRequestOptions requestOptions, OperationContext operationContext) +177
ObsidianData.Azure.Storage.GetContainer(CloudBlobClient client, Containers targetContainer) in D:\Dev\nSource\Obsidian\Source\ObsidianData\Azure\Storage.vb:84
ObsidianWeb.Leads.HandleListenLink(String fileName, HyperLink link) in D:\Dev\nSource\Obsidian\Source\ObsidianWeb\Bdc\Leads.aspx.vb:188
ObsidianWeb.Leads.LoadEntity_ContactDetails(BoLead lead) in D:\Dev\nSource\Obsidian\Source\ObsidianWeb\Bdc\Leads.aspx.vb:147
ObsidianWeb.Leads.LoadEntity(BoLead Lead) in D:\Dev\nSource\Obsidian\Source\ObsidianWeb\Bdc\Leads.aspx.vb:62
EntityPages.EntityPage`1.LoadEntity() +91
EntityPages.EntityPage`1.Page_LoadComplete(Object sender, EventArgs e) +151
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +4018
Folgendes habe ich versucht ...
Der AzureStorageConnectionString, der in dieser Umgebung ausfällt, funktioniert definitiv in der ProduktionAndere Verbindungszeichenfolgen (aus der anderen Produktionsumgebung, die funktioniert) erhalten hier ebenfalls eine 403Es schien ein Problem mit Zeitstempeln in einigen alten Versionen der REST-API zu geben (die ich nicht direkt verwende ...), daher habe ich sichergestellt, dass die Zeiten korrekt sind, und sogar versucht, den Server auf UTC-Zeit umzustellen.Versucht, die Verbindungszeichenfolge zwischen http / https umzuschalten.Upgrade auf die neueste Version der API (v3.1)Es wurde versucht, mit dem Code zu fummeln, um sicherzustellen, dass jeder Aufruf von Azure Storage den Wert 403 erhält.In der Verzweiflung installierte Azure Powershell auf dem Server, um zu überprüfen, ob eine Art von Kommunikation mit Azure funktioniert. Und das hat gut funktioniert.Sie haben auch das Azure-Verwaltungsportal aufgerufen, und das funktioniert einwandfrei.Irgendwelche Ideen? Dies sollte nur über Port 80 oder 443 erfolgen, oder? Es sollte also keine Möglichkeit geben, dass dies eine Art Netzwerkproblem ist. Lass es mich wissen, wenn das falsch ist.
Der funktionierende Produktionscomputer ist eine Azure-VM (Server 2008 R2 mit IIS 7.5). Es gibt auch einige Unterschiede zum Server:Dieser neue Computer ist physische Hardware (Server 2012 und IIS 8)Dies verwendet ein anderes Speicherkonto in meinem Azure-Abonnement. Es wurden jedoch insgesamt 3 Verbindungszeichenfolgen ausprobiert, und keine davon funktioniert hier.AKTUALISIEREN: jemand fragte nach dem Code. Okay, ich habe eine Klasse namens Azure.Storage geschrieben, die nur meinen Cloud-Speichercode abstrahiert. Bei einem Aufruf von Storage.Exists scheitern wir. Daher ist hier der Teil dieser Klasse, der sich relevant anfühlt:
Public Shared Function Exists(container As Containers, blobName As String) As Boolean
Dim Dir As CloudBlobContainer = GetContainer(container)
Dim Blob As CloudBlockBlob = Dir.GetBlockBlobReference(blobName.ToLower())
Return Blob.Exists()
End Function
Private Shared Function GetContainer(client As CloudBlobClient, targetContainer As Containers)
Dim Container As CloudBlobContainer = client.GetContainerReference(targetContainer.ToString.ToLower())
Container.CreateIfNotExists()
Container.SetPermissions(New BlobContainerPermissions() With {.PublicAccess = BlobContainerPublicAccessType.Blob})
Return Container
End Function
Private Shared Function GetCloudBlobClient() As CloudBlobClient
Dim Account As CloudStorageAccount = CloudStorageAccount.Parse(Settings.Cloud.AzureStorageConnectionString())
Return Account.CreateCloudBlobClient()
End Function
...Behälter ist nur eine Aufzählung von Containernamen (es gibt mehrere):
Public Enum Containers
CallerWavs
CampaignImports
Delve
Exports
CampaignImages
Logos
ReportLogos
WebLinkImages
End Enum
... Ja, sie haben Großbuchstaben, was zu Problemen führt. Alles muss in Kleinbuchstaben geschrieben werden, bevor es erlischt.
Außerdem habe ich überprüft, ob der richtige AzureConnectionString aus meiner Einstellungsklasse stammt. Wieder habe ich ein paar ausprobiert, die woanders funktionieren. Und dieser arbeitet auch woanders!