Certificates with UD running in Linux Container?

I’m struggling to get this to work. I’ve seen the blog post with UD running with nginx and using certs from Let’s Encrypt, but I can’t seem to figure out what to pass to the -certificatefile and -certificatefilepassword parameters to get the dashboard to work. I generated some self-signed certs in bash and tried .crt cert with the password, but I’m not having any luck.

When you say it doesn’t work, what issue are you getting? Does the dashboard fail to start or you can’t access it?

Well the site doesn’t come up at all. I tried putting the .cert in my image and that didn’t work. I think it has something to do with needed the right format and or actually issuing it on something running Ubuntu, but I’m not sure how that’s work with a container.

Some progress but still no luck. I decided to try and use openssl and just create a self-signed cert upon building the image. I used this post for help: https://stackoverflow.com/questions/44047315/generate-a-self-signed-certificate-in-docker

This is my DockerFile portion relating to the certs:

RUN openssl genrsa -des3 -passout pass:hello -out /Panorama/server.pass.key 2048 && \
openssl rsa -passin pass:hello -in /Panorama/server.pass.key -out /Panorama/server.key && \
rm /Panorama/server.pass.key && \
openssl req -new -key /Panorama/server.key -out /Panorama/server.csr \
    -subj "/C=UK/ST=Warwickshire/L=Leamington/O=OrgName/OU=IT Department/CN=example.com" && \
openssl x509 -req -days 365 -in /Panorama/server.csr -signkey /Panorama/server.key -out /Panorama/server.crt

and the dashboard.ps1 portion:

$cert = (Get-Content -Path "$Cache:RootPath/server.crt" -Raw)
$p = (ConvertTo-SecureString -String "hello" -AsPlainText -Force)
$Dashboard = New-UDDashboard @DashboardParameters
Start-UDDashboard -Name "Panorama" -Dashboard $Dashboard -Port $port -PublishedFolder 
$Folder -AdminMode -Wait -CertificateFile $cert -CertificateFilePassword $p

I get an error on building the image:

Generating RSA private key, 2048 bit long modulus (2 primes)
..............................................................................................+++++
........................+++++
e is 65537 (0x010001)
writing RSA key
Can't load /root/.rnd into RNG
139972598919616:error:2406F079:random number generator:RAND_load_file:Cannot open 
file:../crypto/rand/randfile.c:88:Filename=/root/.rnd
Signature ok
subject=C = UK, ST = Warwickshire, L = Leamington, O = OrgName, OU = IT Department, CN = 
example.com
Getting Private key

When I inspect the logs from the container:

Application startup exception: Interop+Crypto+OpenSslCryptographicException: error:2006D002:BIO routines:BIO_new_file:system lib
   at Interop.Crypto.CheckValidOpenSslHandle(SafeHandle handle)
   at Internal.Cryptography.Pal.CertificatePal.FromFile(String fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags)
   at System.Security.Cryptography.X509Certificates.X509Certificate..ctor(String fileName, String password, X509KeyStorageFlags keyStorageFlags)
   at System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(String fileName, String password)
   at Microsoft.AspNetCore.Hosting.ListenOptionsHttpsExtensions.UseHttps(ListenOptions listenOptions, String fileName, String password)
   at UniversalDashboard.Server.<>c__DisplayClass38_0.<Start>b__3(ListenOptions listenOptions) in D:\a\1\s\src\UniversalDashboard\Server\Server.cs:line 133
   at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerOptions.Listen(IPEndPoint endPoint, Action`1 configure)
   at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerOptions.Listen(IPAddress address, Int32 port, Action`1 configure)
   at UniversalDashboard.Server.<>c__DisplayClass38_0.<Start>b__1(KestrelServerOptions options) in D:\a\1\s\src\UniversalDashboard\Server\Server.cs:line 144
   at Microsoft.Extensions.Options.ConfigureNamedOptions`1.Configure(String name, TOptions options)
   at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
   at Microsoft.Extensions.Options.OptionsManager`1.<>c__DisplayClass5_0.<Get>b__0()
   at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
   at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
   at System.Lazy`1.CreateValue()
   at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd(String name, Func`1 createOptions)
   at Microsoft.Extensions.Options.OptionsManager`1.Get(String name)
   at Microsoft.Extensions.Options.OptionsManager`1.get_Value()
   at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServer.CreateServiceContext(IOptions`1 options, ILoggerFactory loggerFactory)
   at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServer..ctor(IOptions`1 options, ITransportFactory transportFactory, ILoggerFactory loggerFactory)
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(IServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitSingleton(SingletonCallSite singletonCallSite, ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(IServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(IServiceCallSite callSite, ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.EnsureServer()
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication()
Start-UDDashboard : error:2006D002:BIO routines:BIO_new_file:system lib
At /Panorama/dashboard.ps1:47 char:1
+ Start-UDDashboard -Name "Panorama" -Dashboard $Dashboard -Port $port  ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : NotSpecified: (:) [Start-UDDashboard], OpenSslCryptographicException
+ FullyQualifiedErrorId : Interop+Crypto+OpenSslCryptographicException,UniversalDashboard.Cmdlets.StartDashboardCommand

Application is shutting down...

Should I pass in the .key file instead?

Hmmm. I’ve always used a PFX file on Windows but I’m not sure how that applies to linux.

Man, try the freeware
https://www.paessler.com/tools/certificateimporter
This software was intented to help you import certificates to Paessler PRTG.
However it also converts from pfx to crt, key and pem files for importing to anything linuxy.

Works so much better than trying to do it manually with openssl installed in gitbash…

So it sounds like it might have to do with permissions. I think when docker builds the image (which is were i’m attempting to create the cert) it does it as root, and then when UD gets the pfx file, it throws that long error above. https://github.com/dotnet/corefx/issues/25064

Made some progress, but not quite enough.

$cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::CreateFromCertFile("$Cache:RootPath/p.crt")

$Dashboard = New-UDDashboard @DashboardParameters

Start-UDDashboard -Name "Panorama" -Dashboard $Dashboard -Port $port -PublishedFolder $Folder -ListenAddress '0.0.0.0' -AdminMode -Wait -Certificate $Cert 

Now the container logs show:

Hosting environment: Production
Content root path: /root/.local/share/powershell/Modules/UniversalDashboard/2.7.0/netstandard2.0/../client
Now listening on: https://0.0.0.0:10001
Application started. Press Ctrl+C to shut down.

But when I go to localhost:10001 or https://localhost:10001 or 0.0.0.0:10001 or https://0.0.0.0:100001 the browser returns a

This site can’t be reached
localhost unexpectedly closed the connection.