无法从本地环境将blob存储上传/下载到容器

时间:2020-01-17 09:04:57

标签: azure azure-functions azure-blob-storage application-settings

我有一个退出功能的应用程序,该应用程序具有从sftp下载文件,处理文件并将文件上传到blob存储的功能。此功能应用已在天蓝色部署并且可以正常工作。但是,当我从Visual Studio(本地)运行相同的文件时,将文件上传到Blob存储时会出错。

Microsoft.Azure.Storage.StorageException:无权使用此权限执行此操作。

我确保此应用在存储帐户中分配了必要的贡献者角色(这就是为什么它从azure开始工作的原因)。我是否需要在本地设置或项目设置中配置其他设置,才能使这些功能像部署到天蓝色时一样工作?还是存储帐户中有任何设置可以覆盖从开发人员运行但仅从天蓝运行时执行上传操作的要求?

我确保我使用的本地设置是从具有存储帐户名称,blob存储的连接字符串,sftp url和具有sft站点详细信息的密钥库名称的应用程序配置中复制的,

更新: 忘了提到从我的计算机上载命令行成功从命令行上传az存储容器上载命令。

更新2: 根据我的建议,我遵循了tutorial,成功地创建了容器,上传了blob并进行了清理,而没有出现错误。 然后,我合并了代码以将简单的下载blob模拟到内存流中,这也引发了错误

此请求无权使用此命令执行此操作 允许 (请参阅底部的完整日志)

下载Blob的代码:

static async Task TokenCredentialsSample()
{
    var tenantId = "xxxxx-xxxx-xxxx-xxxx-xxxxxxxx";
    var tokenProvider = new AzureServiceTokenProvider().GetAccessTokenAsync("https://storage.azure.com/",tenantId);
    var tokenCredential = new TokenCredential(tokenProvider.Result);
    var storageCredentials = new StorageCredentials(tokenCredential);
    var uri = new Uri("https://mystorageaccount.blob.core.windows.net/mycontainer/inbound/myfile.csv");

    var cloudBlockBlob = new CloudBlockBlob(uri, storageCredentials);

    var memoryStream = new MemoryStream();

    cloudBlockBlob.DownloadToStream(memoryStream); // Error here
    memoryStream.Position = 0;
    memoryStream.Close();

}

我还确保我从命令行键入az登录以切换以选择正确的订阅,并且在Visual Studio选项中也选择了该帐户。

错误日志:

Microsoft.Azure.Storage.StorageException HResult = 0x80131500 Message =此请求无权使用此权限执行此操作。 源= Microsoft.Azure.Storage.Common 堆栈跟踪: 在Microsoft.Azure.Storage.Core.Executor.Executor.d__1 1.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter 1.GetResult() at Microsoft.Azure.Storage.Core.Executor.Executor。<> c__DisplayClass0_0 1.<ExecuteSync>b__0() at Microsoft.Azure.Storage.Core.Util.CommonUtility.RunWithoutSynchronizationContext[T](Func 1 actionToRun) 在Microsoft.Azure.Storage.Core.Executor.Executor.ExecuteSync [T](RESTCommand 1 cmd, IRetryPolicy policy, OperationContext operationContext) at Microsoft.Azure.Storage.Blob.CloudBlob.DownloadRangeToStream(Stream target, Nullable 1偏移量,可为空的1个长度,AccessCondition accessCondition,BlobRequestOptions选项,OperationContext operationContext)处 在Microsoft.Azure.Storage.Blob.CloudBlob.DownloadToStream(流目标,AccessCondition accessCondition,BlobRequestOptions选项,OperationContext operationContext) 在C:... \ source \ repos \ BlobStorage \ Program.cs:line 111中的BlobStorage.Program.d__2.MoveNext() 在System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务) 在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务) 在System.Runtime.CompilerServices.TaskAwaiter.GetResult() 在C:... \ source \ repos \ BlobStorage \ Program.cs:line 19中的BlobStorage.Program.d__0.MoveNext()中

