Exemple #1
0
        /// <summary>
        /// Show banner
        /// </summary>
        private void ShowBanner()
        {
#if DEBUG
            var build = "DEBUG";
#else
            var build = "RELEASE";
#endif
            var version = Assembly.GetExecutingAssembly().GetName().Version;
            var iis     = _container.Resolve <IIISClient>().Version;
            Console.WriteLine();
            _log.Information(LogType.Screen, "A simple Windows ACMEv2 client (WACS)");
            _log.Information(LogType.Screen, "Software version {version} ({build})", version, build);
            _log.Information(LogType.Disk | LogType.Event, "Software version {version} ({build}) started", version, build);
            if (_args != null)
            {
                _log.Information("ACME server {ACME}", _args.GetBaseUri());
            }
            if (iis.Major > 0)
            {
                _log.Information("IIS version {version}", iis);
            }
            else
            {
                _log.Information("IIS not detected");
            }
            _log.Information("Please report issues at {url}", "https://github.com/PKISharp/win-acme");
            Console.WriteLine();
        }
Exemple #2
0
        /// <summary>
        /// Find and/or create path of the configuration files
        /// </summary>
        /// <param name="options"></param>
        private void CreateConfigPath(MainArguments options)
        {
            var configRoot = "";

            var userRoot = Settings.Default.ConfigurationPath;

            if (!string.IsNullOrEmpty(userRoot))
            {
                configRoot = userRoot;

                // Path configured in settings always wins, but
                // check for possible sub directories with client name
                // to keep bug-compatible with older releases that
                // created a subfolder inside of the users chosen config path
                foreach (var clientName in ClientNames)
                {
                    var configRootWithClient = Path.Combine(userRoot, clientName);
                    if (Directory.Exists(configRootWithClient))
                    {
                        configRoot = configRootWithClient;
                        break;
                    }
                }
            }
            else
            {
                // When using a system folder, we have to create a sub folder
                // with the most preferred client name, but we should check first
                // if there is an older folder with an less preferred (older)
                // client name.

                // Stop looking if the directory has been found
                if (!Directory.Exists(configRoot))
                {
                    var appData = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
                    foreach (var clientName in ClientNames.Reverse())
                    {
                        configRoot = Path.Combine(appData, clientName);
                        if (Directory.Exists(configRoot))
                        {
                            // Stop looking if the directory has been found
                            break;
                        }
                    }
                }
            }

            // This only happens when invalid options are provided
            if (options != null)
            {
                ConfigPath = Path.Combine(configRoot, options.GetBaseUri().CleanBaseUri());
                _log.Debug("Config folder: {_configPath}", ConfigPath);
                Directory.CreateDirectory(ConfigPath);
            }
        }
Exemple #3
0
 private string TaskName(string clientName)
 {
     return($"{clientName} renew ({_options.GetBaseUri().CleanBaseUri()})");
 }
        public void EnsureTaskScheduler()
        {
            using (var taskService = new TaskService())
            {
                var  taskName     = "";
                var  uri          = _runLevel.HasFlag(RunLevel.Import) ? _options.GetBaseUri(true) : _options.GetBaseUri();
                Task existingTask = null;
                foreach (var clientName in _settings.ClientNames.Reverse())
                {
                    taskName     = $"{clientName} renew ({uri.CleanBaseUri()})";
                    existingTask = taskService.GetTask(taskName);
                    if (existingTask != null)
                    {
                        break;
                    }
                }

                if (existingTask != null)
                {
                    if (!_runLevel.HasFlag(RunLevel.Advanced) || !_input.PromptYesNo($"Do you want to replace the existing task?", false))
                    {
                        return;
                    }

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

                var currentExec  = Assembly.GetExecutingAssembly().Location;
                var actionString = $"--{nameof(MainArguments.Renew).ToLowerInvariant()} --{nameof(MainArguments.BaseUri).ToLowerInvariant()} \"{uri}\"";

                _log.Information("Adding Task Scheduler entry with the following settings", taskName);
                _log.Information("- Name {name}", taskName);
                _log.Information("- Path {action}", Path.GetDirectoryName(currentExec));
                _log.Information("- Command {exec} {action}", Path.GetFileName(currentExec), actionString);
                _log.Information("- Start at {start}", _settings.ScheduledTaskStartBoundary);
                if (_settings.ScheduledTaskRandomDelay.TotalMinutes > 0)
                {
                    _log.Information("- Random delay {delay}", _settings.ScheduledTaskRandomDelay);
                }
                _log.Information("- Time limit {limit}", _settings.ScheduledTaskExecutionTimeLimit);

                // 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.ScheduledTaskStartBoundary.Hours,
                                           _settings.ScheduledTaskStartBoundary.Minutes,
                                           _settings.ScheduledTaskStartBoundary.Seconds);

                task.Triggers.Add(new DailyTrigger {
                    DaysInterval  = 1,
                    StartBoundary = runtime,
                    RandomDelay   = _settings.ScheduledTaskRandomDelay
                });
                task.Settings.ExecutionTimeLimit         = _settings.ScheduledTaskExecutionTimeLimit;
                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(currentExec, actionString, Path.GetDirectoryName(currentExec)));

                task.Principal.RunLevel = TaskRunLevel.Highest;
                while (true)
                {
                    try
                    {
                        if (!_options.UseDefaultTaskUser &&
                            _runLevel.HasFlag(RunLevel.Advanced) &&
                            _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 = _input.RequestString("Enter the username (Domain\\username)");
                            var password = _input.ReadPassword("Enter the user's password");
                            _log.Debug("Creating task to run as {username}", username);
                            taskService.RootFolder.RegisterTaskDefinition(
                                taskName,
                                task,
                                TaskCreation.Create,
                                username,
                                password,
                                TaskLogonType.Password);
                        }
                        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 = _input.ReadPassword($"Password for {username}");
                            }
                            task.Principal.UserId    = existingTask.Definition.Principal.UserId;
                            task.Principal.LogonType = existingTask.Definition.Principal.LogonType;
                            taskService.RootFolder.RegisterTaskDefinition(
                                taskName,
                                task,
                                TaskCreation.CreateOrUpdate,
                                username,
                                password,
                                existingTask.Definition.Principal.LogonType);
                        }
                        else
                        {
                            _log.Debug("Creating task to run as system user");
                            task.Principal.UserId    = "SYSTEM";
                            task.Principal.LogonType = TaskLogonType.ServiceAccount;
                            taskService.RootFolder.RegisterTaskDefinition(
                                taskName,
                                task,
                                TaskCreation.CreateOrUpdate,
                                null,
                                null,
                                TaskLogonType.ServiceAccount);
                        }
                        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;
                    }
                }
            }
        }