Azure 存储 CloudBlobContainer.Exists 权限

Azure Storage CloudBlobContainer.Exists permissions

我有一个生成 SAS Uri 的进程,用于将一些文件上传到 Azure 存储。现在它正在使用旧的“Microsoft.Azure.Storage”包,因为我使用的是 Microsoft.Azure.Storage.DataMovement.dll,因为它可以轻松上传大文件。

当我在存储资源管理器中使用 SAS Uri 时,一切正常。如果我不检查容器是否存在,它也能正常工作,但进行存在检查会导致权限错误。我已经尝试为生成 SAS 的应用程序提供 IAM 角色中的所有权限,但它仍然发生。

var sasUri = @"<sas uri>";
var backupsContainer = new Microsoft.Azure.Storage.Blob.CloudBlobContainer(new Uri(sasUri));
backupsContainer.Exists();

这是给我 'This request is not authorized to perform this operation' 错误的代码片段。

我看过类似的问题: 但我没有任何防火墙规则。

我应该提一下,之前我是使用存储帐户的密钥生成 SAS 的。当我更新它而不是使用应用程序时,它就坏了。我更新了它,因为最终我希望它使用 Managed Identity 凭据。我也包含了生成 SAS 的代码

BlobSasBuilder blobSasBuilder = new BlobSasBuilder
{
  BlobContainerName = ExportSASInfo.ExportContainerName,
  //c for container
  Resource = "c",   
  // Access expires in 2 hours
  ExpiresOn = DateTimeOffset.UtcNow.AddHours(sasSettingsModel.SasExpirationHours)
 };
    
 //allow adding blobs
 blobSasBuilder.SetPermissions(
  BlobContainerSasPermissions.Read
  | BlobContainerSasPermissions.Add
  | BlobContainerSasPermissions.Create
  | BlobContainerSasPermissions.Write
  | BlobContainerSasPermissions.Delete
  | BlobContainerSasPermissions.List);
string scheme = "https";
string host = $"{customerInfo.AzureStorageAccountName}.blob.core.windows.net";
string blobEndpoint = $"{scheme}://{host}";
DefaultAzureCredential azureCredential = new DefaultAzureCredential(new DefaultAzureCredentialOptions() { ExcludeVisualStudioCodeCredential = true, ExcludeVisualStudioCredential = true, ExcludeSharedTokenCacheCredential = true });
BlobServiceClient blobServiceClient = new BlobServiceClient(
  serviceUri: new Uri(blobEndpoint),
  credential: azureCredential);
  BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient(ExportSASInfo.ExportContainerName);                        

await containerClient.CreateIfNotExistsAsync();
UserDelegationKey key = await blobServiceClient.GetUserDelegationKeyAsync(
  startsOn: DateTimeOffset.UtcNow.AddMinutes(-5),
  expiresOn: DateTimeOffset.UtcNow.AddHours(sasSettingsModel.SasExpirationHours));            var sasToken = blobSasBuilder.ToSasQueryParameters(
  userDelegationKey: key,
  accountName: customerInfo.AzureStorageAccountName);  
BlobUriBuilder blobUriBuilder = new BlobUriBuilder(containerClient.Uri)
{
  Sas = sasToken
};
return new ExportSASInfo() { sasUri = blobUriBuilder.ToUri() }; 

 

你的角色足够了,我也可以重现你的问题,因为你生成的是一个容器级别的SAS,要检查这个容器的存在,SAS需要权限来列出帐户中的所有容器,即帐户级别SAS,无论你的MSI(managed identity)和blobSasBuilder.SetPermissions()中的权限是什么角色,它都不起作用。

在您的情况下,您使用 MSI 来验证和创建用户委托 SAS,不支持创建帐户级别的 SAS,只需使用存储帐户密钥对其进行签名即可,因此如果您想检查容器的存在,您的选择是直接使用 ExistsAsync 方法。

string blobEndpoint = string.Format("https://{0}.blob.core.windows.net","joystoragev2");
BlobServiceClient blobServiceClient = new BlobServiceClient(new Uri(blobEndpoint), new ManagedIdentityCredential());
BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient("test");
containerClient.ExistsAsync().GetAwaiter().GetResult();

注意: 在我的截图中,我像上面的代码一样用 EnvironmentCredential in local, if you want to use MSI to auth, just replace it with ManagedIdentityCredential 测试它,还要确保你是 运行 Azure 中的代码启用了 MSI 的环境,例如网络应用程序,那么它将正常工作。

之后就可以使用SAS对容器进行操作了,比如上传大文件。