Загрузка сертификата X509: ошибка в Azure, невозможно воспроизвести локально - PullRequest
0 голосов
/ 31 октября 2019

У меня есть код для загрузки сертификата X509 из моего файла appsettings.json вместе с паролем (pfx-файл в кодировке base64), который выглядит следующим образом:

    public static X509Certificate2 LoadSsoCertificate(IConfiguration config)
    {
        //this should be a self-signed PFX certificate with the private key included.
        var certificateText = config["SSO:x509Certificate"];
        //this should be the password to open/ read the certificate.
        var certificatePassword = config["SSO:SecretKeyPassphrase"];

        var certificateBytes = Convert.FromBase64String(certificateText);
        var cert = new X509Certificate2(certificateBytes, certificatePassword);
        return cert;
    }

Это прекрасно работает при локальном тестировании,но при развертывании в службе приложений Azure я получил следующее загадочное исключение:

Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: The specified network password is not correct
   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)
   at System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(Byte[] rawData, String password)
   at MyCompany.AuthenticationServices.Core.Configuration.SingleSignOn.LoadSsoCertificate(IConfiguration config) in d:\a\1\s\MyCompany.AuthenticationServices.Core\Configuration\SingleSignOn.cs:line 43
   at MyCompany.AuthenticationServices.Core.Configuration.ConfigureMultiTenantSaml2Options.Configure(Saml2Options options) in d:\a\1\s\MyCompany.AuthenticationServices.Core\Configuration\ConfigureMultiTenantSaml2Options.cs:line 51
   at MyCompany.AuthenticationServices.Core.Configuration.ConfigureMultiTenantSaml2Options.Configure(String name, Saml2Options options) in d:\a\1\s\MyCompany.AuthenticationServices.Core\Configuration\ConfigureMultiTenantSaml2Options.cs:line 78
   at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
   at Sustainsys.Saml2.AspNetCore2.Saml2Handler.<>c__DisplayClass6_0.<InitializeAsync>b__0()
   at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
--- End of stack trace from previous location where exception was thrown ---
   at System.Lazy`1.CreateValue()
   at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd(String name, Func`1 createOptions)
   at Sustainsys.Saml2.AspNetCore2.Saml2Handler.InitializeAsync(AuthenticationScheme scheme, HttpContext context)
   at Microsoft.AspNetCore.Authentication.AuthenticationHandlerProvider.GetHandlerAsync(HttpContext context, String authenticationScheme)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at MyCompany.SoaToolkit.LoggingContext.AspNetCore.Middleware.Configuration.<>c.<<UseLoggingContextRequests>b__0_0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Server.IISIntegration.IISMiddleware.Invoke(HttpContext httpContext)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)

Он говорит, что указанный «сетевой» пароль неверен, но это тот же пароль, который работает локально, поэтому я не могупредставьте, что проблема на самом деле в пароле, и он не должен пытаться использовать «сеть». Кто-нибудь может пролить некоторый свет на то, в чем здесь проблема, и предложить предложения о том, как заставить этот относительно простой код работать?

ОБНОВЛЕНИЕ

Основано на комментариях @ Crypt32Я создал новый сертификат непосредственно в Azure и сохранил его в виде PFX на своем локальном рабочем столе, затем закодировал его в Base64 и включил в свой файл appsettings. Опять же, это работало хорошо локально, но когда я развернул в Azure, я получил похожее, но также мистифицирующее исключение:

Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: The system cannot find the file specified
   at Internal.Cryptography.Pal.StorePal.FromBlobOrFile(Byte[] rawData, String fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags)
   at System.Security.Cryptography.X509Certificates.X509Certificate2Collection.Import(Byte[] rawData, String password, X509KeyStorageFlags keyStorageFlags)
   at MyCompany.AuthenticationServices.Core.Configuration.SingleSignOn.LoadSsoCertificate(IConfiguration config) in D:\a\1\s\MyCompany.AuthenticationServices.Core\Configuration\SingleSignOn.cs:line 40
   at MyCompany.AuthenticationServices.Core.Configuration.ConfigureMultiTenantSaml2Options.Configure(Saml2Options options) in D:\a\1\s\MyCompany.AuthenticationServices.Core\Configuration\ConfigureMultiTenantSaml2Options.cs:line 51
   at MyCompany.AuthenticationServices.Core.Configuration.ConfigureMultiTenantSaml2Options.Configure(String name, Saml2Options options) in D:\a\1\s\MyCompany.AuthenticationServices.Core\Configuration\ConfigureMultiTenantSaml2Options.cs:line 78
   at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
   at Sustainsys.Saml2.AspNetCore2.Saml2Handler.<>c__DisplayClass6_0.<InitializeAsync>b__0()
   at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
--- End of stack trace from previous location where exception was thrown ---
   at System.Lazy`1.CreateValue()
   at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd(String name, Func`1 createOptions)
   at Sustainsys.Saml2.AspNetCore2.Saml2Handler.InitializeAsync(AuthenticationScheme scheme, HttpContext context)
   at Microsoft.AspNetCore.Authentication.AuthenticationHandlerProvider.GetHandlerAsync(HttpContext context, String authenticationScheme)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at MyCompany.SoaToolkit.LoggingContext.AspNetCore.Middleware.Configuration.<>c.<<UseLoggingContextRequests>b__0_0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Server.IISIntegration.IISMiddleware.Invoke(HttpContext httpContext)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)

1 Ответ

0 голосов
/ 31 октября 2019

ОК, @ Crypt32 привел меня на правильный путь, но это не очевидно.

1) Проблема не имеет ничего общего с паролем. Это было связано с тем, что я сделал самозаверяющий сертификат, используя openssl с алгоритмами, которые, очевидно, поддерживает Windows 10 ... но Azure нет. Я создал новый сертификат в Azure, и он работал нормально.

2) У меня также была проблема с хранилищем ключей (это была ошибка, связанная с невозможностью найти файл), по причинам, которые я не понимаю. Кажется, Azure не может понять, как создать хранилище ключей учетной записи службы для службы приложений, и это поражает меня. Я переключился на хранилище ключей на основе BLOB-объектов (см. здесь ), и внезапно все снова начинает работать ... или, по крайней мере, не перестает запускаться.

Моральистория: сообщения об ошибках X509 хуже, чем ничего не стоящие. Это убило бы MS, чтобы сделать сообщение об ошибке, которое фактически описало проблему? Надеюсь, этот ответ поможет кому-то еще.

...