Exemple #1
0
 /// <summary>
 /// Process a single renewal
 /// </summary>
 /// <param name="renewal"></param>
 private static void ProcessRenewal(ScheduledRenewal renewal)
 {
     _log.Information(true, "Renewing certificate for {renewal}", renewal.Binding.Host);
     try
     {
         // Let the plugin run
         var result = Renew(renewal, RunLevel.Unattended);
         _renewalService.Save(renewal, result);
     }
     catch (Exception ex)
     {
         HandleException(ex);
         _log.Error("Renewal for {host} failed, will retry on next run", renewal.Binding.Host);
     }
 }
Exemple #2
0
        internal static ILifetimeScope Renewal(IContainer main, ScheduledRenewal renewal, RunLevel runLevel, int type = 0)
        {
            IResolver resolver = null;

            if (runLevel > RunLevel.Unattended)
            {
                resolver = main.Resolve <InteractiveResolver>(
                    new TypedParameter(typeof(ScheduledRenewal), renewal),
                    new TypedParameter(typeof(RunLevel), runLevel)
                    ,
                    new TypedParameter(typeof(int), type));
            }
            else
            {
                resolver = main.Resolve <UnattendedResolver>(new TypedParameter(typeof(ScheduledRenewal), renewal));
            }
            return(main.BeginLifetimeScope(builder =>
            {
                builder.RegisterType <AcmeClientWrapper>().SingleInstance();
                builder.RegisterType <CertificateService>().SingleInstance();

                builder.RegisterInstance(resolver);
                if (renewal != null)
                {
                    builder.RegisterInstance(renewal);
                }
                builder.Register(c => runLevel).As <RunLevel>();

                builder.RegisterType <TaskSchedulerService>().
                WithParameter(new TypedParameter(typeof(RunLevel), runLevel)).
                SingleInstance();

                builder.Register(c => resolver.GetTargetPlugin(main)).As <ITargetPluginFactory>().SingleInstance();
                builder.Register(c => resolver.GetInstallationPlugins(main)).As <List <IInstallationPluginFactory> >().SingleInstance();
                builder.Register(c => resolver.GetValidationPlugin(main)).As <IValidationPluginFactory>().SingleInstance();
                builder.Register(c => resolver.GetStorePlugin(main)).As <IStorePluginFactory>().SingleInstance();

                builder.Register(c => c.Resolve(c.Resolve <ITargetPluginFactory>().Instance)).As <ITargetPlugin>().SingleInstance();
                builder.Register(c => c.Resolve(c.Resolve <IStorePluginFactory>().Instance)).As <IStorePlugin>().SingleInstance();
            }));
        }
Exemple #3
0
        /// <summary>
        /// If renewal is already Scheduled, replace it with the new options
        /// </summary>
        /// <param name="target"></param>
        /// <returns></returns>
        private static ScheduledRenewal CreateRenewal(ScheduledRenewal temp)
        {
            var renewal = _renewalService.Find(temp.Binding);

            if (renewal == null)
            {
                renewal = temp;
            }
            else
            {
                renewal.New = true;
            }
            renewal.Test             = temp.Test;
            renewal.Binding          = temp.Binding;
            renewal.CentralSslStore  = temp.CentralSslStore;
            renewal.KeepExisting     = temp.KeepExisting;
            renewal.Script           = temp.Script;
            renewal.ScriptParameters = temp.ScriptParameters;
            renewal.Warmup           = temp.Warmup;
            return(renewal);
        }
Exemple #4
0
        private static RenewResult Renew(ILifetimeScope renewalScope, ScheduledRenewal renewal)
        {
            var targetPlugin = renewalScope.Resolve <ITargetPlugin>();

            renewal.Binding = targetPlugin.Refresh(renewal.Binding);
            if (renewal.Binding == null)
            {
                _log.Error("Renewal target not found");
                return(new RenewResult(new Exception("Renewal target not found")));
            }
            var split = targetPlugin.Split(renewal.Binding);

            renewal.Binding.AlternativeNames = split.SelectMany(s => s.AlternativeNames).ToList();
            foreach (var target in split)
            {
                var auth = Authorize(renewalScope, target);
                if (auth.Status != _authorizationValid)
                {
                    return(OnRenewFail(auth));
                }
            }
            return(OnRenewSuccess(renewalScope, renewal));
        }
