def __init__(self, logger): self.environ = Environment() self.logger = logger self.ch = CommandHelper(self.logger) self.yumloc = "/usr/bin/yum" self.install = self.yumloc + " install -y " self.remove = self.yumloc + " remove -y " self.search = self.yumloc + " list " self.checkupdates = self.search + "updates " self.listavail = self.search + "available " self.listinstalled = self.search + "installed " self.updatepkg = self.yumloc + " update -y --obsoletes " myos = self.environ.getostype().lower() if re.search("red hat.*?release 6", myos) or \ re.search("^centos$", myos.strip()): self.rpmloc = "/bin/rpm" else: self.rpmloc = "/usr/bin/rpm" self.provides = self.rpmloc + " -qf " self.query = self.rpmloc + " -qa "
def setUp(self): ''' Setup what we need for the test. @author: ekkehard j. koch @param self:essential if you override this definition ''' self.environ = Environment() self.environ.setverbosemode(True) self.environ.setdebugmode(True) self.config = Configuration(self.environ) self.logdispatch = LogDispatcher(self.environ) self.statechglogger = StateChgLogger(self.logdispatch, self.environ) self.rule = None self.rulename = "" self.rulenumber = ""
def __init__(self): self.unittestprefix = 'zzzTestFramework' self.initlist = ['__init__.py', '__init__.pyc', '__init__.pyo'] self.environ = Environment() self.environ.setdebugmode(False) self.environ.setverbosemode(True) self.effectiveUserID = self.environ.geteuid() self.config = Configuration(self.environ) self.logdispatch = LogDispatcher(self.environ) self.statechglogger = StateChgLogger(self.logdispatch, self.environ) self.scriptPath = self.environ.get_script_path() self.stonixPath = self.environ.get_resources_path() self.rulesPath = self.environ.get_rules_path() self.frameworkpath = self.stonixPath + "/" self.frameworkdictionary = {} self.keys = None self.key = None self.keyIndexNumber = 0 self.keysNumberOf = 0 self.dictinaryItem = None self.initializeDictionary()
def __init__(self): Observable.__init__(self) self.environ = Environment() self.mode = "gui" self.fix = False self.report = False self.undo = False self.runrule = None self.pcf = False self.pcs = False self.list = False if not self.safetycheck(): self.logger.log(LogPriority.CRITICAL, ['SafetyCheck', 'ERROR: Installation safety checks failed!']) self.logger.log(LogPriority.WARNING, ['SafetyCheck', 'STONIX files may only be writable by the ' + 'root user!']) self.logger.log(LogPriority.WARNING, ['SafetyCheck', 'Validate and correct permissions on all ' + 'STONIX files and try again.']) self.logger.log(LogPriority.WARNING, ['SafetyCheck', 'STONIX will now exit.']) sys.exit(1) self.lockfile = '/var/run/stonix.pid' if(self.environ.get_test_mode()): self.setuptesting() if not self.mode == 'test': self.prog_args = ProgramArguments() self.processargs() self.config = Configuration(self.environ) self.numrulesrunning = 0 self.numrulescomplete = 0 self.currulename = '' self.currulenum = 0 self.logger = LogDispatcher(self.environ) self.logger.log(LogPriority.DEBUG, 'Logging Started') self.tryacquirelock() if self.mode == 'gui': # This resets the UI to the command line if GUI was selected on the # command line and PyQt4 isn't present. if 'PyQt4' not in sys.modules and self.mode == 'gui': self.mode = 'cli' self.logger.log(LogPriority.ERROR, 'GUI Selected but PyQt4 not available. ' + 'Please install PyQt4 and dependencies for ' + 'GUI functionality.') else: app = QtGui.QApplication(sys.argv) splashart = os.path.join(self.environ.get_icon_path(), 'StonixSplash.png') splashimage = QtGui.QPixmap(splashart) splash = QtGui.QSplashScreen(splashimage, QtCore.Qt.WindowStaysOnTopHint) splash.setMask(splashimage.mask()) splash.show() app.processEvents() self.statechglogger = StateChgLogger(self.logger, self.environ) # NB We don't have a main event loop at this point so we call # the app.processEvents() again to make the splash screen show if self.mode == 'gui': app.processEvents() self.logger.log(LogPriority.DEBUG, 'State Logger Started') if not(self.mode == 'test'): # This resets the UI to the command line if GUI was selected on the # command line and PyQt4 isn't present. if 'PyQt4' not in sys.modules and self.mode == 'gui': self.mode = 'cli' self.logger.log(LogPriority.ERROR, 'GUI Selected but PyQt4 not available. ' + 'Please install PyQt4 and dependencies for ' + 'GUI functionality.') self.statechglogger = StateChgLogger(self.logger, self.environ) self.logger.log(LogPriority.DEBUG, 'State Logger Started') self.logger.log(LogPriority.DEBUG, 'Running in ' + self.mode) starttime = time.time() allrules = self.getrules(self.config, self.environ) etime = time.time() - starttime self.logger.log(LogPriority.DEBUG, 'Rules Processed in ' + str(etime)) self.installedrules = self.findapplicable(allrules) etime = time.time() - starttime self.logger.log(LogPriority.DEBUG, 'Rules Applicable in ' + str(etime)) self.numexecutingrules = len(self.installedrules) self.environ.setnumrules(self.numexecutingrules) self.logger.logRuleCount() self.logger.log(LogPriority.DEBUG, str(self.numexecutingrules) + ' rules loaded') self.logger.log(LogPriority.DEBUG, ['CurrentEUID', str(self.environ.geteuid())]) self.logger.log(LogPriority.DEBUG, ['OSFamily', self.environ.getosfamily()]) self.logger.log(LogPriority.DEBUG, ['OSType', self.environ.getostype()]) self.logger.log(LogPriority.DEBUG, ['OSVersion', self.environ.getosver()]) self.list = self.prog_args.getList() if self.list: self.__listrules() if self.mode == 'cli': self.__clirun() elif self.mode == 'gui': myui = GUI(self, self.environ, self.logger) splash.finish(myui) sys.exit(app.exec_()) elif self.mode == 'test': pass
class Controller(Observable): """This is the main worker object for stonix. It handles the stand up and tear down of the rest of the program. """ def __init__(self): Observable.__init__(self) self.environ = Environment() self.mode = "gui" self.fix = False self.report = False self.undo = False self.runrule = None self.pcf = False self.pcs = False self.list = False if not self.safetycheck(): self.logger.log(LogPriority.CRITICAL, ['SafetyCheck', 'ERROR: Installation safety checks failed!']) self.logger.log(LogPriority.WARNING, ['SafetyCheck', 'STONIX files may only be writable by the ' + 'root user!']) self.logger.log(LogPriority.WARNING, ['SafetyCheck', 'Validate and correct permissions on all ' + 'STONIX files and try again.']) self.logger.log(LogPriority.WARNING, ['SafetyCheck', 'STONIX will now exit.']) sys.exit(1) self.lockfile = '/var/run/stonix.pid' if(self.environ.get_test_mode()): self.setuptesting() if not self.mode == 'test': self.prog_args = ProgramArguments() self.processargs() self.config = Configuration(self.environ) self.numrulesrunning = 0 self.numrulescomplete = 0 self.currulename = '' self.currulenum = 0 self.logger = LogDispatcher(self.environ) self.logger.log(LogPriority.DEBUG, 'Logging Started') self.tryacquirelock() if self.mode == 'gui': # This resets the UI to the command line if GUI was selected on the # command line and PyQt4 isn't present. if 'PyQt4' not in sys.modules and self.mode == 'gui': self.mode = 'cli' self.logger.log(LogPriority.ERROR, 'GUI Selected but PyQt4 not available. ' + 'Please install PyQt4 and dependencies for ' + 'GUI functionality.') else: app = QtGui.QApplication(sys.argv) splashart = os.path.join(self.environ.get_icon_path(), 'StonixSplash.png') splashimage = QtGui.QPixmap(splashart) splash = QtGui.QSplashScreen(splashimage, QtCore.Qt.WindowStaysOnTopHint) splash.setMask(splashimage.mask()) splash.show() app.processEvents() self.statechglogger = StateChgLogger(self.logger, self.environ) # NB We don't have a main event loop at this point so we call # the app.processEvents() again to make the splash screen show if self.mode == 'gui': app.processEvents() self.logger.log(LogPriority.DEBUG, 'State Logger Started') if not(self.mode == 'test'): # This resets the UI to the command line if GUI was selected on the # command line and PyQt4 isn't present. if 'PyQt4' not in sys.modules and self.mode == 'gui': self.mode = 'cli' self.logger.log(LogPriority.ERROR, 'GUI Selected but PyQt4 not available. ' + 'Please install PyQt4 and dependencies for ' + 'GUI functionality.') self.statechglogger = StateChgLogger(self.logger, self.environ) self.logger.log(LogPriority.DEBUG, 'State Logger Started') self.logger.log(LogPriority.DEBUG, 'Running in ' + self.mode) starttime = time.time() allrules = self.getrules(self.config, self.environ) etime = time.time() - starttime self.logger.log(LogPriority.DEBUG, 'Rules Processed in ' + str(etime)) self.installedrules = self.findapplicable(allrules) etime = time.time() - starttime self.logger.log(LogPriority.DEBUG, 'Rules Applicable in ' + str(etime)) self.numexecutingrules = len(self.installedrules) self.environ.setnumrules(self.numexecutingrules) self.logger.logRuleCount() self.logger.log(LogPriority.DEBUG, str(self.numexecutingrules) + ' rules loaded') self.logger.log(LogPriority.DEBUG, ['CurrentEUID', str(self.environ.geteuid())]) self.logger.log(LogPriority.DEBUG, ['OSFamily', self.environ.getosfamily()]) self.logger.log(LogPriority.DEBUG, ['OSType', self.environ.getostype()]) self.logger.log(LogPriority.DEBUG, ['OSVersion', self.environ.getosver()]) self.list = self.prog_args.getList() if self.list: self.__listrules() if self.mode == 'cli': self.__clirun() elif self.mode == 'gui': myui = GUI(self, self.environ, self.logger) splash.finish(myui) sys.exit(app.exec_()) elif self.mode == 'test': pass def getrules(self, config, environ): """ Private method to process the stonix rules file to populate the rules. @return: List of instantiated rule objects @return: list : a list of instantiated rule classes @author: D. Kennel """ instruleclasses = [] validrulefiles = [] initlist = ['__init__.py', '__init__.pyc', '__init__.pyo'] stonixPath = self.environ.get_resources_path() self.logger.log(LogPriority.DEBUG, ['STONIX Path:', str(stonixPath)]) rulesPath = self.environ.get_rules_path() self.logger.log(LogPriority.DEBUG, ['Rules Path:', str(rulesPath)]) sys.path.append(stonixPath) sys.path.append(rulesPath) for path in sys.path: self.logger.log(LogPriority.DEBUG, ['Sys Path Element:', str(path)]) rulefiles = os.listdir(str(rulesPath)) # print str(rulefiles) for rfile in rulefiles: if rfile in initlist: continue else: validrulefiles.append(rfile) self.logger.log(LogPriority.DEBUG, ['validrulefiles:', str(validrulefiles)]) # This is a list comprehension to build a list of module names to # import based on the names of valid rule files from stonix/rules # destination list = [ *transform* *source* *filter* ] modulenames = [mod.replace('.py', '') for mod in validrulefiles if re.search("\.py$", mod)] self.logger.log(LogPriority.DEBUG, ['Module names:', str(modulenames)]) # The output of this section is a list of valid, fully qualified, # rule class names. classnames = [] for module in modulenames: module = module.split("/")[-1] # print module classname = 'stonix_resources.rules.' + module + '.' + module classnames.append(classname) # This is odd and requires detailed comments. This block imports the # modules then recurses down, instantiates the main rule class and # appends the class to a list. for cls in classnames: starttime = time.time() parts = cls.split(".") # the module is the class less the last element module = ".".join(parts[:-1]) # Using the __import__ built in function to import the module # since our names are only known at runtime. self.logger.log(LogPriority.DEBUG, 'Attempting to load: ' + module) try: mod = __import__(module) except Exception: trace = traceback.format_exc() self.logger.log(LogPriority.ERROR, "Error importing rule: " + trace) continue # Recurse down the class name until we get a reference to the class # itself. Then we instantiate using the reference. for component in parts[1:]: try: mod = getattr(mod, component) except Exception: trace = traceback.format_exc() self.logger.log(LogPriority.ERROR, "Error finding rule class reference: " + trace) continue try: clinst = mod(config, environ, self.logger, self.statechglogger) instruleclasses.append(clinst) etime = time.time() - starttime self.logger.log(LogPriority.DEBUG, 'load time: ' + str(etime)) except (KeyboardInterrupt, SystemExit): # User initiated exit raise except Exception: trace = traceback.format_exc() self.logger.log(LogPriority.ERROR, "Error instantiating rule: " + trace) continue # print instruleclasses return instruleclasses def findapplicable(self, rules): """ This method checks each rule to see if it is applicable on the current platform on which stonix is running. A list of applicable rule objects is returned. @param rules: List of instantiated rule objects @return: List of instantiated rule objects @author: D. Kennel """ applicablerules = [] for rule in rules: try: if rule.isapplicable(): if not self.environ.geteuid() == 0 and rule.getisrootrequired(): continue self.logger.log(LogPriority.DEBUG, 'Adding ' + rule.getrulename() + ' to run list.') applicablerules.append(rule) except Exception: trace = traceback.format_exc() self.logger.log(LogPriority.ERROR, "Error determining rule applicability: " + trace) return applicablerules def getallrulesdata(self): """ This method returns a dictionary of lists containing the data for all installed rules. Returned properties include; rule name, rule number, and the rule help text. The dictionary is keyed by rule number. @return: Dictionary of lists @author: D. Kennel """ rulesdata = {} for rule in self.installedrules: rulenum = rule.getrulenum() rulename = rule.getrulename() ruletxt = rule.gethelptext() ruledetails = [] ruledetails.append(rulename) ruledetails.append(ruletxt) rulesdata[rulenum] = ruledetails return rulesdata def getrulenumbyname(self, name): """ This method takes a name associated with a rule as an argument and translates it into a number associated with a rule class. Acceptable rule names are the section headers from the stonix_resources.conf. These section headers are generated from the rulename property that each rule has. @param string: name of the rule to fetch a number for. @return: int : number for the rule matching the passed name 0 if no match is found. @author: D. Kennel """ rulenum = 0 for rule in self.installedrules: rulename = rule.getrulename() if rulename == name: rulenum = rule.getrulenum() return rulenum def getrulenamebynum(self, rulenum): """ This method takes a number associated with a rule as an argument and translates it into a name associated with a rule class. Acceptable rule number are integers and are found in rule implementations. @param int: number of the rule to fetch a name for. @return: string : name for the rule matching the passed number. None if no match is found. @author: D. Kennel """ rulename = None for rule in self.installedrules: ruleid = rule.getrulenum() if rulenum == ruleid: rulename = rule.getrulename() return rulename def hardensystem(self): """ Call all rules in fix(harden) mode @return void : @author D. Kennel """ self.numrulesrunning = self.numexecutingrules self.numrulescomplete = 0 for rule in self.installedrules: self.currulenum = rule.getrulenum() self.currulename = rule.getrulename() try: starttime = time.time() rule.report() if not rule.getrulesuccess(): self.logger.log(LogPriority.ERROR, [rule.getrulename(), rule.getdetailedresults()]) elif not rule.iscompliant(): rule.fix() if rule.getrulesuccess(): rule.report() if not rule.getrulesuccess(): self.logger.log(LogPriority.ERROR, [rule.getrulename(), rule.getdetailedresults()]) elif not rule.iscompliant(): self.logger.log(LogPriority.WARNING, [rule.getrulename(), rule.getdetailedresults()]) else: self.logger.log(LogPriority.INFO, [rule.getrulename(), rule.getdetailedresults()]) else: self.logger.log(LogPriority.INFO, [rule.getrulename(), rule.getdetailedresults()]) etime = time.time() - starttime self.logger.log(LogPriority.DEBUG, [rule.getrulename(), 'Elapsed Time: ' + str(etime)]) except (KeyboardInterrupt, SystemExit): # User initiated exit raise except Exception: trace = traceback.format_exc() self.logger.log(LogPriority.ERROR, [rule.getrulename(), "Controller caught rule death: " + trace]) self.numrulescomplete = self.numrulescomplete + 1 self.set_dirty() self.notify_check() def auditsystem(self): """ Call all rules in audit(report) mode @return void : @author D. Kennel """ self.numrulesrunning = self.numexecutingrules self.numrulescomplete = 0 for rule in self.installedrules: self.currulenum = rule.getrulenum() self.currulename = rule.getrulename() try: starttime = time.time() rule.report() etime = time.time() - starttime self.logger.log(LogPriority.DEBUG, [rule.getrulename(), 'Elapsed Time: ' + str(etime)]) except (KeyboardInterrupt, SystemExit): # User initiated exit raise except Exception: trace = traceback.format_exc() self.logger.log(LogPriority.ERROR, [rule.getrulename(), "Controller caught rule death: " + trace]) self.numrulescomplete = self.numrulescomplete + 1 if not rule.getrulesuccess(): self.logger.log(LogPriority.ERROR, [rule.getrulename(), rule.getdetailedresults()]) if not rule.iscompliant(): self.logger.log(LogPriority.WARNING, [rule.getrulename(), rule.getdetailedresults()]) else: self.logger.log(LogPriority.INFO, [rule.getrulename(), rule.getdetailedresults()]) self.set_dirty() self.notify_check() def runruleharden(self, ruleid): """ Run a single rule in fix(harden) mode @param int ruleid : @return void : @author D. Kennel """ self.numrulesrunning = 1 self.numrulescomplete = 0 self.logger.log(LogPriority.DEBUG, ['RunRuleHarden', 'Attempting to run ' + str(ruleid)]) for rule in self.installedrules: if ruleid == rule.getrulenum(): if rule.getisrootrequired() and self.environ.geteuid() != 0: self.numrulescomplete = self.numrulescomplete + 1 message = "Could not run rule: insufficient privilege level" self.logger.log(LogPriority.ERROR, [rule.getrulename(), message]) else: starttime = time.time() try: rule.report() except (KeyboardInterrupt, SystemExit): # User initiated exit raise except Exception: trace = traceback.format_exc() self.logger.log(LogPriority.ERROR, [rule.getrulename(), "Controller caught rule death: " + trace]) if not rule.getrulesuccess(): self.logger.log(LogPriority.ERROR, [rule.getrulename(), rule.getdetailedresults()]) self.logger.log(LogPriority.INFO, [rule.getrulename(), 'Rule failed: Rule config in unknown state. Skipping rule']) self.numrulescomplete = self.numrulescomplete + 1 elif not rule.iscompliant(): try: rule.fix() except (KeyboardInterrupt, SystemExit): # User initiated exit raise except Exception: trace = traceback.format_exc() self.logger.log(LogPriority.ERROR, [rule.getrulename(), "Controller caught rule death: " + trace]) if not rule.getrulesuccess(): self.logger.log(LogPriority.ERROR, [rule.getrulename(), rule.getdetailedresults()]) try: rule.report() except (KeyboardInterrupt, SystemExit): # User initiated exit raise except Exception: trace = traceback.format_exc() self.logger.log(LogPriority.ERROR, [rule.getrulename(), "Controller caught rule death: " + trace]) if not rule.iscompliant(): self.logger.log(LogPriority.WARNING, [rule.getrulename(), rule.getdetailedresults()]) else: self.logger.log(LogPriority.INFO, [rule.getrulename(), rule.getdetailedresults()]) self.numrulescomplete = self.numrulescomplete + 1 etime = time.time() - starttime self.logger.log(LogPriority.DEBUG, [rule.getrulename(), 'Elapsed Time: ' + str(etime)]) self.set_dirty() self.notify_check() if self.numrulescomplete == 0: message = "Could not find rule! Searched for ruleid =" \ + str(ruleid) self.logger.log(LogPriority.ERROR, message) def runruleaudit(self, ruleid): """ Run a single rule in audit(report) mode @param int ruleid : @return void : @author D. Kennel """ message = "Controller:runruleaudit: Entering with rule id " + \ str(ruleid) self.logger.log(LogPriority.DEBUG, message) self.numrulesrunning = 1 self.numrulescomplete = 0 for rule in self.installedrules: if ruleid == rule.getrulenum(): message = "Controller:runruleaudit: Matched ruleid" self.logger.log(LogPriority.DEBUG, message) if rule.getisrootrequired() and self.environ.geteuid() != 0: self.numrulescomplete = self.numrulescomplete + 1 message = "Could not run rule: insufficient privilege level" self.logger.log(LogPriority.ERROR, [rule.getrulename(), message]) else: starttime = time.time() try: rule.report() except (KeyboardInterrupt, SystemExit): # User initiated exit raise except Exception: trace = traceback.format_exc() self.logger.log(LogPriority.ERROR, [rule.getrulename(), "Controller caught rule death: " + trace]) self.numrulescomplete = self.numrulescomplete + 1 if not rule.getrulesuccess(): self.logger.log(LogPriority.ERROR, [rule.getrulename(), rule.getdetailedresults()]) if not rule.iscompliant(): self.logger.log(LogPriority.WARNING, [rule.getrulename(), rule.getdetailedresults()]) else: self.logger.log(LogPriority.INFO, [rule.getrulename(), rule.getdetailedresults()]) etime = time.time() - starttime self.logger.log(LogPriority.DEBUG, [rule.getrulename(), 'Elapsed Time: ' + str(etime)]) self.set_dirty() self.notify_check() def undochangessystem(self): """ Undo all changes to the system. @return void : @author D. Kennel """ self.numrulesrunning = self.numexecutingrules self.numrulescomplete = 0 for rule in self.installedrules: self.currulenum = rule.getrulenum() self.currulename = rule.getrulename() try: rule.undo() except (KeyboardInterrupt, SystemExit): # User initiated exit raise except Exception: trace = traceback.format_exc() self.logger.log(LogPriority.ERROR, [rule.getrulename(), "Controller caught rule death: " + trace]) self.numrulescomplete = self.numrulescomplete + 1 if not rule.getrulesuccess(): self.logger.log(LogPriority.ERROR, [rule.getrulename(), rule.getdetailedresults()]) else: self.logger.log(LogPriority.INFO, [rule.getrulename(), rule.getdetailedresults()]) self.set_dirty() self.notify_check() def undorule(self, ruleid): """ Undo the changes from a single rule. Expects the integer rule number as the ruleid @param int ruleid : @return void : @author D. Kennel """ self.numrulesrunning = 1 self.numrulescomplete = 0 for rule in self.installedrules: if ruleid == rule.getrulenum(): if rule.getisrootrequired() and self.environ.geteuid() != 0: self.numrulescomplete = self.numrulescomplete + 1 message = "Could not run rule: insufficient privilege level" self.logger.log(LogPriority.ERROR, [rule.getrulename(), message]) else: try: rule.undo() except (KeyboardInterrupt, SystemExit): # User initiated exit raise except Exception: trace = traceback.format_exc() self.logger.log(LogPriority.ERROR, [rule.getrulename(), "Controller caught rule death: " + trace]) self.numrulescomplete = self.numrulescomplete + 1 if not rule.getrulesuccess(): self.logger.log(LogPriority.ERROR, [rule.getrulename(), rule.getdetailedresults()]) else: self.logger.log(LogPriority.INFO, [rule.getrulename(), rule.getdetailedresults()]) self.set_dirty() self.notify_check() def getrulehelp(self, ruleid): """ Return rule help information. @param int ruleid : int (identifier) of rule to get help text for. @return string : @author D. Kennel """ helptxt = [] for rule in self.installedrules: if ruleid == rule.getrulenum(): helptxt = rule.gethelptext() return helptxt def updatedbs(self): """ Update all databases held by database rules in stonix_resources. @return void : @author D. Kennel """ numdbrules = 0 self.numrulescomplete = 0 for rule in self.installedrules: if rule.isdatabaserule(): numdbrules = numdbrules + 1 self.numrulesrunning = numdbrules for rule in self.installedrules: if rule.isdatabaserule(): self.currulenum = rule.getrulenum() self.currulename = rule.getrulename() try: rule.fix() except (KeyboardInterrupt, SystemExit): # User initiated exit raise except Exception: trace = traceback.format_exc() self.logger.log(LogPriority.ERROR, [rule.getrulename(), "Controller caught rule death: " + trace]) self.numrulescomplete = self.numrulescomplete + 1 self.set_dirty() self.notify_check() def getconfigoptions(self): """ This method retrieves the configitems for all rules and returns a dict of lists where the keys are rule names and the lists contain the rule text and a list of configitem objects for that rule. @return dict : @author D. Kennel """ configdict = {} for rule in self.installedrules: rulename = rule.getrulename() ruledata = [] ruledata.append(rule.gethelptext()) for configitem in rule.getconfigitems(): ruledata.append(configitem) configdict[rulename] = ruledata return configdict def getruleconfigoptions(self, ruleid): """ This method returns the configurationitem object instances associated with a rule. We expect to be passed the integer rule number to id the rule. @param int ruleid : Integer rule number @return list : list of configurationitem objects @author D. Kennel """ cilist = [] for rule in self.installedrules: if ruleid == rule.getrulenum(): cilist = rule.getconfigitems() return cilist def regenerateconfig(self, simpleconf): """ This method will write the stonix configuration file with the current configuration data. If simpleconf is True then we only write changed rules and rules that are marked as being in the simple config. The configuration file object actually does most of the work here. @param bool simpleconf : Whether or not we are generating a simple configuration file or not. @return : void @author D. Kennel """ currdata = self.getconfigoptions() self.config.writeconfig(simpleconf, currdata) def validateconfig(self): """ FIXME - unimplemented method, is this still required/desirable at this level? @return bool : @author """ pass def getcurrentrule(self): """ This method returns the rule name for the currently executing rule. This method only returns valid data when called while the whole rule stack is running. @return string : rulename @author D. Kennel """ return self.currulename def getrulecompstatus(self, ruleid): """ This method returns the compliance status for the named rule. This info is only valid after the rule has had the report or fix methods called. @param int: ruleid @return: bool @author: D. Kennel """ compliant = False for rule in self.installedrules: if ruleid == rule.getrulenum(): compliant = rule.iscompliant() return compliant def getruledetailedresults(self, ruleid): """ This method returns the detailed results from the rule with a given rule id. Returned data will be a string. @param int: ruleid @return: string @author: D. Kennel """ detailedresults = [] for rule in self.installedrules: if ruleid == rule.getrulenum(): detailedresults = rule.getdetailedresults() return detailedresults def getcompletionpercentage(self): """ This method returns the percentage of items on the to-do list completed. This only returns valid data when called while the whole rule stack is running. @return int : range 0 - 100 @author D. Kennel """ total = float(self.numrulesrunning) curr = float(self.numrulescomplete) if self.environ.getdebugmode(): print "Controller:getcompletionpercentage: Total: " + str(total) print "Controller:getcompletionpercentage: Current: " + str(curr) if curr == 0: percent = 0 else: percent = int((curr / total) * 100) if self.environ.getdebugmode(): print "Controller:getcompletionpercentage: Percent: " + str(percent) return percent def displaylastrun(self): """ Returns the contents of the log file by way of the logger object. @return string : @author """ return self.logger.displaylastrun() def updatestatus(self, callingobject): """ WARNING! FIX ME! This was intended to be a part of the comms between the controller and the view. I'm not sure this method still makes sense. @param object_ callingobject : @return : @author """ pass def tryacquirelock(self): """ Try to set a lock file at /var/run/stonix_resources.pid. If the lock file already exists check to see if a stonix process with that PID is already running. If so exit with error else re-create lock file with our PID. @return: void @author: D. Kennel """ lockmessage = """ !WARNING! Another copy of STONIX appears to be running! Running more than one copy of STONIX at a time may result in unintended behavior! If STONIX is not running remove the file /var/run/stonix.pid and re-launch STONIX. ABORTING EXECUTION!""" if not self.environ.geteuid() == 0: # only grab a lock file for privileged use. return if os.path.exists(self.lockfile): rw_lockfile = open(self.lockfile, 'r+') lockpid = rw_lockfile.readline() lockpid = lockpid.strip() self.logger.log(LogPriority.DEBUG, ['TryAcquireLock', 'Found lock for PID: ' + lockpid]) try: if int(lockpid) == os.getpid(): # PID is the same, reuse PID file return except (TypeError, ValueError): self.logger.log(LogPriority.DEBUG, ['TryAcquireLock', 'Could not coerce PID to INT: ' + lockpid]) command = None if self.environ.getosfamily() == 'freebsd': command = '/bin/ps -aux' elif self.environ.getosfamily() == 'solaris': command = '/usr/bin/ps -ef' else: command = '/bin/ps -ef' self.logger.log(LogPriority.DEBUG, ['TryAcquireLock', 'PS command is: ' + str(command)]) if not type(command) is None: pscom = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, close_fds=True) psout = pscom.stdout.readlines() for line in psout: if re.search('stonix', line): splits = line.split() pspid = splits[1] self.logger.log(LogPriority.DEBUG, ['TryAcquireLock', 'Checking PIDs: ' + lockpid + ' ' + \ pspid]) if pspid == lockpid: self.logger.log(LogPriority.DEBUG, ['TryAcquireLock', 'Matched PIDs: ' + lockpid + ' ' \ + pspid]) self.logger.log(LogPriority.CRITICAL, ['TryAcquireLock', lockmessage]) rw_lockfile.close() sys.exit(2) self.logger.log(LogPriority.DEBUG, ['TryAcquireLock', 'Truncating existing Lockfile']) rw_lockfile.truncate(0) rw_lockfile.write(str(os.getpid())) rw_lockfile.close() else: self.logger.log(LogPriority.DEBUG, ['TryAcquireLock', 'Creating new Lockfile']) rw_lockfile = open(self.lockfile, 'w') rw_lockfile.write(str(os.getpid())) rw_lockfile.close() def safetycheck(self): """ Check that the installation of STONIX is safe from a security perspective. All files must only be writable by root. @author: dkennel @return: bool True if install passes checks """ safe = True return safe def releaselock(self): """ Cleans up the stonix lock file in the event of normal program exit. @return: void @author: D. Kennel """ if os.path.exists(self.lockfile): try: os.remove(self.lockfile) except: # the lock release can cause errors when run w/o privilege # and a lock file has been left behind by a privileged run. pass def processargs(self): """ This method calls the prog_args instance to process the command line args and then jumps to the appropriate execution mode. @author: R. Nielsen, D. Kennel @return: void """ self.environ.setverbosemode(self.prog_args.get_verbose()) self.environ.setdebugmode(self.prog_args.get_debug()) self.fix = self.prog_args.get_fix() self.report = self.prog_args.get_report() self.undo = self.prog_args.get_rollback() self.environ.setinstallmode(self.prog_args.get_install()) self.pcf = self.prog_args.getPrintConfigFull() self.pcs = self.prog_args.getPrintConfigSimple() if self.prog_args.get_update(): # update(debug) pass if self.prog_args.get_rollback(): # rollback() pass if not re.match("^\s*$", self.prog_args.get_module()): self.runrule = self.prog_args.get_module() if self.prog_args.get_gui(): self.mode = 'gui' # print "Launching UI" # uiinstance = view.View(uimode) if self.prog_args.get_cli(): self.mode = 'cli' def setuptesting(self): """ this method is called when the environment object determins that the controller is in test mode - e.g. running from a unittest. @author: ekkehard j. Koch @return: void """ self.environ.setverbosemode(True) self.environ.setdebugmode(True) self.fix = False self.report = False self.undo = False self.environ.setinstallmode(False) self.runrule = "" self.mode = 'test' def __listrules(self): """ Private method that prints the list of currently installed and applicable rules. This is a part of the STONIX CLI user interface and is needed for users to be able to list rules available to run in module mode. The program will exit after this method is complete. @author: D. Kennel @return: void """ rulelist = [] for rule in self.installedrules: rulenum = rule.getrulenum() rulename = rule.getrulename() rulestring = rulename + ' (' + str(rulenum) + ')' rulelist.append(rulestring) rulelist.sort(key=str.lower) print "STONIX rules for this platform:" for rule in rulelist: print rule try: self.logger.closereports() except: pass self.releaselock() def __clirun(self): """ This private method performs a cli run based on the passed flags. @author: D. Kennel @return: void """ self.logger.log(LogPriority.DEBUG, ['Controller.__clirun', ' __clirun called']) myui = Cli(self.environ) # self.logger.register_listener(myui) self.register_listener(myui) if not self.runrule: self.logger.log(LogPriority.DEBUG, 'Entering full system run') if self.fix: self.logger.log(LogPriority.DEBUG, 'Mode is Fix') self.hardensystem() self.logger.closereports() if self.report: self.logger.log(LogPriority.DEBUG, 'Mode is Report') self.auditsystem() self.logger.postreport() if self.undo: self.logger.log(LogPriority.DEBUG, 'Mode is Undo') self.undochangessystem() self.logger.closereports() if self.pcf: self.logger.log(LogPriority.DEBUG, 'Generating Full config file') self.regenerateconfig(False) self.logger.closereports() if self.pcs: self.logger.log(LogPriority.DEBUG, 'Generating Simple config file') self.regenerateconfig(True) self.logger.closereports() if not self.fix and not self.report and not self.undo and \ not self.pcf and not self.pcs: self.logger.log(LogPriority.INFO, 'No action specified. Please check command syntax') self.logger.closereports() else: self.logger.log(LogPriority.DEBUG, 'Entering single rule run ' + self.runrule) ruleid = self.getrulenumbyname(self.runrule) self.logger.log(LogPriority.DEBUG, 'Rule ID number ' + str(ruleid)) if self.fix: self.logger.log(LogPriority.DEBUG, 'Mode is Fix') self.runruleharden(ruleid) self.logger.closereports() if self.report: self.logger.log(LogPriority.DEBUG, 'Mode is Report') self.runruleaudit(ruleid) self.logger.closereports() if self.undo: self.logger.log(LogPriority.DEBUG, 'Mode is Undo') self.undorule(ruleid) self.logger.closereports() if not self.fix and not self.report and not self.undo: self.logger.log(LogPriority.INFO, 'No action specified. Please pass the -r, -f, or -u flag') self.logger.closereports() self.releaselock()
def __init__(self, ptype, ecode, errmsg=""): ''' class init @param ptype: string; package manager name; valid values: apt dnf yum zypper @param ecode: int; exit code @param errmsg: string; (OPTIONAL); include any error string you want this class to parse in order to more accurately determine the success or failure of the pkg mgr action @return: void @author: Breen Malmberg ''' super(repoError, self).__init__(ptype, ecode, errmsg) self.environ = Environment() self.logger = LogDispatcher(self.environ) # default initialization of variables msg = "No further information available" successrange = [] self.success = True self.errmsgdict = { "Error parsing config": False, "Could not parse": False, "No repomd file": False, "repositories failed": False, "doesn't have enough cached data to continue": False, "Abort, retry, ignore": False, "System management is locked": False } try: if ptype == "zypper": msg = self.zypperCodes(ecode) successrange = [0, 100, 101, 102, 103, 104, 106] elif ptype == "yum": msg = self.yumCodes(ecode) successrange = [0, 100] elif ptype == "apt": msg = self.aptCodes(ecode) successrange = [0] elif ptype == "dnf": msg = self.dnfCodes(ecode) successrange = [0, 100] else: self.logger.log( LogPriority.DEBUG, "Unable to identify package manager. Cannot guarantee package manager action success!" ) except (KeyboardInterrupt, SystemExit): raise try: # First we try to go based off of the content of the error message # Since that is more reliable than exit codes, when trying to determine # Actual success or failure of the package manager command if errmsg: # (maybe we couldn't identify the package manager and # as a result couldn't populate the errmsgdict) if self.errmsgdict: for entry in self.errmsgdict: if re.search(entry, errmsg, re.IGNORECASE): self.success = self.errmsgdict[entry] if self.success: # If success then the message passed is merely informational in nature self.logger.log(LogPriority.INFO, errmsg) else: # If not success, then the message passed indicates an actual problem self.logger.log(LogPriority.WARNING, errmsg) return else: # If there is no error message passed, then we do our best # To determine success or failure based off of what the exit # Code indicates if ecode in successrange: self.logger.log(LogPriority.INFO, msg) else: self.success = False self.logger.log(LogPriority.WARNING, msg) except IndexError as indexE: self.logger.log(LogPriority.WARNING, str(indexE)) return
class RuleDictionary (): ''' This class is designed encapsulate the dictionary object for rules. @author: ekkehard j. koch @note: None @change: 2015-02-25 - ekkehard - Original Implementation ''' def __init__(self): self.unittestprefix = 'zzzTestRule' self.initlist = ['__init__.py', '__init__.pyc', '__init__.pyo'] self.environ = Environment() self.environ.setdebugmode(False) self.environ.setverbosemode(True) self.effectiveUserID = self.environ.geteuid() self.config = Configuration(self.environ) self.logdispatch = LogDispatcher(self.environ) self.statechglogger = StateChgLogger(self.logdispatch, self.environ) self.scriptPath = self.environ.get_script_path() self.stonixPath = self.environ.get_resources_path() self.rulesPath = self.environ.get_rules_path() self.unittestpath = self.scriptPath + "/" self.ruledictionary = {} self.keys = None self.key = None self.keyIndexNumber = 0 self.keysNumberOf = 0 self.dictinaryItem = None self.initializeRuleInfo() self.initializeRuleUnitTestData() self.initializeRuleContextData() def gotoFirstRule(self): self.keyIndexNumber = 0 self.keys = sorted(self.ruledictionary.keys()) self.keysNumberOf = len(self.keys) self.key = self.keys[self.keyIndexNumber] self.dictinaryItem = self.ruledictionary[self.key] def gotoNextRule(self): self.keyIndexNumber = self.keyIndexNumber + 1 self.keys = sorted(self.ruledictionary.keys()) self.keysNumberOf = len(self.keys) if (self.keysNumberOf - 1) < self.keyIndexNumber: self.keyIndexNumber = 0 self.dictinaryItem = None else: self.key = self.keys[self.keyIndexNumber] self.dictinaryItem = self.ruledictionary[self.key] def getCorrectEffectiveUserid(self): return self.ruledictionary[self.key]["rulecorrecteffectiveuserid"] def getCurrentRuleItem(self): return self.dictinaryItem def getIsApplicable(self): return self.ruledictionary[self.key]["ruleisapplicable"] def getHasRule(self): return self.ruledictionary[self.key]["rulefound"] def getHasUnitTest(self): return self.ruledictionary[self.key]["unittestfound"] def getRuleName(self): return self.ruledictionary[self.key]["rulename"] def getRuleNumber(self): return self.ruledictionary[self.key]["rulenumber"] def getTestName(self): return self.ruledictionary[self.key]["unittestname"] def initializeRuleInfo(self): ''' Fill in all the rule information @author: ekkehard j. koch @note: None ''' success = True messagestring = "--------------------------------- start" self.logdispatch.log(LogPriority.INFO, str(messagestring)) self.validrulefiles = [] self.modulenames = [] self.classnames = [] rulefiles = os.listdir(str(self.rulesPath)) for rfile in rulefiles: rule_class = None if rfile in self.initlist: continue elif re.search("\.py$", rfile): rulename = rfile.replace('.py', '') rulefilename = rfile ruleclassname = 'rules.' + rulename + '.' + rulename ruleclasspath = self.rulesPath + "/" + rfile parts = ruleclassname.split(".") rulemoduleimportstring = "stonix_resources." + \ ".".join(parts[:-1]) ruleinstanciatecommand = "rule_class = mod." + ruleclassname unittestname = self.unittestprefix + rulename unittestfilename = self.unittestprefix + rfile unittestclasspath = self.unittestpath + unittestfilename unittestclassname = unittestname + "." + unittestname unittestmoduleimportstring = unittestname unittestinstanciatecommand = "unittest_class = mod." + \ unittestclassname self.initializeDictoniaryItem(rulename) self.ruledictionary[rulename]["rulename"] = rulename self.ruledictionary[rulename]["ruleclassname"] = ruleclassname self.ruledictionary[rulename]["ruleclasspath"] = ruleclasspath self.ruledictionary[rulename]["rulefilename"] = rulefilename self.ruledictionary[rulename]["ruleclassname"] = ruleclassname self.ruledictionary[rulename]["rulemoduleimportstring"] = rulemoduleimportstring self.ruledictionary[rulename]["ruleinstanciatecommand"] = ruleinstanciatecommand self.ruledictionary[rulename]["ruleobject"] = None self.ruledictionary[rulename]["ruleisapplicable"] = True self.ruledictionary[rulename]["rulecorrecteffectiveuserid"] = True self.ruledictionary[rulename]["rulefound"] = True self.ruledictionary[rulename]["unittestname"] = unittestname self.ruledictionary[rulename]["unittestclasspath"] = unittestclasspath self.ruledictionary[rulename]["unittestfilename"] = unittestfilename self.ruledictionary[rulename]["unittestclassname"] = unittestclassname self.ruledictionary[rulename]["unittestmoduleimportstring"] = unittestmoduleimportstring self.ruledictionary[rulename]["unittestinstanciatecommand"] = unittestinstanciatecommand self.ruledictionary[rulename]["unittestobject"] = None self.ruledictionary[rulename]["unittestfound"] = False self.ruledictionary[rulename]["errormessage"] = [] try: mod = __import__(rulemoduleimportstring) except Exception: trace = traceback.format_exc() messagestring = "Error importing rule: " + rulename + " " + \ rulemoduleimportstring + " - " + trace self.ruledictionary[rulename]["errormessage"].append(messagestring) self.logdispatch.log(LogPriority.ERROR, messagestring) continue try: exec(ruleinstanciatecommand) # rule_class = getattr(mod, classimportname) # exec("rule_class = mod.rules." + name + "." + name) except Exception: trace = traceback.format_exc() messagestring = "Error importing rule: " + rulename + " " + \ rulemoduleimportstring + " - " + trace self.logdispatch.log(LogPriority.ERROR, "Error finding rule class reference: " + trace) continue try: self.rule = rule_class(self.config, self.environ, self.logdispatch, self.statechglogger) self.ruledictionary[rulename]["ruleobject"] = self.rule except Exception: trace = traceback.format_exc() messagestring = "Error initializing rule: " + rulename + \ " - " + trace self.ruledictionary[rulename]["errormessage"].append(messagestring) self.logdispatch.log(LogPriority.ERROR, messagestring) continue else: continue return success def initializeRuleUnitTestData(self): ''' Fill in all the unit test data @author: ekkehard j. koch @note: None ''' success = True messagestring = "--------------------------------- start" self.logdispatch.log(LogPriority.INFO, str(messagestring)) ruletestfiles = os.listdir(str(self.unittestpath)) for rtfile in ruletestfiles: if rtfile in self.initlist: continue elif re.search("\.py$", rtfile): if rtfile.startswith(self.unittestprefix): unittestmodule = rtfile.replace('.py', '') module = unittestmodule.replace(self.unittestprefix, "") if self.findDictonaryItem(module): self.dictinaryItem["unittestfound"] = True else: self.dictinaryItem["rulename"] = module self.dictinaryItem["rulefound"] = False self.dictinaryItem["unittestname"] = unittestmodule self.dictinaryItem["unittestfound"] = True else: continue return success def initializeRuleContextData(self): ''' Make sure you have all the contextual data for rules @author: ekkehard j. koch @note: None ''' success = True messagestring = "--------------------------------- start" self.logdispatch.log(LogPriority.INFO, str(messagestring)) keys = sorted(self.ruledictionary.keys()) for key in keys: ruleclassname = self.ruledictionary[key]["ruleclassname"] classimportname = "." + ruleclassname rulename = self.ruledictionary[key]["rulename"] ruleclasspath = self.ruledictionary[key]["ruleclasspath"] rule_class = self.ruledictionary[key]["ruleobject"] rulemoduleimportstring = \ self.ruledictionary[key]["rulemoduleimportstring"] ruleclasspath = \ self.ruledictionary[key]["ruleclasspath"] ruleinstanciatecommand = \ self.ruledictionary[key]["ruleinstanciatecommand"] try: mod = __import__(rulemoduleimportstring) except Exception: trace = traceback.format_exc() messagestring = "Error importing rule: " + rulename + " " + \ rulemoduleimportstring + " - " + trace self.ruledictionary[key]["errormessage"].append(messagestring) self.logdispatch.log(LogPriority.ERROR, messagestring) continue try: exec(ruleinstanciatecommand) # rule_class = getattr(mod, classimportname) # exec("rule_class = mod.rules." + rulename + "." + rulename) except Exception: trace = traceback.format_exc() messagestring = "Error importing rule: " + rulename + " " + \ rulemoduleimportstring + " - " + trace self.logdispatch.log(LogPriority.ERROR, "Error finding rule class reference: " + trace) continue try: self.rule = rule_class(self.config, self.environ, self.logdispatch, self.statechglogger) rulenumber = self.rule.getrulenum() self.ruledictionary[key]["rulenumber"] = rulenumber messagestring = str(key) + "(" + str(rulenumber) + ") initialized!" isapplicable = self.rule.isapplicable() isRootRequired = self.rule.getisrootrequired() if not isapplicable: self.ruledictionary[key]["ruleisapplicable"] = False messagestring = messagestring + " is not applicable." else: self.ruledictionary[key]["ruleisapplicable"] = True messagestring = messagestring + " is applicable." if self.effectiveUserID == 0 and isRootRequired: self.ruledictionary[key]["rulecorrecteffectiveuserid"] = True messagestring = messagestring + " is running in " + \ "correct context." elif not self.effectiveUserID == 0 and not isRootRequired: self.ruledictionary[key]["rulecorrecteffectiveuserid"] = True messagestring = messagestring + " is running in " + \ "correct context." else: self.ruledictionary[key]["rulecorrecteffectiveuserid"] = False messagestring = messagestring + " is not running in " + \ "correct context." self.logdispatch.log(LogPriority.INFO, str(messagestring)) except Exception: trace = traceback.format_exc() messagestring = "Error initializing rule: " + rulename + \ " - " + trace self.ruledictionary[key]["errormessage"].append(messagestring) self.logdispatch.log(LogPriority.ERROR, messagestring) continue return success def findDictonaryItem(self, rulename): self.dictinaryItem = self.ruledictionary[rulename] if self.dictinaryItem == None: success = False else: success = True return success def initializeDictoniaryItem(self, rulename): success = True item = {"rulename": "", "rulenumber": 0, "ruleclassname": "", "ruleclasspath": "", "rulefilename": "", "ruleclassname": "", "rulemoduleimportstring": "", "ruleinstanciatecommand": "", "ruleobject": "", "ruleisapplicable": False, "rulecorrecteffectiveuserid": False, "rulefound": False, "unittestname": "", "unittestclasspath": "", "unittestfilename": "", "unittestclassname": "", "unittestmoduleimportstring": "", "unittestinstanciatecommand": "", "unittestobject": None, "unittestfound": False, "errormessage": []} self.ruledictionary[rulename] = item self.dictinaryItem = self.ruledictionary[rulename] return success def ruleReport(self): success = True messagestring = "start --------------------------------------------" self.logdispatch.log(LogPriority.INFO, str(messagestring)) self.gotoFirstRule() messagestring = "stonixtest rule tested: --------------------------------------------------" self.logdispatch.log(LogPriority.INFO, str(messagestring)) while not (self.getCurrentRuleItem() == None): ruleName = self.getRuleName() ruleNumber = self.getRuleNumber() ruleTestName = self.getTestName() ruleCorrectEffectiveUserid = self.getCorrectEffectiveUserid() ruleIsApplicable = self.getIsApplicable() if ruleIsApplicable and ruleCorrectEffectiveUserid: messagestring = str(ruleName) + "(" + str(ruleNumber) + "):" + \ str(ruleTestName) + " - isApplicable=" + \ str(ruleIsApplicable) + " - CorrectEffectiveUserid=" + \ str(ruleCorrectEffectiveUserid) + ";" self.logdispatch.log(LogPriority.INFO, str(messagestring)) self.gotoNextRule() self.gotoFirstRule() messagestring = "stonixtest rule not tested: --------------------------------------------------" self.logdispatch.log(LogPriority.INFO, str(messagestring)) while not (self.getCurrentRuleItem() == None): ruleName = self.getRuleName() ruleNumber = self.getRuleNumber() ruleTestName = self.getTestName() ruleCorrectEffectiveUserid = self.getCorrectEffectiveUserid() ruleIsApplicable = self.getIsApplicable() if not(ruleIsApplicable) or not(ruleCorrectEffectiveUserid): messagestring = str(ruleName) + "(" + str(ruleNumber) + "):" + \ str(ruleTestName) + " - isApplicable=" + \ str(ruleIsApplicable) + " - CorrectEffectiveUserid=" + \ str(ruleCorrectEffectiveUserid) + ";" self.logdispatch.log(LogPriority.INFO, str(messagestring)) self.gotoNextRule() messagestring = "end --------------------------------------------" self.logdispatch.log(LogPriority.INFO, str(messagestring)) return success
class FrameworkDictionary(): def __init__(self): self.unittestprefix = 'zzzTestFramework' self.initlist = ['__init__.py', '__init__.pyc', '__init__.pyo'] self.environ = Environment() self.environ.setdebugmode(False) self.environ.setverbosemode(True) self.effectiveUserID = self.environ.geteuid() self.config = Configuration(self.environ) self.logdispatch = LogDispatcher(self.environ) self.statechglogger = StateChgLogger(self.logdispatch, self.environ) self.scriptPath = self.environ.get_script_path() self.stonixPath = self.environ.get_resources_path() self.rulesPath = self.environ.get_rules_path() self.frameworkpath = self.stonixPath + "/" self.frameworkdictionary = {} self.keys = None self.key = None self.keyIndexNumber = 0 self.keysNumberOf = 0 self.dictinaryItem = None self.initializeDictionary() def gotoFirstItem(self): self.keyIndexNumber = 0 self.keys = sorted(self.frameworkdictionary.keys()) self.keysNumberOf = len(self.keys) self.key = self.keys[self.keyIndexNumber] self.dictinaryItem = self.frameworkdictionary[self.key] def gotoNextItem(self): self.keyIndexNumber = self.keyIndexNumber + 1 self.keys = sorted(self.frameworkdictionary.keys()) self.keysNumberOf = len(self.keys) if (self.keysNumberOf - 1) < self.keyIndexNumber: self.keyIndexNumber = 0 self.dictinaryItem = None else: self.key = self.keys[self.keyIndexNumber] self.dictinaryItem = self.frameworkdictionary[self.key] def getCurrentItem(self): return self.dictinaryItem def getTestPath(self): return self.dictinaryItem["path"] def getTestName(self): return self.dictinaryItem["name"] def initializeDictionary(self): ''' Fill in all the rule information @author: ekkehard j. koch @note: None ''' success = True messagestring = "--------------------------------- start" self.logdispatch.log(LogPriority.INFO, str(messagestring)) self.validrulefiles = [] self.modulenames = [] self.classnames = [] rulefiles = os.listdir(str(self.frameworkpath)) for rfile in rulefiles: rule_class = None if rfile in self.initlist: continue elif re.search("\.py$", rfile): modulename = rfile.replace('.py', '') if modulename.startswith(self.unittestprefix): self.initializeDictoniaryItem(modulename) self.dictinaryItem["name"] = modulename self.dictinaryItem["found"] = True else: continue return success def initializeDictoniaryItem(self, name): success = True item = {"name": "", "path": self.frameworkpath, "found": False, "errormessage": []} self.frameworkdictionary[name] = item self.dictinaryItem = self.frameworkdictionary[name] return success
class Yum(object): """The template class that provides a framework that must be implemented by all platform specific pkgmgr classes. """ def __init__(self, logger): self.environ = Environment() self.logger = logger self.ch = CommandHelper(self.logger) self.yumloc = "/usr/bin/yum" self.install = self.yumloc + " install -y " self.remove = self.yumloc + " remove -y " self.search = self.yumloc + " list " self.checkupdates = self.search + "updates " self.listavail = self.search + "available " self.listinstalled = self.search + "installed " self.updatepkg = self.yumloc + " update -y --obsoletes " myos = self.environ.getostype().lower() if re.search("red hat.*?release 6", myos) or \ re.search("^centos$", myos.strip()): self.rpmloc = "/bin/rpm" else: self.rpmloc = "/usr/bin/rpm" self.provides = self.rpmloc + " -qf " self.query = self.rpmloc + " -qa " def installpackage(self, package): """Install a package. Return a bool indicating success or failure. :param package: string; Name of the package to be installed, must be recognizable to the underlying package manager. :return: installed :rtype: bool """ installed = True maxtries = 12 trynum = 0 while psRunning("yum"): trynum += 1 if trynum == maxtries: self.logger.log(LogPriority.DEBUG, "Timed out while attempting to install package due to yum package manager being in-use by another process.") installed = False return installed else: self.logger.log(LogPriority.DEBUG, "Yum package manager is in-use by another process. Waiting for it to be freed...") time.sleep(5) try: self.ch.executeCommand(self.install + package) retcode = self.ch.getReturnCode() if retcode != 0: errstr = self.ch.getErrorString() self.logger.log(LogPriority.DEBUG, "Yum command failed with: " + str(errstr)) installed = False if installed: self.logger.log(LogPriority.DEBUG, "Package " + str(package) + " was installed successfully") else: self.logger.log(LogPriority.DEBUG, "Failed to install package " + str(package)) except Exception: raise return installed def removepackage(self, package): """Remove a package. Return a bool indicating success or failure. :param package: string; Name of the package to be removed, must be recognizable to the underlying package manager. :return: removed :rtype: bool """ removed = True maxtries = 12 trynum = 0 while psRunning("yum"): trynum += 1 if trynum == maxtries: self.logger.log(LogPriority.DEBUG, "Timed out while attempting to remove package, due to yum package manager being in-use by another process.") removed = False return removed else: self.logger.log(LogPriority.DEBUG, "Yum package manager is in-use by another process. Waiting for it to be freed...") time.sleep(5) try: self.ch.executeCommand(self.remove + package) retcode = self.ch.getReturnCode() if retcode != 0: errstr = self.ch.getErrorString() self.logger.log(LogPriority.DEBUG, "Yum command failed with: " + str(errstr)) removed = False if removed: self.logger.log(LogPriority.DEBUG, "Package " + str(package) + " was successfully removed") else: self.logger.log(LogPriority.DEBUG, "Failed to remove package " + str(package)) except Exception: raise return removed def checkInstall(self, package): """Check the installation status of a package. Return a bool; True if the package is installed. :param package: string; Name of the package whose installation status is to be checked, must be recognizable to the underlying package manager. :return: found :rtype: bool """ installed = True maxtries = 12 trynum = 0 acceptablecodes = [1,0] while psRunning("yum"): trynum += 1 if trynum == maxtries: self.logger.log(LogPriority.DEBUG, "Timed out while attempting to check status of package, due to yum package manager being in-use by another process.") installed = False return installed else: self.logger.log(LogPriority.DEBUG, "Yum package manager is in-use by another process. Waiting for it to be freed...") time.sleep(5) try: self.ch.executeCommand(self.listinstalled + package) retcode = self.ch.getReturnCode() if retcode not in acceptablecodes: installed = False errmsg = self.ch.getErrorString() self.logger.log(LogPriority.DEBUG, "Yum command failed with: " + str(errmsg)) else: outputlines = self.ch.getAllList() for line in outputlines: if re.search("No matching Packages", line, re.I): installed = False if installed: self.logger.log(LogPriority.DEBUG, "Package " + str(package) + " is installed") else: self.logger.log(LogPriority.DEBUG, "Package " + str(package) + " is NOT installed") except Exception: raise return installed def Update(self, package=""): """update specified package if any updates are available for it if no package is specified, update all packages which can be updated on the system :param package: string; name of package to update (Default value = "") :return: updated :rtype: bool """ updated = True try: try: self.ch.executeCommand(self.updatepkg + package) retcode = self.ch.getReturnCode() errstr = self.ch.getErrorString() if retcode != 0: updated = False raise repoError('yum', retcode, str(errstr)) except repoError as repoerr: if not repoerr.success: self.logger.log(LogPriority.WARNING, str(errstr)) updated = False if package: if updated: self.logger.log(LogPriority.DEBUG, "Package " + str(package) + " was successfully updated") else: self.logger.log(LogPriority.DEBUG, "No updates were found for package " + str(package)) else: if updated: self.logger.log(LogPriority.DEBUG, "All packages were successfully updated") else: self.logger.log(LogPriority.DEBUG, "No updates were found for this system") except Exception: raise return updated def checkUpdate(self, package=""): """check if there are any updates available for specified package if no package is specified, check if any updates are available for the current system :param package: string; name of package to check (Default value = "") :return: updatesavail :rtype: bool """ updatesavail = False try: try: self.ch.executeCommand(self.checkupdates + package) retcode = self.ch.getReturnCode() output = self.ch.getOutputString() errstr = self.ch.getErrorString() if retcode != 0: raise repoError('yum', retcode, str(errstr)) else: if re.search("Updated packages", output, re.IGNORECASE): updatesavail = True except repoError as repoerr: if not repoerr.success: self.logger.log(LogPriority.WARNING, str(errstr)) else: if re.search("Updated packages", output, re.IGNORECASE): updatesavail = True if package: if updatesavail: self.logger.log(LogPriority.DEBUG, "Updates are available for package " + str(package)) else: self.logger.log(LogPriority.DEBUG, "No updates are available for package " + str(package)) else: if updatesavail: self.logger.log(LogPriority.DEBUG, "Updates are available for this system") else: self.logger.log(LogPriority.DEBUG, "No updates are available for this system") except Exception: raise return updatesavail def checkAvailable(self, package): """check if specified package is available to install return True if it is return False if not :param package: string; name of package to check :return: available :rtype: bool """ available = True maxtries = 12 trynum = 0 while psRunning("yum"): trynum += 1 if trynum == maxtries: self.logger.log(LogPriority.DEBUG, "Timed out while attempting to check availability of package, due to yum package manager being in-use by another process.") available = False return available else: self.logger.log(LogPriority.DEBUG, "Yum package manager is in-use by another process. Waiting for it to be freed...") time.sleep(5) try: self.ch.executeCommand(self.listavail + package) retcode = self.ch.getReturnCode() if retcode in [0,1]: output = self.ch.getAllList() for line in output: if re.search("No matching Packages", line, re.I): available = False else: errstr = self.ch.getErrorString() available = False self.logger.log(LogPriority.DEBUG, errstr) if available: self.logger.log(LogPriority.DEBUG, "Package " + str(package) + " is available to install") else: self.logger.log(LogPriority.DEBUG, "No package " + str(package) + " was found to install") except Exception: raise return available def getPackageFromFile(self, filename): """Returns the name of the package that provides the given filename/path. :param filename: string; The name or path of the file to resolve :return: packagename :rtype: string """ packagename = "" try: try: self.ch.executeCommand(self.provides + filename) retcode = self.ch.getReturnCode() outputstr = self.ch.getOutputString() errstr = self.ch.getErrorString() if retcode != 0: raise repoError('yum', retcode, str(errstr)) else: packagename = outputstr except repoError as repoerr: if not repoerr.success: self.logger.log(LogPriority.WARNING, str(errstr)) except Exception: raise return packagename def getInstall(self): return self.install def getRemove(self): return self.remove
class RuleTest(unittest.TestCase): ############################################################################### def setUp(self): ''' Setup what we need for the test. @author: ekkehard j. koch @param self:essential if you override this definition ''' self.environ = Environment() self.environ.setverbosemode(True) self.environ.setdebugmode(True) self.config = Configuration(self.environ) self.logdispatch = LogDispatcher(self.environ) self.statechglogger = StateChgLogger(self.logdispatch, self.environ) self.rule = None self.rulename = "" self.rulenumber = "" ############################################################################### def tearDown(self): ''' Release anything we no longer need what we need for the test. @author: ekkehard j. koch @param self:essential if you override this definition ''' pass ############################################################################### def simpleRuleTest(self): ''' Run a simple Report, Fix, Report Cycle @author: ekkehard j. koch @param self:essential if you override this definition ''' nextstep = True prefixHeadline = "################################################### " prefixRuleInfo = self.rulename + "(" + str(self.rulenumber) + "): " messagestring = "" # Make Rule Is supposed to run in this environment if nextstep: messagestring = "Make sure Rule Is supposed to run in this " + \ "environment" self.logdispatch.log(LogPriority.DEBUG, prefixHeadline + \ prefixRuleInfo + messagestring) isapplicable = self.rule.isapplicable() messagestring = "rule.isapplicable() = " + str(isapplicable) self.logdispatch.log(LogPriority.DEBUG, prefixRuleInfo + \ messagestring) valueIsInList = isapplicable in [True, False] messagestring = "Invalid isapplicable Type!" self.assertTrue(valueIsInList, prefixRuleInfo + \ messagestring) messagestring = "rule.isapplicable() = " + str(isapplicable) + \ " and should be True." self.assertTrue(isapplicable, prefixRuleInfo + \ messagestring) nextstep = isapplicable # Check to see if we are running in the right context if nextstep: messagestring = "Check to see if we are running in the " + \ "right context" self.logdispatch.log(LogPriority.DEBUG, prefixHeadline + \ prefixRuleInfo + messagestring) effectiveUserID = self.environ.geteuid() messagestring = "environ.geteuid() = " + str(effectiveUserID) self.logdispatch.log(LogPriority.DEBUG, prefixRuleInfo + \ messagestring) isRootRequired = self.rule.getisrootrequired() messagestring = "rule.getisrootrequired() = " + str(isRootRequired) self.logdispatch.log(LogPriority.DEBUG, prefixRuleInfo + \ messagestring) if effectiveUserID == 0 and isRootRequired: nextstep = True elif not isRootRequired: nextstep = True else: nextstep = False messagestring = "Rule requires root and effective uid ='" + \ str(effectiveUserID) + "'" self.assertTrue(nextstep, prefixRuleInfo + \ messagestring) # Run setConditionsForRule to configure system for test if nextstep: messagestring = "Run setConditionsForRule to configure " + \ "system for test" self.logdispatch.log(LogPriority.DEBUG, prefixHeadline + \ prefixRuleInfo + messagestring) setTestConditions = self.setConditionsForRule() self.logdispatch.log(LogPriority.DEBUG, "setConditionsForRule()" + \ " = " + \ str(setTestConditions)) if setTestConditions: nextstep = True else: nextstep = False messagestring = "setConditionsForRule() = " + \ str(setTestConditions) + "." self.assertTrue(setTestConditions, prefixRuleInfo + \ messagestring) # Run rule.report() if nextstep: messagestring = "Run rule.report()" self.logdispatch.log(LogPriority.DEBUG, prefixHeadline + \ prefixRuleInfo + messagestring) report = self.rule.report() self.logdispatch.log(LogPriority.DEBUG, "rule.report() = " + \ str(report)) rulesuccess = self.rule.getrulesuccess() self.logdispatch.log(LogPriority.DEBUG, "rule.getrulesuccess() = " + \ str(rulesuccess)) valueIsInList = rulesuccess in [True, False] messagestring = "Invalid rule.getrulesuccess() Value'" + \ str(rulesuccess) + "'!" self.assertTrue(valueIsInList, prefixRuleInfo + messagestring) if not rulesuccess: nextstep = False messagestring = ": rule.getrulesuccess() is '" + \ str(rulesuccess) + "'" self.assertTrue(rulesuccess, prefixRuleInfo + messagestring) rulecompliance = self.rule.iscompliant() self.logdispatch.log(LogPriority.DEBUG, "rule.iscompliant() = " + \ str(rulecompliance)) valueIsInList = rulecompliance in [True, False] messagestring = "Invalid rule.iscompliant() Value'" + \ str(rulecompliance) + "'!" self.assertTrue(valueIsInList, prefixRuleInfo + messagestring) # Run checkReportForRule() messagestring = "Run checkReportForRule(" + str(rulecompliance) + \ ", " + str(rulesuccess) + ")" self.logdispatch.log(LogPriority.DEBUG, prefixHeadline + \ prefixRuleInfo + messagestring) checkReportConditions = self.checkReportForRule(rulecompliance, rulesuccess) self.logdispatch.log(LogPriority.DEBUG, "checkReportForRule()" + \ " = " + \ str(checkReportConditions)) if checkReportConditions and not rulecompliance: nextstep = True else: nextstep = False messagestring = ": Rule checkReportForRule() = " + \ str(checkReportConditions) + "." self.assertTrue(checkReportConditions, prefixRuleInfo + \ messagestring) self.assertTrue(checkReportConditions, self.rulename + "(" + str(self.rulenumber) + ")" + ": Rule " + \ "checkReportForRule() = " + \ str(checkReportConditions) + ".") # Run rule.fix() if nextstep: messagestring = "Run rule.fix()" self.logdispatch.log(LogPriority.DEBUG, prefixHeadline + \ prefixRuleInfo + messagestring) fix = self.rule.fix() self.logdispatch.log(LogPriority.DEBUG, "rule.fix() = " + \ str(fix)) rulesuccess = self.rule.getrulesuccess() self.logdispatch.log(LogPriority.DEBUG, "rule.getrulesuccess() = " + \ str(rulesuccess)) valueIsInList = rulesuccess in [True, False] messagestring = "Invalid rule.rulesuccess() Value'" + \ str(rulesuccess) + "'!" self.assertTrue(valueIsInList, prefixRuleInfo + messagestring) messagestring = "rule.getrulesuccess() = '" + \ str(rulesuccess) + "'" self.assertTrue(rulesuccess, prefixRuleInfo + messagestring) # Run checkFixForRule() messagestring = "Run checkFixForRule(" + str(rulesuccess) + ")" self.logdispatch.log(LogPriority.DEBUG, prefixHeadline + \ prefixRuleInfo + messagestring) checkFixConditions = self.checkFixForRule(rulesuccess) self.logdispatch.log(LogPriority.DEBUG, "checkFixForRule(" + str(rulesuccess) + \ ")" + " = " + \ str(checkFixConditions)) if checkFixConditions and rulesuccess: nextstep = True else: nextstep = False messagestring = "Rule checkFixForRule() = " + \ str(checkFixConditions) + "." self.assertTrue(nextstep, prefixRuleInfo + messagestring) # Run rule.report() if nextstep: messagestring = "Run rule.report()" self.logdispatch.log(LogPriority.DEBUG, prefixHeadline + \ prefixRuleInfo + messagestring) report = self.rule.report() self.logdispatch.log(LogPriority.DEBUG, "rule.report() = " + \ str(report)) rulesuccess = self.rule.getrulesuccess() self.logdispatch.log(LogPriority.DEBUG, "rule.getrulesuccess() = " + \ str(rulesuccess)) valueIsInList = rulesuccess in [True, False] messagestring = "Invalid rule.getrulesuccess() Value'" + \ str(rulesuccess) + "'!" self.assertTrue(valueIsInList, prefixRuleInfo + messagestring) if not rulesuccess: nextstep = False self.assertTrue(rulesuccess, self.rulename + "(" + str(self.rulenumber) + ")" + ": rule.getrulesuccess() is '" + \ str(rulesuccess) + "' with reported error '" + \ str(self.rule.getdetailedresults())) rulecompliance = self.rule.iscompliant() self.logdispatch.log(LogPriority.DEBUG, "rule.iscompliant() = " + \ str(rulecompliance)) valueIsInList = rulecompliance in [True, False] messagestring = "Invalid rule.iscompliant() Value'" + \ str(rulecompliance) + "'!" self.assertTrue(valueIsInList, prefixRuleInfo + messagestring) messagestring = "rule.iscompliant() is '" + \ str(rulecompliance) + "' after rule.fix() and rule.report() " + \ "have run." self.assertTrue(rulecompliance, prefixRuleInfo + messagestring) if rulecompliance: nextstep = False return nextstep ############################################################################### def setConditionsForRule(self): return True ############################################################################### def checkReportForRule(self, pCompliance, pRuleSuccess): self.logdispatch.log(LogPriority.DEBUG, "pCompliance = " + \ str(pCompliance) + ".") self.logdispatch.log(LogPriority.DEBUG, "pRuleSuccess = " + \ str(pRuleSuccess) + ".") return True ############################################################################### def checkFixForRule(self, pRuleSuccess): self.logdispatch.log(LogPriority.DEBUG, "pRuleSuccess = " + \ str(pRuleSuccess) + ".") return True ############################################################################### def checkUndoForRule(self, pRuleSuccess): self.logdispatch.log(LogPriority.DEBUG, "pRuleSuccess = " + \ str(pRuleSuccess) + ".") return True