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 ошибка?