Exemple #5
0
        /// <summary>
        /// Steps to take on succesful (re)authorization
        /// </summary>
        /// <param name="target"></param>
        private static RenewResult OnRenewSuccess(ILifetimeScope renewalScope, ScheduledRenewal renewal)
        {
            RenewResult result = null;

            try
            {
                var certificateService = renewalScope.Resolve <CertificateService>();
                var storePlugin        = renewalScope.Resolve <IStorePlugin>();
                var oldCertificate     = renewal.Certificate(storePlugin);
                var newCertificate     = certificateService.RequestCertificate(renewal.Binding);

                // Test if a new certificate has been generated
                if (newCertificate == null)
                {
                    return(new RenewResult(new Exception("No certificate generated")));
                }
                else
                {
                    result = new RenewResult(newCertificate);
                }

                // Early escape for testing validation only
                if (_options.Test &&
                    renewal.New &&
                    !_input.PromptYesNo($"[--test] Do you want to install the certificate?"))
                {
                    return(result);
                }

                try
                {
                    // Check if the newly requested certificate is already in the store,
                    // which might be the case due to the cache mechanism built into the
                    // RequestCertificate function
                    var storedCertificate = storePlugin.FindByThumbprint(newCertificate.Certificate.Thumbprint);
                    if (storedCertificate != null)
                    {
                        // Copy relevant properties
                        _log.Warning("Certificate with thumbprint {thumbprint} is already in the store", newCertificate.Certificate.Thumbprint);
                        newCertificate.Store = storedCertificate.Store;
                    }
                    else
                    {
                        // Save to store
                        storePlugin.Save(newCertificate);
                    }
                }
                catch (Exception ex)
                {
                    _log.Error(ex, "Unable to store certificate");
                    result.Success      = false;
                    result.ErrorMessage = $"Store failed: {ex.Message}";
                    return(result);
                }

                // Run installation plugin(s)
                try
                {
                    var installFactories = renewalScope.Resolve <List <IInstallationPluginFactory> >();
                    var steps            = installFactories.Count();
                    for (var i = 0; i < steps; i++)
                    {
                        var installFactory = installFactories[i];
                        if (!(installFactory is INull))
                        {
                            var installInstance = (IInstallationPlugin)renewalScope.Resolve(installFactory.Instance);
                            if (steps > 1)
                            {
                                _log.Information("Installation step {n}/{m}: {name}...", i + 1, steps, installFactory.Name);
                            }
                            else
                            {
                                _log.Information("Installing with {name}...", installFactory.Name);
                            }
                            installInstance.Install(newCertificate, oldCertificate);
                        }
                    }
                }
                catch (Exception ex)
                {
                    _log.Error(ex, "Unable to install certificate");
                    result.Success      = false;
                    result.ErrorMessage = $"Install failed: {ex.Message}";
                }

                // Delete the old certificate if not forbidden, found and not re-used
                if ((!renewal.KeepExisting ?? false) &&
                    oldCertificate != null &&
                    newCertificate.Certificate.Thumbprint != oldCertificate.Certificate.Thumbprint)
                {
                    try
                    {
                        storePlugin.Delete(oldCertificate);
                    }
                    catch (Exception ex)
                    {
                        _log.Error(ex, "Unable to delete previous certificate");
                        //result.Success = false; // not a show-stopper, consider the renewal a success
                        result.ErrorMessage = $"Delete failed: {ex.Message}";
                    }
                }

                // Add or update renewal
                if ((renewal.New || renewal.Updated) &&
                    !_options.NoTaskScheduler &&
                    (!_options.Test ||
                     _input.PromptYesNo($"[--test] Do you want to automatically renew this certificate?")))
                {
                    var taskScheduler = renewalScope.Resolve <TaskSchedulerService>();
                    taskScheduler.EnsureTaskScheduler();
                    _renewalService.Save(renewal, result);
                }

                // Save renewal to store
                return(result);
            }
            catch (Exception ex)
            {
                // Result might still contain the Thumbprint of the certificate
                // that was requested and (partially? installed, which might help
                // with debugging
                HandleException(ex);
                if (result == null)
                {
                    result = new RenewResult(ex);
                }
                else
                {
                    result.Success      = false;
                    result.ErrorMessage = ex.Message;
                }
            }
            return(result);
        }