def post(self): session_id = get_session_id(session, request) if session_id is None: raise CairisHTTPError( status_code=httplib.BAD_REQUEST, message='The session is neither started or no session ID is provided with the request.' ) content_length = request.content_length max_length = 10*1024*1024 if content_length > max_length: raise MissingParameterHTTPError(exception=RuntimeError('File exceeded maximum size (10MB)')) try: file = request.files['file'] except LookupError as ex: raise MissingParameterHTTPError(param_names=['file']) except Exception as ex: raise CairisHTTPError( status_code=httplib.CONFLICT, message=str(ex.message), status='Unknown error' ) dao = UploadDAO(session_id) filename = dao.upload_image(file) resp_dict = {'message': 'File successfully uploaded', 'filename': filename} resp = make_response(json_serialize(resp_dict, session_id=session_id), httplib.OK) resp.contenttype = 'application/json' return resp
def get_fonts(session_id=None): if session_id is not None: b = Borg() settings = b.get_settings(session_id) fontName = settings.get('fontName', None) fontSize = settings.get('fontSize', None) apFontName = settings.get('apFontSize', None) if fontName is None or fontSize is None or apFontName is None: raise CairisHTTPError( status_code=BAD_REQUEST, message= 'The method is not callable without setting up the project settings.' ) elif isinstance(fontName, string_types) and isinstance( fontSize, string_types) and isinstance(apFontName, string_types): return fontName, fontSize, apFontName else: raise CairisHTTPError( status_code=BAD_REQUEST, message= 'The database connection was not properly set up. Please try to reset the connection.' ) else: raise CairisHTTPError( status_code=BAD_REQUEST, message= 'The method is not callable without setting up the project settings.' )
def get_objects_by_2parameters(self, table, environment): try: permissableDimensions = [ 'asset', 'asset_value', 'attacker', 'control', 'countermeasure', 'datastore', 'detection_mechanism', 'diagramDatastore', 'diagramEntity', 'diagramProcess', 'domainproperty', 'dfd_filter', 'entity', 'goal', 'information_asset', 'misusecase', 'obstacle', 'persona', 'process', 'requirement', 'response', 'risk', 'role', 'task', 'task_characteristic', 'threat', 'ugm_filter', 'usecase', 'unconnected_vulnerability', 'unconnected_threat', 'vulnerability', 'component' ] if (table not in permissableDimensions): raise CairisHTTPError( BAD_REQUEST, 'Invalid dimension', table + ' is not a permissable dimension when specifying environment' ) if (self.db_proxy.nameExists(environment, 'environment') == False): raise CairisHTTPError(NOT_FOUND, 'Unknown environment', environment + ' does not exist') return self.db_proxy.getDimensionNames(table, environment) except DatabaseProxyException as ex: self.close() raise ARMHTTPError(ex)
def get_dbproxy(self, session_id): """ Searches the MySQLDatabaseProxy instance associated with the session ID. :param session_id: The session ID :type session_id: str :rtype MySQLDatabaseProxy :return The MySQLDatabaseProxy instance associated with the session ID :raise CairisHTTPError """ if session_id: b = Borg() db_proxy = b.get_dbproxy(session_id) if db_proxy is None: raise CairisHTTPError( status_code=httplib.CONFLICT, message='The database connection could not be created.') elif isinstance(db_proxy, MySQLDatabaseProxy): db_proxy.reconnect(session_id=session_id) return db_proxy else: raise CairisHTTPError( status_code=httplib.CONFLICT, message= 'The database connection was not properly set up. Please try to reset the connection.' ) else: raise MissingParameterHTTPError(param_names=['session_id'])
def get_goal_association(self, environment_name, goal_name, subgoal_name, deleteId=True, pathValues=[]): try: assoc = self.db_proxy.getGoalAssociation(environment_name, goal_name, subgoal_name) if (deleteId == True): del assoc.theId return assoc except ARMException as ex: self.close() raise ARMHTTPError(ex) except ValueError as ex: self.close() raise CairisHTTPError(status_code=http.client.BAD_REQUEST, status="Server error", message='Error unpacking ' + key + ': ' + format(ex)) except Exception as ex: self.close() raise CairisHTTPError(status_code=http.client.BAD_REQUEST, status="Server error", message=format(ex))
def upload_image(self, file): """ :type file: FileStorage """ extension = os.path.splitext(file.filename)[1] f_name = str(uuid.uuid4()) + extension f_path = os.path.join(self.image_dir, f_name) try: file.save(f_path) except IOError: raise CairisHTTPError( status_code=httplib.CONFLICT, status='Unable to save image', message='Please check if the static web directory exists ' + 'and if the application has permission to write in the directory', ) if not os.path.exists(f_path): raise CairisHTTPError( status_code=httplib.CONFLICT, status='Image not found', message='The image could not be saved on the server. \ Please check the server configuration to fix this problem.') img_format = imghdr.what(f_path) if not img_format or img_format not in self.accepted_image_types: os.remove(f_name) raise CairisHTTPError( status_code=httplib.CONFLICT, status='Unsupported file type', message='The provided image file is not supported by CAIRIS') return f_name
def set_permission(self,db_name, user_id, permission, pathValues = []): if (existingAccount(user_id) == False): raise CairisHTTPError(status_code=http.client.NOT_FOUND,status="User not found",message=user_id + " was not found.") if (permission != 'grant' and permission != 'revoke'): raise CairisHTTPError(status_code=http.client.BAD_REQUEST,status="Invalid permission",message=permission + " is an invalid permission.") try: b = Borg() dbUser = b.get_settings(self.session_id)['dbUser'] if (isOwner(dbUser,db_name) == False): raise CairisHTTPError(status_code=http.client.BAD_REQUEST,status="Unauthorised permission",message="Cannot change permissions as you are not the database owner.") if (permission == 'grant'): grantDatabaseAccess(b.rPasswd, b.dbHost, b.dbPort, db_name, user_id) else: revokeDatabaseAccess(b.rPasswd, b.dbHost, b.dbPort, db_name, user_id) msg = 'Permission successfully ' if (permission == 'grant'): msg += 'granted' else: msg += 'revoked' return msg except ARMException as ex: self.close() raise ARMHTTPError(ex)
def get(self, doc_type, doc_format): session_id = get_session_id(session, request) dao = DocumentationDAO(session_id) sectionFlags = [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ] if (doc_format == 'PDF'): filePostfix = 'pdf' doc_format = [0, 0, 1] else: filePostfix = 'rtf' doc_format = [0, 1, 0] b = Borg() reportName = b.tmpDir + '/report.' + filePostfix dao.generate_documentation(doc_type, sectionFlags, doc_format) dao.close() if os.path.isfile(reportName): binary_pdf = open(reportName).read() resp = make_response(binary_pdf) resp.headers['Content-Type'] = 'application/' + filePostfix resp.headers[ 'Content-Disposition'] = 'Attachment; filename=report.' + filePostfix return resp else: raise CairisHTTPError(status_code=500, message='report file not found', status='Unknown error')
def update_usecase(self, usecase, name): usecase_params = UseCaseParameters( ucName=usecase.name(), ucAuth=usecase.author(), ucCode=usecase.code(), ucActors=usecase.actors(), ucDesc=usecase.description(), tags=usecase.tags(), cProps=usecase.environmentProperties()) try: ucId = self.db_proxy.getDimensionId(name, 'usecase') if (self.db_proxy.exceptionRootObstacles(ucId) > 0): raise CairisHTTPError( status_code=http.client.BAD_REQUEST, status="Exception has root obstacles", message= "Cannot update use case while use case exception obstacles are connected to other obstacles, goals, requirements, or domain properties." ) usecase_params.setId(ucId) self.db_proxy.updateUseCase(usecase_params) except DatabaseProxyException as ex: self.close() raise ARMHTTPError(ex) except ARMException as ex: self.close() raise ARMHTTPError(ex)
def update_goal_association(self, assoc, environment_name, goal_name, subgoal_name, pathValues=[]): if (assoc.theGoal == assoc.theSubGoal): raise CairisHTTPError(status_code=http.client.BAD_REQUEST, status="Self-refinement error", message='Cannot self-refine ' + assoc.theGoal) old_assoc = self.get_goal_association(environment_name, goal_name, subgoal_name, False) assocId = old_assoc.theId assocParams = GoalAssociationParameters( envName=assoc.theEnvironmentName, goalName=assoc.theGoal, goalDimName=assoc.theGoalDimension, aType=assoc.theAssociationType, subGoalName=assoc.theSubGoal, subGoalDimName=assoc.theSubGoalDimension, alternativeId=assoc.theAlternativeId, rationale=assoc.theRationale) assocParams.setId(assocId) try: self.db_proxy.updateGoalAssociation(assocParams) except ARMException as ex: self.close() raise ARMHTTPError(ex)
def get_dbproxy(self, session_id): """ Searches the MySQLDatabaseProxy instance associated with the session ID. :param session_id: The session ID :type session_id: str :rtype MySQLDatabaseProxy :return The MySQLDatabaseProxy instance associated with the session ID :raise CairisHTTPError """ if session_id: b = Borg() try: db_proxy = b.get_dbproxy(session_id) except SessionNotFound as ex: raise NoSessionError(ex) if isinstance(db_proxy, MySQLDatabaseProxy): if db_proxy.conn is None: db_proxy.reconnect(session_id=session_id) return db_proxy else: raise CairisHTTPError( status_code=CONFLICT, message= 'The database connection was not properly set up. Please try to reset the connection.' ) else: raise MissingParameterHTTPError(param_names=['session_id'])
def post(self): session_id = get_session_id(session, request) content_length = request.content_length max_length = 30 * 1024 * 1024 if content_length > max_length: raise MissingParameterHTTPError( exception=RuntimeError('File exceeded maximum size (30MB)')) try: wb = request.files['file'] fd, abs_path = mkstemp(suffix='.xlsx') fs_temp = open(abs_path, 'wb') fs_temp.write(wb.stream.read()) fs_temp.close() os.close(fd) dao = self.DAOModule(session_id) postMsg = getattr(dao, self.thePostMethod)(abs_path) dao.close() os.remove(abs_path) resp_dict = {'message': postMsg} resp = make_response( json_serialize(resp_dict, session_id=session_id), OK) resp.contenttype = 'application/json' return resp except DatabaseProxyException as ex: raise ARMHTTPError(ex) except ARMException as ex: raise ARMHTTPError(ex) except LookupError as ex: raise MissingParameterHTTPError(param_names=['file']) except Exception as ex: raise CairisHTTPError(status_code=CONFLICT, message=str(ex), status='Unknown error')
def post(self, type): session_id = get_session_id(session, request) try: if not request.files: raise LookupError() file = request.files['file'] except LookupError: raise MissingParameterHTTPError(param_names=['file']) try: fd, abs_path = mkstemp(suffix='.xml') fs_temp = open(abs_path, 'wb') xml_text = file.stream.read() fs_temp.write(xml_text) fs_temp.close() fd_close(fd) except IOError: raise CairisHTTPError( status_code=CONFLICT, status='Unable to load XML file', message='The XML file could not be loaded on the server.' + 'Please check if the application has permission to write temporary files.' ) try: dao = ImportDAO(session_id) result = dao.file_import(abs_path, type, 1) dao.close() except DatabaseProxyException as ex: raise ARMHTTPError(ex) except ARMException as ex: raise ARMHTTPError(ex) except Exception as ex: raise CairisHTTPError(status_code=500, message=str(ex), status='Unknown error') remove_file(abs_path) message = str(result) if (result == 0): message = file.filename + ' imported' resp_dict = {'message': message} resp = make_response(json_serialize(resp_dict, session_id=session_id), OK) resp.headers['Content-Type'] = 'application/json' return resp
def handle_exception(e): if isinstance(e, AssertionError): return handle_asserterror(e) elif isinstance(e, KeyError): return handle_keyerror(e) else: new_ex = CairisHTTPError(INTERNAL_SERVER_ERROR, str(e), 'Unknown error') return handle_error(new_ex)
def get_permissions(self,db_name, pathValues = []): try: b = Borg() dbUser = b.get_settings(self.session_id)['dbUser'] if (isOwner(dbUser,db_name) == False): raise CairisHTTPError(status_code=http.client.BAD_REQUEST,status="Unauthorised request",message="Not authorised to get permissions for " + db_name) return dbUsers(dbUser + '_' + canonicalDbName(db_name)) except ARMException as ex: self.close() raise ARMHTTPError(ex)
def add_object(self, goal, pathValues = []): goalParams = GoalParameters(goalName=goal.theName,goalOrig=goal.theOriginator,tags=goal.theTags,properties=goal.theEnvironmentProperties) try: if not self.check_existing_goal(goal.theName): self.db_proxy.addGoal(goalParams) else: self.close() raise CairisHTTPError(status_code=http.client.BAD_REQUEST,status="Object exists",message="An object with the name " + goal.theName + " already exists.") except DatabaseProxyException as ex: self.close() raise ARMHTTPError(ex)
def get_objects_by_names(self,table,id): try: permissableDimensions = ['access_right', 'architectural_pattern', 'component_view','asset', 'asset_reference', 'asset_type','attacker','attacker_reference', 'behavioural_variable', 'capability','characteristic_synopsis', 'component', 'concept_reference','connector', 'countermeasure','countermeasure_reference', 'countermeasure_value', 'datastore', 'detection_mechanism', 'dfd_filter', 'document_reference', 'domainproperty','domainproperty_reference', 'entity','environment', 'environment_reference','external_document', 'goal', 'goal_reference','goal_category_type','goal_satisfaction','interface','likelihood','locations','misusability_case','misusecase','misusecase_reference','motivation','obstacle','obstacle_category_type','obstacle_reference','persona','persona_characteristic','persona_characteristic_synopsis','persona_implied_process','persona_reference','persona_type','priority_type', 'privilege', 'process','protocol', 'reference_synopsis','requirement', 'requirement_reference', 'requirement_type','response', 'response_reference', 'risk', 'risk_class','risk_reference','role', 'role_reference', 'role_type', 'securitypattern','severity', 'surface_type', 'task', 'task_characteristic', 'task_reference','template_asset', 'template_goal', 'template_requirement','trace_dimension','threat', 'threat_reference','threat_type', 'threat_value', 'ugm_filter', 'usecase', 'vulnerability','vulnerability_reference', 'vulnerability_type', 'document_reference_synopsis','persona_characteristic_synopsis','user_goal'] if (table not in permissableDimensions): raise CairisHTTPError(BAD_REQUEST,'Invalid dimension',table + ' is not a permissable dimension') if (table == 'persona_characteristic_synopsis' or table == 'document_reference_synopsis' or table == 'user_goal'): return self.db_proxy.getDimensionNames(table,'') else: return sorted(self.db_proxy.getDimensions(table,id).keys()) except DatabaseProxyException as ex: self.close() raise ARMHTTPError(ex)
def post(self): session_id = get_session_id(session, request) json_dict = request.get_json(silent=True) if json_dict is False or json_dict is None: raise MalformedJSONHTTPError(data=request.get_data()) cimport_params = json_dict.get('object', None) check_required_keys(cimport_params or {}, CImportParams.required) file_contents = cimport_params['urlenc_file_contents'] file_contents = unquote(file_contents) type = cimport_params['type'] if file_contents.startswith('<?xml'): fd, abs_path = mkstemp(suffix='.xml') fs_temp = open(abs_path, 'w') fs_temp.write(file_contents) fs_temp.close() fd_close(fd) try: dao = ImportDAO(session_id) result = dao.file_import(abs_path, type, 1) dao.close() except DatabaseProxyException as ex: raise ARMHTTPError(ex) except ARMException as ex: raise ARMHTTPError(ex) except Exception as ex: raise CairisHTTPError(status_code=500,message=str(ex.message),status='Unknown error') remove_file(abs_path) resp_dict = {'message': str(result)} resp = make_response(json_serialize(resp_dict, session_id=session_id), httplib.OK) resp.headers['Content-Type'] = 'application/json' return resp else: raise CairisHTTPError(status_code=httplib.BAD_REQUEST,message='The provided file is not a valid XML file',status='Invalid XML input')
def post(self): session_id = get_session_id(session, request) content_length = request.content_length max_length = 30 * 1024 * 1024 if content_length > max_length: raise MissingParameterHTTPError( exception=RuntimeError('File exceeded maximum size (30MB)')) try: package = request.files['file'] except LookupError as ex: raise MissingParameterHTTPError(param_names=['file']) except Exception as ex: raise CairisHTTPError(status_code=CONFLICT, message=str(ex), status='Unknown error') try: dao = ImportDAO(session_id) dao.package_import(package.stream.read()) dao.close() except DatabaseProxyException as ex: raise ARMHTTPError(ex) except ARMException as ex: raise ARMHTTPError(ex) except Exception as ex: import pytest pytest.set_trace() raise CairisHTTPError(status_code=500, message=str(ex), status='Unknown error') resp_dict = {'message': 'Package successfully imported'} resp = make_response(json_serialize(resp_dict, session_id=session_id), OK) resp.contenttype = 'application/json' return resp
def get_fonts(session_id=None): """ Validates that the fonts to output the SVG models are properly set up :param session_id: The session ID provided by the user :return: The font name, font size and AP font name :rtype : str,str,str :raise CairisHTTPError: Raises a CairisHTTPError when the database could not be properly set up """ if session_id is not None: b = Borg() settings = b.get_settings(session_id) fontName = settings.get('fontName', None) fontSize = settings.get('fontSize', None) apFontName = settings.get('apFontSize', None) if fontName is None or fontSize is None or apFontName is None: raise CairisHTTPError( status_code=BAD_REQUEST, message= 'The method is not callable without setting up the project settings.' ) elif isinstance(fontName, string_types) and isinstance( fontSize, string_types) and isinstance(apFontName, string_types): return fontName, fontSize, apFontName else: raise CairisHTTPError( status_code=BAD_REQUEST, message= 'The database connection was not properly set up. Please try to reset the connection.' ) else: raise CairisHTTPError( status_code=BAD_REQUEST, message= 'The method is not callable without setting up the project settings.' )
def set_image(self, name, content, mimeType): extension = os.path.splitext(name) img_format = imghdr.what(io.BytesIO(content)) if not img_format or img_format not in self.accepted_image_types: raise CairisHTTPError( status_code=http.client.CONFLICT, status='Unsupported file type', message='The provided image file is not supported by CAIRIS') try: self.db_proxy.setImage(name, content, mimeType) except ARMException as ex: self.close() raise ARMHTTPError(ex)
def update_object(self, ug, name): try: ugPCs = self.db_proxy.conflictingPersonaCharacteristics( ug.theActor, name) if (len(ugPCs) == 0): ugId = self.db_proxy.getDimensionId(name, 'synopsis') ug.setId(ugId) self.db_proxy.updateUserGoal(ug) else: excTxt = "Can't associate '" + name + "' with " + ug.theActor + " because it is associated with persona characteristic" if (len(ugPCs) > 1): excTxt += "s " + ', '.join(ugPCs) else: excTxt += " " + ugPCs[0] raise CairisHTTPError(BAD_REQUEST, excTxt) except ARMException as ex: self.close() raise ARMHTTPError(ex)
def add_goal_association(self, assoc): if (assoc.theGoal == assoc.theSubGoal): raise CairisHTTPError(status_code=http.client.BAD_REQUEST, status="Self-refinement error", message='Cannot self-refine ' + assoc.theGoal) assocParams = GoalAssociationParameters( envName=assoc.theEnvironmentName, goalName=assoc.theGoal, goalDimName=assoc.theGoalDimension, aType=assoc.theAssociationType, subGoalName=assoc.theSubGoal, subGoalDimName=assoc.theSubGoalDimension, alternativeId=assoc.theAlternativeId, rationale=assoc.theRationale) try: self.db_proxy.addGoalAssociation(assocParams) except ARMException as ex: self.close() raise ARMHTTPError(ex)
def handle_asserterror(error): err = CairisHTTPError(CONFLICT, str(error), 'Unmet requirement') return handle_error(err)
def post(self): session_id = get_session_id(session, request) json_dict = request.get_json(silent=True) if json_dict is False or json_dict is None: raise MalformedJSONHTTPError(data=request.get_data()) cimport_params = json_dict.get('object', None) check_required_keys(cimport_params or {}, CImportParams.required) file_contents = cimport_params['urlenc_file_contents'] file_contents = unquote(file_contents) file_contents = file_contents.replace("\u2018", "'").replace("\u2019", "'") overwrite = cimport_params['overwrite'] type = cimport_params['type'] if file_contents.startswith('<?xml'): fd, abs_path = mkstemp(suffix='.xml') fs_temp = codecs.open(abs_path, 'w', 'utf-8') fs_temp.write(file_contents) fs_temp.close() fd_close(fd) try: dao = ImportDAO(session_id) if (type in [ 'diagrams.net (Data Flow Diagram)', 'diagrams.net (Asset Model)' ]): environment_name = cimport_params['environment'] result = dao.diagramsnet_import(abs_path, type, environment_name) else: result = dao.file_import(abs_path, type, overwrite) dao.close() except DatabaseProxyException as ex: raise ARMHTTPError(ex) except ARMException as ex: raise ARMHTTPError(ex) remove_file(abs_path) message = str(result) if (result == 0): message = 'Model imported' resp_dict = {'message': message} resp = make_response( json_serialize(resp_dict, session_id=session_id), OK) resp.headers['Content-Type'] = 'application/json' return resp elif type == 'Attack Tree (Dot)': try: environment_name = cimport_params['environment'] contributor_name = cimport_params['contributor'] dao = ImportDAO(session_id) result = dao.import_attack_tree(file_contents, environment_name, contributor_name) dao.close() message = str(result) if (result == 0): message = 'Model imported' resp_dict = {'message': message} resp_dict = {'message': str(result)} resp = make_response( json_serialize(resp_dict, session_id=session_id), OK) resp.headers['Content-Type'] = 'application/json' return resp except DatabaseProxyException as ex: raise ARMHTTPError(ex) except ARMException as ex: raise ARMHTTPError(ex) except Exception as ex: raise CairisHTTPError(status_code=500, message=str(ex), status='Unknown error') else: raise CairisHTTPError( status_code=BAD_REQUEST, message='The provided file is not a valid XML file', status='Invalid XML input')
def handle_asserterror(error): err = CairisHTTPError(httplib.CONFLICT, str(error.message), 'Unmet requirement') return handle_error(err)
def validate_proxy(session, id, request=None, conf=None): """ Validates that the DB proxy object is properly set up :param session: The session object of the request :param id: The session ID provided by the user :param conf: A dictionary containing configuration settings for direct authenrication :return: The MySQLDatabaseProxy object associated to the session :rtype : MySQLDatabaseProxy :raise CairisHTTPError: Raises a CairisHTTPError when the database could not be properly set up """ if session is not None: session_id = session.get('session_id', -1) else: session_id = None if conf is not None: if isinstance(conf, dict): try: db_proxy = MySQLDatabaseProxy(host=conf['host'], port=conf['port'], user=conf['user'], passwd=conf['passwd'], db=conf['db']) if db_proxy is not None: return db_proxy else: raise CairisHTTPError( status_code=httplib.CONFLICT, message='The database connection could not be created.' ) except DatabaseProxyException: raise CairisHTTPError( status_code=httplib.BAD_REQUEST, message= 'The provided settings are invalid and cannot be used to create a database connection' ) if not (session_id is None and id is None): if id is None: id = session_id b = Borg() db_proxy = b.get_dbproxy(id) if db_proxy is None: raise CairisHTTPError( status_code=httplib.CONFLICT, message='The database connection could not be created.') elif isinstance(db_proxy, MySQLDatabaseProxy): return db_proxy else: raise CairisHTTPError( status_code=httplib.CONFLICT, message= 'The database connection was not properly set up. Please try to reset the connection.' ) else: raise CairisHTTPError( status_code=httplib.BAD_REQUEST, message= 'The session is neither started or no session ID is provided with the request.' )
def handle_keyerror(error): err = CairisHTTPError(httplib.BAD_REQUEST, str(error.message), 'Missing attribute') return handle_error(err)
def handle_keyerror(error): err = CairisHTTPError(BAD_REQUEST, str(error), 'Missing attribute') return handle_error(err)