示例#1
0
 async def update_relationships(self, request: web.Request):
     knowledge_svc_handle = self._api_manager.knowledge_svc
     relationship_data = await self._api_manager.extract_data(request)
     if 'criteria' in relationship_data and 'updates' in relationship_data:
         try:
             await knowledge_svc_handle.update_relationship(
                 criteria=relationship_data['criteria'],
                 updates=relationship_data['updates'])
             temp = await self._api_manager.copy_object(
                 relationship_data['criteria'])
             for k in relationship_data['updates']:
                 if isinstance(relationship_data['updates'][k], dict):
                     handle = dict()
                     if k in relationship_data['criteria'] and \
                             isinstance(relationship_data['criteria'][k], dict):
                         handle = relationship_data['criteria'][k]
                     for j in relationship_data['updates'][k]:
                         handle[j] = relationship_data['updates'][k][j]
                     temp[k] = handle
                 else:
                     temp[k] = relationship_data['updates'][k]
             store = await knowledge_svc_handle.get_relationships(
                 criteria=temp)
             resp = await self._api_manager.verify_relationship_integrity(
                 store)
             return web.json_response(dict(updated=resp))
         except Exception as e:
             error_msg = f'Encountered issue updating relationship {relationship_data} - {e}'
             self.log.warning(error_msg)
             raise JsonHttpBadRequest(error_msg)
     raise JsonHttpBadRequest(
         "Need a 'criteria' to match on and 'updates' to apply.")
 def validate_link_data(self, link_data: dict):
     if not link_data.get('executor'):
         raise JsonHttpBadRequest(
             '\'executor\' is a required field for link creation.')
     if not link_data['executor'].get('name'):
         raise JsonHttpBadRequest(
             '\'name\' is a required field for link executor.')
     if not link_data['executor'].get('command'):
         raise JsonHttpBadRequest(
             '\'command\' is a required field for link executor.')
     if not link_data.get('paw'):
         raise JsonHttpBadRequest(
             '\'paw\' is a required field for link creation.')
示例#3
0
    async def add_relationships(self, request: web.Request):
        knowledge_svc_handle = self._api_manager.knowledge_svc
        relationship_data = await self._api_manager.extract_data(request)
        try:
            origin_target = WILDCARD_STRING
            new_relationship = Relationship.load(relationship_data)
            if 'origin' in relationship_data:
                origin_target = relationship_data['origin']
            else:
                new_relationship.origin = origin_target
            shorthand = new_relationship.shorthand
            new_relationship.source.relationships = [shorthand]
            new_relationship.source.source = origin_target
            new_relationship.source.origin_type = OriginType.USER
            if 'target' in relationship_data:
                new_relationship.target.source = origin_target
                new_relationship.target.origin_type = OriginType.USER
                new_relationship.target.relationships = [shorthand]
                await knowledge_svc_handle.add_fact(new_relationship.target)
            await knowledge_svc_handle.add_fact(new_relationship.source)
            await knowledge_svc_handle.add_relationship(new_relationship)

            store = await knowledge_svc_handle.get_relationships(
                criteria=dict(source=new_relationship.source,
                              edge=new_relationship.edge if 'edge' in
                              relationship_data else None,
                              target=new_relationship.target if 'target' in
                              relationship_data else None,
                              origin=origin_target))
            resp = await self._api_manager.verify_relationship_integrity(store)
            return web.json_response(dict(added=resp))
        except Exception as e:
            error_msg = f'Encountered issue saving relationship {relationship_data} - {e}'
            self.log.warning(error_msg)
            raise JsonHttpBadRequest(error_msg)
 async def update_operation_link(self, operation_id: str, link_id: str,
                                 link_data: dict, access: BaseWorld.Access):
     operation = await self.get_operation_object(operation_id, access)
     link = self.search_operation_for_link(operation, link_id)
     if link.access not in access['access']:
         raise JsonHttpForbidden(
             f'Cannot update link {link_id} due to insufficient permissions.'
         )
     if link.is_finished() or link.can_ignore():
         raise JsonHttpForbidden(
             f'Cannot update a finished link: {link_id}')
     if link_data.get('command'):
         command_str = link_data.get('command')
         link.executor.command = command_str
         link.ability = self.build_ability(link_data.get('ability', {}),
                                           link.executor)
         link.command = self._encode_string(command_str)
     if link_data.get('status'):
         link_status = link_data['status']
         if not link.is_valid_status(link_status):
             raise JsonHttpBadRequest(
                 f'Cannot update link {link_id} due to invalid link status.'
             )
         link.status = link_status
     return link.display
 async def create_potential_link(self, operation_id: str, data: dict,
                                 access: BaseWorld.Access):
     self.validate_link_data(data)
     operation = await self.get_operation_object(operation_id, access)
     agent = await self.get_agent(operation, data)
     if data['executor']['name'] not in agent.executors:
         raise JsonHttpBadRequest(
             f'Agent {agent.paw} missing specified executor')
     encoded_command = self._encode_string(
         agent.replace(self._encode_string(data['executor']['command']),
                       file_svc=self.services['file_svc']))
     executor = self.build_executor(data=data.pop('executor', {}),
                                    agent=agent)
     ability = self.build_ability(data=data.pop('ability', {}),
                                  executor=executor)
     link = Link.load(
         dict(command=encoded_command,
              paw=agent.paw,
              ability=ability,
              executor=executor,
              status=operation.link_status(),
              score=data.get('score', 0),
              jitter=data.get('jitter', 0),
              cleanup=data.get('cleanup', 0),
              pin=data.get('pin', 0),
              host=agent.host,
              deadman=data.get('deadman', False),
              used=data.get('used', []),
              relationships=data.get('relationships', [])))
     link.apply_id(agent.host)
     await operation.apply(link)
     return link.display
