public virtual bool SupportsRunLevel(RunLevel runLevel)
		{
			foreach (var attribute in attributes)
			{
				foreach (string s in attribute.RunLevels)
				{
					if (AnyRunLevel.Default.Equals(s) || runLevel.Equals(s))
					{
						return true;
					}
				}
			}

			return false;
		}
예제 #2
0
        public async Task <RenewResult?> Execute(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>();

            var(disabled, disabledReason) = targetPlugin.Disabled;
            if (disabled)
            {
                throw new Exception($"Target plugin is not available. {disabledReason}");
            }
            var target = await targetPlugin.Generate();

            if (target is INull)
            {
                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, target);
                    if (cache != null)
                    {
                        _log.Information("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 orderManager = es.Resolve <OrderManager>();
            var order        = await orderManager.GetOrCreate(renewal, target, runLevel);

            if (order == null)
            {
                return(OnRenewFail(new Challenge()
                {
                    Error = "Unable to create order"
                }));
            }

            // Answer the challenges
            var client = es.Resolve <AcmeClient>();

            foreach (var authUrl in order.Payload.Authorizations)
            {
                // Get authorization details
                _log.Verbose("Handle authorization {n}/{m}",
                             order.Payload.Authorizations.ToList().IndexOf(authUrl) + 1,
                             order.Payload.Authorizations.Length + 1);

                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));
        }
예제 #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)
                {
                    var(disabled, disabledReason) = csrPlugin.Disabled;
                    if (disabled)
                    {
                        return(new RenewResult($"CSR plugin is not available. {disabledReason}"));
                    }
                }
                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(null);
                }

                // 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);
                            }
                            var(disabled, disabledReason) = storePlugin.Disabled;
                            if (disabled)
                            {
                                return(new RenewResult($"Store plugin is not available. {disabledReason}"));
                            }
                            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);
                            }
                            var(disabled, disabledReason) = installPlugin.Disabled;
                            if (disabled)
                            {
                                return(new RenewResult($"Installation plugin is not available. {disabledReason}"));
                            }
                            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(null);
                    }
                    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);
        }
예제 #4
0
        public override FileSystemOptions Aquire(Target target, IArgumentsService arguments, IInputService inputService, RunLevel runLevel)
        {
            // Choose alternative site for validation
            var ret = new FileSystemOptions(BaseAquire(target, arguments, inputService, runLevel));

            if (target.IIS && _iisClient.HasWebSites && string.IsNullOrEmpty(ret.Path))
            {
                if (inputService.PromptYesNo("Use different site for validation?", false))
                {
                    var site = inputService.ChooseFromList("Validation site, must receive requests for all hosts on port 80",
                                                           _iisClient.WebSites,
                                                           x => Choice.Create(x, x.Name, x.Id.ToString()),
                                                           "Automatic (target site)");
                    if (site != null)
                    {
                        ret.Path   = site.Path;
                        ret.SiteId = site.Id;
                    }
                }
            }
            return(ret);
        }
예제 #5
0
파일: IISSites.cs 프로젝트: zyjia/win-acme
        Target ITargetPlugin.Aquire(IOptionsService optionsService, IInputService inputService, RunLevel runLevel)
        {
            var targets = GetSites(optionsService.Options.HideHttps, true).Where(x => x.Hidden == false).ToList();

            inputService.WritePagedList(targets.Select(x => Choice.Create(x, $"{x.Host} ({x.AlternativeNames.Count()} bindings) [@{x.WebRootPath}]", x.TargetSiteId.ToString())).ToList());
            var sanInput    = inputService.RequestString("Enter a comma separated list of site IDs, or 'S' to run for all sites").ToLower().Trim();
            var totalTarget = GetCombinedTarget(targets, sanInput);

            inputService.WritePagedList(totalTarget.AlternativeNames.Select(x => Choice.Create(x, "")));
            totalTarget.ExcludeBindings = inputService.RequestString("Press enter to include all listed hosts, or type a comma-separated lists of exclusions");
            if (runLevel >= RunLevel.Advanced)
            {
                totalTarget.AskForCommonNameChoice(inputService);
            }
            return(totalTarget);
        }
예제 #6
0
        /// <summary>
        /// For renewal and creating scheduled task
        /// </summary>
        /// <param name="target"></param>
        /// <param name="renewal"></param>
        /// <param name="runLevel"></param>
        /// <returns></returns>
        public ILifetimeScope Execution(ILifetimeScope target, Renewal renewal, RunLevel runLevel)
        {
            return(target.BeginLifetimeScope(builder =>
            {
                builder.Register(c => runLevel).As <RunLevel>();
                builder.RegisterType <FindPrivateKey>().SingleInstance();

                // Used to configure TaskScheduler without renewal
                if (renewal != null)
                {
                    builder.RegisterInstance(renewal);

                    builder.RegisterInstance(renewal.StorePluginOptions).As(renewal.StorePluginOptions.GetType());
                    if (renewal.CsrPluginOptions != null)
                    {
                        builder.RegisterInstance(renewal.CsrPluginOptions).As(renewal.CsrPluginOptions.GetType());
                    }
                    if (renewal.OrderPluginOptions != null)
                    {
                        builder.RegisterInstance(renewal.OrderPluginOptions).As(renewal.OrderPluginOptions.GetType());
                    }
                    builder.RegisterInstance(renewal.ValidationPluginOptions).As(renewal.ValidationPluginOptions.GetType());
                    builder.RegisterInstance(renewal.TargetPluginOptions).As(renewal.TargetPluginOptions.GetType());

                    // Find factory based on options
                    builder.Register(x =>
                    {
                        var plugin = x.Resolve <IPluginService>();
                        var match = plugin.GetFactories <IValidationPluginOptionsFactory>(target).First(vp => vp.OptionsType.PluginId() == renewal.ValidationPluginOptions.Plugin);
                        if (match == null)
                        {
                            return new NullValidationFactory();
                        }
                        return match;
                    }).As <IValidationPluginOptionsFactory>().SingleInstance();

                    if (renewal.CsrPluginOptions != null)
                    {
                        builder.RegisterType(renewal.CsrPluginOptions.Instance).As <ICsrPlugin>().SingleInstance();
                    }
                    if (renewal.OrderPluginOptions != null)
                    {
                        builder.RegisterType(renewal.OrderPluginOptions.Instance).As <IOrderPlugin>().SingleInstance();
                    }
                    else
                    {
                        builder.RegisterType <Plugins.OrderPlugins.Single>().As <IOrderPlugin>().SingleInstance();
                    }
                    builder.RegisterType(renewal.ValidationPluginOptions.Instance).As <IValidationPlugin>().SingleInstance();
                    builder.RegisterType(renewal.TargetPluginOptions.Instance).As <ITargetPlugin>().SingleInstance();
                    foreach (var i in renewal.InstallationPluginOptions)
                    {
                        builder.RegisterInstance(i).As(i.GetType());
                    }
                    foreach (var i in renewal.StorePluginOptions)
                    {
                        builder.RegisterInstance(i).As(i.GetType());
                    }
                }
            }));
        }
예제 #7
0
        public override async Task <AcmeOptions?> Aquire(Target target, IInputService input, RunLevel runLevel)
        {
            var ret = new AcmeOptions();
            Uri?uri = null;

            while (ret.BaseUri == null)
            {
                try
                {
                    var userInput = await input.RequestString("URL of the acme-dns server");

                    uri         = new Uri(userInput);
                    ret.BaseUri = uri.ToString();
                }
                catch { }
            }
            if (uri == null)
            {
                return(null);
            }
            var acmeDnsClient = new AcmeDnsClient(_dnsClient, _proxy, _log, _settings, input, uri);
            var identifiers   = target.Parts.SelectMany(x => x.Identifiers).Distinct();

            foreach (var identifier in identifiers)
            {
                var registrationResult = await acmeDnsClient.EnsureRegistration(identifier.Replace("*.", ""), true);

                if (!registrationResult)
                {
                    return(null);
                }
            }
            return(ret);
        }
