def test_list_questions(tmpdir, session): dir = tmpdir.mkdir("questions") dir.join(TEST_QUESTION_NAME + ".json").write( json.dumps(TEST_QUESTION_DICT)) load_questions(question_dir=dir.strpath, session=session) names = [q["name"] for q in list_questions()] assert names == [TEST_QUESTION_NAME]
def test_make_check(question_dir): """Make a check out of the first available question.""" load_questions(question_dir=question_dir) q = list_questions()[0]['name'] qdict = getattr(bfq, q)().make_check().dict() assert qdict.get('assertion') == Assertion(AssertionType.COUNT_EQUALS, 0).dict()
def test_list_questions_default_session(tmpdir): dir = tmpdir.mkdir("questions") dir.join(TEST_QUESTION_NAME + ".json").write( json.dumps(TEST_QUESTION_DICT)) load_questions(question_dir=dir.strpath) names = [q["name"] for q in bf_session.q.list()] assert names == [TEST_QUESTION_NAME]
def main(): random.seed(80) logging.disable(sys.maxsize) parser = argparse.ArgumentParser(description="Batfish Impact Analysis") parser.add_argument("-p", "--snapshot_path", help="BF_SNAPSHOT_PATH", required=True) parser.add_argument("-s", "--snapshot_name", help="SNAPSHOT_NAME", required=True) parser.add_argument("-n", "--network_name", help="BF_NETWORK", required=True) parser.add_argument("-i", "--service_ip", help="SERVICE_IP", default="172.29.236.139") args = vars(parser.parse_args()) BF_NETWORK = args["network_name"] BF_SNAPSHOT_BASE = args["snapshot_name"] BF_SNAPSHOT_PATH = args["snapshot_path"] BF_SNAPSHOT_FAIL = "fail_snapshot" # BATFISH_SERVICE_IP = "172.29.236.139" BATFISH_SERVICE_IP = args["service_ip"] bf_session.host = BATFISH_SERVICE_IP load_questions() bf_set_network(BF_NETWORK) bf_init_snapshot(BF_SNAPSHOT_PATH, name=BF_SNAPSHOT_BASE, overwrite=True) # Print Batfish settings/parameters print_bf_params( DST_IP_REACHABILITY=DST_IP_REACHABILITY, PORT_CHANNEL_MEMBER_SCOPE=PORT_CHANNEL_MEMBER_SCOPE, L3_INTERFACE_SCOPE=L3_INTERFACE_SCOPE, NODE_SCOPE=NODE_SCOPE, ) # Run Batfish tests print("\n[bold]== Deactivating Interfaces ==[/bold]") deactivate_po_members(BF_SNAPSHOT_BASE, BF_SNAPSHOT_FAIL) deactivate_l3_interfaces(BF_SNAPSHOT_BASE, BF_SNAPSHOT_FAIL) print("\n[bold]== Deactivating Nodes ==[/bold]") deactivate_nodes(BF_SNAPSHOT_BASE, BF_SNAPSHOT_FAIL) print( "\n[bold green][SUCCESS] No reachability differences found[/bold green]" ) # Clean up Snapshots/Networks delete_bf_data()
def initialise_batfish(): # Load all the questions. load_questions() # Initialises batfish. bf_set_network(NETWORK_NAME) bf_init_snapshot(BASE_SNAPSHOT_PATH, name=BASE_SNAPSHOT_NAME, overwrite=True)
def main(): parser = argparse.ArgumentParser(description="Script to test network configs with batfish") parser.add_argument( "--host", help="IP/host of the batfish server", default='localhost', type=str ) parser.add_argument( "--candidate", help='Path to directory containing candidate device configuration folder', default='./candidate', type=str ) parser.add_argument( "--failure", help='Path to directory containing candidate device configuration folder with injected failure conditions', default='./candidate-with-failure', type=str ) parser.add_argument( "--log", help='Path to logging file', type=str ) args = parser.parse_args() bf_session.coordinatorHost = args.host bf_logger.setLevel(logging.WARN) if args.log: logging.basicConfig(filename=args.log, format='%(levelname)s: %(message)s', level=logging.INFO) console = logging.StreamHandler() console.setLevel(logging.ERROR) logging.getLogger('').addHandler(console) load_questions() bf_init_snapshot(args.candidate, name='candidate') bf_init_snapshot(args.failure, name='failure') bf_set_snapshot('candidate') csFailed = test_config_sanity(False) cpFailed = test_controlplane(False) dpFailed = test_dataplane(False, fromNode='leaf-3') logging.info("\nProgress: analysing failure conditions") bf_set_snapshot('failure') dpFailedoutage = test_dataplane(False, fromNode='leaf-3') rr = bfq.reducedReachability().answer(snapshot='candidate', reference_snapshot='failure') print_reduced_rechability(rr.get('answerElements')[0]) return 0 if not any([cpFailed, dpFailed, csFailed, dpFailedoutage]) else 1
def resolve(node_spec: str, node_property: str, snapshot: str): data = set() load_questions() result = bfq.nodeProperties(nodes=node_spec, properties=node_property)\ .answer(snapshot=snapshot).frame() for node in result.Node.values: data.add(node) return data
def network(): load_questions(_stable_question_dir) load_questions(_experimental_question_dir) try: bf_delete_network(TEST_NETWORK) except Exception: pass bf_set_network(TEST_NETWORK) yield bf_init_snapshot(join(_this_dir, "snapshot"), name="snapshot") bf_delete_network(TEST_NETWORK)
def network(): load_questions(_stable_question_dir) load_questions(_experimental_question_dir) try: bf_delete_network(TEST_NETWORK) except Exception: pass bf_set_network(TEST_NETWORK) yield bf_init_snapshot(_test_rig_dir + "/example", name="example") bf_delete_network(TEST_NETWORK)
def generate_code_for_questions( question_list: List[Mapping[str, Any]], question_class_map: Mapping[str, QuestionMeta], ) -> List[NotebookNode]: """Generate notebook cells for all questions in a single question category.""" load_questions() cells: List[NotebookNode] = [] for question_data in question_list: cells.extend( generate_code_for_question(question_data, question_class_map)) return cells
def main(): load_questions() o = FindBestOrderPerCommand( Path("/home/leo/repos/sdn-verifier/configs/default"), [ Path( '/home/leo/repos/sdn-verifier/configs/updates/acls/as1border1.cfg' ), Path( '/home/leo/repos/sdn-verifier/configs/updates/acls/as2border1.cfg' ) ]) print(o.find())
def run(path, adj): """ Generates the Batfish routing table :param path: Path to the config files used to generate the routing table :param adj: Adjacency information, not used by Batfish :return: Triplet of routing table, parse warning and init issues of Batfish """ load_questions() bf_set_network('fuzzer') bf_init_snapshot(path) return bfq.routes().answer().frame(), bfq.parseWarning().answer().frame(), bfq.initIssues().answer().frame()
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 check_invalid_policies(path_to_csv: str, snapshot: str) -> bool: global initialized if not initialized: initialized = True # bf_session.host = "10.81.1.21" load_questions() policies = build_policies_from_csv(path_to_csv) bf_init_snapshot(snapshot, "check") for policy in policies: if not policy.eval("", "check"): print(policy) # return False return True
def init_batfish(self): bf_session.host = self.host bf_session.coordinatorHost = self.host bf_set_network(self.NETWORK_NAME) # Initialize Batfish Snapshot bf_init_snapshot(self.snapshot_folder, name=self.NETWORK_NAME, overwrite=True) # Generate Dataplane bf_generate_dataplane() # Load Batfish Questions load_questions()
def main(): parser = argparse.ArgumentParser( description="Script to test network configs with batfish") parser.add_argument("--batfish_server", help="IP/host of the batfish server", default='localhost', type=str) parser.add_argument( "--candidate", help= 'Path to directory containing candidate device configuration folder', default='./candidate', type=str) parser.add_argument("--log", help='Path to logging file', default='batfish.log', type=str) OPTIONS = parser.parse_args() logging.info('=> Batfish server is running on: %s', str(OPTIONS.batfish_server)) bf_session.host = OPTIONS.batfish_server # Configure logging for log file if defined. if OPTIONS.log: logging.basicConfig(filename=OPTIONS.log, format='%(levelname)s: %(message)s', level=logging.INFO) console = logging.StreamHandler() console.setLevel(logging.ERROR) logging.getLogger('').addHandler(console) # Initialize BATFISH session # Batfish server must be running on a container # docker run -p 8888:8888 -p 9997:9997 -p 9996:9996 batfish/allinone load_questions() bf_init_snapshot(OPTIONS.candidate, name='candidate') bf_set_snapshot('candidate') csFailed = test_config_sanity(False) logging.info('=> csFailed status: %s', str(csFailed)) cpFailed = test_controlplane(False) logging.info('=> cpFailed status: %s', str(cpFailed)) if csFailed or cpFailed: return 1 else: return 0
def run(self, tmp=None, task_vars=None): del tmp # モジュールを実行する # ただし、このモジュールは何もしない result = super(ActionModule, self).run(task_vars=task_vars) # # モジュール実行後の後工程処理 # src = self._task.args.get('src') dest = self._task.args.get('dest') snapshot_name = self._task.args.get('snapshot_name') snapshot_path = self._task.args.get('snapshot_path') network_name = self._task.args.get('network_name') application = self._task.args.get('application') condition = self._task.args.get('condition') node = self._task.args.get('node') acl_name = self._task.args.get('acl_name') src_list = self.create_src_list(src) dest_list = self.create_dest_list(dest) application_list = self.create_application_list(application) condition_list = self.create_condition_list(condition) node_list = self.create_node_list(node) acl_list = self.create_acl_list(acl_name) load_questions() bf_set_network(network_name) bf_init_snapshot(snapshot_path, name=snapshot_name, overwrite=True) #init_snapshot(self, snapshot_name, snapshot_path) msg = self.answer_testfilters_question(src_list, node_list, acl_list, dest_list, application_list) #msg = self.answer_testfilters_question(src, node, acl_name, dest, application) answer = msg msg1 = self.judge_condition(condition, answer) result['batfish_result'] = json.loads(msg) #result['judge'] = json.loads(msg1) if msg1 == 'PASS': result['msg'] = 'PASS' return result else: result['failed'] = True return result
def test_list_questions(): current_path = os.path.abspath(os.path.dirname(__file__)) question_directory = os.path.join(current_path, "../../questions") load_questions(question_dir=question_directory) assert list_questions() != []
def run(self, tmp=None, task_vars=None): del tmp # モジュールを実行する # ただし、このモジュールは何もしない result = super(ActionModule, self).run(task_vars=task_vars) # # モジュール実行後の後工程処理 # snapshot_name = self._task.args.get('snapshot_name') snapshot_path = self._task.args.get('snapshot_path') network_name = self._task.args.get('network_name') csv_file_path = self._task.args.get('csv_file_path') PASS = "******" FAIL = "FAIL" result = {} result_list = [] with open(csv_file_path, mode='r') as f: csv_file_list = [x for x in csv.DictReader(f)] answer_list = [] # Batfishの質問、スナップショット及びノードを読見込む load_questions() if network_name and snapshot_name: bf_set_network(network_name) bf_init_snapshot(snapshot_path, name=snapshot_name, overwrite=True) else: bf_set_network() bf_init_snapshot(snapshot_path, overwrite=True) for c in csv_file_list: expect_condition = c.get('expect_condition') test_id = c.get('test_id') src = c.get('src') dest = c.get('dest') acl = c.get('acl_name') node = c.get('node') application = c.get('application') src_int = c.get('src_int') dest_int = c.get('dest_int') if expect_condition == '' or expect_condition == None: result['failed'] = True result['msg'] = 'expect_condition parameter is required.' return result if expect_condition != 'deny' and expect_condition != 'permit': result['failed'] = True result[ 'msg'] = 'expect_condition parameter should be permit or deny. ' return result if test_id == '' or test_id == None: result['failed'] = True result['msg'] = 'test_id parameter is required.' return result #srcは必ず必要なパラメータ if src == '': result['failed'] = True result['msg'] = 'src parameter is required.' return result if node == '': result['failed'] = True result['msg'] = 'node parameter is required.' return result if src_int != '' and node == '': result['failed'] = True result[ 'msg'] = 'node must be specified if you want to test src_int.' return result if acl == '' or acl == None: ip_flow = HeaderConstraints(srcIps=src) answer = bfq.testFilters(headers=ip_flow, nodes=node).answer() show = answer.frame() answer = show.to_json() json_answer = json.loads(answer) json_answer["Test_id"] = test_id json_answer["expect_condition"] = expect_condition answer_list.append(json_answer) if dest != '' and application != '': ip_flow = HeaderConstraints(srcIps=src, dstIps=dest, applications=application) answer = bfq.testFilters(headers=ip_flow, nodes=node, filters=acl).answer() show = answer.frame() answer = show.to_json() json_answer = json.loads(answer) json_answer["Test_id"] = test_id json_answer["expect_condition"] = expect_condition answer_list.append(json_answer) # 一つ上の条件が一致した場合は以下セクションを読み込む必要がないのでelifを使う elif dest != '' and application == '': ip_flow = HeaderConstraints(srcIps=src, dstIps=dest) answer = bfq.testFilters(headers=ip_flow, nodes=node, filters=acl).answer() show = answer.frame() answer = show.to_json() json_answer = json.loads(answer) json_answer["Test_id"] = test_id json_answer["expect_condition"] = expect_condition answer_list.append(json_answer) elif dest == '' and application != '': ip_flow = HeaderConstraints(srcIps=src, applications=application) answer = bfq.testFilters(headers=ip_flow, nodes=node, filters=acl).answer() show = answer.frame() answer = show.to_json() json_answer = json.loads(answer) json_answer["Test_id"] = test_id json_answer["expect_condition"] = expect_condition answer_list.append(json_answer) # あるノードのintに着信したパケットが出力intとして指定したintで # どのように処理されるかテストする # nodeの指定がない場合はエラーになるよう上で実装済 # # ある着信がdeny or permitをテストしたい時のセクション #ノードとintを正確に指定しても動作しないので保留 #if src_int != '' and dest_int == '' and application == '' and dest == '': # flow = HeaderConstraints(srcIps=src) # answer = bfq.testFilters(headers=flow, # startLocation="@enter(" + node + "[" + src_int + "])", # filters="@out(" + dest_int + ")").answer() # # show = answer.frame() # answer = show.to_json() # json_answer = json.loads(answer) # json_answer["Test_id"] = test_id # json_answer["expect_condition"] = expect_condition # answer_list.append(json_answer) #if src_int != '' and dest_int != '' and application != '' and dest != '' and application != '': # flow = HeaderConstraints(srcIps=src, # dstIps=dest, # applications=application) # answer = bfq.testFilters(headers=flow, # startLocation="@enter(" + node + "[" + src_int + "])", # filters="@out(" + dest_int + ")").answer() # # show = answer.frame() # answer = show.to_json() # json_answer = json.loads(answer) # json_answer["Test_id"] = test_id # json_answer["expect_condition"] = expect_condition # answer_list.append(json_answer) result['batfish_result'] = answer_list for answer in answer_list: action = answer['Action'] action_num = action["0"] condition = answer["expect_condition"] test_id = answer["Test_id"] # Batfishが出す結果(DENY or PERMIT)とexpect_conditionがマッチしなければFAIL if action_num != condition.upper(): result['failed'] = True result_list.append('test_id {0} is {1}.'.format(test_id, FAIL)) else: result_list.append('test_id {0} is {1}.'.format(test_id, PASS)) result['msg'] = result_list return result
def check_traffic(self, snapshot: str, reference_snapshot: str): # bf_set_snapshot(name) load_questions() result = bfq.differentialReachability(headers=self.header, pathConstraints=self.path) \ .answer(snapshot=snapshot, reference_snapshot=reference_snapshot).frame() result.to_csv('diff.csv')
from pybatfish.question.question import load_questions from pybatfish.datamodel.flow import HeaderConstraints, PathConstraints from pybatfish.question import bfq import random import sys import argparse parser = argparse.ArgumentParser(description="Batfish Shell") parser.add_argument("-p", "--snapshot_path", help="SNAPSHOT_PATH", required=True) parser.add_argument("-s", "--snapshot_name", help="SNAPSHOT_NAME", required=True) parser.add_argument("-n", "--network_name", help="NETWORK_NAME", required=True) BATFISH_SERVICE_IP = "172.29.236.139" args = vars(parser.parse_args()) bf_session.host = BATFISH_SERVICE_IP load_questions() print("[*] Initializing BASE_SNAPSHOT") bf_set_network(args["network_name"]) bf_init_snapshot(args["snapshot_path"], name=args["snapshot_name"], overwrite=True) print("[OK] Success - Batfish imports ready...")
def __init__(self, snapshot): bf_logger.setLevel(logging.ERROR) load_questions() bf_init_snapshot(snapshot)
def run(self, tmp=None, task_vars=None): del tmp # モジュールを実行する # ただし、このモジュールは何もしない result = super(ActionModule, self).run(task_vars=task_vars) import csv # # モジュール実行後の後工程処理 # snapshot_name = self._task.args.get('snapshot_name') snapshot_path = self._task.args.get('snapshot_path') network_name = self._task.args.get('network_name') csv_file_path = self._task.args.get('csv_file_path') csv_file_list = [] PASS = "******" FAIL = "FAIL" result = {} result_list = [] with open(csv_file_path) as f: csv_file_list = [x for x in csv.DictReader(f)] answer_list = [] load_questions() bf_set_network(network_name) bf_init_snapshot(snapshot_path, name=snapshot_name, overwrite=True) result = {} for csv in csv_file_list: intend_condition = csv.get('intend_condition') test_id = csv.get('test_id') src = csv.get('src') dest = csv.get('dest') acl = csv.get('acl_name') node = csv.get('node') application = csv.get('application') if intend_condition == '' or intend_condition == None: result['failed'] = True result['msg'] = 'intend_condition parameter is required.' return result if test_id == '' or test_id == None: result['failed'] = True result['msg'] = 'test_id parameter is required.' return result #srcは必ず必要なパラメータ if src == '': result['failed'] = True result['msg'] = 'src parameter is required.' return result if node == '': result['failed'] = True result['msg'] = 'node parameter is required.' return result if acl == '': result['failed'] = True result['msg'] = 'acl parameter is required.' return result if dest != '' and application != '': ip_flow = HeaderConstraints(srcIps=src, dstIps=dest, applications=application) answer = bfq.testFilters(headers=ip_flow, nodes=node, filters=acl).answer() show = answer.frame() answer = show.to_json() json_answer = json.loads(answer) json_answer["Test_id"] = test_id json_answer["Intend_condition"] = intend_condition answer_list.append(json_answer) elif dest != '' and application == '': ip_flow = HeaderConstraints(srcIps=src, dstIps=dest) answer = bfq.testFilters(headers=ip_flow, nodes=node, filters=acl).answer() show = answer.frame() answer = show.to_json() json_answer = json.loads(answer) json_answer["Test_id"] = test_id json_answer["Intend_condition"] = intend_condition answer_list.append(json_answer) elif application != '' and dest == '': ip_flow = HeaderConstraints(srcIps=src, applications=application) answer = bfq.testFilters(headers=ip_flow, nodes=node, filters=acl).answer() show = answer.frame() answer = show.to_json() json_answer = json.loads(answer) json_answer["Test_id"] = test_id json_answer["Intend_condition"] = intend_condition answer_list.append(json_answer) result['batfish_result'] = answer_list for answer in answer_list: action = answer['Action'] action_num = action["0"] condition = answer["Intend_condition"] test_id = answer["Test_id"] if action_num != condition.upper(): result['failed'] = True result_list.append('{0}. test_id {1} test is failed.'.format( FAIL, test_id)) else: result_list.append(PASS) result_list.append('{0}. {1} test is passed.'.format( PASS, test_id)) result['msg'] = result_list return result
def test_list_questions(question_dir): load_questions(question_dir=question_dir) assert list_questions() != []
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"))