def test_event_config_cli(self): """ Tests the custom event configuration meant to be used with the CLI """ # backup current user eventcfg (if exists) if os.path.isfile('eventcfg.yml'): shutil.move('eventcfg.yml', '.eventcfg.yml.original') # load eventdict eventdict = EventLogger.load_eventcfg() # report unmatched file hashes as error eventdict['evt_pd_itg_invalid_md5'] = 'error' # report vdu image not found as error eventdict['evt_vnfd_itg_vdu_image_not_found'] = 'error' # write eventdict EventLogger.dump_eventcfg(eventdict) # perform validation test pkg_path = os.path.join(SAMPLES_DIR, 'packages', 'sonata-demo-invalid-md5.son') validator = Validator(workspace=self._workspace) validator.validate_package(pkg_path) # should return 1 error self.assertEqual(validator.error_count, 2) self.assertEqual(validator.warning_count, 0) # report unmatched file hashes as warning eventdict['evt_pd_itg_invalid_md5'] = 'warning' # do not report vdu image not found eventdict['evt_vnfd_itg_vdu_image_not_found'] = 'none' # write eventdict EventLogger.dump_eventcfg(eventdict) # perform validation test pkg_path = os.path.join(SAMPLES_DIR, 'packages', 'sonata-demo-invalid-md5.son') validator = Validator(workspace=self._workspace) validator.validate_package(pkg_path) # should return 1 warning self.assertEqual(validator.error_count, 0) self.assertEqual(validator.warning_count, 1) # delete temporary eventcfg os.remove('eventcfg.yml') # restore user eventcfg if os.path.isfile('.eventcfg.yml.original'): shutil.move('.eventcfg.yml.original', 'eventcfg.yml')
def test_validate_service_invalid_topology(self): """ Test the validation of an integrity-invalid SONATA service. It ensures that syntax is valid. It ensures that integrity is valid. """ service_path = os.path.join(SAMPLES_DIR, 'services', 'invalid_topology.yml') functions_path = os.path.join(SAMPLES_DIR, 'functions', 'valid') validator = Validator() # syntax and integrity validation -> should return OK validator.configure(dpath=functions_path, syntax=True, integrity=True, topology=False) validator.validate_service(service_path) self.assertEqual(validator.error_count, 0) self.assertEqual(validator.warning_count, 0) # syntax, integrity and topology validation -> should return ERROR(S) validator.configure(topology=True) validator.validate_service(service_path) self.assertGreater(validator.error_count, 0)
def __init__(self, workspace, project=None, services=None, functions=None, dst_path=None, generate_pd=True, version="1.0"): # Assign parameters coloredlogs.install(level=workspace.log_level) self._version = version self._package_descriptor = None self._workspace = workspace self._project = project self._services = services self._functions = functions # Create a son-access client self._access = AccessClient(self._workspace, log_level=self._workspace.log_level) # Create a validator self._validator = Validator(workspace=workspace) self._validator.configure(syntax=True, integrity=False, topology=False) # Create a schema validator self._schema_validator = SchemaValidator(workspace) # Keep track of VNF packaging referenced in NS self._ns_vnf_registry = {} # location to write the package self._dst_path = dst_path if dst_path else '.' # temporary working directory self._workdir = '.package-' + str(time.time()) # Specifies THE service template of this package self._entry_service_template = None # Keep a list of repositories and # catalogue servers that this package depend on. # This will be included in the Package Resolver Section self._package_resolvers = [] # Keep a list of external artifact # dependencies that this package depends up on # This will be included in the Artifact Dependencies Section self._artifact_dependencies = [] # States if this package is self-contained, # i.e. if contains all its relevant artifacts self._sealed = True # Clear and create package specific folder if generate_pd: self.init_package_skeleton() self.build_package()
def test_validate_package_invalid_struct(self): """ Tests the validation of a multiple SONATA packages with a bad file structure. """ # invalid struct #1 pkg_path = os.path.join(SAMPLES_DIR, 'packages', 'sonata-demo-invalid-struct-1.son') validator = Validator(workspace=self._workspace) validator.validate_package(pkg_path) self.assertEqual(validator.error_count, 1) # invalid struct #2 pkg_path = os.path.join(SAMPLES_DIR, 'packages', 'sonata-demo-invalid-struct-2.son') validator = Validator(workspace=self._workspace) validator.validate_package(pkg_path) self.assertEqual(validator.error_count, 1)
def test_validate_package_signature(self): """ Tests the package signature validation function of son-validate. To accomplish this: 1) a private/public key pair is generated 2) a signature is created based on a private key and a package file 3) the signature validation function is called with the generated signature and the public key """ # generate private/public key pair random_generator = Random.new().read key = RSA.generate(1024, random_generator) self.assertTrue(key.can_encrypt()) self.assertTrue(key.can_sign()) self.assertTrue(key.has_private()) # create signature of a file pkg_path = os.path.join(SAMPLES_DIR, 'packages', 'sonata-demo-valid.son') file_data = None try: with open(pkg_path, 'rb') as _file: file_data = _file.read() except IOError as err: print("I/O error: {0}".format(err)) pkg_hash = SHA256.new(file_data).digest() signature = str(key.sign(pkg_hash, '')[0]) pubkey = key.publickey().exportKey('DER') # export in binary encoding # call signature validation function validator = Validator(workspace=self._workspace) result = validator.validate_package_signature(pkg_path, signature, pubkey) # signature must be valid self.assertTrue(result) # call signature validation with a different file pkg_path = os.path.join(SAMPLES_DIR, 'packages', 'sonata-demo-invalid-md5.son') validator = Validator(workspace=self._workspace) result = validator.validate_package_signature(pkg_path, signature, pubkey) # signature must be invalid self.assertFalse(result)
def test_validate_project_invalid(self): """ Tests the validation of an invalid SONATA project. """ prj_path = os.path.join(SAMPLES_DIR, 'sample_project_invalid') project = Project(self._workspace, prj_path) validator = Validator(workspace=self._workspace) validator.validate_project(project) self.assertGreater(validator.error_count, 0)
def _validate_object(keypath, path, obj_type, syntax, integrity, topology, pkg_signature=None, pkg_pubkey=None): # protect against incorrect parameters perrors = validate_parameters(obj_type, syntax, integrity, topology) if perrors: return perrors, 400 rid = gen_resource_key(keypath, obj_type, syntax, integrity, topology) vid = gen_validation_key(path) resource = get_resource(rid) validation = get_validation(vid) if resource and validation: log.info("Returning cached result for '{0}'".format(vid)) update_resource_validation(rid, vid) return validation['result'] log.info("Starting validation [type={}, path={}, flags={}" "resource_id:={}, validation_id={}]".format( obj_type, path, get_flags(syntax, integrity, topology), rid, vid)) set_resource(rid, keypath, obj_type, syntax, integrity, topology) validator = Validator() validator.configure(syntax, integrity, topology, debug=app.config['DEBUG'], pkg_signature=pkg_signature, pkg_pubkey=pkg_pubkey) # remove default dpath validator.dpath = None val_function = getattr(validator, 'validate_' + obj_type) result = val_function(path) print_result(validator, result) json_result = gen_report_result(rid, validator) net_topology = gen_report_net_topology(validator) net_fwgraph = gen_report_net_fwgraph(validator) set_validation(vid, result=json_result, net_topology=net_topology, net_fwgraph=net_fwgraph) update_resource_validation(rid, vid) return json_result
def test_validate_function_valid(self): """ Tests the validation of a valid SONATA function. """ functions_path = os.path.join(SAMPLES_DIR, 'functions', 'valid') validator = Validator() validator.configure(syntax=True, integrity=True, topology=True) validator.validate_function(functions_path) self.assertEqual(validator.error_count, 0) self.assertEqual(validator.warning_count, 0)
def test_validate_project_warning(self): """ Tests the validation of a SONATA project with warnings. """ prj_path = os.path.join(SAMPLES_DIR, 'sample_project_warning') project = Project(self._workspace, prj_path) validator = Validator(workspace=self._workspace) validator.validate_project(project) self.assertEqual(validator.error_count, 0) self.assertGreater(validator.warning_count, 0)
def test_validate_package_invalid_integrigy(self): """ Tests the validation of several SONATA packages with incorrect integrity. """ # invalid integrity #1 pkg_path = os.path.join(SAMPLES_DIR, 'packages', 'sonata-demo-invalid-integrity-1.son') validator = Validator(workspace=self._workspace) validator.validate_package(pkg_path) self.assertEqual(validator.error_count, 1) self.assertEqual(validator.warning_count, 0) # invalid integrity #2 pkg_path = os.path.join(SAMPLES_DIR, 'packages', 'sonata-demo-invalid-integrity-2.son') validator = Validator(workspace=self._workspace) validator.validate_package(pkg_path) self.assertEqual(validator.error_count, 1) self.assertEqual(validator.warning_count, 0)
def test_validate_service_invalid_syntax(self): """ Tests the validation of an syntax-invalid SONATA service. """ service_path = os.path.join(SAMPLES_DIR, 'services', 'invalid_syntax.yml') validator = Validator() validator.configure(syntax=True, integrity=False, topology=False) validator.validate_service(service_path) self.assertGreater(validator.error_count, 0)
def test_validate_package_invalid_md5(self): """ Tests the validation of a SONATA package with incorrect MD5 sums """ self.reset_counters() pkg_path = os.path.join(SAMPLES_DIR, 'packages', 'sonata-demo-invalid-md5.son') validator = Validator(workspace=self._workspace) validator.validate_package(pkg_path) self.assertEqual(val.log.error.counter, 0) self.assertEqual(val.log.warning.counter, 4)
def test_validate_package_valid(self): """ Tests the validation of a valid SONATA package. """ self.reset_counters() pkg_path = os.path.join(SAMPLES_DIR, 'packages', 'sonata-demo-valid.son') validator = Validator(workspace=self._workspace) validator.validate_package(pkg_path) self.assertEqual(val.log.error.counter, 0) self.assertEqual(val.log.warning.counter, 0)
def test_validate_project_valid(self): """ Tests the validation of a valid SONATA project. """ self.reset_counters() prj_path = os.path.join(SAMPLES_DIR, 'sample_project_valid') project = Project(self._workspace, prj_path) validator = Validator(workspace=self._workspace) validator.validate_project(project) self.assertEqual(val.log.error.counter, 0) self.assertEqual(val.log.warning.counter, 0)
def test_validate_function_invalid_syntax(self): """ Tests the validation of a syntax-invalid SONATA function. """ functions_path = os.path.join(SAMPLES_DIR, 'functions', 'invalid_syntax') validator = Validator() validator.configure(syntax=True, integrity=False, topology=False) validator.validate_function(functions_path) self.assertGreater(validator.error_count, 0)
def test_validate_service_valid(self): """ Tests the validation of a valid SONATA service. """ service_path = os.path.join(SAMPLES_DIR, 'services', 'valid.yml') functions_path = os.path.join(SAMPLES_DIR, 'functions', 'valid') validator = Validator() validator.configure(dpath=functions_path) validator.validate_service(service_path) self.assertEqual(validator.error_count, 0) self.assertEqual(validator.warning_count, 0)
def validate_function(): file = request.files['function'] filepath = upload_file(file) validator = Validator() validator.configure(syntax=True, integrity=False, topology=False, debug=app.debug) result = validator.validate_function(filepath) print_result(validator, result) remove_file(filepath) return generate_result(validator)
def test_validate_function_invalid_integrity(self): """ Tests the validation of a integrity-invalid SONATA function. It ensures that syntax is valid. """ functions_path = os.path.join(SAMPLES_DIR, 'functions', 'invalid_integrity') validator = Validator() # syntax validation -> should return OK validator.configure(syntax=True, integrity=False, topology=False) validator.validate_function(functions_path) self.assertEqual(validator.error_count, 0) self.assertEqual(validator.warning_count, 0) # syntax and integrity validation -> should return ERROR(S) validator.configure(integrity=True) validator.validate_function(functions_path) self.assertGreater(validator.error_count, 0)
def validate_package(): file = request.files['package'] filepath = upload_file(file) syntax = (False if 'syntax' not in request.form else eval( request.form['syntax'])) integrity = (False if 'integrity' not in request.form else eval( request.form['integrity'])) topology = (False if 'topology' not in request.form else eval( request.form['topology'])) validator = Validator() validator.configure(syntax=syntax, integrity=integrity, topology=topology, debug=app.debug) result = validator.validate_package(filepath) print_result(validator, result) remove_file(filepath) return generate_result(validator)
def test_validate_package_invalid_md5(self): """ Tests the validation of a SONATA package with incorrect MD5 sums """ pkg_path = os.path.join(SAMPLES_DIR, 'packages', 'sonata-demo-invalid-md5.son') validator = Validator(workspace=self._workspace) validator.validate_package(pkg_path) eventdict = EventLogger.load_eventcfg() invalid_md5_config = str(eventdict['evt_pd_itg_invalid_md5']).lower() if invalid_md5_config == 'error': error_count = 1 warn_count = 1 elif invalid_md5_config == 'warning': error_count = 0 warn_count = 2 elif invalid_md5_config == 'none': error_count = 0 warn_count = 1 else: self.fail("Invalid value of event 'evt_pd_itg_invalid_md5'") self.assertEqual(validator.error_count, error_count) self.assertEqual(validator.warning_count, warn_count)