예제 #8
0
        /// <summary>
        /// Request certificate from the ACME server
        /// </summary>
        /// <param name="csrPlugin">Plugin used to generate CSR if it has not been provided in the target</param>
        /// <param name="runLevel"></param>
        /// <param name="renewal"></param>
        /// <param name="target"></param>
        /// <param name="order"></param>
        /// <returns></returns>
        public async Task <CertificateInfo> RequestCertificate(
            ICsrPlugin?csrPlugin,
            RunLevel runLevel,
            Renewal renewal,
            Target target,
            OrderDetails order)
        {
            // What are we going to get?
            var cacheKey    = CacheKey(renewal, target);
            var pfxFileInfo = new FileInfo(GetPath(renewal, $"-{cacheKey}{PfxPostFix}"));

            // Determine/check the common name
            var identifiers     = target.GetHosts(false);
            var commonNameUni   = target.CommonName;
            var commonNameAscii = string.Empty;

            if (!string.IsNullOrWhiteSpace(commonNameUni))
            {
                var idn = new IdnMapping();
                commonNameAscii = idn.GetAscii(commonNameUni);
                if (!identifiers.Contains(commonNameAscii, StringComparer.InvariantCultureIgnoreCase))
                {
                    _log.Warning($"Common name {commonNameUni} provided is invalid.");
                    commonNameAscii = identifiers.First();
                    commonNameUni   = idn.GetUnicode(commonNameAscii);
                }
            }

            // Determine the friendly name
            var friendlyNameBase = renewal.FriendlyName;

            if (string.IsNullOrEmpty(friendlyNameBase))
            {
                friendlyNameBase = target.FriendlyName;
            }
            if (string.IsNullOrEmpty(friendlyNameBase))
            {
                friendlyNameBase = commonNameUni;
            }
            var friendyName = $"{friendlyNameBase} @ {_inputService.FormatDate(DateTime.Now)}";

            // Try using cached certificate first to avoid rate limiting during
            // (initial?) deployment troubleshooting. Real certificate requests
            // will only be done once per day maximum unless the --force parameter
            // is used.
            var cache = CachedInfo(renewal, target);

            if (cache != null && cache.CacheFile != null)
            {
                if (cache.CacheFile.LastWriteTime >
                    DateTime.Now.AddDays(_settings.Cache.ReuseDays * -1))
                {
                    if (runLevel.HasFlag(RunLevel.IgnoreCache))
                    {
                        _log.Warning("Cached certificate available but not used with the --{switch} switch. " +
                                     "Use 'Manage renewals > Run renewal' in the main menu to run unscheduled " +
                                     "renewals without hitting rate limits.",
                                     nameof(MainArguments.Force).ToLower());
                    }
                    else
                    {
                        _log.Warning("Using cached certificate for {friendlyName}. To force issue of a " +
                                     "new certificate within {days} days, delete the .pfx file from the CertificatePath " +
                                     "or run with the --{switch} switch. Be ware that you might run into rate " +
                                     "limits doing so.",
                                     friendlyNameBase,
                                     _settings.Cache.ReuseDays,
                                     nameof(MainArguments.Force).ToLower());
                        return(cache);
                    }
                }
            }

            // Clear cache and write new cert
            ClearCache(renewal, postfix: CsrPostFix);

            if (target.CsrBytes == null)
            {
                if (csrPlugin == null)
                {
                    throw new InvalidOperationException("Missing csrPlugin");
                }
                var keyFile = GetPath(renewal, ".keys");
                var csr     = await csrPlugin.GenerateCsr(keyFile, commonNameAscii, identifiers);

                var keySet = await csrPlugin.GetKeys();

                target.CsrBytes   = csr.GetDerEncoded();
                target.PrivateKey = keySet.Private;
                var csrPath = GetPath(renewal, CsrPostFix);
                File.WriteAllText(csrPath, _pemService.GetPem("CERTIFICATE REQUEST", target.CsrBytes));
                _log.Debug("CSR stored at {path} in certificate cache folder {folder}", Path.GetFileName(csrPath), Path.GetDirectoryName(csrPath));
            }

            _log.Verbose("Submitting CSR");
            order = await _client.SubmitCsr(order, target.CsrBytes);

            if (order.Payload.Status != AcmeClient.OrderValid)
            {
                _log.Error("Unexpected order status {status}", order.Payload.Status);
                throw new Exception($"Unable to complete order");
            }

            _log.Information("Requesting certificate {friendlyName}", friendlyNameBase);
            var rawCertificate = await _client.GetCertificate(order);

            if (rawCertificate == null)
            {
                throw new Exception($"Unable to get certificate");
            }

            // Build pfx archive including any intermediates provided
            var          text        = Encoding.UTF8.GetString(rawCertificate);
            var          pfx         = new bc.Pkcs.Pkcs12Store();
            var          startIndex  = 0;
            var          endIndex    = 0;
            const string startString = "-----BEGIN CERTIFICATE-----";
            const string endString   = "-----END CERTIFICATE-----";

            while (true)
            {
                startIndex = text.IndexOf(startString, startIndex);
                if (startIndex < 0)
                {
                    break;
                }
                endIndex = text.IndexOf(endString, startIndex);
                if (endIndex < 0)
                {
                    break;
                }
                endIndex += endString.Length;
                var pem           = text[startIndex..endIndex];
예제 #9
0
 Target ITargetPlugin.Aquire(IOptionsService optionsService, IInputService inputService, RunLevel runLevel)
 {
     return(inputService.ChooseFromList("Choose site",
                                        GetBindings(optionsService.Options.HideHttps, true).Where(x => x.Hidden == false),
                                        x => Choice.Create(x, description: $"{x.Host} (SiteId {x.TargetSiteId}) [@{x.WebRootPath}]"),
                                        true));
 }
예제 #10
0
 public abstract TOptions Aquire(Target target, IOptionsService optionsService, IInputService inputService, RunLevel runLevel);
예제 #11
0
 InstallationPluginOptions IInstallationPluginOptionsFactory.Aquire(Target target, IOptionsService optionsService, IInputService inputService, RunLevel runLevel)
 {
     return(Aquire(target, optionsService, inputService, runLevel));
 }
예제 #12
0
        /// <summary>
        /// Single round of aquiring settings
        /// </summary>
        /// <param name="input"></param>
        /// <param name="allBindings"></param>
        /// <param name="visibleBindings"></param>
        /// <param name="allSites"></param>
        /// <param name="visibleSites"></param>
        /// <param name="runLevel"></param>
        /// <returns></returns>
        private async Task <IISOptions?> TryAquireSettings(
            IInputService input,
            List <IISHelper.IISBindingOption> allBindings,
            List <IISHelper.IISBindingOption> visibleBindings,
            List <IISHelper.IISSiteOption> allSites,
            List <IISHelper.IISSiteOption> visibleSites,
            RunLevel runLevel)
        {
            input.CreateSpace();
            input.Show(null, "Please select which website(s) should be scanned for host names. " +
                       "You may input one or more site identifiers (comma-separated) to filter by those sites, " +
                       "or alternatively leave the input empty to scan *all* websites.");

            var options = new IISOptions();
            await input.WritePagedList(
                visibleSites.Select(x => Choice.Create(
                                        item: x,
                                        description: $"{x.Name} ({x.Hosts.Count()} binding{(x.Hosts.Count() == 1 ? "" : "s")})",
                                        command: x.Id.ToString(),
                                        color: x.Https ? ConsoleColor.DarkGray : (ConsoleColor?)null)));

            var raw = await input.RequestString("Site identifier(s) or <Enter> to choose all");

            if (!ParseSiteOptions(raw, allSites, options))
            {
                return(null);
            }

            var filtered = _iisHelper.FilterBindings(visibleBindings, options);

            await ListBindings(input, filtered);

            input.CreateSpace();
            input.Show(null,
                       "Listed above are the bindings found on the selected site(s). By default all of " +
                       "them will be included, but you may either pick specific ones by typing the host names " +
                       "or identifiers (comma-separated) or filter them using one of the options from the " +
                       "menu.");
            var askExclude = true;
            var filters    = new List <Choice <Func <Task> > >
            {
                Choice.Create <Func <Task> >(() => {
                    return(InputPattern(input, options));
                }, "Pick bindings based on a search pattern", command: "P"),
                Choice.Create <Func <Task> >(() => {
                    askExclude = false;
                    return(Task.CompletedTask);
                }, "Pick *all* bindings", @default: true, command: "A")
            };

            if (runLevel.HasFlag(RunLevel.Advanced))
            {
                filters.Insert(1, Choice.Create <Func <Task> >(() => {
                    askExclude = true;
                    return(InputRegex(input, options));
                }, "Pick bindings based on a regular expression", command: "R"));
            }

            // Handle undefined input
            Choice <Func <Task> > processUnkown(string unknown)
            {
                return(Choice.Create <Func <Task> >(() =>
                {
                    askExclude = false;
                    return ProcessInputHosts(
                        unknown,
                        allBindings,
                        filtered,
                        options,
                        () => options.IncludeHosts, x => options.IncludeHosts = x);
                }));
            }

            var chosen = await input.ChooseFromMenu(
                "Binding identifiers(s) or menu option",
                filters,
                processUnkown);

            await chosen.Invoke();

            filtered = _iisHelper.FilterBindings(allBindings, options);

            // Exclude specific bindings
            if (askExclude && filtered.Count > 1 && runLevel.HasFlag(RunLevel.Advanced))
            {
                await ListBindings(input, filtered);

                input.CreateSpace();
                input.Show(null, "The listed bindings match your current filter settings. " +
                           "If you wish to exclude one or more of them from the certificate, please " +
                           "input those bindings now. Press <Enter> to include all listed bindings.");
                await InputHosts("Exclude bindings",
                                 input, allBindings, filtered, options,
                                 () => options.ExcludeHosts, x => options.ExcludeHosts = x);

                if (options.ExcludeHosts != null)
                {
                    filtered = _iisHelper.FilterBindings(allBindings, options);
                }
            }

            // Now the common name
            if (filtered.Select(x => x.HostUnicode).Distinct().Count() > 1)
            {
                await InputCommonName(input, filtered, options);
            }
            return(options);
        }
예제 #13
0
 Task <ValidationPluginOptions?> IValidationPluginOptionsFactory.Aquire(Target target, IInputService inputService, RunLevel runLevel) => Task.FromResult <ValidationPluginOptions?>(default);
예제 #14
0
 public override Task <DomainOptions> Aquire(IInputService inputService, RunLevel runLevel) => Default();
예제 #15
0
        /// <summary>
        /// Make sure we have authorization for every host in target
        /// </summary>
        /// <param name="target"></param>
        /// <returns></returns>
        private async Task <Challenge> Authorize(
            ILifetimeScope execute, RunLevel runLevel,
            ValidationPluginOptions options, TargetPart targetPart,
            Authorization authorization)
        {
            var invalid = new Challenge {
                Status = AcmeClient.AuthorizationInvalid
            };
            var valid = new Challenge {
                Status = AcmeClient.AuthorizationValid
            };
            var client     = execute.Resolve <AcmeClient>();
            var identifier = authorization.Identifier.Value;

            try
            {
                _log.Information("Authorize identifier: {identifier}", identifier);
                if (authorization.Status == AcmeClient.AuthorizationValid &&
                    !runLevel.HasFlag(RunLevel.Test) &&
                    !runLevel.HasFlag(RunLevel.IgnoreCache))
                {
                    _log.Information("Cached authorization result: {Status}", authorization.Status);
                    return(valid);
                }
                else
                {
                    using var validation = _scopeBuilder.Validation(execute, options, targetPart, identifier);
                    IValidationPlugin?validationPlugin = null;
                    try
                    {
                        validationPlugin = validation.Resolve <IValidationPlugin>();
                    }
                    catch (Exception ex)
                    {
                        _log.Error(ex, "Error resolving validation plugin");
                    }
                    if (validationPlugin == null)
                    {
                        _log.Error("Validation plugin not found or not created.");
                        return(invalid);
                    }
                    if (validationPlugin.Disabled)
                    {
                        _log.Error("Validation plugin is not available to the current user, try running as administrator.");
                        return(invalid);
                    }
                    var challenge = authorization.Challenges.FirstOrDefault(c => c.Type == options.ChallengeType);
                    if (challenge == null)
                    {
                        _log.Error("Expected challenge type {type} not available for {identifier}.",
                                   options.ChallengeType,
                                   authorization.Identifier.Value);
                        return(invalid);
                    }

                    if (challenge.Status == AcmeClient.AuthorizationValid &&
                        !runLevel.HasFlag(RunLevel.Test) &&
                        !runLevel.HasFlag(RunLevel.IgnoreCache))
                    {
                        _log.Information("{dnsIdentifier} already validated by {challengeType} validation ({name})",
                                         authorization.Identifier.Value,
                                         options.ChallengeType,
                                         options.Name);
                        return(valid);
                    }

                    _log.Information("Authorizing {dnsIdentifier} using {challengeType} validation ({name})",
                                     identifier,
                                     options.ChallengeType,
                                     options.Name);
                    try
                    {
                        var details = await client.DecodeChallengeValidation(authorization, challenge);

                        await validationPlugin.PrepareChallenge(details);
                    }
                    catch (Exception ex)
                    {
                        _log.Error(ex, "Error preparing for challenge answer");
                        return(invalid);
                    }

                    _log.Debug("Submitting challenge answer");
                    challenge = await client.AnswerChallenge(challenge);

                    if (challenge.Status != AcmeClient.AuthorizationValid)
                    {
                        if (challenge.Error != null)
                        {
                            _log.Error(challenge.Error.ToString());
                        }
                        _log.Error("Authorization result: {Status}", challenge.Status);
                        return(invalid);
                    }
                    else
                    {
                        _log.Information("Authorization result: {Status}", challenge.Status);
                        return(valid);
                    }
                }
            }
            catch (Exception ex)
            {
                _log.Error("Error authorizing {renewal}", targetPart);
                _exceptionHandler.HandleException(ex);
                return(invalid);
            }
        }
예제 #16
0
 ValidationPluginOptions IValidationPluginOptionsFactory.Aquire(Target target, IArgumentsService arguments, IInputService inputService, RunLevel runLevel)
 {
     return(Aquire(target, arguments, inputService, runLevel));
 }
예제 #17
0
 Task <InstallationPluginOptions> IInstallationPluginOptionsFactory.Aquire(Target target, IInputService inputService, RunLevel runLevel) => Task.FromResult <InstallationPluginOptions>(new NullInstallationOptions());
예제 #18
0
        /// <summary>
        /// Setup a new scheduled renewal
        /// </summary>
        /// <param name="runLevel"></param>
        internal async Task SetupRenewal(RunLevel runLevel)
        {
            if (_args.Test)
            {
                runLevel |= RunLevel.Test;
            }
            if (_args.Force)
            {
                runLevel |= RunLevel.IgnoreCache;
            }
            _log.Information(LogType.All, "Running in mode: {runLevel}", runLevel);
            var tempRenewal = Renewal.Create(_args.Id, _settings.ScheduledTask.RenewalDays, _passwordGenerator);

            using var configScope = _scopeBuilder.Configuration(_container, tempRenewal, runLevel);
            // Choose target plugin
            var targetPluginOptionsFactory = configScope.Resolve <ITargetPluginOptionsFactory>();

            if (targetPluginOptionsFactory is INull)
            {
                _exceptionHandler.HandleException(message: $"No target plugin could be selected");
                return;
            }
            if (targetPluginOptionsFactory.Disabled)
            {
                _exceptionHandler.HandleException(message: $"Target plugin {targetPluginOptionsFactory.Name} is not available to the current user, try running as administrator");
                return;
            }
            var targetPluginOptions = runLevel.HasFlag(RunLevel.Unattended) ?
                                      await targetPluginOptionsFactory.Default() :
                                      await targetPluginOptionsFactory.Aquire(_input, runLevel);

            if (targetPluginOptions == null)
            {
                _exceptionHandler.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)
                {
                    _exceptionHandler.HandleException(message: $"Target plugin {targetPluginOptionsFactory.Name} was unable to generate a target");
                    return;
                }
                if (!initialTarget.IsValid(_log))
                {
                    _exceptionHandler.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 = await _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)
                {
                    _exceptionHandler.HandleException(message: $"No validation plugin could be selected");
                    return;
                }
            }

            // Configure validation
            try
            {
                var validationOptions = runLevel.HasFlag(RunLevel.Unattended)
                    ? await validationPluginOptionsFactory.Default(initialTarget)
                    : await validationPluginOptionsFactory.Aquire(initialTarget, _input, runLevel);

                if (validationOptions == null)
                {
                    _exceptionHandler.HandleException(message: $"Validation plugin {validationPluginOptionsFactory.Name} was unable to generate options");
                    return;
                }
                tempRenewal.ValidationPluginOptions = validationOptions;
            }
            catch (Exception ex)
            {
                _exceptionHandler.HandleException(ex, $"Validation plugin {validationPluginOptionsFactory.Name} aborted or failed");
                return;
            }

            // Choose CSR plugin
            if (initialTarget.CsrBytes == null)
            {
                var csrPluginOptionsFactory = configScope.Resolve <ICsrPluginOptionsFactory>();
                if (csrPluginOptionsFactory is INull)
                {
                    _exceptionHandler.HandleException(message: $"No CSR plugin could be selected");
                    return;
                }

                // Configure CSR
                try
                {
                    var csrOptions = runLevel.HasFlag(RunLevel.Unattended) ?
                                     await csrPluginOptionsFactory.Default() :
                                     await csrPluginOptionsFactory.Aquire(_input, runLevel);

                    if (csrOptions == null)
                    {
                        _exceptionHandler.HandleException(message: $"CSR plugin {csrPluginOptionsFactory.Name} was unable to generate options");
                        return;
                    }
                    tempRenewal.CsrPluginOptions = csrOptions;
                }
                catch (Exception ex)
                {
                    _exceptionHandler.HandleException(ex, $"CSR plugin {csrPluginOptionsFactory.Name} aborted or failed");
                    return;
                }
            }

            // Choose and configure store plugins
            var resolver = configScope.Resolve <IResolver>();
            var storePluginOptionsFactories = new List <IStorePluginOptionsFactory>();

            try
            {
                while (true)
                {
                    var storePluginOptionsFactory = await resolver.GetStorePlugin(configScope, storePluginOptionsFactories);

                    if (storePluginOptionsFactory == null)
                    {
                        _exceptionHandler.HandleException(message: $"Store could not be selected");
                    }
                    if (storePluginOptionsFactory is NullStoreOptionsFactory)
                    {
                        if (storePluginOptionsFactories.Count == 0)
                        {
                            throw new Exception();
                        }
                        break;
                    }
                    StorePluginOptions storeOptions;
                    try
                    {
                        storeOptions = runLevel.HasFlag(RunLevel.Unattended)
                            ? await storePluginOptionsFactory.Default()
                            : await storePluginOptionsFactory.Aquire(_input, runLevel);
                    }
                    catch (Exception ex)
                    {
                        _exceptionHandler.HandleException(ex, $"Store plugin {storePluginOptionsFactory.Name} aborted or failed");
                        return;
                    }
                    if (storeOptions == null)
                    {
                        _exceptionHandler.HandleException(message: $"Store plugin {storePluginOptionsFactory.Name} was unable to generate options");
                        return;
                    }
                    tempRenewal.StorePluginOptions.Add(storeOptions);
                    storePluginOptionsFactories.Add(storePluginOptionsFactory);
                }
            }
            catch (Exception ex)
            {
                _exceptionHandler.HandleException(ex, "Invalid selection of store plugins");
                return;
            }

            // Choose and configure installation plugins
            var installationPluginFactories = new List <IInstallationPluginOptionsFactory>();

            try
            {
                while (true)
                {
                    var installationPluginFactory = await resolver.GetInstallationPlugin(configScope,
                                                                                         tempRenewal.StorePluginOptions.Select(x => x.Instance),
                                                                                         installationPluginFactories);

                    if (installationPluginFactory == null)
                    {
                        _exceptionHandler.HandleException(message: $"Installation plugin could not be selected");
                    }
                    InstallationPluginOptions installOptions;
                    try
                    {
                        installOptions = runLevel.HasFlag(RunLevel.Unattended)
                            ? await installationPluginFactory.Default(initialTarget)
                            : await installationPluginFactory.Aquire(initialTarget, _input, runLevel);
                    }
                    catch (Exception ex)
                    {
                        _exceptionHandler.HandleException(ex, $"Installation plugin {installationPluginFactory.Name} aborted or failed");
                        return;
                    }
                    if (installOptions == null)
                    {
                        _exceptionHandler.HandleException(message: $"Installation plugin {installationPluginFactory.Name} was unable to generate options");
                        return;
                    }
                    if (installationPluginFactory is NullInstallationOptionsFactory)
                    {
                        if (installationPluginFactories.Count == 0)
                        {
                            tempRenewal.InstallationPluginOptions.Add(installOptions);
                            installationPluginFactories.Add(installationPluginFactory);
                        }
                        break;
                    }
                    tempRenewal.InstallationPluginOptions.Add(installOptions);
                    installationPluginFactories.Add(installationPluginFactory);
                }
            }
            catch (Exception ex)
            {
                _exceptionHandler.HandleException(ex, "Invalid selection of installation plugins");
                return;
            }

            // Try to run for the first time
            var renewal = await CreateRenewal(tempRenewal, runLevel);

            var result = await _renewalExecution.Renew(renewal, runLevel);

            if (!result.Success)
            {
                _exceptionHandler.HandleException(message: $"Create certificate failed: {result.ErrorMessage}");
            }
            else
            {
                _renewalStore.Save(renewal, result);
            }
        }
예제 #19
0
        /// <summary>
        /// Get webroot path manually
        /// </summary>
        public HttpValidationOptions <TPlugin> BaseAquire(Target target, IArgumentsService options, IInputService input, RunLevel runLevel)
        {
            var    allowEmtpy = AllowEmtpy(target);
            string path       = options.TryGetArgument(null, input, WebrootHint(allowEmtpy));

            while (
                (!string.IsNullOrEmpty(path) && !PathIsValid(path)) ||
                (string.IsNullOrEmpty(path) && !allowEmtpy))
            {
                path = options.TryGetArgument(null, input, WebrootHint(allowEmtpy));
            }
            return(new TOptions {
                Path = path,
                CopyWebConfig = target.IIS || input.PromptYesNo("Copy default web.config before validation?", false)
            });
        }
 public override void Aquire(ScheduledRenewal renewal, IOptionsService optionsService, IInputService inputService, RunLevel runLevel, int?siteID = null)
 {
     inputService.Show("Full instructions", "https://github.com/PKISharp/win-acme/wiki/Install-Script");
     do
     {
         renewal.Script = optionsService.TryGetOption(optionsService.Options.Script, inputService, "Enter the path to the script that you want to run after renewal");
     }while (!renewal.Script.ValidFile(_log));
     inputService.Show("{0}", "Hostname");
     inputService.Show("{1}", ".pfx password");
     inputService.Show("{2}", ".pfx path");
     inputService.Show("{3}", "Certificate store name");
     inputService.Show("{4}", "Certificate friendly name");
     inputService.Show("{5}", "Certificate thumbprint");
     inputService.Show("{6}", "Central SSL store path");
     renewal.ScriptParameters = optionsService.TryGetOption(optionsService.Options.ScriptParameters, inputService, "Enter the parameter format string for the script, e.g. \"--hostname {0}\"");
 }
예제 #21
0
 private void RunLevelChanged(RunLevel oldLevel, RunLevel newLevel)
 {
     RunLevel = newLevel;
 }
예제 #22
0
        /// <summary>
        /// Request certificate from the ACME server
        /// </summary>
        /// <param name="csrPlugin">Plugin used to generate CSR if it has not been provided in the target</param>
        /// <param name="runLevel"></param>
        /// <param name="renewal"></param>
        /// <param name="target"></param>
        /// <param name="order"></param>
        /// <returns></returns>
        public async Task <CertificateInfo> RequestCertificate(ICsrPlugin?csrPlugin, RunLevel runLevel, Order order)
        {
            if (order.Details == null)
            {
                throw new InvalidOperationException("No order details found");
            }

            // What are we going to get?
            var cacheKey    = CacheKey(order);
            var pfxFileInfo = new FileInfo(GetPath(order.Renewal, $"-{cacheKey}{PfxPostFix}"));

            // Determine/check the common name
            var identifiers     = order.Target.GetHosts(false);
            var commonNameUni   = order.Target.CommonName;
            var commonNameAscii = string.Empty;

            if (!string.IsNullOrWhiteSpace(commonNameUni))
            {
                var idn = new IdnMapping();
                commonNameAscii = idn.GetAscii(commonNameUni);
                if (!identifiers.Contains(commonNameAscii, StringComparer.InvariantCultureIgnoreCase))
                {
                    _log.Warning($"Common name {commonNameUni} provided is invalid.");
                    commonNameAscii = identifiers.First();
                    commonNameUni   = idn.GetUnicode(commonNameAscii);
                }
            }

            // Determine the friendly name base (for the renewal)
            var friendlyNameBase = order.Renewal.FriendlyName;

            if (string.IsNullOrEmpty(friendlyNameBase))
            {
                friendlyNameBase = order.Target.FriendlyName;
            }
            if (string.IsNullOrEmpty(friendlyNameBase))
            {
                friendlyNameBase = commonNameUni;
            }

            // Determine the friendly name for this specific certificate
            var friendlyNameIntermediate = friendlyNameBase;

            if (!string.IsNullOrEmpty(order.FriendlyNamePart))
            {
                friendlyNameIntermediate += $" [{order.FriendlyNamePart}]";
            }
            var friendlyName = $"{friendlyNameIntermediate} @ {_inputService.FormatDate(DateTime.Now)}";

            // Try using cached certificate first to avoid rate limiting during
            // (initial?) deployment troubleshooting. Real certificate requests
            // will only be done once per day maximum unless the --force parameter
            // is used.
            var cache = CachedInfo(order);

            if (cache != null && cache.CacheFile != null)
            {
                if (cache.CacheFile.LastWriteTime > DateTime.Now.AddDays(_settings.Cache.ReuseDays * -1))
                {
                    if (runLevel.HasFlag(RunLevel.IgnoreCache))
                    {
                        _log.Warning("Cached certificate available on disk but not used due to --{switch} switch.",
                                     nameof(MainArguments.Force).ToLower());
                    }
                    else
                    {
                        _log.Warning("Using cached certificate for {friendlyName}. To force a new request of the " +
                                     "certificate within {days} days, run with the --{switch} switch.",
                                     friendlyNameIntermediate,
                                     _settings.Cache.ReuseDays,
                                     nameof(MainArguments.Force).ToLower());
                        return(cache);
                    }
                }
            }

            if (order.Details.Payload.Status != AcmeClient.OrderValid)
            {
                // Clear cache and write new cert
                ClearCache(order.Renewal, postfix: CsrPostFix);

                if (order.Target.CsrBytes == null)
                {
                    if (csrPlugin == null)
                    {
                        throw new InvalidOperationException("Missing csrPlugin");
                    }
                    // Backwards compatible with existing keys, which are not split per order yet.
                    var keyFile = new FileInfo(GetPath(order.Renewal, $".keys"));
                    if (!keyFile.Exists)
                    {
                        keyFile = new FileInfo(GetPath(order.Renewal, $"-{cacheKey}.keys"));
                    }
                    var csr = await csrPlugin.GenerateCsr(keyFile.FullName, commonNameAscii, identifiers);

                    var keySet = await csrPlugin.GetKeys();

                    order.Target.CsrBytes   = csr.GetDerEncoded();
                    order.Target.PrivateKey = keySet.Private;
                    var csrPath = GetPath(order.Renewal, $"-{cacheKey}{CsrPostFix}");
                    await File.WriteAllTextAsync(csrPath, _pemService.GetPem("CERTIFICATE REQUEST", order.Target.CsrBytes));

                    _log.Debug("CSR stored at {path} in certificate cache folder {folder}", Path.GetFileName(csrPath), Path.GetDirectoryName(csrPath));
                }

                _log.Verbose("Submitting CSR");
                order.Details = await _client.SubmitCsr(order.Details, order.Target.CsrBytes);

                if (order.Details.Payload.Status != AcmeClient.OrderValid)
                {
                    _log.Error("Unexpected order status {status}", order.Details.Payload.Status);
                    throw new Exception($"Unable to complete order");
                }
            }

            _log.Information("Requesting certificate {friendlyName}", friendlyNameIntermediate);
            var certInfo = await _client.GetCertificate(order.Details);

            if (certInfo == null || certInfo.Certificate == null)
            {
                throw new Exception($"Unable to get certificate");
            }
            var alternatives = new List <X509Certificate2Collection>
            {
                ParseCertificate(certInfo.Certificate, friendlyName, order.Target.PrivateKey)
            };

            foreach (var alt in certInfo.Links["alternate"])
            {
                try
                {
                    var altCertRaw = await _client.GetCertificate(alt);

                    var altCert = ParseCertificate(altCertRaw, friendlyName, order.Target.PrivateKey);
                    alternatives.Add(altCert);
                }
                catch (Exception ex)
                {
                    _log.Warning("Unable to get alternate certificate: {ex}", ex.Message);
                }
            }
            var selected = Select(alternatives);

            ClearCache(order.Renewal, postfix: $"*{PfxPostFix}");
            ClearCache(order.Renewal, postfix: $"*{PfxPostFixLegacy}");
            await File.WriteAllBytesAsync(pfxFileInfo.FullName, selected.Export(X509ContentType.Pfx, order.Renewal.PfxPassword?.Value));

            _log.Debug("Certificate written to cache file {path} in certificate cache folder {folder}. It will be " +
                       "reused when renewing within {x} day(s) as long as the Target and Csr parameters remain the same and " +
                       "the --force switch is not used.",
                       pfxFileInfo.Name,
                       pfxFileInfo.Directory.FullName,
                       _settings.Cache.ReuseDays);

            if (csrPlugin != null)
            {
                try
                {
                    var cert = selected.
                               OfType <X509Certificate2>().
                               Where(x => x.HasPrivateKey).
                               FirstOrDefault();
                    if (cert != null)
                    {
                        var certIndex  = selected.IndexOf(cert);
                        var newVersion = await csrPlugin.PostProcess(cert);

                        if (newVersion != cert)
                        {
                            newVersion.FriendlyName = friendlyName;
                            selected[certIndex]     = newVersion;
                            await File.WriteAllBytesAsync(pfxFileInfo.FullName, selected.Export(X509ContentType.Pfx, order.Renewal.PfxPassword?.Value));

                            newVersion.Dispose();
                        }
                    }
                }
                catch (Exception ex)
                {
                    _log.Warning("Private key conversion error: {ex}", ex.Message);
                }
            }

            pfxFileInfo.Refresh();

            // Update LastFriendlyName so that the user sees
            // the most recently issued friendlyName in
            // the WACS GUI
            order.Renewal.LastFriendlyName = friendlyNameBase;

            // Recreate X509Certificate2 with correct flags for Store/Install
            return(FromCache(pfxFileInfo, order.Renewal.PfxPassword?.Value));
        }
예제 #23
0
        /// <summary>
        /// Setup a new scheduled renewal
        /// </summary>
        /// <param name="runLevel"></param>
        internal async Task SetupRenewal(RunLevel runLevel, Renewal?tempRenewal = null)
        {
            if (_args.Test)
            {
                runLevel |= RunLevel.Test;
            }
            if (_args.Force)
            {
                runLevel |= RunLevel.IgnoreCache;
            }
            _log.Information(LogType.All, "Running in mode: {runLevel}", runLevel);
            if (tempRenewal == null)
            {
                tempRenewal = Renewal.Create(_args.Id, _settings.ScheduledTask.RenewalDays, _passwordGenerator);
            }
            else
            {
                tempRenewal.InstallationPluginOptions.Clear();
                tempRenewal.StorePluginOptions.Clear();
            }
            using var configScope = _scopeBuilder.Configuration(_container, tempRenewal, runLevel);
            // Choose target plugin
            var targetPluginOptionsFactory = configScope.Resolve <ITargetPluginOptionsFactory>();

            if (targetPluginOptionsFactory is INull)
            {
                _exceptionHandler.HandleException(message: $"No source plugin could be selected");
                return;
            }
            var(targetPluginDisabled, targetPluginDisabledReason) = targetPluginOptionsFactory.Disabled;
            if (targetPluginDisabled)
            {
                _exceptionHandler.HandleException(message: $"Source plugin {targetPluginOptionsFactory.Name} is not available. {targetPluginDisabledReason}");
                return;
            }
            var targetPluginOptions = runLevel.HasFlag(RunLevel.Unattended) ?
                                      await targetPluginOptionsFactory.Default() :
                                      await targetPluginOptionsFactory.Acquire(_input, runLevel);

            if (targetPluginOptions == null)
            {
                _exceptionHandler.HandleException(message: $"Source plugin {targetPluginOptionsFactory.Name} aborted or failed");
                return;
            }
            tempRenewal.TargetPluginOptions = targetPluginOptions;

            // Generate Target and validation plugin choice
            using var targetScope = _scopeBuilder.Target(_container, tempRenewal, runLevel);
            var initialTarget = targetScope.Resolve <Target>();

            if (initialTarget is INull)
            {
                _exceptionHandler.HandleException(message: $"Source plugin {targetPluginOptionsFactory.Name} was unable to generate a target");
                return;
            }
            if (!initialTarget.IsValid(_log))
            {
                _exceptionHandler.HandleException(message: $"Source plugin {targetPluginOptionsFactory.Name} generated an invalid target");
                return;
            }
            _log.Information("Source generated using plugin {name}: {target}", targetPluginOptions.Name, initialTarget);

            // Choose FriendlyName
            if (!string.IsNullOrEmpty(_args.FriendlyName))
            {
                tempRenewal.FriendlyName = _args.FriendlyName;
            }
            else if (runLevel.HasFlag(RunLevel.Advanced | RunLevel.Interactive))
            {
                var alt = await _input.RequestString($"Suggested friendly name '{initialTarget.FriendlyName}', press <Enter> to accept or type an alternative");

                if (!string.IsNullOrEmpty(alt))
                {
                    tempRenewal.FriendlyName = alt;
                }
            }
            tempRenewal.LastFriendlyName = tempRenewal.FriendlyName ?? initialTarget.FriendlyName;

            // Choose validation plugin
            var validationPluginOptionsFactory = targetScope.Resolve <IValidationPluginOptionsFactory>();

            if (validationPluginOptionsFactory is INull)
            {
                _exceptionHandler.HandleException(message: $"No validation plugin could be selected");
                return;
            }

            // Configure validation
            try
            {
                var validationOptions = runLevel.HasFlag(RunLevel.Unattended)
                    ? await validationPluginOptionsFactory.Default(initialTarget)
                    : await validationPluginOptionsFactory.Acquire(initialTarget, _input, runLevel);

                if (validationOptions == null)
                {
                    _exceptionHandler.HandleException(message: $"Validation plugin {validationPluginOptionsFactory.Name} was unable to generate options");
                    return;
                }
                tempRenewal.ValidationPluginOptions = validationOptions;
            }
            catch (Exception ex)
            {
                _exceptionHandler.HandleException(ex, $"Validation plugin {validationPluginOptionsFactory.Name} aborted or failed");
                return;
            }

            // Choose order plugin
            var orderPluginOptionsFactory = targetScope.Resolve <IOrderPluginOptionsFactory>();

            if (orderPluginOptionsFactory is INull)
            {
                _exceptionHandler.HandleException(message: $"No order plugin could be selected");
                return;
            }

            // Configure order
            try
            {
                var orderOptions = runLevel.HasFlag(RunLevel.Unattended) ?
                                   await orderPluginOptionsFactory.Default() :
                                   await orderPluginOptionsFactory.Acquire(_input, runLevel);

                if (orderOptions == null)
                {
                    _exceptionHandler.HandleException(message: $"Order plugin {orderPluginOptionsFactory.Name} was unable to generate options");
                    return;
                }
                tempRenewal.OrderPluginOptions = orderOptions;
            }
            catch (Exception ex)
            {
                _exceptionHandler.HandleException(ex, $"Order plugin {orderPluginOptionsFactory.Name} aborted or failed");
                return;
            }

            // Choose CSR plugin
            if (initialTarget.CsrBytes == null)
            {
                var csrPluginOptionsFactory = configScope.Resolve <ICsrPluginOptionsFactory>();
                if (csrPluginOptionsFactory is INull)
                {
                    _exceptionHandler.HandleException(message: $"No CSR plugin could be selected");
                    return;
                }

                // Configure CSR
                try
                {
                    var csrOptions = runLevel.HasFlag(RunLevel.Unattended) ?
                                     await csrPluginOptionsFactory.Default() :
                                     await csrPluginOptionsFactory.Acquire(_input, runLevel);

                    if (csrOptions == null)
                    {
                        _exceptionHandler.HandleException(message: $"CSR plugin {csrPluginOptionsFactory.Name} was unable to generate options");
                        return;
                    }
                    tempRenewal.CsrPluginOptions = csrOptions;
                }
                catch (Exception ex)
                {
                    _exceptionHandler.HandleException(ex, $"CSR plugin {csrPluginOptionsFactory.Name} aborted or failed");
                    return;
                }
            }

            // Choose and configure store plugins
            var resolver = configScope.Resolve <IResolver>();
            var storePluginOptionsFactories = new List <IStorePluginOptionsFactory>();

            try
            {
                while (true)
                {
                    var storePluginOptionsFactory = await resolver.GetStorePlugin(configScope, storePluginOptionsFactories);

                    if (storePluginOptionsFactory == null)
                    {
                        _exceptionHandler.HandleException(message: $"Store could not be selected");
                        return;
                    }
                    StorePluginOptions?storeOptions;
                    try
                    {
                        storeOptions = runLevel.HasFlag(RunLevel.Unattended)
                            ? await storePluginOptionsFactory.Default()
                            : await storePluginOptionsFactory.Acquire(_input, runLevel);
                    }
                    catch (Exception ex)
                    {
                        _exceptionHandler.HandleException(ex, $"Store plugin {storePluginOptionsFactory.Name} aborted or failed");
                        return;
                    }
                    if (storeOptions == null)
                    {
                        _exceptionHandler.HandleException(message: $"Store plugin {storePluginOptionsFactory.Name} was unable to generate options");
                        return;
                    }
                    var isNull = storePluginOptionsFactory is NullStoreOptionsFactory;
                    if (!isNull || storePluginOptionsFactories.Count == 0)
                    {
                        tempRenewal.StorePluginOptions.Add(storeOptions);
                        storePluginOptionsFactories.Add(storePluginOptionsFactory);
                    }
                    if (isNull)
                    {
                        break;
                    }
                }
            }
            catch (Exception ex)
            {
                _exceptionHandler.HandleException(ex, "Invalid selection of store plugins");
                return;
            }

            // Choose and configure installation plugins
            var installationPluginFactories = new List <IInstallationPluginOptionsFactory>();

            try
            {
                while (true)
                {
                    var installationPluginOptionsFactory = await resolver.GetInstallationPlugin(configScope,
                                                                                                tempRenewal.StorePluginOptions.Select(x => x.Instance),
                                                                                                installationPluginFactories);

                    if (installationPluginOptionsFactory == null)
                    {
                        _exceptionHandler.HandleException(message: $"Installation plugin could not be selected");
                        return;
                    }
                    InstallationPluginOptions installOptions;
                    try
                    {
                        installOptions = runLevel.HasFlag(RunLevel.Unattended)
                            ? await installationPluginOptionsFactory.Default(initialTarget)
                            : await installationPluginOptionsFactory.Acquire(initialTarget, _input, runLevel);
                    }
                    catch (Exception ex)
                    {
                        _exceptionHandler.HandleException(ex, $"Installation plugin {installationPluginOptionsFactory.Name} aborted or failed");
                        return;
                    }
                    if (installOptions == null)
                    {
                        _exceptionHandler.HandleException(message: $"Installation plugin {installationPluginOptionsFactory.Name} was unable to generate options");
                        return;
                    }
                    var isNull = installationPluginOptionsFactory is NullInstallationOptionsFactory;
                    if (!isNull || installationPluginFactories.Count == 0)
                    {
                        tempRenewal.InstallationPluginOptions.Add(installOptions);
                        installationPluginFactories.Add(installationPluginOptionsFactory);
                    }
                    if (isNull)
                    {
                        break;
                    }
                }
            }
            catch (Exception ex)
            {
                _exceptionHandler.HandleException(ex, "Invalid selection of installation plugins");
                return;
            }

            // Try to run for the first time
            var renewal = await CreateRenewal(tempRenewal, runLevel);

retry:
            var result = await _renewalExecution.HandleRenewal(renewal, runLevel);

            if (result.Abort)
            {
                _exceptionHandler.HandleException(message: $"Create certificate cancelled");
            }
            else if (!result.Success)
            {
                if (runLevel.HasFlag(RunLevel.Interactive) &&
                    await _input.PromptYesNo("Create certificate failed, retry?", false))
                {
                    goto retry;
                }
                if (!renewal.New &&
                    await _input.PromptYesNo("Save these new settings anyway?", false))
                {
                    _renewalStore.Save(renewal, result);
                }
                _exceptionHandler.HandleException(message: $"Create certificate failed: {string.Join("\n\t- ", result.ErrorMessages)}");
            }
            else
            {
                try
                {
                    _renewalStore.Save(renewal, result);
                    await _notification.NotifyCreated(renewal, _log.Lines);
                }
                catch (Exception ex)
                {
                    _exceptionHandler.HandleException(ex);
                }
            }
        }
예제 #24
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);
            using (var configScope = _scopeBuilder.Configuration(_container, runLevel))
            {
                // Choose target plugin
                var tempRenewal = Renewal.Create(_passwordGenerator);
                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 storage 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> >();
                    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);
                }
            }
        }
