asp.net - net - Error 403 en la producción de WindowsAzure.Storage
download file from azure blob storage c# (2)
Por favor, compruebe el reloj en los servidores en cuestión. Además de la clave de cuenta incorrecta, también puede obtener el error 403 si el tiempo en el servidor no está sincronizado con la hora en los servidores de almacenamiento (Dar o recibir +/- 15 minutos de desviación está permitido).
Tengo una aplicación WebForms que utiliza la API WindowsAzure.Storage v3. Funciona bien en el desarrollo y en un entorno de producción, pero estoy implementando una nueva instancia y cualquier código que invoque Azure Blob Storage me da un error 403.
He estado jugando con esto por un tiempo, y falla en cualquier llamada a Blob Storage, así que en lugar de mostrar mi código mostraré mi rastro de pila:
[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
Esto es lo que he intentado ...
- AzureStorageConnectionString que falla en este entorno definitivamente funciona en producción
- Otras cadenas de conexión (del otro entorno de producción, que funciona) también obtienen un 403 aquí
- Parecía haber un problema con las marcas de tiempo en algunas versiones anteriores de la API REST (que no estoy usando directamente ...) así que me aseguré de que los tiempos fueran los correctos, incluso intenté cambiar el servidor a la hora UTC.
- Intenté alternar la cadena de conexión entre http / https.
- Actualizada a la última versión de la API (v3.1)
- Intenté jugar con el código para asegurar que cada llamada a Azure Storage obtenga 403. Lo hace.
- En su desesperación, instaló Azure Powershell en el servidor solo para verificar que algún tipo de comunicación con Azure esté funcionando. Y eso funcionó bien.
- También se buscó en el portal de administración azul y funciona bien.
¿Algunas ideas? Esto debería ser usando el puerto 80 o 443, ¿verdad? Entonces no debería haber ninguna manera de que esto sea algún tipo de problema de red. Avísame si eso está mal.
- La máquina de producción en funcionamiento es una VM Azure (Server 2008 R2 con IIS 7.5). También existen algunas diferencias con el servidor:
- Esta nueva máquina es hardware físico (Servidor 2012 e IIS 8)
- Esto ES usar una cuenta de almacenamiento diferente dentro de mi suscripción azul, sin embargo, he intentado un total de 3 cadenas de conexión y ninguna de ellas funciona aquí.
ACTUALIZACIÓN: alguien pidió ver el código. De acuerdo, escribí una clase llamada Azure.Storage, que simplemente abstrae mi código de almacenamiento en la nube. Estamos fallando en una llamada a Storage.Exists, así que esta es la parte de esa clase que se siente relevante:
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
... Containers es solo una enumeración de nombres de contenedores (hay varios):
Public Enum Containers
CallerWavs
CampaignImports
Delve
Exports
CampaignImages
Logos
ReportLogos
WebLinkImages
End Enum
... Sí, tienen caracteres en mayúscula, lo que causa problemas. Todo se fuerza a minúsculas antes de que se apague.
También verifiqué que la AzureConnectionString correcta está saliendo de mi clase de configuración. De nuevo, probé algunos que funcionan en otros lugares. ¡Y este también funciona en otro lado!
También encontré este error. Mi problema era que había activado las restricciones dinámicas de seguridad de IP en mi web.config y que el número de archivos que se descargaban en algunos casos (por ejemplo, con páginas con muchas imágenes) excedía los umbrales máximos que había definido en mi web.config.