Как распространять ключи защиты данных с помощью веб-приложения ASP.NET Core

  • Михаил
  • 12 мин. на прочтение
  • 170
  • 15 Nov 2022
  • 15 Nov 2022

Когда вы настраиваете защиту данных в своем веб-приложении ASP.NET Core, по умолчанию оно инициализируется со стандартными конфигурациями, обычно подходящими для одного компьютера и одного экземпляра веб-приложения.

Веб-приложениям часто требуется хранить конфиденциальные данные.

Стек защиты данных ASP.NET Core предназначен для долгосрочной замены элемента <machineKey> в ASP.NET 1.x — 4.x.

Если вы видите себя в одном из следующих сценариев, это руководство для вас:

  • Ваше приложение распределено между несколькими машинами
  • У вас есть несколько приложений на одном компьютере с общими данными
  • По соображениям соответствия

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

AddDataProtection

Метод расширения AddDataProtectionдля IServiceCollectionинтерфейса возвращает объект IDataProtectionBuilder, который «открывает» другие методы расширения для настройки наилучшего сценария для вашего приложения.

Методы расширения для IDataProtectionBuilder.

Имейте в виду, что когда вы настраиваете сервисы вашего приложения (аутентификация, сеанс, защита от подделки), некоторые из них пытаются добавить уровень защиты данных. Таким образом, рекомендуется зарегистрировать DataProtection до того, как это произойдет.

SetApplicationName

Дескриптор приложения в системе защиты данных позволяет изолировать приложения. По умолчанию именем является корневой путь к содержимому, но в некоторых сценариях, перечисленных выше, путь может отличаться для разных сред. Поэтому важно всегда задавать имя приложения, если вы хотите поделиться защищенными полезными нагрузками между приложениями.

Уникальное имя этого приложения в системе защиты данных.

Настройте SetApplicationName в каждом приложении с одним и тем же значением.

PersistKeysTo* и ProtectKeysWith*

Перед настройкой хранилища ключей важно объяснить, что такое конфигурации PersistKeysTo* и ProtectKeysWith*. Если вы уже знаете об этом, переходите к следующей главе.

PersistKeysTo*

Методы расширения, запускаемые PersistKeysTo*для IDataProtectionBuilderинтерфейса, настраивают хранилище ключей, в котором будут храниться действительные и устаревшие ключи. Чтобы совместно использовать ключи между приложениями, хранилище ключей должно быть доступно каждому приложению. например, сервер Redis, сервер базы данных, большой двоичный объект Azure или даже файловая система. Здесь вы можете увидеть некоторые хранилища ключей, доступные в дистрибутиве ASP.NET Core. По умолчанию ключи генерируются с периодом проверки 90 дней с момента активации. Ниже вы можете увидеть пример формата ключа, хранящегося в хранилище ключей.

<?xml version="1.0" encoding="utf-8"?>
<key id="80732141-ec8f-4b80-af9c-c4d2d1ff8901" version="1">
 <creationDate>2015-03-19T23:32:02.3949887Z</creationDate>
 <activationDate>2015-03-19T23:32:02.3839429Z</activationDate>
 <expirationDate>2015-06-17T23:32:02.3839429Z</expirationDate>
 <descriptor deserializerType="{deserializerType}">
   <descriptor>
     <encryption algorithm="AES_256_CBC" />
     <validation algorithm="HMACSHA256" />
     <enc:encryptedSecret decryptorType="{decryptorType}" xmlns:enc="...">
       <encryptedKey>
         <!-- This key is encrypted with Windows DPAPI. -->
         <value>AQAAANCM...8/zeP8lcwAg==</value>
       </encryptedKey>
     </enc:encryptedSecret>
   </descriptor>
 </descriptor>
</key>

Сгенерированный образец ключа для ASP.NET Core

По истечении срока действия необходимо сохранить устаревший ключ, чтобы снять защиту с данных, которые ранее были защищены этим ключом. По моему опыту, развертывание новых ключей и использование устаревших работает очень хорошо, а ASP.NET Core оптимизирует процесс кэширования ключей в памяти. Подробнее см . здесь .