示例#6
0
 async def _error_if_object_with_id_exists(self, obj_id: str):
     """Throw an error if an object (of the same type) exists with the given id"""
     if obj_id:
         search = {self.id_property: obj_id}
         if self._api_manager.find_object(self.ram_key, search):
             raise JsonHttpBadRequest(
                 f'{self.description.capitalize()} with given id already exists: {obj_id}'
             )
 async def validate_operation_state(self,
                                    data: dict,
                                    existing: Operation = None):
     if not existing:
         if data.get('state') in Operation.get_finished_states():
             raise JsonHttpBadRequest('Cannot create a finished operation.')
         elif data.get('state') not in Operation.get_states():
             raise JsonHttpBadRequest('state must be one of {}'.format(
                 Operation.get_states()))
     else:
         if await existing.is_finished():
             raise JsonHttpBadRequest(
                 'This operation has already finished.')
         elif 'state' in data and data.get(
                 'state') not in Operation.get_states():
             raise JsonHttpBadRequest('state must be one of {}'.format(
                 Operation.get_states()))
示例#8
0
 async def extract_data(request: web.Request):
     fact_data = None
     if request.body_exists:
         try:
             fact_data = await request.json()
         except JSONDecodeError as e:
             raise JsonHttpBadRequest('Received invalid json', details=e)
     return fact_data
示例#9
0
 async def update_facts(self, request: web.Request):
     knowledge_svc_handle = self._api_manager.knowledge_svc
     fact_data = await self._api_manager.extract_data(request)
     if 'criteria' in fact_data and 'updates' in fact_data:
         try:
             await knowledge_svc_handle.update_fact(criteria=fact_data['criteria'],
                                                    updates=fact_data['updates'])
             temp = await self._api_manager.copy_object(fact_data['criteria'])
             for k in fact_data['updates']:
                 temp[k] = fact_data['updates'][k]
             store = await knowledge_svc_handle.get_facts(criteria=temp)
             resp = await self._api_manager.verify_fact_integrity(store)
             return web.json_response(dict(updated=resp))
         except Exception as e:
             error_msg = f'Encountered issue updating fact {fact_data} - {e}'
             self.log.warning(error_msg)
             raise JsonHttpBadRequest(error_msg)
     raise JsonHttpBadRequest("Need a 'criteria' to match on and 'updates' to apply.")
示例#10
0
 async def extract_data(request: web.Request):
     fact_data = None
     raw_body = await request.read()
     if raw_body:
         try:
             fact_data = json.loads(raw_body)
         except JSONDecodeError as e:
             raise JsonHttpBadRequest('Received invalid json', details=e)
     return fact_data
示例#11
0
 async def get_facts(self, request: web.Request):
     fact_data = await self._api_manager.extract_data(request)
     resp = []
     if fact_data:
         try:
             resp = await self._find_and_verify_facts(fact_data)
         except Exception as e:
             error_msg = f'Encountered issue retrieving fact {fact_data} - {e}'
             self.log.warning(error_msg)
             raise JsonHttpBadRequest(error_msg)
     return web.json_response(dict(found=resp))
