/// <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); } }
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(); })); }
/// <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); }
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)); }
/// <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); }