예제 #25
0
        public override CsrOptions Aquire(IArgumentsService arguments, IInputService inputService, RunLevel runLevel)
        {
            var args = arguments.GetArguments <CsrArguments>();
            var ret  = new CsrOptions();

            do
            {
                ret.CsrFile = arguments.TryGetArgument(
                    args.CsrFile,
                    inputService,
                    "Enter the path to the CSR");
            }while (!ret.CsrFile.ValidFile(_log));

            string pkFile;

            do
            {
                pkFile = arguments.TryGetArgument(args.CsrFile,
                                                  inputService,
                                                  "Enter the path to the corresponding private key, or <ENTER> to create a certificate without one");
            }while (!(string.IsNullOrWhiteSpace(pkFile) || pkFile.ValidFile(_log)));

            if (!string.IsNullOrWhiteSpace(pkFile))
            {
                ret.PkFile = pkFile;
            }

            return(ret);
        }
예제 #26
0
 public Sftp(SftpOptions options, HttpValidationParameters pars, RunLevel runLevel) : base(options, runLevel, pars)
 {
     _sshFtpClient = new SshFtpClient(_options.Credential.GetCredential(), pars.LogService);
 }
예제 #27
0
파일: Program.cs 프로젝트: b01t/win-acme
        private static void CreateNewCertificate(RunLevel runLevel)
        {
            _log.Information(true, "Running in {runLevel} mode", runLevel);
            var tempRenewal = CreateRenewal(_options);

            using (var scope = AutofacBuilder.Renewal(_container, tempRenewal, runLevel))
            {
                // Choose target plugin
                var targetPluginFactory = scope.Resolve <ITargetPluginFactory>();
                if (targetPluginFactory is INull)
                {
                    return; // User cancelled or unable to resolve
                }

                // Aquire target
                var targetPlugin   = scope.Resolve <ITargetPlugin>();
                var target         = runLevel == RunLevel.Unattended ? targetPlugin.Default(_optionsService) : targetPlugin.Aquire(_optionsService, _input, runLevel);
                var originalTarget = tempRenewal.Binding;
                tempRenewal.Binding = target;
                if (target == null)
                {
                    _log.Error("Plugin {name} was unable to generate a target", targetPluginFactory.Name);
                    return;
                }
                tempRenewal.Binding.TargetPluginName     = targetPluginFactory.Name;
                tempRenewal.Binding.SSLPort              = _options.SSLPort;
                tempRenewal.Binding.ValidationPort       = _options.ValidationPort;
                tempRenewal.Binding.ValidationPluginName = originalTarget.ValidationPluginName;
                _log.Information("Plugin {name} generated target {target}", targetPluginFactory.Name, tempRenewal.Binding);

                // Choose validation plugin
                var validationPluginFactory = scope.Resolve <IValidationPluginFactory>();
                if (validationPluginFactory is INull)
                {
                    return; // User cancelled
                }
                else if (!validationPluginFactory.CanValidate(target))
                {
                    // Might happen in unattended mode
                    _log.Error("Validation plugin {name} is unable to validate target", validationPluginFactory.Name);
                    return;
                }

                // Configure validation
                try
                {
                    if (runLevel == RunLevel.Unattended)
                    {
                        validationPluginFactory.Default(target, _optionsService);
                    }
                    else
                    {
                        validationPluginFactory.Aquire(target, _optionsService, _input, runLevel);
                    }
                    tempRenewal.Binding.ValidationPluginName = $"{validationPluginFactory.ChallengeType}.{validationPluginFactory.Name}";
                }
                catch (Exception ex)
                {
                    _log.Error(ex, "Invalid validation input");
                    return;
                }

                // Choose and configure installation plugins
                try
                {
                    var installFactories = scope.Resolve <List <IInstallationPluginFactory> >();
                    if (installFactories.Count == 0)
                    {
                        // User cancelled, otherwise we would at least have the Null-installer
                        return;
                    }
                    foreach (var installFactory in installFactories)
                    {
                        if (runLevel == RunLevel.Unattended)
                        {
                            installFactory.Default(tempRenewal, _optionsService);
                        }
                        else
                        {
                            installFactory.Aquire(tempRenewal, _optionsService, _input, runLevel);
                        }
                    }
                    tempRenewal.InstallationPluginNames = installFactories.Select(f => f.Name).ToList();
                }
                catch (Exception ex)
                {
                    _log.Error(ex, "Invalid installation input");
                    return;
                }

                var result = Renew(scope, CreateRenewal(tempRenewal));
                if (!result.Success)
                {
                    _log.Error("Create certificate failed");
                }
            }
        }
