diff --git a/src/LetsEncrypt/Services/LetsEncryptService.cs b/src/LetsEncrypt/Services/LetsEncryptService.cs index 667d438..f45a593 100644 --- a/src/LetsEncrypt/Services/LetsEncryptService.cs +++ b/src/LetsEncrypt/Services/LetsEncryptService.cs @@ -107,7 +107,7 @@ public class LetsEncryptService : ILetsEncryptService { } else { // New Account request - + state.JwsService = new JwsService(accountKey); var letsEncryptOrder = new Account { TermsOfServiceAgreed = true, @@ -118,7 +118,7 @@ public class LetsEncryptService : ILetsEncryptService { if (!postAccountResult.IsSuccess || account?.Result?.Location == null) return postAccountResult; - state.JwsService = new JwsService(accountKey); + state.JwsService.SetKeyId(account.Result.Location.ToString()); if (account.Result.Status != "valid") { diff --git a/src/LetsEncryptServer/Services/CertsFlowService.cs b/src/LetsEncryptServer/Services/CertsFlowService.cs index 313d9ce..26185db 100644 --- a/src/LetsEncryptServer/Services/CertsFlowService.cs +++ b/src/LetsEncryptServer/Services/CertsFlowService.cs @@ -154,9 +154,13 @@ public class CertsFlowService : ICertsFlowService { if (!uploadResult.IsSuccess) return (null, uploadResult); - var notifyResult = NotifyHaproxy(results.Select(x => x.Key)); - if (!notifyResult.IsSuccess) - return (null, notifyResult); + //var notifyResult = NotifyHaproxy(results); + //if (!notifyResult.IsSuccess) + // return (null, notifyResult); + + var reloadResult = ReloadServer(); + if (!reloadResult.IsSuccess) + return (null, reloadResult); return IDomainResult.Success(results); } @@ -201,8 +205,40 @@ public class CertsFlowService : ICertsFlowService { return IDomainResult.Success(); } + private IDomainResult ReloadServer() { + var server = _appSettings.Server; - private IDomainResult NotifyHaproxy(IEnumerable certFiles) { + try { + using (SSHService sshClient = (server.PrivateKeys != null && server.PrivateKeys.Any(x => !string.IsNullOrWhiteSpace(x))) + ? new SSHService(_logger, server.Ip, server.SSHPort, server.Username, server.PrivateKeys) + : !string.IsNullOrWhiteSpace(server.Password) + ? new SSHService(_logger, server.Ip, server.SSHPort, server.Username, server.Password) + : throw new ArgumentNullException("Neither private keys nor password was provided")) { + + var sshConnectResult = sshClient.Connect(); + if (!sshConnectResult.IsSuccess) + return sshConnectResult; + + // TODO: Prefer to create the native linux service which can receive the signal to reload the services + return sshClient.RunSudoCommand("", "systemctl reload haproxy"); + } + } + catch (Exception ex) { + var message = "Unable to upload files to remote server"; + _logger.LogError(ex, message); + + return IDomainResult.CriticalDependencyError(message); + } + + return IDomainResult.Success(); + } + + /// + /// Currently not working + /// + /// + /// + private IDomainResult NotifyHaproxy(Dictionary results) { var server = _appSettings.Server; try { @@ -212,25 +248,38 @@ public class CertsFlowService : ICertsFlowService { using (var reader = new StreamReader(networkStream, Encoding.ASCII)) { writer.AutoFlush = true; - foreach (var certFile in certFiles) { + foreach (var result in results) { + var certFile = result.Key; // Prepare the certificate - string prepareCommand = $"new ssl cert {server.Path}/{certFile}\n"; + string prepareCommand = $"new ssl cert {server.Path}/{certFile}"; writer.WriteLine(prepareCommand); + writer.Flush(); string prepareResponse = reader.ReadLine(); - if (prepareResponse.Contains("error", StringComparison.OrdinalIgnoreCase)) { - _logger.LogError($"Error while preparing certificate {certFile}: {prepareResponse}"); - return IDomainResult.CriticalDependencyError($"Error while preparing certificate {certFile}"); - } + //if (prepareResponse.Contains("error", StringComparison.OrdinalIgnoreCase)) { + // _logger.LogError($"Error while preparing certificate {certFile}: {prepareResponse}"); + // return IDomainResult.CriticalDependencyError($"Error while preparing certificate {certFile}"); + //} + + // Set the certificate + string setCommand = $"set ssl cert {server.Path}/{certFile} <<\n{result.Value}\n"; + writer.WriteLine(setCommand); + writer.Flush(); + string setResponse = reader.ReadLine(); + //if (setResponse.Contains("error", StringComparison.OrdinalIgnoreCase)) { + // _logger.LogError($"Error while setting certificate {certFile}: {setResponse}"); + // return IDomainResult.CriticalDependencyError($"Error while setting certificate {certFile}"); + //} // Commit the certificate - string commitCommand = $"commit ssl cert {server.Path}/{certFile}\n"; + string commitCommand = $"commit ssl cert {server.Path}/{certFile}"; writer.WriteLine(commitCommand); + writer.Flush(); string commitResponse = reader.ReadLine(); - if (commitResponse.Contains("error", StringComparison.OrdinalIgnoreCase)) { - _logger.LogError($"Error while committing certificate {certFile}: {commitResponse}"); - return IDomainResult.CriticalDependencyError($"Error while committing certificate {certFile}"); - } + //if (commitResponse.Contains("error", StringComparison.OrdinalIgnoreCase)) { + // _logger.LogError($"Error while committing certificate {certFile}: {commitResponse}"); + // return IDomainResult.CriticalDependencyError($"Error while committing certificate {certFile}"); + //} } _logger.LogInformation("Certificates committed successfully."); @@ -248,6 +297,7 @@ public class CertsFlowService : ICertsFlowService { + private void DeleteExporedChallenges() { var currentDate = DateTime.Now; diff --git a/src/SSHProvider/SSHService.cs b/src/SSHProvider/SSHService.cs index 419f4b0..b39e609 100644 --- a/src/SSHProvider/SSHService.cs +++ b/src/SSHProvider/SSHService.cs @@ -125,42 +125,36 @@ namespace MaksIT.SSHProvider { } public IDomainResult RunSudoCommand(string password, string command) { - try { command = $"sudo {command}"; + using (var shellStream = _sshClient.CreateShellStream("xterm", 80, 24, 800, 600, 1024, new Dictionary { + { TerminalModes.ECHO, 53 } + })) { + // Get logged in + string rep = shellStream.Expect(new Regex(@"[$>]"), TimeSpan.FromSeconds(10)); // expect user prompt with timeout + _logger.LogInformation("Initial prompt: {Prompt}", rep); - var shellStream = _sshClient.CreateShellStream("xterm", 80, 24, 800, 600, 1024, new Dictionary { - { TerminalModes.ECHO, 53 } - }); + // Send command + shellStream.WriteLine(command); + rep = shellStream.Expect(new Regex(@"([$#>:])"), TimeSpan.FromSeconds(10)); // expect password or user prompt with timeout + _logger.LogInformation("After command prompt: {Prompt}", rep); - //Get logged in - string rep = shellStream.Expect(new Regex(@"[$>]")); //expect user prompt - //this.writeOutput(results, rep); - _logger.LogInformation(rep); + // Check to send password + if (rep.Contains(":")) { + // Send password + shellStream.WriteLine(password); + rep = shellStream.Expect(new Regex(@"[$#>]"), TimeSpan.FromSeconds(10)); // expect user or root prompt with timeout + _logger.LogInformation("After password prompt: {Prompt}", rep); + } - //send command - shellStream.WriteLine(command); - rep = shellStream.Expect(new Regex(@"([$#>:])")); //expect password or user prompt - _logger.LogInformation(rep); - - //check to send password - if (rep.Contains(":")) { - //send password - shellStream.WriteLine(password); - rep = shellStream.Expect(new Regex(@"[$#>]")); //expect user or root prompt - _logger.LogInformation(rep); + return IDomainResult.Success(); } - - return IDomainResult.Success(); } catch (Exception ex) { - _logger.LogError(ex, "SSH Service unhandled exeption"); + _logger.LogError(ex, "SSH Service unhandled exception"); return IDomainResult.CriticalDependencyError(); } - - - } public void Dispose() {