diff options
author | Wouter Tinus <wouter.tinus@gmail.com> | 2020-06-17 20:48:31 +0200 |
---|---|---|
committer | Wouter Tinus <wouter.tinus@gmail.com> | 2020-06-17 20:48:31 +0200 |
commit | c21744bac5c93aa52ce879166abde2cee6f45e3d (patch) | |
tree | 290b51de68c9c09d3a023f13f5884889fca44c4f /src | |
parent | 8edfefc8fe0ce3c145a7370df9fa26ce7e167bca (diff) | |
download | letsencrypt-win-simple-c21744bac5c93aa52ce879166abde2cee6f45e3d.zip letsencrypt-win-simple-c21744bac5c93aa52ce879166abde2cee6f45e3d.tar.gz letsencrypt-win-simple-c21744bac5c93aa52ce879166abde2cee6f45e3d.tar.bz2 |
don't attempt to validate orders which are already valid
Diffstat (limited to 'src')
-rw-r--r-- | src/main.lib/Context/ValidationContext.cs | 14 | ||||
-rw-r--r-- | src/main.lib/Plugins/ValidationPlugins/Http/HttpValidation.cs | 48 | ||||
-rw-r--r-- | src/main.lib/RenewalExecutor.cs | 2 | ||||
-rw-r--r-- | src/main.lib/RenewalValidator.cs | 55 | ||||
-rw-r--r-- | src/main.test/Mock/MockContainer.cs | 1 | ||||
-rw-r--r-- | src/main.test/Tests/RenewalTests/RenewalServiceTests.cs | 5 |
6 files changed, 94 insertions, 31 deletions
diff --git a/src/main.lib/Context/ValidationContext.cs b/src/main.lib/Context/ValidationContext.cs index c5c9544..4dddb76 100644 --- a/src/main.lib/Context/ValidationContext.cs +++ b/src/main.lib/Context/ValidationContext.cs @@ -11,19 +11,21 @@ namespace PKISharp.WACS.Context { public ValidationContextParameters( Authorization authorization, - TargetPart? targetPart, + TargetPart targetPart, string challengeType, - string pluginName) + string pluginName, + bool orderValid) { TargetPart = targetPart; Authorization = authorization; ChallengeType = challengeType; PluginName = pluginName; + OrderValid = orderValid; } - + public bool OrderValid { get; } public string ChallengeType { get; } public string PluginName { get; } - public TargetPart? TargetPart { get; } + public TargetPart TargetPart { get; } public Authorization Authorization { get; } } @@ -40,6 +42,10 @@ namespace PKISharp.WACS.Context ChallengeType = parameters.ChallengeType; PluginName = parameters.PluginName; ValidationPlugin = scope.Resolve<IValidationPlugin>(); + if (parameters.OrderValid) + { + Success = true; + } } public ILifetimeScope Scope { get; } public string Identifier { get; } diff --git a/src/main.lib/Plugins/ValidationPlugins/Http/HttpValidation.cs b/src/main.lib/Plugins/ValidationPlugins/Http/HttpValidation.cs index 768fcce..ee6a996 100644 --- a/src/main.lib/Plugins/ValidationPlugins/Http/HttpValidation.cs +++ b/src/main.lib/Plugins/ValidationPlugins/Http/HttpValidation.cs @@ -21,7 +21,7 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins where TOptions : HttpValidationOptions<TPlugin> where TPlugin : IValidationPlugin { - private readonly List<string> _filesWritten = new List<string>(); + private readonly List<string> _filesWritten = new List<string>(); protected TOptions _options; protected ILogService _log; @@ -190,12 +190,16 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins var destination = CombinePath(_path, challenge.HttpResourcePath.Replace(partialPath, "web.config")); if (!_filesWritten.Contains(destination)) { - _log.Debug("Writing web.config"); - var content = GetWebConfig(); - WriteFile(destination, content); - _filesWritten.Add(destination); + var content = GetWebConfig().Value; + if (content != null) + { + _log.Debug("Writing web.config"); + WriteFile(destination, content); + _filesWritten.Add(destination); + } + } - } + } catch (Exception ex) { _log.Warning("Unable to write web.config: {ex}", ex.Message); ; @@ -207,7 +211,16 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins /// Get the template for the web.config /// </summary> /// <returns></returns> - private string GetWebConfig() => File.ReadAllText(TemplateWebConfig); + private Lazy<string?> GetWebConfig() => new Lazy<string?>(() => { + try + { + return File.ReadAllText(TemplateWebConfig); + } + catch + { + return null; + } + }); /// <summary> /// Combine root path with relative path @@ -287,20 +300,29 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins { if (_path != null) { + var folders = new List<string>(); foreach (var file in _filesWritten) { - _log.Debug("Deleting answer"); + _log.Debug("Deleting files"); await DeleteFile(file); - if (_settings.Validation.CleanupFolders) + var folder = file.Substring(0, file.LastIndexOf(PathSeparator)); + if (!folders.Contains(folder)) + { + folders.Add(folder); + } + } + if (_settings.Validation.CleanupFolders) + { + _log.Debug("Deleting empty folders"); + foreach (var folder in folders) { - var folder = file.Substring(0, file.LastIndexOf(PathSeparator)); if (await DeleteFolderIfEmpty(folder)) { - var idx = file.LastIndexOf(PathSeparator); + var idx = folder.LastIndexOf(PathSeparator); if (idx >= 0) { - folder = folder.Substring(0, folder.LastIndexOf(PathSeparator)); - await DeleteFolderIfEmpty(folder); + var parent = folder.Substring(0, folder.LastIndexOf(PathSeparator)); + await DeleteFolderIfEmpty(parent); } } } diff --git a/src/main.lib/RenewalExecutor.cs b/src/main.lib/RenewalExecutor.cs index fb70a28..5f17bef 100644 --- a/src/main.lib/RenewalExecutor.cs +++ b/src/main.lib/RenewalExecutor.cs @@ -172,7 +172,7 @@ namespace PKISharp.WACS var context = new ExecutionContext(execute, order, runLevel, result); // Authorize the order (validation) - await _validator.AuthorizeOrder(context); + await _validator.AuthorizeOrder(context, runLevel); if (context.Result.Success) { // Execute final steps (CSR, store, install) diff --git a/src/main.lib/RenewalValidator.cs b/src/main.lib/RenewalValidator.cs index 65a0919..5f44ef8 100644 --- a/src/main.lib/RenewalValidator.cs +++ b/src/main.lib/RenewalValidator.cs @@ -1,4 +1,5 @@ -using Autofac; +using ACMESharp.Protocol.Resources; +using Autofac; using PKISharp.WACS.Clients.Acme; using PKISharp.WACS.Context; using PKISharp.WACS.DomainObjects; @@ -9,6 +10,7 @@ using PKISharp.WACS.Services; using System; using System.Collections.Generic; using System.Linq; +using System.Security.Policy; using System.Threading.Tasks; namespace PKISharp.WACS @@ -38,7 +40,7 @@ namespace PKISharp.WACS /// <param name="result"></param> /// <param name="runLevel"></param> /// <returns></returns> - public async Task AuthorizeOrder(ExecutionContext context) + public async Task AuthorizeOrder(ExecutionContext context, RunLevel runLevel) { // Sanity check if (context.Order.Details == null) @@ -47,6 +49,22 @@ namespace PKISharp.WACS return; } + // Maybe validation is not needed at all + var orderValid = false; + if (context.Order.Details.Payload.Status == AcmeClient.OrderReady || + context.Order.Details.Payload.Status == AcmeClient.OrderValid) + { + if (!runLevel.HasFlag(RunLevel.Test) && + !runLevel.HasFlag(RunLevel.IgnoreCache)) + { + return; + } + else + { + orderValid = true; + } + } + // Get validation plugin var options = context.Renewal.ValidationPluginOptions; var validationScope = _scopeBuilder.Validation(context.Scope, options); @@ -54,25 +72,23 @@ namespace PKISharp.WACS if (validationPlugin == null) { _log.Error("Validation plugin not found or not created"); - context.Result.AddErrorMessage("Validation plugin not found or not created"); + context.Result.AddErrorMessage("Validation plugin not found or not created", !orderValid); return; } var (disabled, disabledReason) = validationPlugin.Disabled; if (disabled) { _log.Error($"Validation plugin is not available. {disabledReason}"); - context.Result.AddErrorMessage("Validation plugin is not available"); + context.Result.AddErrorMessage("Validation plugin is not available", !orderValid); return; } // Get authorization details var authorizations = context.Order.Details.Payload.Authorizations.ToList(); - var contextParamTasks = authorizations.Select(authorizationUri => GetValidationContextParameters(context, authorizationUri, options)); - var contextParams = (await Task.WhenAll(contextParamTasks)).ToList(); - var missingTarget = contextParams.FirstOrDefault(x => x.TargetPart == null); - if (missingTarget != null) + var contextParamTasks = authorizations.Select(authorizationUri => GetValidationContextParameters(context, authorizationUri, options, orderValid)); + var contextParams = (await Task.WhenAll(contextParamTasks)).OfType<ValidationContextParameters>().ToList(); + if (!context.Result.Success) { - context.Result.AddErrorMessage($"Unable to match challenge {missingTarget.Authorization.Identifier.Value} to target"); return; } @@ -201,18 +217,33 @@ namespace PKISharp.WACS /// <param name="authorizationUri"></param> /// <param name="options"></param> /// <returns></returns> - private async Task<ValidationContextParameters> GetValidationContextParameters(ExecutionContext context, string authorizationUri, ValidationPluginOptions options) + private async Task<ValidationContextParameters?> GetValidationContextParameters(ExecutionContext context, string authorizationUri, ValidationPluginOptions options, bool orderValid) { // Get authorization challenge details from server var client = context.Scope.Resolve<AcmeClient>(); - var authorization = await client.GetAuthorizationDetails(authorizationUri); + var authorization = default(Authorization); + try + { + authorization = await client.GetAuthorizationDetails(authorizationUri); + } + catch + { + context.Result.AddErrorMessage($"Unable to get authorization details from {authorizationUri}", !orderValid); + return null; + } // Find a targetPart that matches the challenge var targetPart = context.Target.Parts. FirstOrDefault(tp => tp.GetHosts(false). Any(h => authorization.Identifier.Value == h.Replace("*.", ""))); - return new ValidationContextParameters(authorization, targetPart, options.ChallengeType, options.Name); + if (targetPart == null) + { + context.Result.AddErrorMessage($"Unable to match challenge {authorization.Identifier.Value} to target", !orderValid); + return null; + } + + return new ValidationContextParameters(authorization, targetPart, options.ChallengeType, options.Name, orderValid); } /// <summary> diff --git a/src/main.test/Mock/MockContainer.cs b/src/main.test/Mock/MockContainer.cs index 1e06ebb..76560ae 100644 --- a/src/main.test/Mock/MockContainer.cs +++ b/src/main.test/Mock/MockContainer.cs @@ -57,6 +57,7 @@ namespace PKISharp.WACS.UnitTests.Mock _ = builder.RegisterType<mock.CertificateService>().As<real.ICertificateService>().SingleInstance(); _ = builder.RegisterType<real.TaskSchedulerService>().SingleInstance(); _ = builder.RegisterType<real.NotificationService>().SingleInstance(); + _ = builder.RegisterType<RenewalValidator>().SingleInstance(); _ = builder.RegisterType<RenewalExecutor>().SingleInstance(); _ = builder.RegisterType<RenewalManager>().SingleInstance(); _ = builder.Register(c => c.Resolve<real.IArgumentsService>().MainArguments).SingleInstance(); diff --git a/src/main.test/Tests/RenewalTests/RenewalServiceTests.cs b/src/main.test/Tests/RenewalTests/RenewalServiceTests.cs index 82b805a..6c17610 100644 --- a/src/main.test/Tests/RenewalTests/RenewalServiceTests.cs +++ b/src/main.test/Tests/RenewalTests/RenewalServiceTests.cs @@ -22,8 +22,11 @@ namespace PKISharp.WACS.UnitTests.Tests.RenewalTests { var container = new MockContainer().TestScope(); var renewalStore = container.Resolve<real.IRenewalStore>(); + var renewalValidator = container.Resolve<RenewalValidator>( + new TypedParameter(typeof(IContainer), container)); var renewalExecutor = container.Resolve<RenewalExecutor>( - new TypedParameter(typeof(IContainer), container)); + new TypedParameter(typeof(RenewalValidator), renewalValidator), + new TypedParameter(typeof(IContainer), container)); var renewalManager = container.Resolve<RenewalManager>( new TypedParameter(typeof(IContainer), container), new TypedParameter(typeof(RenewalExecutor), renewalExecutor)); |