Fixed: Ensure SSL cert exists before saving config

Trap missing certificate exception to avoid bootloop

(cherry picked from commit 78c7372a0d64e15734b14b0ca9852ae7c0a47132)
This commit is contained in:
ta264 2020-05-14 19:24:41 +01:00
parent 4da0fe80f3
commit c9ee3f8b8a
3 changed files with 71 additions and 4 deletions

View file

@ -1,6 +1,7 @@
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography.X509Certificates;
using FluentValidation;
using Lidarr.Http;
using NzbDrone.Common.Extensions;
@ -18,7 +19,10 @@ namespace Lidarr.Api.V1.Config
private readonly IConfigService _configService;
private readonly IUserService _userService;
public HostConfigModule(IConfigFileProvider configFileProvider, IConfigService configService, IUserService userService)
public HostConfigModule(IConfigFileProvider configFileProvider,
IConfigService configService,
IUserService userService,
FileExistsValidator fileExistsValidator)
: base("/config/host")
{
_configFileProvider = configFileProvider;
@ -43,7 +47,14 @@ namespace Lidarr.Api.V1.Config
SharedValidator.RuleFor(c => c.SslPort).ValidPort().When(c => c.EnableSsl);
SharedValidator.RuleFor(c => c.SslPort).NotEqual(c => c.Port).When(c => c.EnableSsl);
SharedValidator.RuleFor(c => c.SslCertPath).NotEmpty().When(c => c.EnableSsl);
SharedValidator.RuleFor(c => c.SslCertPath)
.Cascade(CascadeMode.StopOnFirstFailure)
.NotEmpty()
.IsValidPath()
.SetValidator(fileExistsValidator)
.Must((resource, path) => IsValidSslCertificate(resource)).WithMessage("Invalid SSL certificate file or password")
.When(c => c.EnableSsl);
SharedValidator.RuleFor(c => c.Branch).NotEmpty().WithMessage("Branch name is required, 'master' is the default");
SharedValidator.RuleFor(c => c.UpdateScriptPath).IsValidPath().When(c => c.UpdateMechanism == UpdateMechanism.Script);
@ -53,6 +64,21 @@ namespace Lidarr.Api.V1.Config
SharedValidator.RuleFor(c => c.BackupRetention).InclusiveBetween(1, 90);
}
private bool IsValidSslCertificate(HostConfigResource resource)
{
X509Certificate2 cert;
try
{
cert = new X509Certificate2(resource.SslCertPath, resource.SslCertPassword, X509KeyStorageFlags.DefaultKeySet);
}
catch
{
return false;
}
return cert != null;
}
private HostConfigResource GetHostConfig()
{
var resource = _configFileProvider.ToResource(_configService);