/// <summary> /// Setup a new scheduled renewal /// </summary> /// <param name="runLevel"></param> private void CreateNewCertificate(RunLevel runLevel) { if (_args.Test) { runLevel |= RunLevel.Test; } _log.Information(true, "Running in mode: {runLevel}", runLevel); var tempRenewal = Renewal.Create(_passwordGenerator); using (var configScope = _scopeBuilder.Configuration(_container, tempRenewal, runLevel)) { // Choose target plugin var targetPluginOptionsFactory = configScope.Resolve <ITargetPluginOptionsFactory>(); if (targetPluginOptionsFactory is INull) { HandleException(message: $"No target plugin could be selected"); return; } var targetPluginOptions = runLevel.HasFlag(RunLevel.Unattended) ? targetPluginOptionsFactory.Default(_arguments) : targetPluginOptionsFactory.Aquire(_arguments, _input, runLevel); if (targetPluginOptions == null) { HandleException(message: $"Target plugin {targetPluginOptionsFactory.Name} aborted or failed"); return; } tempRenewal.TargetPluginOptions = targetPluginOptions; // Generate Target and validation plugin choice Target initialTarget = null; IValidationPluginOptionsFactory validationPluginOptionsFactory = null; using (var targetScope = _scopeBuilder.Target(_container, tempRenewal, runLevel)) { initialTarget = targetScope.Resolve <Target>(); if (initialTarget == null) { HandleException(message: $"Target plugin {targetPluginOptionsFactory.Name} was unable to generate a target"); return; } if (!initialTarget.IsValid(_log)) { HandleException(message: $"Target plugin {targetPluginOptionsFactory.Name} generated an invalid target"); return; } _log.Information("Target generated using plugin {name}: {target}", targetPluginOptions.Name, initialTarget); // Choose FriendlyName if (runLevel.HasFlag(RunLevel.Advanced) && runLevel.HasFlag(RunLevel.Interactive) && string.IsNullOrEmpty(_args.FriendlyName)) { var alt = _input.RequestString($"Suggested FriendlyName is '{initialTarget.FriendlyName}', press enter to accept or type an alternative"); if (!string.IsNullOrEmpty(alt)) { tempRenewal.FriendlyName = alt; } } tempRenewal.LastFriendlyName = initialTarget.FriendlyName; // Choose validation plugin validationPluginOptionsFactory = targetScope.Resolve <IValidationPluginOptionsFactory>(); if (validationPluginOptionsFactory is INull) { HandleException(message: $"No validation plugin could be selected"); return; } } // Configure validation try { ValidationPluginOptions validationOptions = null; if (runLevel.HasFlag(RunLevel.Unattended)) { validationOptions = validationPluginOptionsFactory.Default(initialTarget, _arguments); } else { validationOptions = validationPluginOptionsFactory.Aquire(initialTarget, _arguments, _input, runLevel); } if (validationOptions == null) { HandleException(message: $"Validation plugin {validationPluginOptionsFactory.Name} was unable to generate options"); return; } tempRenewal.ValidationPluginOptions = validationOptions; } catch (Exception ex) { HandleException(ex, $"Validation plugin {validationPluginOptionsFactory.Name} aborted or failed"); return; } // Choose CSR plugin var csrPluginOptionsFactory = configScope.Resolve <ICsrPluginOptionsFactory>(); if (csrPluginOptionsFactory is INull) { HandleException(message: $"No CSR plugin could be selected"); return; } // Configure CSR try { CsrPluginOptions csrOptions = null; if (runLevel.HasFlag(RunLevel.Unattended)) { csrOptions = csrPluginOptionsFactory.Default(_arguments); } else { csrOptions = csrPluginOptionsFactory.Aquire(_arguments, _input, runLevel); } if (csrOptions == null) { HandleException(message: $"CSR plugin {csrPluginOptionsFactory.Name} was unable to generate options"); return; } tempRenewal.CsrPluginOptions = csrOptions; } catch (Exception ex) { HandleException(ex, $"CSR plugin {csrPluginOptionsFactory.Name} aborted or failed"); return; } // Choose store plugin var storePluginOptionsFactory = configScope.Resolve <IStorePluginOptionsFactory>(); if (storePluginOptionsFactory is INull) { HandleException(message: $"No store plugin could be selected"); return; } // Configure storage try { StorePluginOptions storeOptions = null; if (runLevel.HasFlag(RunLevel.Unattended)) { storeOptions = storePluginOptionsFactory.Default(_arguments); } else { storeOptions = storePluginOptionsFactory.Aquire(_arguments, _input, runLevel); } if (storeOptions == null) { HandleException(message: $"Store plugin {storePluginOptionsFactory.Name} was unable to generate options"); return; } tempRenewal.StorePluginOptions = storeOptions; } catch (Exception ex) { HandleException(ex, $"Store plugin {storePluginOptionsFactory.Name} aborted or failed"); return; } // Choose and configure installation plugins try { var installationPluginOptionsFactories = configScope.Resolve <List <IInstallationPluginOptionsFactory> >( new TypedParameter(typeof(IStorePlugin), storePluginOptionsFactory.Name) ); if (installationPluginOptionsFactories.Count() == 0) { // User cancelled, otherwise we would at least have the Null-installer HandleException(message: $"User aborted"); return; } foreach (var installationPluginOptionsFactory in installationPluginOptionsFactories) { InstallationPluginOptions installOptions; try { if (runLevel.HasFlag(RunLevel.Unattended)) { installOptions = installationPluginOptionsFactory.Default(initialTarget, _arguments); } else { installOptions = installationPluginOptionsFactory.Aquire(initialTarget, _arguments, _input, runLevel); } } catch (Exception ex) { HandleException(ex, $"Install plugin {installationPluginOptionsFactory.Name} aborted or failed"); return; } if (installOptions == null) { HandleException(message: $"Installation plugin {installationPluginOptionsFactory.Name} was unable to generate options"); return; } tempRenewal.InstallationPluginOptions.Add(installOptions); } } catch (Exception ex) { HandleException(ex, "Invalid selection of installation plugins"); return; } // Try to run for the first time var renewal = CreateRenewal(tempRenewal, runLevel); var result = Renew(renewal, runLevel); if (!result.Success) { HandleException(message: $"Create certificate failed: {result.ErrorMessage}"); } else { _renewalService.Save(renewal, result); } } }
/// <summary> /// Steps to take on succesful (re)authorization /// </summary> /// <param name="target"></param> private RenewResult OnRenewSuccess(ILifetimeScope renewalScope, Renewal renewal, Target target, OrderDetails order, RunLevel runLevel) { RenewResult result = null; try { var certificateService = renewalScope.Resolve <CertificateService>(); var storePlugin = renewalScope.Resolve <IStorePlugin>(); var csrPlugin = renewalScope.Resolve <ICsrPlugin>(); var oldCertificate = certificateService.CachedInfo(renewal); var newCertificate = certificateService.RequestCertificate(csrPlugin, renewal, target, order); // Test if a new certificate has been generated if (newCertificate == null) { return(new RenewResult("No certificate generated")); } else { result = new RenewResult(newCertificate); } // Early escape for testing validation only if (renewal.New && runLevel.HasFlag(RunLevel.Test) && !_input.PromptYesNo($"[--test] Do you want to install the certificate?")) { return(new RenewResult("User aborted")); } try { 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 steps = renewal.InstallationPluginOptions.Count(); for (var i = 0; i < steps; i++) { var installOptions = renewal.InstallationPluginOptions[i]; var installPlugin = (IInstallationPlugin)renewalScope.Resolve(installOptions.Instance); if (!(installPlugin is INull)) { if (steps > 1) { _log.Information("Installation step {n}/{m}: {name}...", i + 1, steps, installOptions.Name); } else { _log.Information("Installing with {name}...", installOptions.Name); } installPlugin.Install(storePlugin, 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.StorePluginOptions.KeepExisting && 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}"; } } if (renewal.New && !_args.NoTaskScheduler) { if (runLevel.HasFlag(RunLevel.Test) && !_input.PromptYesNo($"[--test] Do you want to automatically renew this certificate?")) { // Early out for test runs return(new RenewResult("User aborted")); } else { // Make sure the Task Scheduler is configured renewalScope.Resolve <TaskSchedulerService>().EnsureTaskScheduler(); } } return(result); } catch (Exception ex) { HandleException(ex); // Result might still contain the Thumbprint of the certificate // that was requested and (partially? installed, which might help // with debugging if (result == null) { result = new RenewResult(ex.Message); } else { result.Success = false; result.ErrorMessage = ex.Message; } } return(result); }
/// <summary> /// Steps to take on succesful (re)authorization /// </summary> /// <param name="target"></param> private async Task <RenewResult> OnValidationSuccess(ILifetimeScope renewalScope, Renewal renewal, Target target, OrderDetails order, RunLevel runLevel) { RenewResult?result = null; try { var certificateService = renewalScope.Resolve <ICertificateService>(); var csrPlugin = target.CsrBytes == null?renewalScope.Resolve <ICsrPlugin>() : null; if (csrPlugin != null && csrPlugin.Disabled.Item1) { return(new RenewResult($"CSR plugin is not available. {csrPlugin.Disabled.Item2}")); } var oldCertificate = certificateService.CachedInfo(renewal); var newCertificate = await certificateService.RequestCertificate(csrPlugin, runLevel, renewal, target, order); // Test if a new certificate has been generated if (newCertificate == null) { return(new RenewResult("No certificate generated")); } else { result = new RenewResult(newCertificate); } // Early escape for testing validation only if (renewal.New && runLevel.HasFlag(RunLevel.Test) && !await _input.PromptYesNo($"[--test] Do you want to install the certificate?", true)) { return(new RenewResult("User aborted")); } // Run store plugin(s) var storePluginOptions = new List <StorePluginOptions>(); var storePlugins = new List <IStorePlugin>(); try { var steps = renewal.StorePluginOptions.Count(); for (var i = 0; i < steps; i++) { var storeOptions = renewal.StorePluginOptions[i]; var storePlugin = (IStorePlugin)renewalScope.Resolve(storeOptions.Instance); if (!(storePlugin is INull)) { if (steps > 1) { _log.Information("Store step {n}/{m}: {name}...", i + 1, steps, storeOptions.Name); } else { _log.Information("Store with {name}...", storeOptions.Name); } if (storePlugin.Disabled.Item1) { return(new RenewResult($"Store plugin is not available. {storePlugin.Disabled.Item2}")); } await storePlugin.Save(newCertificate); storePlugins.Add(storePlugin); storePluginOptions.Add(storeOptions); } } } catch (Exception ex) { var reason = _exceptionHandler.HandleException(ex, "Unable to store certificate"); result.ErrorMessage = $"Store failed: {reason}"; result.Success = false; return(result); } // Run installation plugin(s) try { var steps = renewal.InstallationPluginOptions.Count(); for (var i = 0; i < steps; i++) { var installOptions = renewal.InstallationPluginOptions[i]; var installPlugin = (IInstallationPlugin)renewalScope.Resolve( installOptions.Instance, new TypedParameter(installOptions.GetType(), installOptions)); if (!(installPlugin is INull)) { if (steps > 1) { _log.Information("Installation step {n}/{m}: {name}...", i + 1, steps, installOptions.Name); } else { _log.Information("Installing with {name}...", installOptions.Name); } if (installPlugin.Disabled.Item1) { return(new RenewResult($"Installation plugin is not available. {installPlugin.Disabled.Item2}")); } await installPlugin.Install(storePlugins, newCertificate, oldCertificate); } } } catch (Exception ex) { var reason = _exceptionHandler.HandleException(ex, "Unable to install certificate"); result.Success = false; result.ErrorMessage = $"Install failed: {reason}"; } // Delete the old certificate if not forbidden, found and not re-used for (var i = 0; i < storePluginOptions.Count; i++) { if (!storePluginOptions[i].KeepExisting && oldCertificate != null && newCertificate.Certificate.Thumbprint != oldCertificate.Certificate.Thumbprint) { try { await storePlugins[i].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}"; } } } if ((renewal.New || renewal.Updated) && !_args.NoTaskScheduler) { if (runLevel.HasFlag(RunLevel.Test) && !await _input.PromptYesNo($"[--test] Do you want to automatically renew this certificate?", true)) { // Early out for test runs return(new RenewResult("User aborted")); } else { // Make sure the Task Scheduler is configured await renewalScope.Resolve <TaskSchedulerService>().EnsureTaskScheduler(runLevel, false); } } return(result); } catch (Exception ex) { _exceptionHandler.HandleException(ex); while (ex.InnerException != null) { ex = ex.InnerException; } // Result might still contain the Thumbprint of the certificate // that was requested and (partially? installed, which might help // with debugging if (result == null) { result = new RenewResult(ex.Message); } else { result.Success = false; result.ErrorMessage = ex.Message; } } return(result); }