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