public void Run(RunOptions options) { config = GetConfig(options); logger.Info("Loaded {0} with {1} triggers and {2} services", options.ConfigFile, config.Triggers.Count, config.Services.Count); // Secrets stores must be loaded before any services or notifyservices as they can use it in their options var secretsStoreTypes = GetSubTypes(typeof(BaseSecretsStore)); logger.Debug("Loaded {0} secrets store types", secretsStoreTypes.Count); var secretsStores = new List <Tuple <BaseSecretsStore, SecretsStoreConfig> >(); if (config.SecretsStores != null) { foreach (var secretsStoreConfig in config.SecretsStores) { var secretsStoreType = secretsStoreTypes.SingleOrDefault(t => t.Name.Equals(secretsStoreConfig.Type, StringComparison.InvariantCultureIgnoreCase)); if (secretsStoreType == null) { logger.Error("Unable to find secrets store {0}, skipping", secretsStoreConfig.Type); } else { try { logger.Debug("Adding secrets store {0}", secretsStoreType.FullName); // secretsStoreConfig.Options is a JObject, we need to convert it to the SecretsStoreOptions on the service // This is kind of dirty (see BaseService discussion) but it works var secretsStoreOptionsType = secretsStoreType.GetNestedType("SecretsStoreOptions", BindingFlags.Public | BindingFlags.NonPublic); if (secretsStoreOptionsType == null) { logger.Trace("Did not locate SecretsStoreOptions nested type for secrets store {0}", secretsStoreOptionsType.FullName); secretsStoreConfig.Options = null; } else { logger.Trace("Located SecretsStoreOptions nested type {0} for secrets store {1}", secretsStoreOptionsType.FullName, secretsStoreOptionsType.FullName); secretsStoreConfig.Options = ((JObject)secretsStoreConfig.Options).ToObject(secretsStoreOptionsType); } var secretsStore = (BaseSecretsStore)Activator.CreateInstance(secretsStoreType, secretsStoreConfig.Options); secretsStores.Add(new Tuple <BaseSecretsStore, SecretsStoreConfig>(secretsStore, secretsStoreConfig)); logger.Info("Loaded secrets store {0}", secretsStoreConfig.Type); } catch (Exception ex) { logger.Error(ex, "Error while loading secrets store {0}, skipping", secretsStoreConfig.Type); } } } } secretsStoreManager = new SecretsStoreManager(secretsStores); var notifyServiceTypes = GetSubTypes(typeof(BaseNotifyService)); logger.Debug("Loaded {0} notify service types", notifyServiceTypes.Count); if (config.NotifyServices != null) { foreach (var notifyServiceConfig in config.NotifyServices) { var notifyServiceType = notifyServiceTypes.SingleOrDefault(t => t.Name.Equals(notifyServiceConfig.Type, StringComparison.InvariantCultureIgnoreCase)); if (notifyServiceType == null) { logger.Error("Unable to find notify service {0}, skipping", notifyServiceConfig.Type); } else { try { logger.Debug("Adding notify service {0}", notifyServiceType.FullName); // notifyServiceConfig.Options is a JObject, we need to convert it to the ServiceOptions on the service // This is kind of dirty (see BaseService discussion) but it works var notifyServiceOptionsType = notifyServiceType.GetNestedType("NotifyServiceOptions", BindingFlags.Public | BindingFlags.NonPublic); if (notifyServiceOptionsType == null) { logger.Trace("Did not locate NotifyServiceOptions nested type for notify service {0}", notifyServiceType.FullName); notifyServiceConfig.Options = null; } else { logger.Trace("Located ServiceOptions nested type {0} for notify service {1}", notifyServiceOptionsType.FullName, notifyServiceType.FullName); notifyServiceConfig.Options = ((JObject)notifyServiceConfig.Options).ToObject(notifyServiceOptionsType); } var notifyService = (BaseNotifyService)Activator.CreateInstance(notifyServiceType, secretsStoreManager, notifyServiceConfig.Options); notifyServices.Add(new Tuple <BaseNotifyService, NotifyServiceConfig>(notifyService, notifyServiceConfig)); logger.Info("Loaded notify service {0}", notifyServiceConfig.Type); } catch (Exception ex) { logger.Error(ex, "Error while loading notify service {0}, skipping", notifyServiceConfig.Type); } } } } // Send notification ASAP about startup foreach (var notifyService in notifyServices.Where(t => t.Item2.NotifyStartup)) { try { notifyService.Item1.NotifyStartup(); } catch (Exception ex) { logger.Error(ex, "Error while trying to notify startup for notify service {0}", notifyService.Item2.Type); } } // Start up web server for multi-factor requests //if (config.EnableMultiFactorRequests) //{ #if DEBUG webServer = new SentryWebServer(options.MfaBindUrl); webServer.Start(); logger.Info("Started web server bound to {0}", options.MfaBindUrl); #endif //} var serviceTypes = GetSubTypes(typeof(BaseService)); logger.Debug("Loaded {0} service types", serviceTypes.Count); foreach (var serviceConfig in config.Services) { var serviceType = serviceTypes.SingleOrDefault(t => t.Name.Equals(serviceConfig.Type, StringComparison.InvariantCultureIgnoreCase)); if (serviceType == null) { logger.Error("Unable to find service {0}, skipping {1}", serviceConfig.Type, serviceConfig.Id); } else { try { logger.Debug("Adding service {0} with Id {1}", serviceType.FullName, serviceConfig.Id); // serviceConfig.Options is a JObject, we need to convert it to the ServiceOptions on the service // This is kind of dirty (see BaseService discussion) but it works var serviceOptionsType = serviceType.GetNestedType("ServiceOptions", BindingFlags.Public | BindingFlags.NonPublic); if (serviceOptionsType == null) { logger.Trace("Did not locate ServiceOptions nested type for service {0}", serviceType.FullName); serviceConfig.Options = null; } else { logger.Trace("Located ServiceOptions nested type {0} for service {1}", serviceOptionsType.FullName, serviceType.FullName); serviceConfig.Options = ((JObject)serviceConfig.Options).ToObject(serviceOptionsType); } var service = (BaseService)Activator.CreateInstance(serviceType, secretsStoreManager, serviceConfig.Id, serviceConfig.Options); services.Add(serviceConfig.Id.ToLowerInvariant(), service); logger.Info("Loaded service {0}", serviceConfig.Id); } catch (Exception ex) { logger.Error(ex, "Error while loading service {0}, skipping", serviceConfig.Id); } } } if (options.SkipVerify) { logger.Info("Skipping verify step"); } else { var servicesToRemove = new List <string>(); foreach (var service in services) { logger.Debug("Verifying {0}", service.Key); try { service.Value.Verify(); logger.Info("Verified {0}", service.Key); } catch (Exception ex) { logger.Error(ex, "Error verifying {0}, removing", service.Key); servicesToRemove.Add(service.Key); } } foreach (var serviceToRemove in servicesToRemove) { services.Remove(serviceToRemove); } } if (options.JustFuckMyShitUpFam) { if (options.SkipJFMSUFConfirmation) { logger.Info("Skipping JustFuckMyShitUpFam mode confirmation"); } else { logger.Warn("JustFuckMyShitUpFam mode requested"); Console.WriteLine("**********************************************************"); Console.WriteLine(" WARNING: JustFuckMyShitUpFam mode will run ALL triggers"); Console.WriteLine(" As if ALL trigger phrases had been detected"); Console.WriteLine(" The following actions will be performed:"); Console.WriteLine(""); var triggerConfigs = config.Triggers.SelectMany(t => t.Services).ToList(); foreach (var trigger in triggerConfigs) { var actionsAggregated = trigger.Actions.Aggregate((sum, addition) => sum + ", " + addition); Console.WriteLine(" Service: " + trigger.Id + " Actions: " + actionsAggregated); } Console.WriteLine(""); Console.WriteLine(" These actions may not be reversible"); Console.WriteLine(" There is no additional confirmation or delay"); Console.WriteLine(" Are you SURE you want to do this?"); Console.WriteLine("**********************************************************"); Console.Write("Enter JFMSUF to confirm: "); var userInput = Console.ReadLine(); if (userInput != "JFMSUF") { logger.Info("JustFuckMyShitUpFam mode canceled"); Environment.Exit(1); return; } } JFMSUF(options); } else { // Start main checking loop Loop(options); } // If cancellation is requested via cancellationToken, this exits the main thread exitEvent.Set(); }
protected BaseNotifyService(SecretsStoreManager secretsStoreManager) { this.logger = LogManager.GetLogger(this.GetType().Name); this.secretsStoreManager = secretsStoreManager; }
protected BaseService(SecretsStoreManager secretsStoreManager, string id) { this.logger = LogManager.GetLogger(id); this.secretsStoreManager = secretsStoreManager; }
/** * NotifyServices should implement this constructor. * Ideally implement a sub-class called "NotifyServiceOptions" and it will be casted here */ public BaseNotifyService(SecretsStoreManager secretsStoreManager, object NotifyServiceOptions) : this(secretsStoreManager) { }
/** * Services should implement this constructor. * Ideally implement a sub-class called "ServiceOptions" and it will be casted here */ public BaseService(SecretsStoreManager secretsStoreManager, string id, object ServiceOptions) : this(secretsStoreManager, id) { }