C# 如何使用AzureKeyVault调试ProtectKeys?

C# 如何使用AzureKeyVault调试ProtectKeys?,c#,azure,asp.net-core,azure-keyvault,C#,Azure,Asp.net Core,Azure Keyvault,尝试使用AzureKeyVault保护密钥时,出现以下错误: 00:01:41错误]读取钥匙圈时出错。 Microsoft.Azure.KeyVault.Models.KeyVault错误异常:操作返回无效的状态代码“禁止” 位于Microsoft.Azure.KeyVault.KeyVaultClient.WrapkeyWithHttpMessageAsync(字符串vaultBaseUrl、字符串keyName、字符串keyVersion、字符串算法、字节[]值、字典`2 CustomHea

尝试使用AzureKeyVault保护密钥时,出现以下错误:

00:01:41错误]读取钥匙圈时出错。 Microsoft.Azure.KeyVault.Models.KeyVault错误异常:操作返回无效的状态代码“禁止” 位于Microsoft.Azure.KeyVault.KeyVaultClient.WrapkeyWithHttpMessageAsync(字符串vaultBaseUrl、字符串keyName、字符串keyVersion、字符串算法、字节[]值、字典`2 CustomHeader、CancellationToken CancellationToken) 位于Microsoft.Azure.KeyVault.KeyVaultClientExtensions.WrapKeyAsync(IKeyVaultClient操作,字符串keyIdentifier,字符串算法,字节[]键,CancellationToken CancellationToken) 位于Microsoft.AspNetCore.DataProtection.AzureKeyVault.AzureKeyVault XmlEncryptor.EncryptAsync(XElement plaintextElement) 位于Microsoft.AspNetCore.DataProtection.AzureKeyVault.AzureKeyVault XmlEncryptor.Encrypt(XElement plaintextElement) 在Microsoft.AspNetCore.DataProtection.XmlEncryption.XmlEncryptionExtensions.EncryptifEssential(IXmlEncryptor encryptor encryptor,XElement元素)上 位于Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IIInternalXMLKeyManager.CreateNewKey(Guid-keyId、DateTimeOffset-creationDate、DateTimeOffset-activationDate、DateTimeOffset-expirationDate) 在Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.CreateNewKey(DateTimeOffset activationDate,DateTimeOffset expirationDate) 在Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider.CreateCacheableKeyRingCore(现在是DateTimeOffset,IKey keyJustAdded) 位于Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider.Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.ICacheableKeyRingProvider.GetCacheableKeyRing(现在是DateTimeOffset) 位于Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider.GetCurrentKeyRingCore(DateTime utcNow)

我尝试使用这样的方法:

            services.AddDataProtection()
            .SetApplicationName("APPLICATIONNAME")
            .PersistKeysToAzureBlobStorage(container, "keys.xml")
            .ProtectKeysWithAzureKeyVault(KeyVaultClientFactory.Create(), "https://KEYVAULTNAME.vault.azure.net/keys/DATAPROTECTIONKEY/");
我检查过的东西:

  • KeyVault中的应用程序具有“包裹/展开”权限(我启用了所有权限只是为了让它正常工作)
  • 上述代码在不使用AzureKeyVault的情况下工作ProtectKeys
  • KeyVaultClientFactory.Create()
    返回可以检索机密的有效
    KeyVault
  • (RSA)密钥已启用并存在于KeyVault中-对该密钥允许的操作也都已启用

  • 我现在不知道如何进一步调试它。我想我遗漏了一些明显的东西,欢迎提供任何建议

    我建议您更改以下实施方式:

    {
      "DataProtection": {
        "KeyVaultKeyId": "https://mykeyvaultname.vault.azure.net/keys/DataProtectionKey/bfc1bda979bc4081b89ab6f43bad12b8"
      }
    }
    
    var kvClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(_tokenProvider.KeyVaultTokenCallback));
    
    services.AddDataProtection()
        .ProtectKeysWithAzureKeyVault(kvClient, settings.KeyVaultKeyId);
    
    请确保为应用程序提供钥匙库的解包密钥和包裹密钥权限。请注意,t在授予许可后的某个时候需要时间来反映更改

    您可以在此处查看参考代码:

    附加参考:

    我的startup.cs是这样的:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Identity;
    using Microsoft.AspNetCore.Identity.UI;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.HttpsPolicy;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.EntityFrameworkCore;
    using KeyVaultSample.Data;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Azure.KeyVault;
    using Microsoft.Azure.Services.AppAuthentication;
    using Microsoft.AspNetCore.DataProtection;
    using Microsoft.AspNetCore.DataProtection.KeyManagement;
    using Microsoft.AspNetCore.DataProtection.AzureStorage;
    
    
    using Microsoft.WindowsAzure.Storage.Blob;
    using Microsoft.Rest;
    using Microsoft.WindowsAzure.Storage.Auth;
    
    namespace KeyVaultSample
    {
        public class DataProtectionSettings
        {
            public string KeyVaultKeyId { get; set; }
            public string AadTenantId { get; set; }
            public string StorageAccountName { get; set; }
            public string StorageKeyContainerName { get; set; }
            public string StorageKeyBlobName { get; set; }
        }
        public class Startup
        {
            private readonly AzureServiceTokenProvider _tokenProvider;
    
            public Startup(IConfiguration configuration)
            {
                Configuration = configuration;
                _tokenProvider = new AzureServiceTokenProvider();
            }
    
            public IConfiguration Configuration { get; }
    
            // This method gets called by the runtime. Use this method to add services to the container.
            public void ConfigureServices(IServiceCollection services)
            {
                services.Configure<CookiePolicyOptions>(options =>
                {
                    // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                    options.CheckConsentNeeded = context => true;
                    options.MinimumSameSitePolicy = SameSiteMode.None;
                });
    
                var settings = Configuration.GetSection("DataProtection").Get<DataProtectionSettings>();
    
                var kvClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(_tokenProvider.KeyVaultTokenCallback));
    
                services.AddDataProtection()
                    .ProtectKeysWithAzureKeyVault(kvClient, settings.KeyVaultKeyId);
                // Replicates PersistKeysToAzureBlobStorage
                // There is no overload to give it the func it ultimately uses
                // We need to do that so that we can get refreshed tokens when needed
                services.Configure<KeyManagementOptions>(options =>
                {
                    options.XmlRepository = new AzureBlobXmlRepository(() =>
                    {
                        // This func is called every time before getting the blob and before modifying the blob
                        // Get access token for Storage
                        // User / managed identity needs Blob Data Contributor on the Storage Account (container was not enough)
                        string accessToken = _tokenProvider.GetAccessTokenAsync("https://storage.azure.com/", tenantId: settings.AadTenantId)
                     .GetAwaiter()
                     .GetResult();
                        // Create blob reference with token
                        var tokenCredential = new TokenCredential(accessToken);
                        var storageCredentials = new StorageCredentials(tokenCredential);
                        var uri = new Uri($"https://{settings.StorageAccountName}.blob.core.windows.net/{settings.StorageKeyContainerName}/{settings.StorageKeyBlobName}");
                        // Note this func is expected to return a new instance on each call
                        var blob = new CloudBlockBlob(uri, storageCredentials);
                        return blob;
                    });
                });
                services.AddDbContext<ApplicationDbContext>(options =>
                    options.UseSqlServer(
                        Configuration.GetConnectionString("DefaultConnection")));
                services.AddDefaultIdentity<IdentityUser>()
                    .AddDefaultUI(UIFramework.Bootstrap4)
                    .AddEntityFrameworkStores<ApplicationDbContext>();
    
    
                services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
            }
    
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IHostingEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                    app.UseDatabaseErrorPage();
                }
                else
                {
                    app.UseExceptionHandler("/Error");
                    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                    app.UseHsts();
                }
    
                app.UseHttpsRedirection();
                app.UseStaticFiles();
                app.UseCookiePolicy();
    
                app.UseAuthentication();
    
                app.UseMvc();
            }
        }
    }
    
    使用系统;
    使用System.Collections.Generic;
    使用System.Linq;
    使用System.Threading.Tasks;
    使用Microsoft.AspNetCore.Builder;
    使用Microsoft.AspNetCore.Identity;
    使用Microsoft.AspNetCore.Identity.UI;
    使用Microsoft.AspNetCore.Hosting;
    使用Microsoft.AspNetCore.Http;
    使用Microsoft.AspNetCore.HttpsPolicy;
    使用Microsoft.AspNetCore.Mvc;
    使用Microsoft.EntityFrameworkCore;
    使用KeyVaultSample.Data;
    使用Microsoft.Extensions.Configuration;
    使用Microsoft.Extensions.DependencyInjection;
    使用Microsoft.Azure.KeyVault;
    使用Microsoft.Azure.Services.AppAuthentication;
    使用Microsoft.AspNetCore.DataProtection;
    使用Microsoft.AspNetCore.DataProtection.KeyManagement;
    使用Microsoft.AspNetCore.DataProtection.AzureStorage;
    使用Microsoft.WindowsAzure.Storage.Blob;
    使用微软.Rest;
    使用Microsoft.WindowsAzure.Storage.Auth;
    名称空间KeyVaultSample
    {
    公共类数据保护设置
    {
    公共字符串KeyVaultKeyId{get;set;}
    公共字符串AadTenantId{get;set;}
    公共字符串StorageAccountName{get;set;}
    公共字符串StorageKeyContainerName{get;set;}
    公共字符串StorageKeyBlobName{get;set;}
    }
    公营创业
    {
    专用只读AzureServiceTokenProvider\u tokenProvider;
    公共启动(IConfiguration配置)
    {
    配置=配置;
    _tokenProvider=新AzureServiceTokenProvider();
    }
    公共IConfiguration配置{get;}
    //此方法由运行时调用。请使用此方法将服务添加到容器中。
    public void配置服务(IServiceCollection服务)
    {
    配置(选项=>
    {
    //此lambda确定给定请求是否需要非必要cookie的用户同意。
    options.checkApprovered=context=>true;
    options.MinimumSameSitePolicy=SameSiteMode.None;
    });
    var settings=Configuration.GetSection(“数据保护”).Get();
    var kvClient=new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(_tokenProvider.KeyVaultTokenCallback));
    services.AddDataProtection()
    .ProtectKeysWithAzureKeyVault(kvClient,settings.KeyVault KeyId);
    //复制PersistKeysAzureBlobstorage
    //没有重载来提供它最终使用的函数
    //我们需要这样做,以便在需要时获得刷新的令牌
    配置(选项=>
    {
    options.XmlRepository=新AzureBlobXmlRepository(()=>
    {
    //每次在获取blob和修改blob之前都会调用此func
    //获取存储的访问令牌
    //