.NET Core 2.2, веб-API Azure, новый X509Certificate2 «Системе не удается найти указанный файл» и «доступ запрещен» - PullRequest
1 голос
/ 07 марта 2019

My Azure Web API загружает сертификат, хранящийся в виде секрета в хранилище ключей, а затем пытается создать новый сертификат из байтового массива. При локальном запуске все работает , но при развертывании в Azure мы получаем Доступ запрещен или Системе не удается найти указанный файл в зависимости от KeyStorageFlags, переданных конструктору. Веб-API использует .Net Core 2.2

Я некоторое время читал много информации, связанной с этим, но не с этим конкретным сценарием.

Использование флага MachineKeySet: certificate = new X509Certificate2(pfxBytes, "", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);

Исключение

ex = доступ запрещен, стек = в Internal.Cryptography.Pal.CertificatePal.FilterPFXStore (байт [] rawData, SafePasswordHandle пароль, PfxCertStoreFlags pfxCertStoreFlags) в Internal.Cryptography.Pal.CertificatePal.FromBlobOrFile (байт [] rawData, строковое имя файла, пароль SafePasswordHandle, X509KeyStorageFlags keyStorageFlags) в System.Security.Cryptography.X509Certificates.X509Certificate..ctor (байт [] rawData, строковый пароль, X509KeyStorageFlags keyStorageFlags)

Использование флага UserKeySet: certificate = new X509Certificate2(pfxBytes, "", X509KeyStorageFlags.UserKeySet | X509KeyStorageFlags.Exportable);

Исключение

ex = Система не может найти указанный файл, stack = at Internal.Cryptography.Pal.CertificatePal.FilterPFXStore (байт [] rawData, SafePasswordHandle пароль, PfxCertStoreFlags pfxCertStoreFlags) в Internal.Cryptography.Pal.CertificatePal.FromBlobOrFile (байт [] rawData, строковое имя файла, пароль SafePasswordHandle, X509KeyStorageFlags keyStorageFlags) в System.Security.Cryptography.X509Certificates.X509Certificate..ctor (байт [] rawData, строковый пароль, X509KeyStorageFlags keyStorageFlags)

Я следил за сертификатом загрузки как секретом, используя эту статью [https://www.rahulpnath.com/blog/pfx-certificate-in-azure-key-vault/][1] Похоже, что это не имеет никакого отношения к хранилищу ключей, поскольку локально загружает секрет из хранилища ключей, и загрузка в Azure происходит не там, где выдается исключение. Но это может быть связано с тем, как хранится сертификат?

Вот полный код, который мы используем

private async Task<X509Certificate2> GetSecretCertificateFromKVAPI()
        {
            try
            {
                var keyVaultName = _configuration["Secrets:KeyVaultName"];

                var keyVaultEndpoint = $"https://{keyVaultName}.vault.azure.net:443/secrets/";
                var provider = new AzureServiceTokenProvider();
                var client = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(provider.KeyVaultTokenCallback));
                SecretBundle secretRetrieved;

                secretRetrieved = await client.GetSecretAsync($"{keyVaultEndpoint}OdysseyCA");

                var pfxBytes = Convert.FromBase64String(secretRetrieved?.Value);

                //note, must pass an empty password when loading from keyvault in Azure
                X509Certificate2 certificate;
                try
                {
                    // or recreate the certificate directly
                    certificate = new X509Certificate2(pfxBytes, "",
                            X509KeyStorageFlags.MachineKeySet |
                            X509KeyStorageFlags.PersistKeySet |
                            X509KeyStorageFlags.Exportable);

                    // alternative, try using import
                    //var coll = new X509Certificate2Collection();
                    //coll.Import(pfxBytes, null, X509KeyStorageFlags.Exportable);
                    //certificate = coll[0];
                }
                catch (Exception ex)
                {
                    _logger.Trace($"create new X509 failed, ex={ex.Message}, stack={ex.StackTrace}");
                    throw;
                }

                return certificate;
            }
            catch (Exception ex)
            {
                _logger.Trace($"GetSecretCertificateFromKVAPI threw an exception, ex={ex.Message}, stack = {ex.StackTrace}");
                throw;
            }
        }

В коде, который вы видите, мы пытались использовать метод .import класса X509Certificate2Collection, чтобы обойти это, но результаты те же. Мы активно копируем .Net Core 2.1 и 2.0, чтобы выяснить, является ли это новой ошибкой, и ищем другие ответы.

Как нам заставить это работать?

Редактировать: основываясь на предложении в комментариях ниже, пробовал флаг EphemeralKeySet, но стек исключений почти такой же, как и другие:

certificate = new X509Certificate2(pfxBytes, "", X509KeyStorageFlags.EphemeralKeySet | X509KeyStorageFlags.Exportable);

ex = Система не может найти указанный файл, stack = at Internal.Cryptography.Pal.CertificatePal.FilterPFXStore (байт [] rawData, SafePasswordHandle пароль, PfxCertStoreFlags pfxCertStoreFlags) в Internal.Cryptography.Pal.CertificatePal.FromBlobOrFile (байт [] rawData, строковое имя файла, пароль SafePasswordHandle, X509KeyStorageFlags keyStorageFlags) в System.Security.Cryptography.X509Certificates.X509Certificate..ctor (байт [] rawData, строковый пароль, X509KeyStorageFlags keyStorageFlags)

Кто-нибудь может подтвердить, что это работает с .Net любой версии? возможное ядро ​​или 2.2 ошибка?

1 Ответ

0 голосов
/ 18 марта 2019

В API, размещенном в Azure, добавление параметра приложения: WEBSITE_LOAD_USER_PROFILE = 1 решило проблему. Мы остались с EphemeralKeySet, но я подозреваю, что флаги UserKeySet также будут работать.

...