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