def get_image_policies(self, image): # load default and image override policies, merge (if new # checks are in default), and save (if there is a diff after # the merge) try: policy = anchore_policy.read_policy(name='default', file=self.default_gatepol) policy_data = policy['default'] except Exception as err: policy_data = [] default_policies = anchore_policy.structure_policy(policy_data) policy_data = self.anchoreDB.load_gate_policy(image.meta['imageId']) image_policies = anchore_policy.structure_policy(policy_data) if image_policies and default_policies: policies = self.merge_policies(image_policies, default_policies) if policies != image_policies: self.save_policy(image.meta['imageId'], policies) else: policies = default_policies self.save_policy(image.meta['imageId'], policies) return (policies)
def edit_policy_file(self, editpolicy=False, whitelist=False): ret = True if not editpolicy and not whitelist: # nothing to do return(ret) for imageId in self.images: if editpolicy: data = self.anchoreDB.load_gate_policy(imageId) else: data = self.anchoreDB.load_gate_whitelist(imageId) if not data: self._logger.info("Cannot find existing data to edit, skipping: " + str(imageId)) else: tmpdir = anchore_utils.make_anchoretmpdir("/tmp") try: thefile = os.path.join(tmpdir, "anchorepol."+imageId) anchore_utils.write_plainfile_fromlist(thefile, data) if "EDITOR" in os.environ: cmd = os.environ["EDITOR"].split() cmd.append(thefile) try: subprocess.check_output(cmd, shell=False) except: ret = False elif os.path.exists("/bin/vi"): try: rc = os.system("/bin/vi " + thefile) if rc: ret = False except: ret = False else: self._logger.info("Cannot find editor to use: please set the EDITOR environment variable and try again") break #newdata = anchore_utils.read_plainfile_tolist(thefile) try: policy = anchore_policy.read_policy(name='default', file=thefile) newdata = policy['default'] except Exception as err: newdata = [] if editpolicy: self.anchoreDB.save_gate_policy(imageId, newdata) else: self.anchoreDB.save_gate_whitelist(imageId, newdata) except Exception as err: pass finally: if tmpdir: shutil.rmtree(tmpdir) return(ret)
def load_policies(self, image): policies = {} if self.policy_override: try: policy = anchore_policy.read_policy(name='default', file=self.policy_override) policy_data = policy['default'] except Exception as err: policy_data = [] policies = anchore_policy.structure_policy(policy_data) else: policies = self.get_image_policies(image) return(policies)
def load_policies(self, image): policies = {} if self.policy_override: try: policy = anchore_policy.read_policy(name='default', file=self.policy_override) policy_data = policy['default'] except Exception as err: policy_data = [] policies = anchore_policy.structure_policy(policy_data) else: policies = self.get_image_policies(image) return (policies)
def updatepolicy(self, newpolicyfile): #policy_data = anchore_utils.read_plainfile_tolist(newpolicyfile) try: policy = anchore_policy.read_policy(name='default', file=newpolicyfile) policy_data = policy['default'] except Exception as err: policy_data = [] newpol = anchore_policy.structure_policy(policy_data) for imageId in self.images: if imageId in self.allimages: try: self.save_policy(imageId, newpol) except Exception as err: self._logger.error("failed to update policy for image ("+imageId+"). bailing out: " + str(err)) return(False) return(True)
def updatepolicy(self, newpolicyfile): #policy_data = anchore_utils.read_plainfile_tolist(newpolicyfile) try: policy = anchore_policy.read_policy(name='default', file=newpolicyfile) policy_data = policy['default'] except Exception as err: policy_data = [] newpol = anchore_policy.structure_policy(policy_data) for imageId in self.images: if imageId in self.allimages: try: self.save_policy(imageId, newpol) except Exception as err: self._logger.error("failed to update policy for image (" + imageId + "). bailing out: " + str(err)) return (False) return (True)
def get_image_policies(self, image): # load default and image override policies, merge (if new # checks are in default), and save (if there is a diff after # the merge) try: policy = anchore_policy.read_policy(name='default', file=self.default_gatepol) policy_data = policy['default'] except Exception as err: policy_data = [] default_policies = anchore_policy.structure_policy(policy_data) policy_data = self.anchoreDB.load_gate_policy(image.meta['imageId']) image_policies = anchore_policy.structure_policy(policy_data) if image_policies and default_policies: policies = self.merge_policies(image_policies, default_policies) if policies != image_policies: self.save_policy(image.meta['imageId'], policies) else: policies = default_policies self.save_policy(image.meta['imageId'], policies) return(policies)
def edit_policy_file(self, editpolicy=False, whitelist=False): ret = True if not editpolicy and not whitelist: # nothing to do return (ret) for imageId in self.images: if editpolicy: data = self.anchoreDB.load_gate_policy(imageId) else: data = self.anchoreDB.load_gate_whitelist(imageId) if not data: self._logger.info( "Cannot find existing data to edit, skipping: " + str(imageId)) else: tmpdir = anchore_utils.make_anchoretmpdir("/tmp") try: thefile = os.path.join(tmpdir, "anchorepol." + imageId) anchore_utils.write_plainfile_fromlist(thefile, data) if "EDITOR" in os.environ: cmd = os.environ["EDITOR"].split() cmd.append(thefile) try: subprocess.check_output(cmd, shell=False) except: ret = False elif os.path.exists("/bin/vi"): try: rc = os.system("/bin/vi " + thefile) if rc: ret = False except: ret = False else: self._logger.info( "Cannot find editor to use: please set the EDITOR environment variable and try again" ) break #newdata = anchore_utils.read_plainfile_tolist(thefile) try: policy = anchore_policy.read_policy(name='default', file=thefile) newdata = policy['default'] except Exception as err: newdata = [] if editpolicy: self.anchoreDB.save_gate_policy(imageId, newdata) else: self.anchoreDB.save_gate_whitelist(imageId, newdata) except Exception as err: pass finally: if tmpdir: shutil.rmtree(tmpdir) return (ret)
def execute_gates(self, image, refresh=True): self._logger.debug("gate policy evaluation for image " + str(image.meta['imagename']) + ": begin") success = True imagename = image.meta['imageId'] gatesdir = '/'.join([self.config["scripts_dir"], "gates"]) workingdir = '/'.join([self.config['anchore_data_dir'], 'querytmp']) outputdir = workingdir self._logger.info(image.meta['shortId'] + ": evaluating policies ...") for d in [outputdir, workingdir]: if not os.path.exists(d): os.makedirs(d) imgfile = '/'.join( [workingdir, "queryimages." + str(random.randint(0, 99999999))]) anchore_utils.write_plainfile_fromstr(imgfile, image.meta['imageId']) if self.policy_override: #policy_data = anchore_utils.read_plainfile_tolist(self.policy_override) try: policy = anchore_policy.read_policy(name='default', file=self.policy_override) policy_data = policy['default'] except Exception as err: policy_data = [] policies = anchore_policy.structure_policy(policy_data) else: policies = self.get_image_policies(image) try: gmanifest, failedgates = anchore_utils.generate_gates_manifest() if failedgates: self._logger.error( "some gates failed to run - check the gate(s) modules for errors: " + str(','.join(failedgates))) success = False else: success = True for gatecheck in policies.keys(): # get all commands that match the gatecheck gcommands = [] for gkey in gmanifest.keys(): if gmanifest[gkey]['gatename'] == gatecheck: gcommands.append(gkey) # assemble the params from the input policy for this gatecheck params = [] for trigger in policies[gatecheck].keys(): if 'params' in policies[gatecheck][ trigger] and policies[gatecheck][trigger][ 'params']: params.append( policies[gatecheck][trigger]['params']) if not params: params = ['all'] if gcommands: for command in gcommands: cmd = [command] + [ imgfile, self.config['image_data_store'], outputdir ] + params self._logger.debug("running gate command: " + str(' '.join(cmd))) (rc, sout, cmdstring) = anchore_utils.run_command(cmd) if rc: self._logger.error("FAILED") self._logger.error("\tCMD: " + str(cmdstring)) self._logger.error("\tEXITCODE: " + str(rc)) self._logger.error("\tOUTPUT: " + str(sout)) success = False else: self._logger.debug("") self._logger.debug("\tCMD: " + str(cmdstring)) self._logger.debug("\tEXITCODE: " + str(rc)) self._logger.debug("\tOUTPUT: " + str(sout)) self._logger.debug("") else: self._logger.warn( "WARNING: gatecheck (" + str(gatecheck) + ") line in policy, but no gates were found that match this gatecheck" ) except Exception as err: self._logger.error("gate evaluation failed - exception: " + str(err)) finally: if imgfile and os.path.exists(imgfile): try: os.remove(imgfile) except: self._logger.error("could not remove tempfile: " + str(imgfile)) if success: report = self.generate_gates_report(image) self.anchoreDB.save_gates_report(image.meta['imageId'], report) self._logger.info(image.meta['shortId'] + ": evaluated.") self._logger.debug("gate policy evaluation for image " + str(image.meta['imagename']) + ": end") return (success)
def evaluate_gates_results(self, image): ret = list() fullret = list() final_gate_action = 'GO' policies_whitelist = self.load_whitelist(image) global_whitelist = self.load_global_whitelist() if self.policy_override: #policy_data = anchore_utils.read_plainfile_tolist(self.policy_override) try: policy = anchore_policy.read_policy(name='default', file=self.policy_override) policy_data = policy['default'] except Exception as err: policy_data = [] policies = anchore_policy.structure_policy(policy_data) else: policies = self.get_image_policies(image) for m in policies.keys(): gdata = self.anchoreDB.load_gate_output(image.meta['imageId'], m) for l in gdata: (k, v) = re.match('(\S*)\s*(.*)', l).group(1, 2) imageId = image.meta['imageId'] check = m trigger = k output = v triggerId = hashlib.md5(''.join([check, trigger, output])).hexdigest() # if the output is structured (i.e. decoded as an # anchore compatible json string) then extract the # elements for display try: json_output = json.loads(output) if 'id' in json_output: triggerId = str(json_output['id']) if 'desc' in json_output: output = str(json_output['desc']) except: pass if k in policies[m]: trigger = k action = policies[check][trigger]['action'] r = { 'imageId': imageId, 'check': check, 'triggerId': triggerId, 'trigger': trigger, 'output': output, 'action': action } # this is where whitelist check should go whitelisted = False whitelist_type = "none" if [m, triggerId] in global_whitelist: whitelisted = True whitelist_type = "global" elif r in policies_whitelist['ignore']: whitelisted = True whitelist_type = "image" else: # look for prefix wildcards try: for [gmod, gtriggerId] in global_whitelist: if gmod == m: # special case for backward compat try: if gmod == 'ANCHORESEC' and not re.match( ".*\*.*", gtriggerId) and re.match( "^CVE.*|^RHSA.*", gtriggerId): gtriggerId = gtriggerId + "*" except Exception as err: self._logger.warn( "problem with backward compat modification of whitelist trigger - exception: " + str(err)) matchtoks = [] for tok in gtriggerId.split("*"): matchtoks.append(re.escape(tok)) rematch = "^" + '(.*)'.join( matchtoks) + "$" self._logger.debug( "checking regexp wl<->triggerId for match: " + str(rematch) + " : " + str(triggerId)) if re.match(rematch, triggerId): self._logger.debug( "found wildcard whitelist match") whitelisted = True whitelist_type = "global" break except Exception as err: self._logger.warn( "problem with prefix wildcard match routine - exception: " + str(err)) fullr = {} fullr.update(r) fullr['whitelisted'] = whitelisted fullr['whitelist_type'] = whitelist_type fullret.append(fullr) if not whitelisted: if policies[m][k]['action'] == 'STOP': final_gate_action = 'STOP' elif final_gate_action != 'STOP' and policies[m][k][ 'action'] == 'WARN': final_gate_action = 'WARN' ret.append(r) else: # whitelisted, skip evaluation pass self.save_whitelist(image, policies_whitelist, ret) ret.append({ 'imageId': image.meta['imageId'], 'check': 'FINAL', 'trigger': 'FINAL', 'output': "", 'action': final_gate_action }) fullret.append({ 'imageId': image.meta['imageId'], 'check': 'FINAL', 'trigger': 'FINAL', 'output': "", 'action': final_gate_action, 'whitelisted': False, 'whitelist_type': "none", 'triggerId': "N/A" }) for i in ret: self.anchoreDB.del_gate_eval_output(image.meta['imageId'], i['check']) evals = {} for i in ret: if i['check'] not in evals: evals[i['check']] = list() evals[i['check']].append(' '.join([i['trigger'], i['action']])) for i in evals.keys(): self.anchoreDB.save_gate_eval_output(image.meta['imageId'], i, evals[i]) self.anchoreDB.save_gates_eval_report(image.meta['imageId'], ret) return (ret, fullret)