Exemple #1
0
 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);
 }
Exemple #2
0
        /// <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);
        }
Exemple #3
0
        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));
        }