def visualise_rules(main_domain, is_source, rules, size_multiplier = 1): # dictionary containing sets of edges corresponding to each attribute # attribute_edges['attribute'] = [edges_corresponding_to_attribute] attribute_edges = defaultdict(list) #edges corresponding to boolean-conditioned rules conditional_edges = set() edge_labels = defaultdict(list) #booleans and edges they controll booleans = defaultdict(set) #TODO skip loops (edge form vertex to itself) for i in rules: source = str(i.source) target = str(i.target) if is_source: #change source to "main_domain" if it is an attribute if data.is_attribute(i.source): attribute_edges[source].append((main_domain, target)) source = main_domain else: #change target to "main_domain" if it is an attribute if data.is_attribute(i.target): attribute_edges[target].append((source, main_domain)) target = main_domain edge_labels[(source, target)].extend([str(x) for x in i.perms]) if data.is_conditional(i): booleans[data.is_conditional(i)].add(target if is_source else source) conditional_edges.add((source, target)) #print booleans print("Boolean conditioned edges (dashed lines):\n") for key,value in booleans.items(): print(key+":") for t in value: print("\t",t) process_edge_labels(edge_labels) #remove self loops edge_labels.pop((main_domain, main_domain), None) make_graph(edge_labels, attribute_edges, conditional_edges, main_domain, size_multiplier)
def gather_rules_gephi(self): rules = [] self.domain_grouping = grouping.group_types_cil() #print("Got grouping, getting rules.") self.main_group = self.domain_grouping.get(self.qargs.main_domain) if not self.main_group: print("Error: Unknown package \"" + self.qargs.main_domain + "\"!", file=sys.stderr) sys.exit() print(self.qargs.main_domain) package_types = set(self.main_group.types) package_attributes = set() #get all attributes corresponding to types in given package for t in package_types: package_attributes |= set(data.get_attributes_of_str(t)) if self.qargs.filter_attrs: package_attributes -= set( self.qargs.filter_attrs) #TODO should there really be "-="? self.package_attributes = package_attributes all_rules = data.get_type_enf_rules(ruletype=["allow"], tclass=self.qargs.tclass, perms=self.qargs.perms, booleans=self.qargs.boolean) # get only rules corresponding to given package for rule in all_rules: if rule.source == rule.target: #remove self loops TODO - parametrise continue source = str(rule.source) if data.is_attribute(rule.source): if (source in package_attributes): rules.append(rule) elif (source in package_types): rules.append(rule) target = str(rule.target) if data.is_attribute(rule.target): if (target in package_attributes): rules.append(rule) elif (target in package_types): rules.append(rule) return rules
def expand_rules(self, rules): expanded_rules = [] other_side = "target" if self.qargs.source else "source" #attributes = data.get_attributes for rule in rules: if data.is_attribute(getattr(rule, other_side)): expanded_rules.extend( data.half_expand_rule(rule, not self.qargs.source)) else: expanded_rules.append(rule) return expanded_rules
def filter_attribute_rules(self, rules): # filter attribute rules filtered_rules = [] if self.qargs.export: #TODO gephi for rule in rules: if (data.is_attribute(rule.source) and (str(rule.source) in self.qargs.filter_attrs)) or \ (data.is_attribute(rule.target) and (str(rule.target) in self.qargs.filter_attrs)): continue filtered_rules.append(rule) return filtered_rules for rule in rules: attr = str( getattr(rule, "source" if self.qargs.source else "target")) #skip filtered attributes if attr in self.qargs.filter_attrs: continue filtered_rules.append(rule) return filtered_rules
def rewrite_rules_grouping(self, rules): results = [] for rule in rules: if self.qargs.source: # Can be either one of [source_type, main_domain_group, attribute_of_source] source = self.main_group.name.upper() if self.qargs.source_group and \ (not data.is_attribute(rule.source)) \ else rule.source target = self.reverse_grouping.get(rule.target) #can be attribute -> won't be found in reverse_grouping target = target.name.upper() if target else rule.target else: #target is main target = self.main_group.name.upper() if self.qargs.target_group and \ (not data.is_attribute(rule.target)) \ else rule.target source = self.reverse_grouping.get(rule.source) #can be attribute -> won't be found in reverse_grouping source = source.name.upper() if source else rule.source results.append(data.make_expanded_rule(rule, source, target)) return results
def apply_query(query): rules = data.get_type_enf_rules(_ruletype = ["allow"], _source = query.source, _target = query.target, _tclass = query.tclass, _perms = query.perms, _booleans = query.boolean ) # filtering if query.filter_bools != None: rules = data.filter_terules_boolean(rules, query.filter_bools) #attribute containing "main domain" main_domain = "source" if query.source else "target" # filter attribute rules filtered_rules = [] if query.filter_attrs: for rule in rules: attr = str(getattr(rule, main_domain)) #skip filtered attributes if attr in query.filter_attrs: continue filtered_rules.append(rule) # expand rules ending in attribute if True: rules = [] other_side = "source" if main_domain == "target" else "target" attributes = data.get_attributes for rule in filtered_rules: if data.is_attribute(getattr(rule, other_side)): rules.extend(data.half_expand_rule(rule, main_domain == "target")) else: rules.append(rule) #apply_domain_grouping() else: rules = filtered_rules visualise_rules(query.main_domain, bool(query.source), rules)
def export_package(package, package_attributes, rules): edge_labels = defaultdict(list) #edges with permissions attribute_edges_dict = defaultdict( list) #special edges connecting attributes and corresponding types package_types = set(package.types) attribute_nodes = set( ) # should be assigned special attribute so that gephi recognises them for rule in rules: source = str(rule.source) target = str(rule.target) sources = set([source]) #expanded from attributes targets = set([target]) if data.is_attribute(rule.source): attribute_nodes.add(source) if (source in package_attributes): #sources = set(data.get_types_of(rule.source)) & package_types attribute_edges_dict[source].extend( set(data.get_types_of(rule.source)) & package_types) pass else: attribute_nodes.add(source) if data.is_attribute(rule.target): attribute_nodes.add(target) if (target in package_attributes): #targets = set(data.get_types_of(rule.target)) & package_types attribute_edges_dict[target].extend( set(data.get_types_of(rule.target)) & package_types) pass else: attribute_nodes.add(target) # generate edges for the final graph for s in sources: for t in targets: edge_labels[(s, t)].extend([str(x) for x in rule.perms]) process_edge_labels(edge_labels) G = nx.DiGraph() # Add special attributes for Gephi (color, type, ...) G.add_edges_from([(key[0], key[1], { "label": val, "color": "cyan" }) for key, val in edge_labels.items()]) attribute_edges = set() for attr, val in attribute_edges_dict.items(): for t in val: attribute_edges.add((attr, t)) G.add_edges_from([(v, u, { "type": "typeattr", "color": "redorange" }) for (u, v) in attribute_edges]) #assign color to each node (attribute vs type from selected package vs other type) nodes_gephi = [] for n in G.nodes(): nodetype = "type" nodecolor = "cyan" #"skyblue turquoise" if n in attribute_nodes: nodetype = "attribute" nodecolor = "darkorange" elif n in package_types: nodetype = "selected" nodecolor = "green" nodes_gephi.append((n, {"type": nodetype, "color": nodecolor})) # nodecolor = (0,197,255) # if n in attribute_nodes: # nodetype = "attribute" # nodecolor = (255,107,23) # elif n in package_types: # nodetype = "selected" # nodecolor = (1,231,0) # nodes_gephi.append((n,{"label":n,"type":nodetype, "r":nodecolor[0], "g":nodecolor[1], "b":nodecolor[2]})) G.add_nodes_from(nodes_gephi) #TODO: allow user to specify output file name nx.write_graphml(G, str(package) + ".graphml")
def apply_query_grouping(self, domain_grouping): #if self.qargs.source_group or self.qargs.target_group: main_group = None for group in domain_grouping.values(): if group.contains(self.qargs.main_domain): main_group = group break else: pass # TODO: raise exception rules = [] #get all rules corresponding to source/target domain group for type_ in main_group.types: source = type_ if self.qargs.source else None target = type_ if self.qargs.target else None rules += data.get_type_enf_rules(ruletype=["allow"], source=source, target=target, tclass=self.qargs.tclass, perms=self.qargs.perms, booleans=self.qargs.boolean) # filtering if self.qargs.filter_bools != None: rules = data.filter_terules_boolean(rules, self.qargs.filter_bools) #attribute containing "main domain" main_domain = "source" if self.qargs.source else "target" # filter attribute rules filtered_rules = [] if self.qargs.filter_attrs: for rule in rules: attr = str(getattr(rule, main_domain)) #skip filtered attributes if attr in self.qargs.filter_attrs: continue filtered_rules.append(rule) else: filtered_rules = rules # expand rules ending in attribute if False: rules = [] other_side = "target" if self.qargs.source else "source" #attributes = data.get_attributes for rule in filtered_rules: if data.is_attribute(getattr(rule, other_side)): rules.extend(data.half_expand_rule(rule, self.qargs.source)) else: rules.append(rule) #apply_domain_grouping() else: rules = filtered_rules rules = _rewrite_rules_grouping(rules, domain_grouping) #return QueryResults(self.qargs, rules) #vis.visualise_rules(self.qargs.main_domain, bool(self.qargs.source), rules) vis.visualise_rules_grouping(main_group, bool(self.qargs.source), rules)