下载存储 blob 时如何修复 "KeyVaultErrorException: Operation returned an invalid status code 'Forbidden'"

How to fix "KeyVaultErrorException: Operation returned an invalid status code 'Forbidden'" when downloading a storage blob

我收到 KeyVaultErrorException:当我尝试下载存储 blob (DownloadToStream) 时,操作返回无效状态代码“禁止”。

我尝试创建另一个 rsa 密钥。但是出现了同样的错误。 当我使用秘密时。一切正常。 我检查了密钥库访问策略。 用户帐户具有完全权限。 该应用程序具有获取和列出密钥和机密的权限。

这是完整的代码。 它基于此 sample.

using System;
using System.Threading.Tasks;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System.Configuration;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
using Microsoft.Azure.KeyVault;
using System.Threading;
using System.IO;

namespace KeyVaultTest
{
   class Program
   {
      static void Main(string[] args)
      {
         // This is standard code to interact with Blob Storage
         StorageCredentials creds = new StorageCredentials(
             ConfigurationManager.AppSettings["accountName"],
             ConfigurationManager.AppSettings["accountKey"]);
         CloudStorageAccount account = new CloudStorageAccount(creds, useHttps: true);
         CloudBlobClient client = account.CreateCloudBlobClient();
         CloudBlobContainer contain = client.GetContainerReference("test123");
         contain.CreateIfNotExists();

         // The Resolver object is used to interact with Key Vault for Azure Storage
         // This is where the GetToken method from above is used
         KeyVaultKeyResolver cloudResolver = new KeyVaultKeyResolver(GetToken);

         // Retrieve the key that you created previously
         // The IKey that is returned here is an RsaKey
         // Remember that we used the names contosokeyvault and testrsakey1
         var rsa = cloudResolver.ResolveKeyAsync("https://mykeystorage.vault.azure.net/keys/testkey9000/", CancellationToken.None).GetAwaiter().GetResult();


         // Now you simply use the RSA key to encrypt by setting it in the BlobEncryptionPolicy. 
         BlobEncryptionPolicy policy = new BlobEncryptionPolicy(rsa, null);
         BlobRequestOptions options = new BlobRequestOptions() { EncryptionPolicy = policy };

         // Reference a block blob
         CloudBlockBlob blob = contain.GetBlockBlobReference("MyFile.txt");

         // Upload using the UploadFromStream method
         using (var stream = System.IO.File.OpenRead(@"C:\temp\MyFile.txt"))
            blob.UploadFromStream(stream, stream.Length, null, options, null);


         // In this case we will not pass a key and only pass the resolver because 
         //  this policy will only be used for downloading / decrypting
         policy = new BlobEncryptionPolicy(null, cloudResolver);
         options = new BlobRequestOptions() { EncryptionPolicy = policy };

         using (var np = File.Open(@"C:\temp\MyFileDecrypted.txt", FileMode.Create))
            blob.DownloadToStream(np, null, options, null);
      }

      private async static Task<string> GetToken(string authority, string resource, string scope)
      {
         var authContext = new AuthenticationContext(authority);
         ClientCredential clientCred = new ClientCredential(
             ConfigurationManager.AppSettings["clientId"],
             ConfigurationManager.AppSettings["clientSecret"]);
         AuthenticationResult result = await authContext.AcquireTokenAsync(resource, clientCred);

         if (result == null)
            throw new InvalidOperationException("Failed to obtain the JWT token");

         return result.AccessToken;
      }
   }
}

如果你想访问key vault资源,你需要为你的AD应用配置访问策略,让它有足够的权限访问key vault资源。详情请参考.