.Net Core Machine Ключевые альтернативы для webfarm

Я использую ядро ​​dotnet для создания приложения, которое выполняется в кластере Kubernetes на хостах Linux. Когда я тестировал, он заметил получение исключений при проверке токенов CSRF, это имеет смысл, так как я не редактировал машинный ключ, чтобы быть тем же самым на каждом экземпляре. Когда я начал устанавливать машинный ключ в web.config, я заметил, что это больше не будет работать в .Net Core.

Как теперь используется API DataProtection, машинный ключ больше не работает. Я попытался реализовать api в своем приложении, но когда я прочитал, мне нужно было бы использовать общий сетевой ресурс для обмена ключами между всеми экземплярами, я был ошеломлен. Разумеется, должен быть более простой (и лучший) способ достичь этого, не полагаясь на долю, которая должна быть онлайн-права?

Я попытался установить следующее в классе Startup в методе ConfigureServices:

services.AddDataProtection().SetApplicationName("DockerTestApplication");

Я как-то ожидал, что ключи будут сгенерированы с использованием имени приложения, но это не решило проблему.

Я нашел несколько интересных документов, которые используют код, который больше не будет компилироваться, я думаю, что Microsoft изменила некоторые вещи:

https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/compatibility/replacing-machinekey

Кто-нибудь знает решение этой проблемы, которое также будет работать в Linux и может делиться токенами по сети между экземплярами?

Спасибо заранее!

Ответ 1

Я сделал несколько тестов для резервного копирования моего комментария о копировании ключей. Сначала я создал простое консольное приложение со следующим кодом:

var serviceCollection = new ServiceCollection();
serviceCollection.AddDataProtection()
    .SetApplicationName("my-app")
    .PersistKeysToFileSystem(new DirectoryInfo(@"G:\tmp\so\keys"));
var services = serviceCollection.BuildServiceProvider();
var provider = services.GetService<IDataProtectionProvider>();
var protector = provider.CreateProtector("some_purpose");                
Console.WriteLine(Convert.ToBase64String(protector.Protect(Encoding.UTF8.GetBytes("hello world"))));

Итак, просто создайте контейнер DI, зарегистрируйте защиту данных там с определенной папкой для ключей, разрешите и защитите что-то.

Это создало следующий ключевой файл в целевой папке:

<?xml version="1.0" encoding="utf-8"?>
<key id="e6cbce11-9afd-43e6-94be-3f6057cb8a87" version="1">
  <creationDate>2017-04-10T15:28:18.0565235Z</creationDate>
  <activationDate>2017-04-10T15:28:18.0144946Z</activationDate>
  <expirationDate>2017-07-09T15:28:18.0144946Z</expirationDate>
  <descriptor deserializerType="Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60">
    <descriptor>
      <encryption algorithm="AES_256_CBC" />
      <validation algorithm="HMACSHA256" />
      <masterKey p4:requiresEncryption="true" xmlns:p4="http://schemas.asp.net/2015/03/dataProtection">
        <!-- Warning: the key below is in an unencrypted form. -->
        <value>rVDib1M1BjbCqGctcP+N25zb+Xli9VWX46Y7+9tsoGywGnIg4p9K5QTM+c388i0mC0JBSLaFS2pZBRdR49hsLQ==</value>
      </masterKey>
    </descriptor>
  </descriptor>
</key>

Как видите, файл относительно прост. Он описывает создание, активацию, даты истечения срока действия, используемые алгоритмы, ссылку на класс десериализатора и сам ключ курса.

Теперь я настроил приложение asp.net(так, другое приложение, а не консольное):

services.AddDataProtection()
    .SetApplicationName("my-app")
    .PersistKeysToFileSystem(new DirectoryInfo(@"G:\tmp\so\keys-asp"))
    .DisableAutomaticKeyGeneration();

Если вы теперь пытаетесь запустить приложение и сделать что-то, что требует защиты, оно будет терпеть неудачу, потому что нет ключей и автоматическое создание ключей отключено. Однако, если я скопирую ключи, созданные консольным приложением, в целевую папку - это будет счастливо использовать их.

Поэтому обратите внимание на обычные проблемы с безопасностью с помощью ключей копирования до истечения срока действия этих ключей (настраиваемых с помощью SetDefaultKeyLifetime) и с использованием той же версии Microsoft.AspNetCore.DataProtection во всех приложениях, которыми вы делитесь ключами с (потому что его версия указана в ключевом файле xml) - и все должно быть в порядке. Лучше создавать общие ключи в одном месте и во всех других местах, установленных DisableAutomaticKeyGeneration.