def remove_links(path: str): bf_init_snapshot(path, 'remove_links') results = bfq.reachability(pathConstraints=PathConstraints(startLocation="/host[0-9]+/"))\ .answer(snapshot='remove_links').frame() removable_interfaces = set() for idx, result in results.iterrows(): if result.TraceCount <= 1: continue visited_interfaces = {} for trace in result.Traces: if trace.disposition == "NO_ROUTE": continue for hop in trace.hops: node = hop.node if "host" in node: continue for step in hop.steps: interface = None if hasattr(step.detail, "inputInterface"): interface = step.detail.inputInterface elif hasattr(step.detail, "outputInterface"): interface = step.detail.outputInterface if interface is not None: iname = f"{node}:{interface}" if iname not in visited_interfaces: visited_interfaces[iname] = 0 visited_interfaces[iname] += 1 interfaces = list(filter(lambda it: it[1] > 1, visited_interfaces.items())) if len(interfaces) > 0: removable_interfaces.add(interfaces[0][0]) print(removable_interfaces) remove_interface_in_config(path, list(removable_interfaces))
def get_reachable_interfaces(snapshot: str, switches: Set[str]) -> Set[str]: # bf_init_snapshot(str(snapshot), "reachable", overwrite=True) nodes = [] results = bfq.nodeProperties().answer().frame() for _, result in results.iterrows(): nodes.append(result.Node) reachable = set() for switch in switches: for node in nodes: results = bfq.reachability( pathConstraints=PathConstraints(startLocation=switch, endLocation=node)) \ .answer(snapshot=snapshot) results = results.frame() for _, result in results.iterrows(): for trace in result.Traces: for hop in trace.hops: for step in hop.steps: if hasattr(step.detail, "outputInterface"): reachable.add( f"{hop.node}:{step.detail.outputInterface}" ) if hasattr(step.detail, "inputInterface"): reachable.add( f"{hop.node}:{step.detail.inputInterface}") return reachable
def BF_assert_flows_exist(task: Task, debug: bool = False, startLocation: str = None, endLocation: str = None, transitLocations: str = None, forbiddenLocations: str = None, actions: str = 'SUCCESS', **kwargs) -> Result: result = bfq.reachability(pathConstraints=PathConstraints( startLocation=startLocation, endLocation=endLocation, transitLocations=transitLocations, forbiddenLocations=forbiddenLocations, ), headers=HeaderConstraints(**kwargs), actions=actions).answer() result = { 'Results': result['answerElements'][0]['rows'], 'Summary': result['answerElements'][0]['summary'], } assert result['Results'] != [], "NO FLOW FOUNDED" if not debug: result = 'FLOW EXISTS' return Result( host=task.host, result=result, )
def ip_flow_validation(bfq, src_ip, dst_ip, start_device, end_dev=""): pprint(src_ip) return bfq.reachability( pathConstraints=PathConstraints( startLocation=start_device, endLocation=end_dev), headers=HeaderConstraints(srcIps=src_ip, dstIps=dst_ip), actions="SUCCESS,FAILURE" ).answer().frame()
def build_reachability(snapshot: str): bf_init_snapshot(snapshot, "reachability", overwrite=True) out = open(os.path.join(snapshot, "policies.csv"), "w") results = bfq.reachability().answer().frame() out.write("type,subnet,specifics,source,Destinations,Environments,Status,Sources\n") for idx, result in results.iterrows(): out.write(f"PolicyType.Reachability,0.0.0.0,2," f"{result.Flow.ingressNode},123 ({result.Flow.dstIp}/32),9,PolicyStatus.HOLDS,123\n")
def eval(self, ori_snapshot: str, new_snapshot: str) -> bool: answer = bfq.reachability(headers=HeaderConstraints(dstIps=self.dst), pathConstraints=PathConstraints(startLocation=self.src)) \ .answer(snapshot=new_snapshot) if hasattr(answer, "frame"): return answer.frame().size > 0 else: return False
def check_traffic(self, snapshot: str, reference_snapshot: str): # bf_set_snapshot(name) load_questions() header = HeaderConstraints(srcIps="0.0.0.0/0", dstIps="0.0.0.0/0", ipProtocols=["tcp"]) path = PathConstraints(startLocation="/as2/", endLocation="/as3/") # result = bfq.differentialReachability(headers=header) \ # .answer(snapshot=snapshot, reference_snapshot=reference_snapshot).frame() result = bfq.reachability(headers=header, pathConstraints=path) \ .answer(snapshot=reference_snapshot).frame() result.to_csv('out.csv')
def get_reachable_nodes(snapshot: str, config_path: str, switches: Set[str]) -> Set[str]: nodes = nodes_from_snapshot(config_path) reachable = set() switch_constraint = f"/{'|'.join(switches)}/" for node in nodes: if node in switches: reachable.add(node) continue results = bfq.reachability( pathConstraints=PathConstraints(startLocation=switch_constraint, endLocation=node)) \ .answer(snapshot=snapshot) results = results.frame() if results.size > 0: reachable.add(node) return reachable
def port_flow_validation(bfq, src_ip, dst_ip, start_device, dst_port, end_dev=""): pprint(src_ip) return bfq.reachability( pathConstraints=PathConstraints(startLocation=start_device, endLocation=end_dev), headers=HeaderConstraints( srcIps=src_ip, dstIps=dst_ip, dstPorts=dst_port, ipProtocols=[ # "UDP", "TCP" ]), actions="SUCCESS,FAILURE").answer().frame()
def get_reachable_nodes_intersect(snapshot: str, switches: Set[str]) -> Set[str]: nodes = [] results = bfq.nodeProperties().answer().frame() for _, result in results.iterrows(): nodes.append(result.Node) reachable = {} for switch in switches: for node in nodes: results = bfq.reachability( pathConstraints=PathConstraints(startLocation=switch, endLocation=node)) \ .answer(snapshot=snapshot) results = results.frame() if results.size > 0: if node not in reachable: reachable[node] = 0 reachable[node] += 1 return set( map( lambda it: it[0], filter(lambda elem: elem[1] >= len(switches) // 3, reachable.items())))
def eval(self, ori_snapshot: str, new_snapshot: str) -> bool: result = bfq.reachability(headers=HeaderConstraints(dstIps=self.dst), pathConstraints=PathConstraints(transitLocations=self.waypoint, startLocation=self.src)) \ .answer(snapshot=new_snapshot).frame() return result.size > 0
def get_traffic(self, snapshot: str): load_questions() result = bfq.reachability(headers=self.header, pathConstraints=self.path) \ .answer(snapshot=snapshot).frame() print(result.to_csv("path.csv"))