mirror of
https://github.com/Radarr/Radarr.git
synced 2024-11-04 10:02:40 +01:00
Fixed: Ensure SSL cert exists before saving config
Trap missing certificate exception to avoid bootloop Fixes #4403
This commit is contained in:
parent
6ad3653c04
commit
78c7372a0d
26
src/NzbDrone.Core/Validation/Paths/FileExistsValidator.cs
Normal file
26
src/NzbDrone.Core/Validation/Paths/FileExistsValidator.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
using FluentValidation.Validators;
|
||||||
|
using NzbDrone.Common.Disk;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Validation.Paths
|
||||||
|
{
|
||||||
|
public class FileExistsValidator : PropertyValidator
|
||||||
|
{
|
||||||
|
private readonly IDiskProvider _diskProvider;
|
||||||
|
|
||||||
|
public FileExistsValidator(IDiskProvider diskProvider)
|
||||||
|
: base("File does not exist")
|
||||||
|
{
|
||||||
|
_diskProvider = diskProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool IsValid(PropertyValidatorContext context)
|
||||||
|
{
|
||||||
|
if (context.PropertyValue == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _diskProvider.FileExists(context.PropertyValue.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Security.Cryptography;
|
||||||
using System.Security.Cryptography.X509Certificates;
|
using System.Security.Cryptography.X509Certificates;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
@ -10,6 +11,7 @@
|
|||||||
using NLog;
|
using NLog;
|
||||||
using NLog.Extensions.Logging;
|
using NLog.Extensions.Logging;
|
||||||
using NzbDrone.Common.EnvironmentInfo;
|
using NzbDrone.Common.EnvironmentInfo;
|
||||||
|
using NzbDrone.Common.Exceptions;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Common.Serializer;
|
using NzbDrone.Common.Serializer;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
@ -72,7 +74,21 @@ public void StartServer()
|
|||||||
{
|
{
|
||||||
options.ConfigureHttpsDefaults(configureOptions =>
|
options.ConfigureHttpsDefaults(configureOptions =>
|
||||||
{
|
{
|
||||||
var certificate = new X509Certificate2(_configFileProvider.SslCertPath, _configFileProvider.SslCertPassword, X509KeyStorageFlags.DefaultKeySet);
|
X509Certificate2 certificate;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
certificate = new X509Certificate2(sslCertPath, _configFileProvider.SslCertPassword, X509KeyStorageFlags.DefaultKeySet);
|
||||||
|
}
|
||||||
|
catch (CryptographicException ex)
|
||||||
|
{
|
||||||
|
if (ex.HResult == 0x2 || ex.HResult == 0x2006D080)
|
||||||
|
{
|
||||||
|
throw new RadarrStartupException(ex, $"The SSL certificate file {sslCertPath} does not exist");
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new RadarrStartupException(ex);
|
||||||
|
}
|
||||||
|
|
||||||
configureOptions.ServerCertificate = certificate;
|
configureOptions.ServerCertificate = certificate;
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Core.Authentication;
|
using NzbDrone.Core.Authentication;
|
||||||
@ -18,7 +19,10 @@ public class HostConfigModule : RadarrRestModule<HostConfigResource>
|
|||||||
private readonly IConfigService _configService;
|
private readonly IConfigService _configService;
|
||||||
private readonly IUserService _userService;
|
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")
|
: base("/config/host")
|
||||||
{
|
{
|
||||||
_configFileProvider = configFileProvider;
|
_configFileProvider = configFileProvider;
|
||||||
@ -43,7 +47,14 @@ public HostConfigModule(IConfigFileProvider configFileProvider, IConfigService c
|
|||||||
|
|
||||||
SharedValidator.RuleFor(c => c.SslPort).ValidPort().When(c => c.EnableSsl);
|
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.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.Branch).NotEmpty().WithMessage("Branch name is required, 'master' is the default");
|
||||||
SharedValidator.RuleFor(c => c.UpdateScriptPath).IsValidPath().When(c => c.UpdateMechanism == UpdateMechanism.Script);
|
SharedValidator.RuleFor(c => c.UpdateScriptPath).IsValidPath().When(c => c.UpdateMechanism == UpdateMechanism.Script);
|
||||||
@ -53,6 +64,21 @@ public HostConfigModule(IConfigFileProvider configFileProvider, IConfigService c
|
|||||||
SharedValidator.RuleFor(c => c.BackupRetention).InclusiveBetween(1, 90);
|
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()
|
private HostConfigResource GetHostConfig()
|
||||||
{
|
{
|
||||||
var resource = _configFileProvider.ToResource(_configService);
|
var resource = _configFileProvider.ToResource(_configService);
|
||||||
|
Loading…
Reference in New Issue
Block a user