ProtectKeysWith*

Ключи вашего хранилища ключей можно защитить с помощью сертификата X.509. Это может иметь смысл для следующих сценариев:

  • Репозиторий может быть доступен для многих пользователей/приложений
  • По соображениям соответствия

ProtectKeys можно настроить с помощью установленного на вашем компьютере сертификата или службы, которая управляет вашими сертификатами, например AzureVault или Windows DPAPI .

ВАЖНО: ваши сертификаты защищены, и я предполагаю, что никто не имеет к ним доступа.

PersistKeysToRedis

Пакет Microsoft.AspNetCore.DataProtection.StackExchangeRedis позволяет хранить ключи защиты данных в кэше Redis, поддерживаемом записью списка. Эта запись списка будет храниться в ключе redis, полученном во втором параметре, например «DataProtection-Keys», как вы можете видеть ниже.

Конфигурация Redis в качестве хранилища ключей защиты данных

В разделе «Пошаговая настройка » вы можете увидеть, как вручную настроить репозиторий XML, получив URI redis и ключ redis из конфигураций приложения.

ВАЖНО: Redis по умолчанию является непостоянной базой данных, убедитесь, что Redis настроен как постоянный.

Настройка параметров управления ключами

Если вы используете конфигурации Microsoft.Extensions.Configurationс внедрением зависимостей, вы можете загрузить эти конфигурации и привязать их KeyManagementOptionsавтоматически.

Ниже вы можете увидеть два способа загрузки параметров. Вы можете сделать это, используя константы (волшебную строку и число) или загрузив конфигурации из раздела конфигурации.

Настройка KeyManagementOptions из конфигураций приложения

Пошаговая настройка

  1. Добавьте зависимости защиты данных;
  2. Установить имя приложения;
  3. Настройте хранилище ключей (Redis или FileSystem, AzureBlob, EntityFramework и т. д.);
  4. Персонализируйте KeyManagementOptions;
  5. (Необязательно) Защитите свои ключи сертификатом X509.

ОК, и все! Вы можете посмотреть ниже пример всего процесса и, если хотите, вы можете увидеть больше примеров здесь .

… и, как всегда, не стесняйтесь обращаться ко мне, если у вас есть какие-либо вопросы.

public static IServiceCollection AddCustomDataProtection(this IServiceCollection serviceCollection)
{
   var builder = serviceCollection
       .AddDataProtection()
       .SetApplicationName("MyApp");
#if DEBUG
   builder
       .PersistKeysToFileSystem(new DirectoryInfo(@"c:\dataprotection-persistkeys"))
       .AddKeyManagementOptions(options =>
       {
           options.NewKeyLifetime = new TimeSpan(365, 0, 0, 0);
           options.AutoGenerateKeys = true;
       });
#else
   serviceCollection
       .AddOptions<KeyManagementOptions>()
       .Configure<IConfiguration>((options, configuration) =>
       {
           configuration.GetSection("KeyManagement").Bind(options);
       })
       .Configure<MyAppOptions>((options, myAppOptions) => 
       {
           options.XmlRepository = new Microsoft.AspNetCore.DataProtection.StackExchangeRedis.RedisXmlRepository(
               () => ConnectionMultiplexer.Connect(myAppOptions.RedisConfigurationString).GetDatabase(),
               myAppOptions.DataProtectionRedisKeyForPersistKeys);
       });
   //.PersistKeysToStackExchangeRedis(ConnectionMultiplexer.Connect("<URI>"), "DataProtection-Keys");
#endif
   return serviceCollection;
}

Вывод

Data Protection предлагает простой ориентированный на потребителя API и простоту конфигураций с практически нулевой настройкой. Как мы выяснили, в некоторых случаях необходимо настроить определенный аспект Redis в качестве хранилища ключей. Однако можно пойти глубже и настроить защиту данных с безграничными возможностями.

Плюсы: использование Redis в качестве хранилища ключей — лучший способ обмена ключами для нескольких приложений, поскольку некоторые веб-приложения уже используют его для обмена файлами cookie аутентификации или защитой CSRF на нескольких серверах.

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