C# 在ASP.NET Core 3中配置DataProtection密钥管理选项时出现问题:“;读取钥匙圈时出错;

C# 在ASP.NET Core 3中配置DataProtection密钥管理选项时出现问题:“;读取钥匙圈时出错;,c#,asp.net-core,kubernetes,data-protection,C#,Asp.net Core,Kubernetes,Data Protection,我之所以这么做是因为我的Kestrel服务器的kubernetes副本集需要共享会话cookie数据库。我有一个基本的ASP.NET Core 3 C#web应用程序 我使用Azure cli 创建一个存储帐户 在该帐户内创建blob存储容器 记录了存储帐户密钥 我找不到创建空blob的命令,发现如果我上传一个,它们是按需创建的 我创建了一个密钥库,并能够获取密钥库密钥 以下是我在ConfigureServices函数中的代码: WriteLine("Begin ConfigureSe

我之所以这么做是因为我的Kestrel服务器的kubernetes副本集需要共享会话cookie数据库。我有一个基本的ASP.NET Core 3 C#web应用程序

我使用Azure cli

  • 创建一个存储帐户
  • 在该帐户内创建blob存储容器
  • 记录了存储帐户密钥
  • 我找不到创建空blob的命令,发现如果我上传一个,它们是按需创建的
  • 我创建了一个密钥库,并能够获取密钥库密钥
  • 以下是我在ConfigureServices函数中的代码:

    WriteLine("Begin ConfigureServices");
    var redisName = GetEnvironmentVariable(name: "REDIS_DNS_NAME", "my-redis-master.default.svc.cluster.local");
    var redisPassword = GetEnvironmentVariable(name: "REDIS_PASSWORD", "xxxxxxxxxxx");
    
    var settings = Configuration.GetSection("DataProtection").Get<DataProtectionSettings>();
    
    WriteLine($"settings={settings}");
    WriteLine($"AddDataProtection");
    
    services.AddDataProtection() ;
    
    // 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 =>
    {  // https://joonasw.net/view/using-azure-key-vault-and-azure-storage-for-asp-net-core-data-protection-keys
        options.XmlRepository = new AzureBlobXmlRepository(() =>
        {
            WriteLine($"new AzureBlobXmlRepository: settings={settings}");
            // 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();
            WriteLine("Create blob reference with token: new Microsoft.Azure.Storage.Auth.TokenCredential(accessToken)");
            var tokenCredential = new Microsoft.Azure.Storage.Auth.TokenCredential(accessToken);
            WriteLine("new Microsoft.Azure.Storage.Auth.StorageCredentials(tokenCredential)");
            var storageCredentials = new Microsoft.Azure.Storage.Auth.StorageCredentials(tokenCredential);
            var uris = $"https://{settings.StorageAccountName}.blob.core.windows.net/{settings.StorageKeyContainerName}/{settings.StorageKeyBlobName}";
            WriteLine($"new Uil({uris})");
            var uri = new Uri(uris);
            WriteLine($"uri={uri}");
            // Note this func is expected to return a new instance on each call
            WriteLine($"new Microsoft.Azure.Storage.Blob.CloudBlockBlob(uri, storageCredentials);");
            var blob = new Microsoft.Azure.Storage.Blob.CloudBlockBlob(uri, storageCredentials);
            return blob;
        });
    });
    
    这就是它想要的吗?我应该在哪里将其添加到代码中

    我还可以使用它创建连接字符串:

    az.cmd storage account show-connection-string --blob-endpoint $AZ_ASPNETCORE_BLOB_NAME -g $AZ_RESOURCE_GROUP_NAME -n $AZ_STORAGE_ACCOUNT
    
    以下是pod日志的结果:

    settings=AadTenantId=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx StorageAccountName=acctstoragexxxxx  StorageKeyContainerName=dataprotection StorageKeyBlobName=keys.xml KeyVaultKeyId=https://keyvaultname.vault.azure.net/keys/keyvaultkey/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    AddDataProtection
    new AzureBlobXmlRepository: settings=AadTenantId=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx StorageAccountName=acctstoragexxxxx  StorageKeyContainerName=dataprotection StorageKeyBlobName=keys.xml KeyVaultKeyId=https://keyvaultname.vault.azure.net/keys/keyvaultkey/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    [41m[30mfail[39m[22m[49m: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[48]
          An error occurred while reading the key ring.
    Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProviderException: Parameters: Connection String: [No connection string specified], Resource: https://storage.azure.com/, Authority: https://login.microsoftonline.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. Exception Message: Tried the following 3 methods to get an access token, but none of them worked.
    Parameters: Connection String: [No connection string specified], Resource: https://storage.azure.com/, Authority: https://login.microsoftonline.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. Exception Message: Tried to get token using Managed Service Identity. Access token could not be acquired. Received a non-retryable error. MSI ResponseCode: BadRequest, Response: {"error":"invalid_request","error_description":"Identity not found"}
    Parameters: Connection String: [No connection string specified], Resource: https://storage.azure.com/, Authority: https://login.microsoftonline.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. Exception Message: Tried to get token using Visual Studio. Access token could not be acquired. Environment variable LOCALAPPDATA not set.
    Parameters: Connection String: [No connection string specified], Resource: https://storage.azure.com/, Authority: https://login.microsoftonline.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. Exception Message: Tried to get token using Azure CLI. Access token could not be acquired. 
    
       at Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProvider.GetAuthResultAsyncImpl(String resource, String authority, Boolean forceRefresh, CancellationToken cancellationToken)
       at Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProvider.GetAccessTokenAsync(String resource, String tenantId, Boolean forceRefresh, CancellationToken cancellationToken)
       at WebApp_OpenIDConnect_DotNet.Startup.<>c__DisplayClass5_0.<ConfigureServices>b__5() in /src/Client/Startup.cs:line 120
       at Microsoft.AspNetCore.DataProtection.AzureStorage.AzureBlobXmlRepository.CreateFreshBlobRef()
       at Microsoft.AspNetCore.DataProtection.AzureStorage.AzureBlobXmlRepository.GetAllElements()
       at Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.GetAllKeys()
       at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider.CreateCacheableKeyRingCore(DateTimeOffset now, IKey keyJustAdded)
       at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider.Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.ICacheableKeyRingProvider.GetCacheableKeyRing(DateTimeOffset now)
       at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider.GetCurrentKeyRingCore(DateTime utcNow, Boolean forceRefresh)
    [40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionHostedService[0]
          Key ring failed to load during application startup.
    Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProviderException: Parameters: Connection String: [No connection string specified], Resource: https://storage.azure.com/, Authority: https://login.microsoftonline.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. Exception Message: Tried the following 3 methods to get an access token, but none of them worked.
    Parameters: Connection String: [No connection string specified], Resource: https://storage.azure.com/, Authority: https://login.microsoftonline.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. Exception Message: Tried to get token using Managed Service Identity. Access token could not be acquired. Received a non-retryable error. MSI ResponseCode: BadRequest, Response: {"error":"invalid_request","error_description":"Identity not found"}
    Parameters: Connection String: [No connection string specified], Resource: https://storage.azure.com/, Authority: https://login.microsoftonline.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. Exception Message: Tried to get token using Visual Studio. Access token could not be acquired. Environment variable LOCALAPPDATA not set.
    Parameters: Connection String: [No connection string specified], Resource: https://storage.azure.com/, Authority: https://login.microsoftonline.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. Exception Message: Tried to get token using Azure CLI. Access token could not be acquired. 
    
       at Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProvider.GetAuthResultAsyncImpl(String resource, String authority, Boolean forceRefresh, CancellationToken cancellationToken)
       at Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProvider.GetAccessTokenAsync(String resource, String tenantId, Boolean forceRefresh, CancellationToken cancellationToken)
       at WebApp_OpenIDConnect_DotNet.Startup.<>c__DisplayClass5_0.<ConfigureServices>b__5() in /src/Client/Startup.cs:line 120
       at Microsoft.AspNetCore.DataProtection.AzureStorage.AzureBlobXmlRepository.CreateFreshBlobRef()
       at Microsoft.AspNetCore.DataProtection.AzureStorage.AzureBlobXmlRepository.GetAllElements()
       at Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.GetAllKeys()
       at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider.CreateCacheableKeyRingCore(DateTimeOffset now, IKey keyJustAdded)
       at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider.Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.ICacheableKeyRingProvider.GetCacheableKeyRing(DateTimeOffset now)
       at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider.GetCurrentKeyRingCore(DateTime utcNow, Boolean forceRefresh)
       at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider.GetCurrentKeyRing()
       at Microsoft.AspNetCore.DataProtection.Internal.DataProtectionHostedService.StartAsync(CancellationToken token)
    
    但我相信这是没有必要的,因为我没有调用ProtectKeysWithAzureKeyVault(现在),因为Jonas说这是可选的

    也许乔纳斯错了,我需要用AzureKeyVault调用ProtectKeys

    乔纳斯的代码不会为我编译:

    var kvClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(_tokenProvider.KeyVaultTokenCallback));
    
    services.AddDataProtection()
    .ProtectKeysWithAzureKeyVault(kvClient, settings.KeyVaultKeyId);
    
    ProtectKeysWithAzureKeyVault
    只有两个重载,都不接受KeyVault客户端

    有人能给我看一些调用ProtectKeysWithAzureKeyVault的示例代码吗?它需要一个keyIdentifier(这是密钥库密钥吗?),一个keyResolver和一个keyResolver需要Azure.core.TokenCredential,这个抽象TokenCredential类有十几个派生类!我想要哪一个?我在任何地方都找不到任何例子

    谢谢


    Siegfried

    更新的官方文件。更新的官方文件。
    az.cmd login --service-principal --username $env:SP_APPID --password $env:SP_SECRET --tenant $env:SP_TENANT
    az account get-access-token --resource https://vault.azure.net
    
    var kvClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(_tokenProvider.KeyVaultTokenCallback));
    
    services.AddDataProtection()
    .ProtectKeysWithAzureKeyVault(kvClient, settings.KeyVaultKeyId);