static void Main(string[] args) { Log.Logger = new LoggerConfiguration() .ReadFrom.AppSettings() .CreateLogger(); Log.Information("The global logger has been configured"); var commandLineParseResult = Parser.Default.ParseArguments<Options>(args); var parsed = commandLineParseResult as Parsed<Options>; if (parsed == null) { #if DEBUG Log.Debug("Program Debug Enabled"); Console.WriteLine("Press enter to continue."); Console.ReadLine(); #endif return; // not parsed } Options = parsed.Value; Log.Debug("{@Options}", Options); Console.WriteLine("Let's Encrypt (Simple Windows ACME Client)"); BaseURI = Options.BaseURI; if (Options.Test) { BaseURI = "https://acme-staging.api.letsencrypt.org/"; Log.Debug("Test paramater set: {BaseURI}", BaseURI); } if (Options.SAN) { Log.Debug("SAN Option Enabled: Running per site and not per host"); } Console.WriteLine($"\nACME Server: {BaseURI}"); Log.Information("ACME Server: {BaseURI}", BaseURI); if (!string.IsNullOrWhiteSpace(Options.CentralSSLStore)) { Console.WriteLine("Using Centralized SSL Path: " + Options.CentralSSLStore); Log.Information("Using Centralized SSL Path: {CentralSSLStore}", Options.CentralSSLStore); CentralSSL = true; } settings = new Settings(clientName, BaseURI); Log.Debug("{@settings}", settings); configPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), clientName, CleanFileName(BaseURI)); Console.WriteLine("Config Folder: " + configPath); Log.Information("Config Folder: {configPath}", configPath); Directory.CreateDirectory(configPath); certificatePath = Properties.Settings.Default.CertificatePath; if (string.IsNullOrWhiteSpace(certificatePath)) { certificatePath = configPath; } else { try { Directory.CreateDirectory(certificatePath); } catch (Exception ex) { Console.WriteLine($"Error creating the certificate directory, {certificatePath}. Defaulting to config path"); Log.Warning("Error creating the certificate directory, {certificatePath}. Defaulting to config path. Error: {@ex}", certificatePath, ex); certificatePath = configPath; } } Console.WriteLine("Certificate Folder: " + certificatePath); Log.Information("Certificate Folder: {certificatePath}", certificatePath); try { using (var signer = new RS256Signer()) { signer.Init(); var signerPath = Path.Combine(configPath, "Signer"); if (File.Exists(signerPath)) { Console.WriteLine($"Loading Signer from {signerPath}"); Log.Information("Loading Signer from {signerPath}", signerPath); using (var signerStream = File.OpenRead(signerPath)) signer.Load(signerStream); } using (client = new AcmeClient(new Uri(BaseURI), new AcmeServerDirectory(), signer)) { client.Init(); Console.WriteLine("\nGetting AcmeServerDirectory"); Log.Information("Getting AcmeServerDirectory"); client.GetDirectory(true); var registrationPath = Path.Combine(configPath, "Registration"); if (File.Exists(registrationPath)) { Console.WriteLine($"Loading Registration from {registrationPath}"); Log.Information("Loading Registration from {registrationPath}", registrationPath); using (var registrationStream = File.OpenRead(registrationPath)) client.Registration = AcmeRegistration.Load(registrationStream); } else { Console.Write("Enter an email address (not public, used for renewal fail notices): "); var email = Console.ReadLine().Trim(); var contacts = new string[] { }; if (!String.IsNullOrEmpty(email)) { Log.Debug("Registration email: {email}", email); email = "mailto:" + email; contacts = new string[] { email }; } Console.WriteLine("Calling Register"); Log.Information("Calling Register"); var registration = client.Register(contacts); if (!Options.AcceptTOS && !Options.Renew) { Console.WriteLine($"Do you agree to {registration.TosLinkUri}? (Y/N) "); if (!PromptYesNo()) return; } Console.WriteLine("Updating Registration"); Log.Information("Updating Registration"); client.UpdateRegistration(true, true); Console.WriteLine("Saving Registration"); Log.Information("Saving Registration"); using (var registrationStream = File.OpenWrite(registrationPath)) client.Registration.Save(registrationStream); Console.WriteLine("Saving Signer"); Log.Information("Saving Signer"); using (var signerStream = File.OpenWrite(signerPath)) signer.Save(signerStream); } if (Options.Renew) { CheckRenewals(); #if DEBUG Console.WriteLine("Press enter to continue."); Console.ReadLine(); #endif return; } var targets = new List<Target>(); if (!Options.SAN) { foreach (var plugin in Target.Plugins.Values) { targets.AddRange(plugin.GetTargets()); } } else { foreach (var plugin in Target.Plugins.Values) { targets.AddRange(plugin.GetSites()); } } if (targets.Count == 0) { Console.WriteLine("No targets found."); Log.Error("No targets found."); } else { int HostsPerPage = 50; try { HostsPerPage = Properties.Settings.Default.HostsPerPage; } catch (Exception ex) { Log.Error("Error getting HostsPerPage setting, setting to default value. Error: {@ex}", ex); } var count = 1; if (targets.Count > HostsPerPage) { do { if ((count + HostsPerPage) <= targets.Count) { int stop = count + HostsPerPage; for (int i = count; i < stop; i++) { if (!Options.SAN) { Console.WriteLine($" {count}: {targets[count - 1]}"); } else { Console.WriteLine($" {count}: SAN - {targets[count - 1]}"); } count++; } } else { for (int i = count; i <= targets.Count; i++) { if (!Options.SAN) { Console.WriteLine($" {count}: {targets[count - 1]}"); } else { Console.WriteLine($" {count}: SAN - {targets[count - 1]}"); } count++; } } if (count < targets.Count) { Console.WriteLine(" Q: Quit"); Console.Write("Press enter to continue to next page "); var continueResponse = Console.ReadLine().ToLowerInvariant(); switch (continueResponse) { case "q": throw new Exception($"Requested to quit application"); default: break; } } } while (count < targets.Count); } else { foreach (var binding in targets) { Console.WriteLine($" {count}: {binding}"); count++; } } } Console.WriteLine(); foreach (var plugin in Target.Plugins.Values) { plugin.PrintMenu(); } Console.WriteLine(" A: Get certificates for all hosts"); Console.WriteLine(" Q: Quit"); Console.Write("Which host do you want to get a certificate for: "); var response = Console.ReadLine().ToLowerInvariant(); switch (response) { case "a": foreach (var target in targets) { Auto(target); } break; case "q": return; default: var targetId = 0; if (Int32.TryParse(response, out targetId)) { targetId--; if (targetId >= 0 && targetId < targets.Count) { var binding = targets[targetId]; Auto(binding); } } else { foreach (var plugin in Target.Plugins.Values) { plugin.HandleMenuResponse(response, targets); } } break; } } } } catch (Exception e) { Log.Error("Error {@e}", e); Console.ForegroundColor = ConsoleColor.Red; var acmeWebException = e as AcmeClient.AcmeWebException; if (acmeWebException != null) { Console.WriteLine(acmeWebException.Message); Console.WriteLine("ACME Server Returned:"); Console.WriteLine(acmeWebException.Response.ContentAsString); } else { Console.WriteLine(e); } Console.ResetColor(); } Console.WriteLine("Press enter to continue."); Console.ReadLine(); }
private static bool TryParseOptions(string[] args) { try { var commandLineParseResult = Parser.Default.ParseArguments<Options>(args); var parsed = commandLineParseResult as Parsed<Options>; if (parsed == null) { LogParsingErrorAndWaitForEnter(); return false; // not parsed } Options = parsed.Value; Log.Debug("{@Options}", Options); return true; } catch { Console.WriteLine("Failed while parsing options."); throw; } }
static void Main(string[] args) { var commandLineParseResult = Parser.Default.ParseArguments<Options>(args); var parsed = commandLineParseResult as Parsed<Options>; if (parsed == null) { #if DEBUG Console.WriteLine("Press enter to continue."); Console.ReadLine(); #endif return; // not parsed } Options = parsed.Value; Console.WriteLine("Let's Encrypt (Simple Windows ACME Client)"); BaseURI = Options.BaseURI; if (Options.Test) BaseURI = "https://acme-staging.api.letsencrypt.org/"; //Console.Write("\nUse production Let's Encrypt server? (Y/N) "); //if (PromptYesNo()) // BaseURI = ProductionBaseURI; Console.WriteLine($"\nACME Server: {BaseURI}"); if (!string.IsNullOrWhiteSpace(Options.CentralSSLStore)) { Console.WriteLine("Using Centralized SSL Path: " + Options.CentralSSLStore); CentralSSL = true; } settings = new Settings(clientName, BaseURI); configPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), clientName, CleanFileName(BaseURI)); Console.WriteLine("Config Folder: " + configPath); Directory.CreateDirectory(configPath); try { using (var signer = new RS256Signer()) { signer.Init(); var signerPath = Path.Combine(configPath, "Signer"); if (File.Exists(signerPath)) { Console.WriteLine($"Loading Signer from {signerPath}"); using (var signerStream = File.OpenRead(signerPath)) signer.Load(signerStream); } using (client = new AcmeClient(new Uri(BaseURI), new AcmeServerDirectory(), signer)) { client.Init(); Console.WriteLine("\nGetting AcmeServerDirectory"); client.GetDirectory(true); var registrationPath = Path.Combine(configPath, "Registration"); if (File.Exists(registrationPath)) { Console.WriteLine($"Loading Registration from {registrationPath}"); using (var registrationStream = File.OpenRead(registrationPath)) client.Registration = AcmeRegistration.Load(registrationStream); } else { Console.Write("Enter an email address (not public, used for renewal fail notices): "); var email = Console.ReadLine().Trim(); var contacts = new string[] { }; if (!String.IsNullOrEmpty(email)) { email = "mailto:" + email; contacts = new string[] { email }; } Console.WriteLine("Calling Register"); var registration = client.Register(contacts); if (!Options.AcceptTOS && !Options.Renew) { Console.WriteLine($"Do you agree to {registration.TosLinkUri}? (Y/N) "); if (!PromptYesNo()) return; } Console.WriteLine("Updating Registration"); client.UpdateRegistration(true, true); Console.WriteLine("Saving Registration"); using (var registrationStream = File.OpenWrite(registrationPath)) client.Registration.Save(registrationStream); Console.WriteLine("Saving Signer"); using (var signerStream = File.OpenWrite(signerPath)) signer.Save(signerStream); } if (Options.Renew) { CheckRenewals(); #if DEBUG Console.WriteLine("Press enter to continue."); Console.ReadLine(); #endif return; } var targets = new List<Target>(); foreach (var plugin in Target.Plugins.Values) { targets.AddRange(plugin.GetTargets()); } if (targets.Count == 0) { Console.WriteLine("No targets found."); } else { var count = 1; foreach (var binding in targets) { Console.WriteLine($" {count}: {binding}"); count++; } } Console.WriteLine(); foreach (var plugin in Target.Plugins.Values) { plugin.PrintMenu(); } Console.WriteLine(" A: Get certificates for all hosts"); Console.WriteLine(" Q: Quit"); Console.Write("Which host do you want to get a certificate for: "); var response = Console.ReadLine().ToLowerInvariant(); switch (response) { case "a": foreach (var target in targets) { Auto(target); } break; case "q": return; default: var targetId = 0; if (Int32.TryParse(response, out targetId)) { targetId--; if (targetId >= 0 && targetId < targets.Count) { var binding = targets[targetId]; Auto(binding); } } else { foreach (var plugin in Target.Plugins.Values) { plugin.HandleMenuResponse(response, targets); } } break; } } } } catch (Exception e) { Console.ForegroundColor = ConsoleColor.Red; var acmeWebException = e as AcmeClient.AcmeWebException; if (acmeWebException != null) { Console.WriteLine(acmeWebException.Message); Console.WriteLine("ACME Server Returned:"); Console.WriteLine(acmeWebException.Response.ContentAsString); } else { Console.WriteLine(e); } Console.ResetColor(); } Console.WriteLine("Press enter to continue."); Console.ReadLine(); }
static void Main(string[] args) { var commandLineParseResult = Parser.Default.ParseArguments<Options>(args); var parsed = commandLineParseResult as Parsed<Options>; if (parsed == null) { #if DEBUG Console.WriteLine("Press enter to continue."); Console.ReadLine(); #endif return; // not parsed } options = parsed.Value; Console.WriteLine("Let's Encrypt (Simple Windows ACME Client)"); BaseURI = options.BaseURI; if (options.Test) BaseURI = "https://acme-staging.api.letsencrypt.org/"; //Console.Write("\nUse production Let's Encrypt server? (Y/N) "); //if (PromptYesNo()) // BaseURI = ProductionBaseURI; Console.WriteLine($"\nACME Server: {BaseURI}"); settings = new Settings(clientName, BaseURI); configPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), clientName, CleanFileName(BaseURI)); Console.WriteLine("Config Folder: " + configPath); Directory.CreateDirectory(configPath); using (var signer = new RS256Signer()) { signer.Init(); var signerPath = Path.Combine(configPath, "Signer"); if (File.Exists(signerPath)) { Console.WriteLine($"Loading Signer from {signerPath}"); using (var signerStream = File.OpenRead(signerPath)) signer.Load(signerStream); } using (client = new AcmeClient(new Uri(BaseURI), new AcmeServerDirectory(), signer)) { client.Init(); Console.WriteLine("\nGetting AcmeServerDirectory"); client.GetDirectory(true); var registrationPath = Path.Combine(configPath, "Registration"); if (File.Exists(registrationPath)) { Console.WriteLine($"Loading Registration from {registrationPath}"); using (var registrationStream = File.OpenRead(registrationPath)) client.Registration = AcmeRegistration.Load(registrationStream); } else { Console.WriteLine("Calling Register"); var registration = client.Register(new string[] { }); if (!options.AcceptTOS && !options.Renew) { Console.WriteLine($"Do you agree to {registration.TosLinkUri}? (Y/N) "); if (!PromptYesNo()) return; } Console.WriteLine("Updating Registration"); client.UpdateRegistration(true, true); Console.WriteLine("Saving Registration"); using (var registrationStream = File.OpenWrite(registrationPath)) client.Registration.Save(registrationStream); Console.WriteLine("Saving Signer"); using (var signerStream = File.OpenWrite(signerPath)) signer.Save(signerStream); } if (options.Renew) { CheckRenewals(); #if DEBUG Console.WriteLine("Press enter to continue."); Console.ReadLine(); #endif return; } Console.WriteLine("\nScanning IIS 7 Site Bindings for Hosts (Elevated Permissions Required)"); if (!IsElevated) { Console.WriteLine("Elevated Permissions Required. Please run under an administrator console."); #if DEBUG Console.WriteLine("Press enter to continue."); Console.ReadLine(); #endif return; } var bindings = GetHostNames(); if (bindings.Count == 0) { Console.WriteLine("No IIS bindings with host names were found. Please add one using IIS Manager. A host name and site path are required to verify domain ownership."); return; } Console.WriteLine("IIS Bindings"); var count = 1; foreach (var binding in bindings) { Console.WriteLine($" {count}: {binding}"); count++; } Console.WriteLine(); Console.WriteLine(" A: Get Certificates for All Bindings"); Console.WriteLine(" Q: Quit"); Console.Write("Which binding do you want to get a cert for: "); var response = Console.ReadLine(); switch (response.ToLowerInvariant()) { case "a": foreach (var binding in bindings) { Auto(binding); } break; case "q": return; default: var bindingId = 0; if (Int32.TryParse(response, out bindingId)) { bindingId--; if (bindingId >= 0 && bindingId < bindings.Count) { var binding = bindings[bindingId]; Auto(binding); } } break; } } } #if DEBUG Console.WriteLine("Press enter to continue."); Console.ReadLine(); #endif }