示例#12
0
 async def get_facts_by_operation_id(self, request: web.Request):
     operation_id = request.match_info.get('operation_id')
     fact_data = {'source': operation_id}
     resp = []
     if fact_data:
         try:
             resp = await self._find_and_verify_facts(fact_data)
         except Exception as e:
             error_msg = f'Encountered issue retrieving facts associated with operation {operation_id} - {e}'
             self.log.warning(error_msg)
             raise JsonHttpBadRequest(error_msg)
     return web.json_response(dict(found=resp))
示例#13
0
 async def delete_relationships(self, request: web.Request):
     knowledge_svc_handle = self._api_manager.knowledge_svc
     relationship_data = await self._api_manager.extract_data(request)
     if relationship_data:
         try:
             store = await knowledge_svc_handle.get_relationships(criteria=relationship_data)
             await knowledge_svc_handle.delete_relationship(criteria=relationship_data)
             resp = await self._api_manager.verify_relationship_integrity(store)
             return web.json_response(dict(removed=resp))
         except Exception as e:
             self.log.warning(f'Encountered issue removing relationship {relationship_data} - {e}')
     raise JsonHttpBadRequest('Invalid relationship data was provided.')
示例#14
0
 async def get_relationships(self, request: web.Request):
     knowledge_svc_handle = self._api_manager.knowledge_svc
     relationship_data = await self._api_manager.extract_data(request)
     resp = []
     if relationship_data:
         try:
             RelationshipSchema(partial=True).load(relationship_data)
             store = await knowledge_svc_handle.get_relationships(criteria=relationship_data)
             resp = await self._api_manager.verify_relationship_integrity(store)
         except Exception as e:
             error_msg = f'Encountered issue retrieving relationship {relationship_data} - {e}'
             self.log.warning(error_msg)
             raise JsonHttpBadRequest(error_msg)
     return web.json_response(dict(found=resp))
示例#15
0
 async def add_facts(self, request: web.Request):
     knowledge_svc_handle = self._api_manager.knowledge_svc
     fact_data = await self._api_manager.extract_data(request)
     try:
         new_fact = Fact.load(fact_data)
         if 'source' not in fact_data:
             new_fact.source = WILDCARD_STRING
         new_fact.origin_type = OriginType.USER
         await self._api_manager.verify_operation_state(new_fact)
         await knowledge_svc_handle.add_fact(new_fact)
         store = await knowledge_svc_handle.get_facts(criteria=dict(trait=new_fact.trait,
                                                                    value=new_fact.value,
                                                                    source=new_fact.source,
                                                                    origin_type=OriginType.USER))
         resp = await self._api_manager.verify_fact_integrity(store)
         return web.json_response(dict(added=resp))
     except Exception as e:
         error_msg = f'Encountered issue saving fact {fact_data} - {e}'
         self.log.warning(error_msg)
         raise JsonHttpBadRequest(error_msg)
示例#16
0
    def _validate_ability_data(self, create: bool, data: dict):
        # Correct ability_id key for ability file saving.
        data['id'] = data.pop('ability_id', '')

        # If a new ability is being created, ensure required fields present.
        if create:
            # Set ability ID if undefined
            if not data['id']:
                data['id'] = str(uuid.uuid4())
            if not data.get('name'):
                raise JsonHttpBadRequest(
                    f'Cannot create ability {data["id"]} due to missing name')
            if 'tactic' not in data:
                raise JsonHttpBadRequest(
                    f'Cannot create ability {data["id"]} due to missing tactic'
                )
            if not data.get('executors'):
                raise JsonHttpBadRequest(
                    f'Cannot create ability {data["id"]}: at least one executor required'
                )
        # Validate ID, used for file creation
        validator = re.compile(r'^[a-zA-Z0-9-_]+$')
        if 'id' in data and not validator.match(data['id']):
            raise JsonHttpBadRequest(
                f'Invalid ability ID {data["id"]}. IDs can only contain '
                'alphanumeric characters, hyphens, and underscores.')

        # Validate tactic, used for directory creation, lower case if present
        if 'tactic' in data:
            if not validator.match(data['tactic']):
                raise JsonHttpBadRequest(
                    f'Invalid ability tactic {data["tactic"]}. Tactics can only contain '
                    'alphanumeric characters, hyphens, and underscores.')
            data['tactic'] = data['tactic'].lower()

        if 'executors' in data and not data.get('executors'):
            raise JsonHttpBadRequest(
                f'Cannot create ability {data["id"]}: at least one executor required'
            )

        if 'name' in data and not data.get('name'):
            raise JsonHttpBadRequest(
                f'Cannot create ability {data["id"]} due to missing name')