Tenemos un STS basado en IdentityServer4 que se ejecuta correctamente en Windows, donde la credencial de firma se instaló en la computadora local con .pfx en Personal > Certificados y .cer en Personas de confianza > Certificados. Entonces podemos cargar la credencial de firma por su nombre común de la siguiente manera:
services.AddIdentityServer() .AddSigningCredential("CN=CERT_NAME") ...Ahora queremos ejecutar nuestra implementación de STS dentro de un contenedor Docker y nos hemos encontrado con la siguiente excepción:
Unhandled Exception: System.PlatformNotSupportedException: Unix LocalMachine X509Store is limited to the Root and CertificateAuthority stores. at Internal.Cryptography.Pal.StorePal.FromSystemStore(String storeName, StoreLocation storeLocation, OpenFlags openFlags) at System.Security.Cryptography.X509Certificates.X509Store.Open(OpenFlags flags) at IdentityModel.X509CertificatesFinder.Find(Object findValue, Boolean validOnly) at Microsoft.Extensions.DependencyInjection.IdentityServerBuilderExtensionsCrypto.AddSigningCredential(IIdentityServerBuilder builder, String name, StoreLocation location, NameType nameType)Según el mensaje de error anterior y la fuente del método AddSigningCredential que estamos usando aquí: https://github.com/IdentityServer/IdentityServer4/blob/ec17672d27f9bed42f9110d73755170ee9265116/src/IdentityServer4/Configuration/DependencyInjection/BuilderExtensions/Crypto.cs# L73 , parece evidente que nuestro problema es que IdentityServer4 está buscando el certificado en el almacén personal ("Mi") de la máquina local; sin embargo, dicho almacén no está disponible en entornos Unix según el mensaje de error.
Por lo tanto, tengo curiosidad por saber si existe alguna práctica recomendada para cargar la Credencial de firma para IdentityServer4 en contenedores Docker, si no es posible cargarla por nombre o huella digital. ¿La única opción sería agrupar el certificado con nuestra aplicación y luego cargarlo por nombre de archivo?
Cuando usa contenedores Docker e IdentityServer, básicamente tiene dos opciones:
COPY certificate.pfx . )-v /path/to/certificate.pfx:/certificate.pfx ) Cualquiera que sea la opción que elija, lo único que necesita es agregar el siguiente código de configuración a ConfigureServices en el Startup
var identityServerBuilder = services.AddIdentityServer(); /* store configuration and etc. is omitted */ if (_hostingEnvironment.IsDevelopment()) { identityServerBuilder.AddDeveloperSigningCredential(); } else { var certificate = new X509Certificate2("certificate.pfx", "certificate_password"); identityServerBuilder.AddSigningCredential(certificate); }También sería una buena idea leer la contraseña del certificado desde la configuración, la variable de entorno o el almacenamiento de secretos.
Estoy desarrollando en una máquina con Windows y uso el siguiente código para obtener el certificado de la tienda
X509Certificate2 cert = null; X509Store certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser); certStore.Open(OpenFlags.ReadOnly); X509Certificate2Collection certCollection = certStore.Certificates.Find( X509FindType.FindByThumbprint, "thumbprint", false); if (certCollection.Count > 0) { cert = certCollection[0]; Log.Logger.Information($"Successfully loaded cert from registry: {cert.Thumbprint}"); } if (cert == null) // Fallback { cert = new X509Certificate2(Path.Combine(_env.ContentRootPath, "certificate.pfx"), "password"); //Log.Logger.Information($"Falling back to cert from file. Successfully loaded: {cert.Thumbprint}"); } else { certStore.Dispose(); }