예제 #28
0
 public override Task <HostOptions> Acquire(IInputService inputService, RunLevel runLevel) => Default();
예제 #29
0
        /// <summary>
        /// Make sure we have authorization for every host in target
        /// </summary>
        /// <param name="target"></param>
        /// <returns></returns>
        private async Task <Challenge> Authorize(
            ILifetimeScope execute, RunLevel runLevel,
            ValidationPluginOptions options, TargetPart targetPart,
            Authorization authorization)
        {
            var invalid = new Challenge {
                Status = AcmeClient.AuthorizationInvalid
            };
            var valid = new Challenge {
                Status = AcmeClient.AuthorizationValid
            };
            var client     = execute.Resolve <AcmeClient>();
            var identifier = authorization.Identifier.Value;
            IValidationPlugin?validationPlugin = null;

            using var validation = _scopeBuilder.Validation(execute, options, targetPart, identifier);
            try
            {
                if (authorization.Status == AcmeClient.AuthorizationValid)
                {
                    if (!runLevel.HasFlag(RunLevel.Test) &&
                        !runLevel.HasFlag(RunLevel.IgnoreCache))
                    {
                        _log.Information("Cached authorization result for {identifier}: {Status}", identifier, authorization.Status);
                        return(valid);
                    }

                    if (runLevel.HasFlag(RunLevel.IgnoreCache))
                    {
                        // Due to the IgnoreCache flag (--force switch)
                        // we are going to attempt to re-authorize the
                        // domain even though its already autorized.
                        // On failure, we can still use the cached result.
                        // This helps for migration scenarios.
                        invalid = valid;
                    }
                }

                _log.Information("Authorize identifier {identifier}", identifier);
                _log.Verbose("Initial authorization status: {status}", authorization.Status);
                _log.Verbose("Challenge types available: {challenges}", authorization.Challenges.Select(x => x.Type ?? "[Unknown]"));
                var challenge = authorization.Challenges.FirstOrDefault(c => string.Equals(c.Type, options.ChallengeType, StringComparison.CurrentCultureIgnoreCase));
                if (challenge == null)
                {
                    if (authorization.Status == AcmeClient.AuthorizationValid)
                    {
                        var usedType = authorization.Challenges.
                                       Where(x => x.Status == AcmeClient.AuthorizationValid).
                                       FirstOrDefault();
                        _log.Warning("Expected challenge type {type} not available for {identifier}, already validated using {valided}.",
                                     options.ChallengeType,
                                     authorization.Identifier.Value,
                                     usedType?.Type ?? "[unknown]");
                        return(valid);
                    }
                    else
                    {
                        _log.Error("Expected challenge type {type} not available for {identifier}.",
                                   options.ChallengeType,
                                   authorization.Identifier.Value);
                        invalid.Error = "Expected challenge type not available";
                        return(invalid);
                    }
                }
                else
                {
                    _log.Verbose("Initial challenge status: {status}", challenge.Status);
                    if (challenge.Status == AcmeClient.AuthorizationValid)
                    {
                        // We actually should not get here because if one of the
                        // challenges is valid, the authorization itself should also
                        // be valid.
                        if (!runLevel.HasFlag(RunLevel.Test) &&
                            !runLevel.HasFlag(RunLevel.IgnoreCache))
                        {
                            _log.Information("Cached authorization result: {Status}", authorization.Status);
                            return(valid);
                        }
                        if (runLevel.HasFlag(RunLevel.IgnoreCache))
                        {
                            // Due to the IgnoreCache flag (--force switch)
                            // we are going to attempt to re-authorize the
                            // domain even though its already autorized.
                            // On failure, we can still use the cached result.
                            // This helps for migration scenarios.
                            invalid = valid;
                        }
                    }
                }

                // We actually have to do validation now
                try
                {
                    validationPlugin = validation.Resolve <IValidationPlugin>();
                }
                catch (Exception ex)
                {
                    _log.Error(ex, "Error resolving validation plugin");
                }
                if (validationPlugin == null)
                {
                    _log.Error("Validation plugin not found or not created.");
                    invalid.Error = "Validation plugin not found or not created.";
                    return(invalid);
                }
                var(disabled, disabledReason) = validationPlugin.Disabled;
                if (disabled)
                {
                    _log.Error($"Validation plugin is not available. {disabledReason}");
                    invalid.Error = "Validation plugin is not available.";
                    return(invalid);
                }
                _log.Information("Authorizing {dnsIdentifier} using {challengeType} validation ({name})",
                                 identifier,
                                 options.ChallengeType,
                                 options.Name);
                try
                {
                    var details = await client.DecodeChallengeValidation(authorization, challenge);

                    await validationPlugin.PrepareChallenge(details);
                }
                catch (Exception ex)
                {
                    _log.Error(ex, "Error preparing for challenge answer");
                    invalid.Error = "Error preparing for challenge answer";
                    return(invalid);
                }

                _log.Debug("Submitting challenge answer");
                challenge = await client.AnswerChallenge(challenge);

                if (challenge.Status != AcmeClient.AuthorizationValid)
                {
                    if (challenge.Error != null)
                    {
                        _log.Error(challenge.Error.ToString());
                    }
                    _log.Error("Authorization result: {Status}", challenge.Status);
                    invalid.Error = challenge.Error;
                    return(invalid);
                }
                else
                {
                    _log.Information("Authorization result: {Status}", challenge.Status);
                    return(valid);
                }
            }
            catch (Exception ex)
            {
                _log.Error("Error authorizing {renewal}", targetPart);
                _exceptionHandler.HandleException(ex);
                invalid.Error = ex.Message;
                return(invalid);
            }
            finally
            {
                if (validationPlugin != null)
                {
                    try
                    {
                        _log.Verbose("Starting post-validation cleanup");
                        await validationPlugin.CleanUp();

                        _log.Verbose("Post-validation cleanup was succesful");
                    }
                    catch (Exception ex)
                    {
                        _log.Warning("An error occured during post-validation cleanup: {ex}", ex.Message);
                    }
                }
            }
        }