此异常最初是在此调用堆栈上抛出的: Microsoft.Azure.Storage.Core.Executor.Executor.ExecuteAsync(Microsoft.Azure.Storage.Core.Executor.RESTCommand,Microsoft.Azure.Storage.RetryPolicies.IRetryPolicy,Microsoft.Azure.Storage.OperationContext,System.Threading.CancellationToken) System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(System.Threading.Tasks.Task) System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(System.Threading.Tasks.Task) System.Runtime.CompilerServices.TaskAwaiter.GetResult() Microsoft.Azure.Storage.Core.Executor.Executor.ExecuteSync.AnonymousMethod__0() Microsoft.Azure.Storage.Core.Util.CommonUtility.RunWithoutSynchronizationContext(System.Func) Microsoft.Azure.Storage.Core.Executor.Executor.ExecuteSync(Microsoft.Azure.Storage.Core.Executor.RESTCommand,Microsoft.Azure.Storage.RetryPolicies.IRetryPolicy,Microsoft.Azure.Storage.OperationContext) Microsoft.Azure.Storage.Blob.CloudBlob.DownloadRangeToStream(System.IO.Stream,long ?, long ?, Microsoft.Azure.Storage.AccessCondition,Microsoft.Azure.Storage.Blob.BlobRequestOptions,Microsoft.Azure.Storage.OperationContext) Microsoft.Azure.Storage.Blob.CloudBlob.DownloadToStream(System.IO.Stream,Microsoft.Azure.Storage.AccessCondition,Microsoft.Azure.Storage.Blob.BlobRequestOptions,Microsoft.Azure.Storage.OperationContext) ... [通话堆栈被截断]

3 个答案:

答案 0 :(得分:1)

1) 我看到您从您的方法中返回了Task,但没有await进行任何操作。
将'async`关键字添加到方法签名并更改以下代码是一种很好的做法:

var tokenProvider = new AzureServiceTokenProvider().GetAccessTokenAsync("https://storage.azure.com/",tenantId);

类似:

var tokenProvider = new AzureServiceTokenProvider();
var token = await tokenProvider.GetAccessTokenAsync("https://storage.azure.com/",tenantId);
var tokenCredential = new TokenCredential(token );

现在,获取访问令牌,您可以使用http://jwt.io之类的工具并将其打开并检查声明。

2) 尝试从以下位置更改访问令牌:

GetAccessTokenAsync("https://storage.azure.com/",tenantId);

收件人:

GetAccessTokenAsync("https://[youraccount].blob.core.windows.net",tenantId);

3) AzureServiceTokenProvider将在一组预定义的位置中查找凭据。

AzureServiceTokenProvider documentation值得一读,以帮助解决问题。
您是否尝试过使用传递RunAs=Developer; DeveloperTool=AzureCli作为连接字符串的第一种选择,以便它明确知道在哪里查找?

因此,在执行azure cli并执行类似azure login之类的命令窗口中,您是否尝试过从那里运行控制台程序?

您登录了哪个订阅? az account list
您有很多订阅吗?
您的默认订阅可能不是您尝试从中访问Blob的订阅。

答案 1 :(得分:1)

好。我找到了解决方法。

我发现this article在笔记中清楚地表明,必须具有数据读取器或数据贡献者角色!像this这样的MS文档都没有像本文一样强调其他角色(数据读取器/数据提供者)的重要性。

请注意,您的用户是以下用户的所有者/贡献者,这是不够 订阅/资源组/存储帐户。用户必须是 分配给数据读取器或数据贡献者角色以访问 使用Azure AD身份验证进行数据。

我们认为贡献者足够,但还不够。

答案 2 :(得分:0)

此外,“数据读取器/贡献者”角色必须位于存储帐户资源本身上……在“订阅”资源级别上不起作用。

说实话,这就像一个错误。 应该允许在订阅级别具有“所有者”或“贡献者”角色的用户/服务原则通过cli上载,而没有补充角色。 如果可以从UI进行操作,那么我也应该可以通过cli进行操作。