private bool ShouldRun(ILifetimeScope target, IEnumerable <Order> orders, Renewal renewal, RunLevel runLevel) { // Check if renewal is needed if (!runLevel.HasFlag(RunLevel.ForceRenew) && !renewal.Updated) { _log.Verbose("Checking {renewal}", renewal.LastFriendlyName); if (!renewal.IsDue()) { var cs = target.Resolve <ICertificateService>(); var abort = true; foreach (var order in orders) { var cache = cs.CachedInfo(order); if (cache == null && !renewal.New) { _log.Information(LogType.All, "Renewal {renewal} running prematurely due to source change", renewal.LastFriendlyName); abort = false; break; } } if (abort) { _log.Information("Renewal {renewal} is due after {date}", renewal.LastFriendlyName, renewal.GetDueDate()); return(false); } } else if (!renewal.New) { _log.Information(LogType.All, "Renewing certificate {renewal}", renewal.LastFriendlyName); } } else if (runLevel.HasFlag(RunLevel.ForceRenew)) { _log.Information(LogType.All, "Force renewing certificate {renewal}", renewal.LastFriendlyName); } return(true); }
/// <summary> /// Determine if the renewal should be executes /// </summary> /// <param name="renewal"></param> /// <param name="runLevel"></param> /// <returns></returns> public async Task <RenewResult> HandleRenewal(Renewal renewal, RunLevel runLevel) { _input.CreateSpace(); _log.Reset(); using var ts = _scopeBuilder.Target(_container, renewal, runLevel); using var es = _scopeBuilder.Execution(ts, renewal, runLevel); // Generate the target var targetPlugin = es.Resolve <ITargetPlugin>(); var(disabled, disabledReason) = targetPlugin.Disabled; if (disabled) { return(new RenewResult($"Target plugin is not available. {disabledReason}")); } var target = await targetPlugin.Generate(); if (target is INull) { return(new RenewResult($"Target plugin did not generate a target")); } if (!target.IsValid(_log)) { return(new RenewResult($"Target plugin generated an invalid target")); } // Check if our validation plugin is (still) up to the task var validationPlugin = es.Resolve <IValidationPluginOptionsFactory>(); if (!validationPlugin.CanValidate(target)) { return(new RenewResult($"Validation plugin is unable to validate the target. A wildcard host was introduced into a HTTP validated renewal.")); } // Create one or more orders based on the target var orderPlugin = es.Resolve <IOrderPlugin>(); var orders = orderPlugin.Split(renewal, target); if (orders == null || orders.Count() == 0) { return(new RenewResult("Order plugin failed to create order(s)")); } _log.Verbose("Targeted convert into {n} order(s)", orders.Count()); // Check if renewal is needed if (!runLevel.HasFlag(RunLevel.ForceRenew) && !renewal.Updated) { _log.Verbose("Checking {renewal}", renewal.LastFriendlyName); if (!renewal.IsDue()) { var cs = es.Resolve <ICertificateService>(); var abort = true; foreach (var order in orders) { var cache = cs.CachedInfo(order); if (cache == null && !renewal.New) { _log.Information(LogType.All, "Renewal for {renewal} running prematurely due to detected target change", renewal.LastFriendlyName); abort = false; break; } } if (abort) { _log.Information("Renewal for {renewal} is due after {date}", renewal.LastFriendlyName, renewal.GetDueDate()); return(new RenewResult() { Abort = true }); } } else if (!renewal.New) { _log.Information(LogType.All, "Renewing certificate for {renewal}", renewal.LastFriendlyName); } } else if (runLevel.HasFlag(RunLevel.ForceRenew)) { _log.Information(LogType.All, "Force renewing certificate for {renewal}", renewal.LastFriendlyName); } // If at this point we haven't retured already with an error/abort // actually execute the renewal var result = await ExecuteRenewal(es, orders.ToList(), runLevel); // Configure task scheduler if (result.Success && !result.Abort) { if ((renewal.New || renewal.Updated) && !_args.NoTaskScheduler) { if (runLevel.HasFlag(RunLevel.Test) && !await _input.PromptYesNo($"[--test] Do you want to automatically renew with these settings?", true)) { // Early out for test runs result.Abort = true; return(result); } else { // Make sure the Task Scheduler is configured await es.Resolve <TaskSchedulerService>().EnsureTaskScheduler(runLevel, false); } } } return(result); }
public async Task <RenewResult> Renew(Renewal renewal, RunLevel runLevel) { using var ts = _scopeBuilder.Target(_container, renewal, runLevel); using var es = _scopeBuilder.Execution(ts, renewal, runLevel); // Generate the target var targetPlugin = es.Resolve <ITargetPlugin>(); if (targetPlugin.Disabled) { throw new Exception($"Target plugin is not available to the current user, try running as administrator"); } var target = await targetPlugin.Generate(); if (target == null) { throw new Exception($"Target plugin did not generate a target"); } if (!target.IsValid(_log)) { throw new Exception($"Target plugin generated an invalid target"); } // Check if our validation plugin is (still) up to the task var validationPlugin = es.Resolve <IValidationPluginOptionsFactory>(); if (!validationPlugin.CanValidate(target)) { throw new Exception($"Validation plugin is unable to validate the target. A wildcard host was introduced into a HTTP validated renewal."); } // Check if renewal is needed if (!runLevel.HasFlag(RunLevel.ForceRenew) && !renewal.Updated) { _log.Verbose("Checking {renewal}", renewal.LastFriendlyName); if (!renewal.IsDue()) { var cs = es.Resolve <ICertificateService>(); var cache = cs.CachedInfo(renewal); if (cache != null && cache.Match(target)) { _log.Information(LogType.All, "Renewal for {renewal} is due after {date}", renewal.LastFriendlyName, renewal.GetDueDate()); return(null); } else if (!renewal.New) { _log.Information(LogType.All, "Renewal for {renewal} running prematurely due to detected target change", renewal.LastFriendlyName); } } else if (!renewal.New) { _log.Information(LogType.All, "Renewing certificate for {renewal}", renewal.LastFriendlyName); } } else if (runLevel.HasFlag(RunLevel.ForceRenew)) { _log.Information(LogType.All, "Force renewing certificate for {renewal}", renewal.LastFriendlyName); } // Create the order var client = es.Resolve <AcmeClient>(); var identifiers = target.GetHosts(false); var order = await client.CreateOrder(identifiers); // Check if the order is valid if (order.Payload.Status != AcmeClient.OrderReady && order.Payload.Status != AcmeClient.OrderPending) { return(OnRenewFail(new Challenge() { Error = order.Payload.Error })); } // Answer the challenges foreach (var authUrl in order.Payload.Authorizations) { // Get authorization details var authorization = await client.GetAuthorizationDetails(authUrl); // Find a targetPart that matches the challenge var targetPart = target.Parts. FirstOrDefault(tp => tp.GetHosts(false). Any(h => authorization.Identifier.Value == h.Replace("*.", ""))); if (targetPart == null) { return(OnRenewFail(new Challenge() { Error = "Unable to match challenge to target" })); } // Run the validation plugin var challenge = await Authorize(es, runLevel, renewal.ValidationPluginOptions, targetPart, authorization); if (challenge.Status != AcmeClient.AuthorizationValid) { return(OnRenewFail(challenge)); } } return(await OnValidationSuccess(es, renewal, target, order, runLevel)); }