.NET Core 2.2, новый веб-API Azure X509Certificate2 «Системе не удается найти указанный файл» и «Отказано в доступе»

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

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

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

Исключение

ex=Access denied, stack= at Internal.Cryptography.Pal.CertificatePal.FilterPFXStore(Byte[] rawData, SafePasswordHandle password, PfxCertStoreFlags pfxCertStoreFlags) at Internal.Cryptography.Pal.CertificatePal.FromBlobOrFile(Byte[] rawData, String fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) at System.Security.Cryptography.X509Certificates.X509Certificate..ctor(Byte[] rawData, String password, X509KeyStorageFlags keyStorageFlags)

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

Исключение

ex=The system cannot find the file specified, stack= at Internal.Cryptography.Pal.CertificatePal.FilterPFXStore(Byte[] rawData, SafePasswordHandle password, PfxCertStoreFlags pfxCertStoreFlags) at Internal.Cryptography.Pal.CertificatePal.FromBlobOrFile(Byte[] rawData, String fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) at System.Security.Cryptography.X509Certificates.X509Certificate..ctor(Byte[] rawData, String password, 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=The system cannot find the file specified, stack = at Internal.Cryptography.Pal.CertificatePal.FilterPFXStore(Byte[] rawData, SafePasswordHandle password, PfxCertStoreFlags pfxCertStoreFlags) at Internal.Cryptography.Pal.CertificatePal.FromBlobOrFile(Byte[] rawData, String fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) at System.Security.Cryptography.X509Certificates.X509Certificate..ctor(Byte[] rawData, String password, X509KeyStorageFlags keyStorageFlags)

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

Для MachineKeySet: вы должны быть администратором. Для UserKeySet (или обычного неявного): вам нужен загруженный профиль пользователя. Для EphemeralKeySet: все должно работать. stackoverflow.com/questions/52750160/…

bartonjs 07.03.2019 20:47

@bartonjs, ДА! использование EmphemeralKeySet действительно сработало!! Почему это нигде не задокументировано, я понятия не имею.

user2503078 07.03.2019 21:16

@bartonjs, НЕТ! Я не уверен, что я сделал, когда я думал, что это работает, но это не работает. Ошибка стека очень похожа на другие. Я отредактирую пост, чтобы показать это. Любые другие идеи, что происходит?

user2503078 08.03.2019 16:30
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
Как установить LAMP Stack 1/2 на Azure Linux VM
Как установить LAMP Stack 1/2 на Azure Linux VM
В дополнение к нашему предыдущему сообщению о намерении Azure прекратить поддержку Azure Database для MySQL в качестве единого сервера после 16...
5
3
2 725
1

Ответы 1

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

после того, как попробовал много решений, например, строковый файл = Path.Combine(Directory.GetCurrentDirectory(), PrivateKey_Path);, предоставил доступ к IIS_IUser для файла, ничего не работает, но ваше решение работает.

Somnath Kadam 17.11.2020 13:58

Похоже, проблема с закрытыми ключами... github.com/projectkudu/kudu/wiki/…

Marty 10.05.2021 18:27

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