예제 #30
0
        Target ITargetPlugin.Aquire(IOptionsService optionsService, IInputService inputService, RunLevel runLevel)
        {
            var input  = inputService.RequestString("Enter comma-separated list of host names, starting with the primary one");
            var target = Create(input);

            if (runLevel >= RunLevel.Advanced)
            {
                target.AskForCommonNameChoice(inputService);
            }
            return(target);
        }
예제 #31
0
        /// <summary>
        /// Controls what modules are running.
        /// </summary>
        /// <param name="runlevel"></param>
        public void InitModules(RunLevel runlevel = RunLevel.Lobby)
        {
            if (runlevel == Runlevel)
                return;

            Runlevel = runlevel;
            if (Runlevel == RunLevel.Lobby)
            {
                _startAt = DateTime.Now.AddSeconds(GameCountdown);
            }
            else if (Runlevel == RunLevel.Game)
            {
                IoCManager.Resolve<IMapManager>().LoadMap(_serverMapName);

                //IoCManager.Resolve<IAtmosManager>().InitializeGasCells();

                EntityManager = new EntityManager(IoCManager.Resolve<ISS14NetServer>());

                IoCManager.Resolve<IRoundManager>().CurrentGameMode.StartGame();
            }
        }
예제 #32
0
        public async System.Threading.Tasks.Task EnsureTaskScheduler(RunLevel runLevel, bool offerRecreate)
        {
            string taskName;
            var    existingTask = ExistingTask;

            taskName = existingTask != null ?
                       existingTask.Name :
                       TaskName(_settings.Client.ClientName);

            using var taskService = new TaskService();
            if (existingTask != null)
            {
                var healthy  = IsHealthy(existingTask);
                var recreate = false;
                if (runLevel.HasFlag(RunLevel.Interactive))
                {
                    if (offerRecreate || !healthy)
                    {
                        recreate = await _input.PromptYesNo($"Do you want to replace the existing task?", false);
                    }
                }

                if (!recreate)
                {
                    if (!healthy)
                    {
                        _log.Error("Proceeding with unhealthy scheduled task, automatic renewals may not work until this is addressed");
                    }
                    return;
                }

                _log.Information("Deleting existing task {taskName} from Windows Task Scheduler.", taskName);
                taskService.RootFolder.DeleteTask(taskName, false);
            }

            var actionString = $"--{nameof(MainArguments.Renew).ToLowerInvariant()} --{nameof(MainArguments.BaseUri).ToLowerInvariant()} \"{_settings.BaseUri}\"";

            _log.Information("Adding Task Scheduler entry with the following settings", taskName);
            _log.Information("- Name {name}", taskName);
            _log.Information("- Path {action}", WorkingDirectory);
            _log.Information("- Command {exec} {action}", ExecutingFile, actionString);
            _log.Information("- Start at {start}", _settings.ScheduledTask.StartBoundary);
            if (_settings.ScheduledTask.RandomDelay.TotalMinutes > 0)
            {
                _log.Information("- Random delay {delay}", _settings.ScheduledTask.RandomDelay);
            }
            _log.Information("- Time limit {limit}", _settings.ScheduledTask.ExecutionTimeLimit);

            // Create a new task definition and assign properties
            var task = taskService.NewTask();

            task.RegistrationInfo.Description = "Check for renewal of ACME certificates.";

            var now     = DateTime.Now;
            var runtime = new DateTime(now.Year, now.Month, now.Day,
                                       _settings.ScheduledTask.StartBoundary.Hours,
                                       _settings.ScheduledTask.StartBoundary.Minutes,
                                       _settings.ScheduledTask.StartBoundary.Seconds);

            task.Triggers.Add(new DailyTrigger
            {
                DaysInterval  = 1,
                StartBoundary = runtime,
                RandomDelay   = _settings.ScheduledTask.RandomDelay
            });
            task.Settings.ExecutionTimeLimit         = _settings.ScheduledTask.ExecutionTimeLimit;
            task.Settings.MultipleInstances          = TaskInstancesPolicy.IgnoreNew;
            task.Settings.RunOnlyIfNetworkAvailable  = true;
            task.Settings.DisallowStartIfOnBatteries = false;
            task.Settings.StopIfGoingOnBatteries     = false;
            task.Settings.StartWhenAvailable         = true;

            // Create an action that will launch the app with the renew parameters whenever the trigger fires
            task.Actions.Add(new ExecAction(_settings.ExePath, actionString, WorkingDirectory));

            task.Principal.RunLevel = TaskRunLevel.Highest;
            while (true)
            {
                try
                {
                    if (!_arguments.UseDefaultTaskUser &&
                        runLevel.HasFlag(RunLevel.Interactive | RunLevel.Advanced) &&
                        await _input.PromptYesNo($"Do you want to specify the user the task will run as?", false))
                    {
                        // Ask for the login and password to allow the task to run
                        var username = await _input.RequestString("Enter the username (Domain\\username)");

                        var password = await _input.ReadPassword("Enter the user's password");

                        _log.Debug("Creating task to run as {username}", username);
                        try
                        {
                            taskService.RootFolder.RegisterTaskDefinition(
                                taskName,
                                task,
                                TaskCreation.Create,
                                username,
                                password,
                                TaskLogonType.Password);
                        }
                        catch (UnauthorizedAccessException)
                        {
                            _log.Error("Unable to register scheduled task, please run as administrator or equivalent");
                        }
                    }
                    else if (existingTask != null)
                    {
                        _log.Debug("Creating task to run with previously chosen credentials");
                        string?password = null;
                        string?username = null;
                        if (existingTask.Definition.Principal.LogonType == TaskLogonType.Password)
                        {
                            username = existingTask.Definition.Principal.UserId;
                            password = await _input.ReadPassword($"Password for {username}");
                        }
                        task.Principal.UserId    = existingTask.Definition.Principal.UserId;
                        task.Principal.LogonType = existingTask.Definition.Principal.LogonType;
                        try
                        {
                            taskService.RootFolder.RegisterTaskDefinition(
                                taskName,
                                task,
                                TaskCreation.CreateOrUpdate,
                                username,
                                password,
                                existingTask.Definition.Principal.LogonType);
                        }
                        catch (UnauthorizedAccessException)
                        {
                            _log.Error("Unable to register scheduled task, please run as administrator or equivalent");
                        }
                    }
                    else
                    {
                        _log.Debug("Creating task to run as system user");
                        task.Principal.UserId    = "SYSTEM";
                        task.Principal.LogonType = TaskLogonType.ServiceAccount;
                        try
                        {
                            taskService.RootFolder.RegisterTaskDefinition(
                                taskName,
                                task,
                                TaskCreation.CreateOrUpdate,
                                null,
                                null,
                                TaskLogonType.ServiceAccount);
                        }
                        catch (UnauthorizedAccessException)
                        {
                            _log.Error("Unable to register scheduled task, please run as administrator or equivalent");
                        }
                    }
                    break;
                }
                catch (COMException cex)
                {
                    if (cex.HResult == -2147023570)
                    {
                        _log.Warning("Invalid username/password, please try again");
                    }
                    else
                    {
                        _log.Error(cex, "Failed to create task");
                        break;
                    }
                }
                catch (Exception ex)
                {
                    _log.Error(ex, "Failed to create task");
                    break;
                }
            }
        }