comparison ServerMonitor/Objects/ServerMonitor.cs @ 5:b6fe203af9d5

Private key passwords and validation
author Brad Greco <brad@bgreco.net>
date Thu, 28 Feb 2019 21:19:32 -0500
parents 3142e52cbe69
children c1dffaac66fa
comparison
equal deleted inserted replaced
4:3142e52cbe69 5:b6fe203af9d5
1 using ServerMonitorApp.Properties; 1 using Renci.SshNet;
2 using Renci.SshNet.Common;
3 using ServerMonitorApp.Properties;
2 using System; 4 using System;
3 using System.Collections.Generic; 5 using System.Collections.Generic;
4 using System.Diagnostics; 6 using System.Diagnostics;
5 using System.IO; 7 using System.IO;
6 using System.Linq; 8 using System.Linq;
16 public class ServerMonitor 18 public class ServerMonitor
17 { 19 {
18 private readonly string configFileDir; 20 private readonly string configFileDir;
19 private readonly Logger logger; 21 private readonly Logger logger;
20 private readonly Dictionary<int, CancellationTokenSource> tokens = new Dictionary<int, CancellationTokenSource>(); 22 private readonly Dictionary<int, CancellationTokenSource> tokens = new Dictionary<int, CancellationTokenSource>();
23 private readonly Dictionary<string, PrivateKeyFile> privateKeys = new Dictionary<string, PrivateKeyFile>();
21 private readonly List<int> pausedChecks = new List<int>(); 24 private readonly List<int> pausedChecks = new List<int>();
22 private bool running, networkAvailable; 25 private bool running, networkAvailable;
23 private Dictionary<Task<CheckResult>, int> tasks; 26 private Dictionary<Task<CheckResult>, int> tasks;
24 private ServerSummaryForm mainForm; 27 private ServerSummaryForm mainForm;
25 28
30 public List<Server> Servers { get; private set; } = new List<Server>(); 33 public List<Server> Servers { get; private set; } = new List<Server>();
31 34
32 public IEnumerable<Check> Checks => Servers.SelectMany(s => s.Checks); 35 public IEnumerable<Check> Checks => Servers.SelectMany(s => s.Checks);
33 36
34 public string ConfigFile { get; private set; } 37 public string ConfigFile { get; private set; }
38
39 public IEnumerable<string> LockedKeys { get { return privateKeys.Where(kvp => kvp.Value == null).Select(kvp => kvp.Key); } }
35 40
36 public ServerMonitor(ServerSummaryForm mainForm) 41 public ServerMonitor(ServerSummaryForm mainForm)
37 { 42 {
38 this.mainForm = mainForm; 43 this.mainForm = mainForm;
39 configFileDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ServerMonitor"); 44 configFileDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ServerMonitor");
65 // Update the Checks so they know what Server they belong to. 70 // Update the Checks so they know what Server they belong to.
66 // Would rather do this in the Server object on deserialization, but 71 // Would rather do this in the Server object on deserialization, but
67 // that doesn't work when using the XML serializer for some reason. 72 // that doesn't work when using the XML serializer for some reason.
68 foreach (Server server in Servers) 73 foreach (Server server in Servers)
69 { 74 {
75 if (server.LoginType == LoginType.PrivateKey)
76 OpenPrivateKey(server.KeyFile);
70 foreach (Check check in server.Checks) 77 foreach (Check check in server.Checks)
71 { 78 {
72 check.Server = server; 79 check.Server = server;
73 if (check.Status == CheckStatus.Running) 80 if (check.Status == CheckStatus.Running)
74 check.Status = check.LastRunStatus; 81 check.Status = check.LastRunStatus;
234 } 241 }
235 242
236 private void CancelCheck(Check check) 243 private void CancelCheck(Check check)
237 { 244 {
238 Task<CheckResult> task = tasks.FirstOrDefault(kvp => kvp.Value == check.Id).Key; 245 Task<CheckResult> task = tasks.FirstOrDefault(kvp => kvp.Value == check.Id).Key;
239 tasks.Remove(task); 246 if (task != null)
247 tasks.Remove(task);
240 pausedChecks.RemoveAll(id => id == check.Id); 248 pausedChecks.RemoveAll(id => id == check.Id);
241 if (tokens.TryGetValue(check.Id, out CancellationTokenSource cts)) 249 if (tokens.TryGetValue(check.Id, out CancellationTokenSource cts))
242 cts.Cancel(); 250 cts.Cancel();
243 } 251 }
244 252
267 networkAvailable = Helpers.IsNetworkAvailable(); 275 networkAvailable = Helpers.IsNetworkAvailable();
268 if (networkAvailable) 276 if (networkAvailable)
269 mainForm.Invoke((MethodInvoker)(() => Run())); 277 mainForm.Invoke((MethodInvoker)(() => Run()));
270 } 278 }
271 279
280 public KeyStatus OpenPrivateKey(string path, string password = null)
281 {
282 KeyStatus keyStatus;
283 if (path == null)
284 return KeyStatus.NotAccessible;
285 if (privateKeys.TryGetValue(path, out PrivateKeyFile key) && key != null)
286 return KeyStatus.Open;
287 try
288 {
289 key = new PrivateKeyFile(path, password);
290 keyStatus = KeyStatus.Open;
291 }
292 catch (Exception e) when (e is SshPassPhraseNullOrEmptyException || e is InvalidOperationException)
293 {
294 keyStatus = KeyStatus.NeedPassword;
295 }
296 catch (Exception)
297 {
298 keyStatus = KeyStatus.NotAccessible;
299 }
300 foreach (Server server in Servers)
301 {
302 if (server.KeyFile == path)
303 {
304 server.PrivateKeyFile = key;
305 server.KeyStatus = keyStatus;
306 }
307 }
308 privateKeys[path] = key;
309 return keyStatus;
310 }
311
272 private void GenerateIds() 312 private void GenerateIds()
273 { 313 {
274 if (Servers.Any()) 314 if (Servers.Any())
275 { 315 {
276 int id = Servers.Max(s => s.Id); 316 int id = Servers.Max(s => s.Id);