def _get_embedded_blob(self, in_blob, share_with, metakeys): if isinstance(in_blob, dict): schema = BlobCreateSpecSchema() blob_spec = load_schema(in_blob, schema) try: blob_obj, is_new = TextBlob.get_or_create( blob_spec["content"], blob_spec["blob_name"], blob_spec["blob_type"], parent=None, share_with=share_with, metakeys=metakeys) except ObjectTypeConflictError: raise Conflict("Object already exists and is not a blob") return blob_obj elif isinstance(in_blob, str): blob_obj = TextBlob.access(in_blob) if not blob_obj: raise NotFound(f"Blob {in_blob} doesn't exist") return blob_obj else: raise BadRequest( "'in-blob' key must be set to blob SHA256 hash or blob specification" )
def post(self, remote_name, identifier): """ --- summary: Push text blob from local to remote instance description: | Push text blob from the local instance to the remote instance security: - bearerAuth: [] tags: - remotes parameters: - in: path name: remote_name description: Name of remote instance schema: type: string - in: path name: identifier description: Object identifier (SHA256/SHA512/SHA1/MD5) schema: type: string requestBody: required: false description: Additional options for object push content: application/json: schema: RemoteOptionsRequestSchema responses: 200: description: Information about pushed text blob 404: description: | When the name of the remote instance is not figured in the application config or object doesn't exist 503: description: | Request canceled due to database statement timeout. """ db_object = TextBlob.access(identifier) if db_object is None: raise NotFound("Object not found") remote = RemoteAPI(remote_name) options = loads_schema(request.get_data(as_text=True), RemoteOptionsRequestSchema()) params = { "blob_name": db_object.blob_name, "blob_type": db_object.blob_type, "content": db_object.content, "upload_as": options["upload_as"], } response = remote.request("POST", "blob", json=params).json() logger.info( f"{db_object.type} pushed remote", extra={ "dhash": db_object.dhash, "remote_name": remote_name }, ) return response
def post(self, remote_name, identifier): """ --- summary: Pulls text blob from remote to local instance description: | Pulls text blob from the remote instance to the local instance security: - bearerAuth: [] tags: - remotes parameters: - in: path name: remote_name description: Name of remote instance schema: type: string - in: path name: identifier description: Blob identifier schema: type: string requestBody: required: false description: Additional options for object pull content: application/json: schema: RemoteOptionsRequestSchema responses: 200: description: Information about pulled text blob content: application/json: schema: BlobItemResponseSchema description: | When the name of the remote instance is not figured in the application config 409: description: Object exists yet but has different type 503: description: | Request canceled due to database statement timeout. """ remote = RemoteAPI(remote_name) spec = remote.request("GET", f"blob/{identifier}").json() options = loads_schema(request.get_data(as_text=True), RemoteOptionsRequestSchema()) share_with = get_shares_for_upload(options["upload_as"]) try: item, is_new = TextBlob.get_or_create( content=spec["content"], blob_name=spec["blob_name"], blob_type=spec["blob_type"], share_with=share_with, ) except ObjectTypeConflictError: raise Conflict("Object already exists and is not a config") return self.create_pulled_object(item, is_new)
def _create_object(self, spec, parent, share_with, metakeys): try: return TextBlob.get_or_create( spec["content"], spec["blob_name"], spec["blob_type"], parent=parent, share_with=share_with, metakeys=metakeys, ) except ObjectTypeConflictError: raise Conflict("Object already exists and is not a blob")
def post(self, remote_name, identifier): """ --- summary: Pulls text blob from remote to local instance description: | Pulls text blob from the remote instance to the local instance security: - bearerAuth: [] tags: - remotes parameters: - in: path name: remote_name description: Name of remote instance schema: type: string - in: path name: identifier description: Blob identifier schema: type: string responses: 200: description: Information about pulled text blob content: application/json: schema: BlobItemResponseSchema description: | When the name of the remote instance is not figured in the application config 409: description: Object exists yet but has different type """ remote = RemoteAPI(remote_name) spec = remote.request("GET", f"blob/{identifier}").json() try: item, is_new = TextBlob.get_or_create( content=spec["content"], blob_name=spec["blob_name"], blob_type=spec["blob_type"], share_with=[ group for group in g.auth_user.groups if group.name != "public" ], ) except ObjectTypeConflictError: raise Conflict("Object already exists and is not a config") return self.create_pulled_object(item, is_new)
def _create_object(self, spec, parent, share_with, attributes, analysis_id, tags): try: return TextBlob.get_or_create( spec["content"], spec["blob_name"], spec["blob_type"], parent=parent, share_with=share_with, attributes=attributes, analysis_id=analysis_id, tags=tags, ) except ObjectTypeConflictError: raise Conflict("Object already exists and is not a blob")
def post(self, remote_name, identifier): """ --- summary: Push text blob from local to remote instance description: | Push text blob from the local instance to the remote instance security: - bearerAuth: [] tags: - remotes parameters: - in: path name: remote_name description: Name of remote instance schema: type: string - in: path name: identifier description: Object identifier (SHA256/SHA512/SHA1/MD5) schema: type: string responses: 200: description: Information about pushed text blob 404: description: | When the name of the remote instance is not figured in the application config or object doesn't exist """ db_object = TextBlob.access(identifier) if db_object is None: raise NotFound("Object not found") remote = RemoteAPI(remote_name) params = { "blob_name": db_object.blob_name, "blob_type": db_object.blob_type, "content": db_object.content, } response = remote.request("POST", "blob", json=params).json() logger.info( f"{db_object.type} pushed remote", extra={ "dhash": db_object.dhash, "remote_name": remote_name }, ) return response
def post(self, remote_name, identifier): """ --- summary: Push config from local to remote instance description: | Push config from the local instance to the remote instance security: - bearerAuth: [] tags: - remotes parameters: - in: path name: remote_name description: Name of remote instance schema: type: string - in: path name: identifier description: Object identifier (SHA256/SHA512/SHA1/MD5) schema: type: string requestBody: required: false description: Additional options for object push content: application/json: schema: RemoteOptionsRequestSchema responses: 200: description: Information about pushed config 404: description: | When the name of the remote instance is not figured in the application config or object doesn't exist """ db_object = Config.access(identifier) if db_object is None: raise NotFound("Object not found") config = db_object.cfg # Extract in-blob references into embedded content for first, second in config.items(): if isinstance(second, dict) and list(second.keys()) == ["in-blob"]: in_blob = second["in-blob"] if not isinstance(in_blob, str): raise BadRequest( "'in-blob' key doesn't contain a correct blob reference" ) embedded_blob = TextBlob.access(in_blob) if not embedded_blob: raise NotFound( f"Referenced blob '{in_blob}' doesn't exist") second["in-blob"] = { "content": embedded_blob.content, "blob_name": embedded_blob.blob_name, "blob_type": embedded_blob.blob_type, } remote = RemoteAPI(remote_name) options = loads_schema(request.get_data(as_text=True), RemoteOptionsRequestSchema()) params = { "family": db_object.family, "cfg": config, "config_type": db_object.config_type, "upload_as": options["upload_as"], } response = remote.request("POST", "config", json=params).json() logger.info( f"{db_object.type} pushed remote", extra={ "dhash": db_object.dhash, "remote_name": remote_name }, ) return response
def post(self, remote_name, identifier): """ --- summary: Pulls config from remote to local instance description: | Pulls config from the remote instance to the local instance security: - bearerAuth: [] tags: - remotes parameters: - in: path name: remote_name description: Name of remote instance schema: type: string - in: path name: identifier description: Config identifier schema: type: string requestBody: required: false description: Additional options for object pull content: application/json: schema: RemoteOptionsRequestSchema responses: 200: description: Information about pulled config content: application/json: schema: ConfigItemResponseSchema 403: description: | No permissions to perform additional operations (e.g. adding parent, metakeys) 404: description: | When the name of the remote instance is not figured in the application config 409: description: Object exists yet but has different type """ remote = RemoteAPI(remote_name) config_spec = remote.request("GET", f"config/{identifier}").json() options = loads_schema(request.get_data(as_text=True), RemoteOptionsRequestSchema()) share_with = get_shares_for_upload(options["upload_as"]) try: config = dict(config_spec["cfg"]) blobs = [] for first, second in config.items(): if isinstance(second, dict) and list( second.keys()) == ["in-blob"]: if not g.auth_user.has_rights(Capabilities.adding_blobs): raise Forbidden( "You are not permitted to add blob objects") in_blob = second["in-blob"] if not isinstance(in_blob, str): raise BadRequest( "'in-blob' is not a correct blob reference") blob_obj = TextBlob.access(in_blob) if not blob_obj: # If blob object doesn't exist locally: pull it as well blob_spec = remote.request("GET", f"blob/{in_blob}").json() blob_obj, _ = TextBlob.get_or_create( content=blob_spec["content"], blob_name=blob_spec["blob_name"], blob_type=blob_spec["blob_type"], share_with=share_with, ) blobs.append(blob_obj) config[first]["in-blob"] = blob_obj.dhash elif isinstance(second, dict) and ("in-blob" in list( second.keys())): raise BadRequest("'in-blob' should be the only key") item, is_new = Config.get_or_create( cfg=config_spec["cfg"], family=config_spec["family"], config_type=config_spec["config_type"], share_with=share_with, ) for blob in blobs: blob.add_parent(item, commit=False) except ObjectTypeConflictError: raise Conflict("Object already exists and is not a config") return self.create_pulled_object(item, is_new)