Erro 403 na produção do WindowsAzure.Storage
Eu tenho um aplicativo WebForms que usa a API WindowsAzure.Storage v3. Funciona bem no desenvolvimento e em um ambiente de produção, mas estou lançando uma nova instância e qualquer código que chama o Armazenamento de Blob do Azure gera um erro 403.
Estou brincando com isso há algum tempo, e ele falha em qualquer chamada para o Blob Storage, então, em vez de mostrar meu código, mostrarei meu rastreamento de pilha:
[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
Aqui está o que eu tentei ...
O AzureStorageConnectionString que falha nesse ambiente definitivamente funciona na produçãoOutras seqüências de conexão (do outro ambiente de produção, que funciona) também recebem 403 aquiParecia haver um problema com carimbos de data e hora em algumas versões antigas da API REST (que não estou usando diretamente ...), por isso, verifiquei se os horários estão corretos, até tentei mudar o servidor para o horário UTC.Tentei alternar a cadeia de conexão entre http / https.Atualizado para a versão mais recente da API (v3.1)Tentei mexer no código para garantir que todas as chamadas para o Armazenamento do Azure sejam 403. Sim.Desesperado, instalou o Azure Powershell no servidor apenas para verificar se algum tipo de comunicação com o Azure está funcionando. E isso funcionou bem.Naveguei até o portal de gerenciamento do azure e isso funciona bem.Alguma ideia? Isso deveria estar apenas usando a porta 80 ou 443, certo? Portanto, não deve haver nenhum problema com a rede. Deixe-me saber se isso está errado.
A máquina de produção em funcionamento é uma VM do Azure (Server 2008 R2 com IIS 7.5) Também há algumas diferenças com o servidor:Esta nova máquina é um hardware físico (Server 2012 e IIS 8)Isso está usando uma conta de armazenamento diferente na minha assinatura do azure, no entanto, tentei um total de três cadeias de conexão e nenhuma delas funciona aqui.ATUALIZAR: alguém pediu para ver o código. Ok, escrevi uma classe chamada Azure.Storage, que apenas abstrai meu código de armazenamento em nuvem. Estamos falhando em uma chamada para Storage.Exists, então aqui está a parte dessa classe que parece 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
...Recipientes é apenas uma enumeração de nomes de contêineres (existem vários):
Public Enum Containers
CallerWavs
CampaignImports
Delve
Exports
CampaignImages
Logos
ReportLogos
WebLinkImages
End Enum
... Sim, eles têm caracteres maiúsculos, o que causa problemas. Tudo é forçado a minúsculo antes de sair.
Também verifiquei se o AzureConnectionString correto está saindo da minha classe de configurações. Mais uma vez, tentei alguns que funcionam em outros lugares. E este também funciona em outro lugar!