.Net CryptographicException "Объект уже существует" в Azure

У нас есть веб-сайт, развернутый в двух веб-приложениях Azure: в рабочей и предварительной версии.

Веб-сайт в определенное время создает контейнер для размещения ключей RSA, используя следующий код:

// -----------------------------
// Part 1 : Initialize csp params
// -----------------------------
const int PROVIDER_RSA_FULL = 1;
const string CONTAINER_NAME = "OurKeyContainer";
CspParameters cspParams;
cspParams = new CspParameters(PROVIDER_RSA_FULL);
cspParams.KeyContainerName = CONTAINER_NAME;
cspParams.Flags = CspProviderFlags.UseMachineKeyStore;
cspParams.ProviderName = "Microsoft Strong Cryptographic Provider";

// --------------------------------------------------
// Part 2 : A try to set folder access rights to "everyone"
// --------------------------------------------------
// http://whowish-programming.blogspot.fr/2010/10/systemsecuritycryptographycryptographic.html
// http://stackru.com/questions/5013881/c-sharp-how-do-i-get-the-everybody-user
var sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
var rule = new CryptoKeyAccessRule(sid, CryptoKeyRights.FullControl, AccessControlType.Allow);
cspParams.CryptoKeySecurity = new CryptoKeySecurity();
cspParams.CryptoKeySecurity.SetAccessRule(rule);

return new RSACryptoServiceProvider(cspParams);

Проблема в том, что этот код работает только для одного сайта, который был впервые запущен на самом деле. Второй бросил CryptographicException "Объект уже существует".

После поиска в Google проблема, по-видимому, вызвана тем, что пользователи, выполняющие веб-сайт, не имеют права доступа к контейнеру ключей, но, к сожалению, рекомендуемое исправление (реализованное в части 2 нашего кода выше) не работает..

Любая идея или совет?

Спасибо

Риана

1 ответ

Решение

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

В этой настройке вы можете изменить три вещи, которые будут давать разные результаты:

  • Идентификационные данные для предоставления доступа
  • Контейнерный магазин
  • Название контейнера

Для идентичности мы можем использовать либо Everyone (как вы пытались) или Current который мы можем получить из WindowsIdentity

    private IdentityReference GetWindowsIdentity()
    {
        return System.Security.Principal.WindowsIdentity.GetCurrent().User;
    }

    private IdentityReference GetEveryoneIdentity()
    {
        return new SecurityIdentifier(WellKnownSidType.WorldSid, null);
    }

Контейнерный магазин может быть machine wide или только для текущего пользователя

// machine wide store
var cspParams = new CspParameters(PROVIDER_RSA_FULL)
{
    ...
    Flags = CspProviderFlags.UseMachineKeyStore;
    ...
};

// default store
var cspParams = new CspParameters(PROVIDER_RSA_FULL)
{
    ...
    Flags = CspProviderFlags.UseDefaultKeyContainer;
    ...
};

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

    KeyContainerName = "OurKeyContainer",

    KeyContainerName = $"OurKeyContainer-{identity}",

Различные комбинации будут давать разные результаты:

Идентификация каждого пользователя, магазин, одно и то же имя контейнера. Сбой в одном из слотов с System.Security.Cryptography.CryptographicException: Object already exists.

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

Идентификация каждого пользователя, хранилище пользователя, одно и то же имя контейнера. Сбой в обоих слотах с System.Security.Cryptography.CryptographicException: The system cannot find the file specified.

Идентичность каждого, хранилище пользователя, контейнер на идентификацию ОК

Текущий идентификатор, общий магазин, то же имя контейнера. Сбой в одном из слотов с System.Security.Cryptography.CryptographicException: Object already exists.

Текущее удостоверение, общий магазин машины, контейнер на удостоверение ОК

Текущий идентификатор, пользовательское хранилище, одно и то же имя контейнера. Сбой в обоих слотах с System.Security.Cryptography.CryptographicException: The system cannot find the file specified.

Текущий идентификатор, пользовательское хранилище, контейнер для каждого идентификатора Сбой в обоих слотах с System.Security.Cryptography.CryptographicException: The system cannot find the file specified.

Итак, подведем итог: изменение имени контейнера для включения чего-то уникального для среды решит проблему. Это не обязательно должен быть идентификатор (но вы получите один идентификатор для каждой службы приложений, которую вы используете на компьютере, так что это довольно безопасно), это может быть имя среды, если вы установите его как ENVIRONMENT VARIABLE в вашем сервисе приложений и убедитесь, что он установлен на pre-prod а также prod соответственно.

Вот код воспроизведения, чтобы проверить это

Другие вопросы по тегам