Exemple #1
0
 def test_ran_ability_id(self, ability, adversary):
     op = Operation(name='test', agents=[], adversary=adversary)
     mock_link = MagicMock(spec=Link,
                           ability=ability(ability_id='123'),
                           finish='2021-01-01 08:00:00')
     op.chain = [mock_link]
     assert op.ran_ability_id('123')
class TestPlanningService(TestBase):
    def setUp(self):
        self.initialize()
        self.ability = Ability(ability_id='123',
                               executor='sh',
                               test=BaseWorld.encode_string('mkdir test'),
                               cleanup=BaseWorld.encode_string('rm -rf test'))
        self.agent = Agent(sleep_min=1, sleep_max=2, watchdog=0)
        self.operation = Operation(name='test1',
                                   agents=self.agent,
                                   adversary='hunter')
        self.run_async(self.data_svc.store(self.ability))

    def test_get_cleanup_links(self):
        self.operation.add_link(
            Link(operation=self.operation,
                 command='',
                 paw=self.agent.paw,
                 ability=self.ability,
                 status=0))
        links = self.run_async(
            self.planning_svc.get_cleanup_links(operation=self.operation,
                                                agent=self.agent))
        link_list = list(links)
        self.assertEqual(len(link_list), 1)
        self.assertEqual(link_list[0].command, self.ability.cleanup)
Exemple #3
0
def op_for_event_logs(operation_agent, operation_adversary, executor, ability,
                      operation_link, encoded_command):
    op = Operation(name='test',
                   agents=[operation_agent],
                   adversary=operation_adversary)
    op.set_start_details()
    command_1 = 'whoami'
    command_2 = 'hostname'
    executor_1 = executor(name='psh', platform='windows', command=command_1)
    executor_2 = executor(name='psh', platform='windows', command=command_2)
    ability_1 = ability(ability_id='123',
                        tactic='test tactic',
                        technique_id='T0000',
                        technique_name='test technique',
                        name='test ability',
                        description='test ability desc',
                        executors=[executor_1])
    ability_2 = ability(ability_id='456',
                        tactic='test tactic',
                        technique_id='T0000',
                        technique_name='test technique',
                        name='test ability 2',
                        description='test ability 2 desc',
                        executors=[executor_2])
    link_1 = operation_link(ability=ability_1,
                            paw=operation_agent.paw,
                            executor=executor_1,
                            command=encoded_command(command_1),
                            status=0,
                            host=operation_agent.host,
                            pid=789,
                            decide=datetime.strptime('2021-01-01 08:00:00',
                                                     '%Y-%m-%d %H:%M:%S'),
                            collect=datetime.strptime('2021-01-01 08:01:00',
                                                      '%Y-%m-%d %H:%M:%S'),
                            finish='2021-01-01 08:02:00')
    link_2 = operation_link(ability=ability_2,
                            paw=operation_agent.paw,
                            executor=executor_2,
                            command=encoded_command(command_2),
                            status=0,
                            host=operation_agent.host,
                            pid=7890,
                            decide=datetime.strptime('2021-01-01 09:00:00',
                                                     '%Y-%m-%d %H:%M:%S'),
                            collect=datetime.strptime('2021-01-01 09:01:00',
                                                      '%Y-%m-%d %H:%M:%S'),
                            finish='2021-01-01 09:02:00')
    discarded_link = operation_link(ability=ability_2,
                                    paw=operation_agent.paw,
                                    executor=executor_2,
                                    command=encoded_command(command_2),
                                    status=-2,
                                    host=operation_agent.host,
                                    pid=7891,
                                    decide=datetime.strptime(
                                        '2021-01-01 10:00:00',
                                        '%Y-%m-%d %H:%M:%S'))
    op.chain = [link_1, link_2, discarded_link]
    return op
Exemple #4
0
 def test_ran_ability_id(self, ability, adversary):
     op = Operation(name='test', agents=[], adversary=adversary)
     mock_link = MagicMock(spec=Link,
                           ability=ability(ability_id='123'),
                           finish=MOCK_LINK_FINISH_TIME)
     op.chain = [mock_link]
     assert op.ran_ability_id('123')
Exemple #5
0
 def test_no_state_change_event_fired_when_setting_same_state(
         self, mock_emit_state_change_method, fake_event_svc, adversary):
     initial_state = 'running'
     op = Operation(name='test',
                    agents=[],
                    adversary=adversary,
                    state=initial_state)
     op.state = initial_state
     mock_emit_state_change_method.assert_not_called()
Exemple #6
0
 def test_state_change_event_fired_on_state_change(
         self, mock_emit_state_change_method, fake_event_svc, adversary):
     op = Operation(name='test',
                    agents=[],
                    adversary=adversary,
                    state='running')
     op.state = 'finished'
     mock_emit_state_change_method.assert_called_with(from_state='running',
                                                      to_state='finished')
Exemple #7
0
def op_for_event_logs(operation_agent, operation_adversary, executor, ability,
                      operation_link, encoded_command, parse_datestring):
    op = Operation(name='test',
                   agents=[operation_agent],
                   adversary=operation_adversary)
    op.set_start_details()
    command_1 = 'whoami'
    command_2 = 'hostname'
    executor_1 = executor(name='psh', platform='windows', command=command_1)
    executor_2 = executor(name='psh', platform='windows', command=command_2)
    ability_1 = ability(ability_id='123',
                        tactic='test tactic',
                        technique_id='T0000',
                        technique_name='test technique',
                        name='test ability',
                        description='test ability desc',
                        executors=[executor_1])
    ability_2 = ability(ability_id='456',
                        tactic='test tactic',
                        technique_id='T0000',
                        technique_name='test technique',
                        name='test ability 2',
                        description='test ability 2 desc',
                        executors=[executor_2])
    link_1 = operation_link(ability=ability_1,
                            paw=operation_agent.paw,
                            executor=executor_1,
                            command=encoded_command(command_1),
                            status=0,
                            host=operation_agent.host,
                            pid=789,
                            decide=parse_datestring(LINK1_DECIDE_TIME),
                            collect=parse_datestring(LINK1_COLLECT_TIME),
                            finish=LINK1_FINISH_TIME)
    link_2 = operation_link(ability=ability_2,
                            paw=operation_agent.paw,
                            executor=executor_2,
                            command=encoded_command(command_2),
                            status=0,
                            host=operation_agent.host,
                            pid=7890,
                            decide=parse_datestring(LINK2_DECIDE_TIME),
                            collect=parse_datestring(LINK2_COLLECT_TIME),
                            finish=LINK2_FINISH_TIME)
    discarded_link = operation_link(
        ability=ability_2,
        paw=operation_agent.paw,
        executor=executor_2,
        command=encoded_command(command_2),
        status=-2,
        host=operation_agent.host,
        pid=7891,
        decide=parse_datestring('2021-01-01T10:00:00Z'))
    op.chain = [link_1, link_2, discarded_link]
    return op
class TestLearningSvc(TestBase):
    def setUp(self):
        self.initialize()
        self.ability = self.run_async(
            self.data_svc.store(
                Ability(ability_id='123',
                        tactic='discovery',
                        technique_id='T1033',
                        technique='Find',
                        name='test',
                        test='d2hvYW1pCg==',
                        description='find active user',
                        cleanup='',
                        executor='sh',
                        platform='darwin',
                        payload='wifi.sh',
                        parsers=[],
                        requirements=[],
                        privilege=None)))
        self.operation = Operation(name='sample', agents=None, adversary=None)
        self.run_async(self.data_svc.store(self.operation))

    def test_learn(self):
        link = Link(operation=self.operation.id,
                    ability=self.ability,
                    command=None,
                    paw=None)
        self.operation.add_link(link)
        self.run_async(
            self.learning_svc.learn(
                link=link,
                blob=BaseWorld.encode_string(
                    'i contain 1 ip address 192.168.0.1 and one file /etc/host.txt. that is all.'
                )))
        self.assertEqual(2, len(link.facts))

    def test_build_relationships(self):
        self.learning_svc.model.add(
            frozenset({'host.user.name', 'target.org.name'}))
        self.learning_svc.model.add(
            frozenset(
                {'host.file.extension', 'host.user.name', 'domain.user.name'}))
        facts = [
            Fact(trait='target.org.name', value='something'),
            Fact(trait='host.user.name', value='admin'),
            Fact(trait='host.user.name', value='root'),
            Fact(trait='domain.user.name', value='user'),
            Fact(trait='not.really.here', value='should never be found')
        ]
        link = Link(operation=self.operation.id,
                    ability=self.ability,
                    command=None,
                    paw=None)
        self.run_async(self.learning_svc._build_relationships(link, facts))
        self.assertEqual(4, len(link.relationships))
 def setUp(self):
     self.initialize()
     self.ability = Ability(ability_id='123',
                            executor='sh',
                            test=BaseWorld.encode_string('mkdir test'),
                            cleanup=BaseWorld.encode_string('rm -rf test'))
     self.agent = Agent(sleep_min=1, sleep_max=2, watchdog=0)
     self.operation = Operation(name='test1',
                                agents=self.agent,
                                adversary='hunter')
     self.run_async(self.data_svc.store(self.ability))
Exemple #10
0
 async def create_operation(self, links, source):
     planner = (await self.get_service('data_svc').locate(
         'planners', match=dict(name='sequential')))[0]
     await self.get_service('data_svc').store(source)
     self.op = Operation(name=BLUE_OP_NAME,
                         agents=self.agents,
                         adversary=self.adversary,
                         source=source,
                         access=self.Access.BLUE,
                         planner=planner,
                         state='running',
                         auto_close=False,
                         jitter='1/4')
     self.op.set_start_details()
     await self.update_operation(links)
Exemple #11
0
def op_without_learning_parser(ability, adversary):
    op = Operation(id='54321',
                   name='testB',
                   agents=[],
                   adversary=adversary,
                   use_learning_parsers=False)
    return op
Exemple #12
0
def op_with_learning_parser(ability, adversary):
    op = Operation(id='12345',
                   name='testA',
                   agents=[],
                   adversary=adversary,
                   use_learning_parsers=True)
    return op
Exemple #13
0
    async def _build_operation_object(self, data):
        name = data.pop('name')
        group = data.pop('group')
        planner = await self.get_service('data_svc').locate(
            'planners', match=dict(name=data.pop('planner')))
        adversary = await self._construct_adversary_for_op(
            data.pop('adversary_id'))
        agents = await self._construct_agents_for_group(group)
        sources = await self.get_service('data_svc').locate(
            'sources', match=dict(name=data.pop('source')))

        return Operation(name=name,
                         planner=planner[0],
                         agents=agents,
                         adversary=adversary,
                         group=group,
                         jitter=data.pop('jitter'),
                         source=next(iter(sources), None),
                         state=data.pop('state'),
                         allow_untrusted=int(data.pop('allow_untrusted')),
                         autonomous=int(data.pop('autonomous')),
                         phases_enabled=bool(int(data.pop('phases_enabled'))),
                         obfuscator=data.pop('obfuscator'),
                         max_time=int(data.pop('max_time')),
                         auto_close=bool(int(data.pop('auto_close'))))
Exemple #14
0
    async def _build_operation_object(self, access, data):
        name = data.pop('name')
        group = data.pop('group', '')
        planner = await self.get_service('data_svc').locate(
            'planners', match=dict(name=data.get('planner', 'atomic')))
        adversary = await self._construct_adversary_for_op(
            data.pop('adversary_id', ''))
        agents = await self.construct_agents_for_group(group)
        sources = await self.get_service('data_svc').locate(
            'sources', match=dict(name=data.pop('source', 'basic')))
        allowed = self._get_allowed_from_access(access)

        return Operation(name=name,
                         planner=planner[0],
                         agents=agents,
                         adversary=adversary,
                         group=group,
                         jitter=data.pop('jitter', '2/8'),
                         source=next(iter(sources), None),
                         state=data.pop('state', 'running'),
                         autonomous=int(data.pop('autonomous', 1)),
                         access=allowed,
                         obfuscator=data.pop('obfuscator', 'plain-text'),
                         auto_close=bool(int(data.pop('auto_close', 0))),
                         visibility=int(data.pop('visibility', '50')))
Exemple #15
0
 async def create_operation(self, links, source):
     planner = (await self.get_service('data_svc').locate(
         'planners', match=dict(name='batch')))[0]
     await self.get_service('data_svc').store(source)
     blue_op_name = self.get_config(prop='op_name', name='response')
     self.op = Operation(name=blue_op_name,
                         agents=self.agents,
                         adversary=self.adversary,
                         source=source,
                         access=self.Access.BLUE,
                         planner=planner,
                         state='running',
                         auto_close=False,
                         jitter='1/4')
     self.op.set_start_details()
     await self.update_operation(links)
Exemple #16
0
    async def _build_operation_object(self, access, data):
        name = data.pop('name')
        group = data.pop('group')
        planner = await self.get_service('data_svc').locate(
            'planners', match=dict(name=data.pop('planner')))
        adversary = await self._construct_adversary_for_op(
            data.pop('adversary_id'))
        agents = await self.construct_agents_for_group(group)
        sources = await self.get_service('data_svc').locate(
            'sources', match=dict(name=data.pop('source')))
        allowed = self.Access.BLUE if self.Access.BLUE in access[
            'access'] else self.Access.RED

        return Operation(name=name,
                         planner=planner[0],
                         agents=agents,
                         adversary=adversary,
                         group=group,
                         jitter=data.pop('jitter'),
                         source=next(iter(sources), None),
                         state=data.pop('state'),
                         autonomous=int(data.pop('autonomous')),
                         access=allowed,
                         phases_enabled=bool(int(data.pop('phases_enabled'))),
                         obfuscator=data.pop('obfuscator'),
                         auto_close=bool(int(data.pop('auto_close'))),
                         visibility=int(data.pop('visibility')))
 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()))
    def test_emit_state_change_event(self, loop, fake_event_svc, adversary):
        op = Operation(name='test', agents=[], adversary=adversary, state='running')
        fake_event_svc.reset()

        loop.run_until_complete(
            op._emit_state_change_event(
                from_state='running',
                to_state='finished'
            )
        )

        expected_key = (Operation.EVENT_EXCHANGE, Operation.EVENT_QUEUE_STATE_CHANGED)
        assert expected_key in fake_event_svc.fired

        event_kwargs = fake_event_svc.fired[expected_key]
        assert event_kwargs['op'] == op.id
        assert event_kwargs['from_state'] == 'running'
        assert event_kwargs['to_state'] == 'finished'
Exemple #19
0
def setup_rest_svc_test(loop, data_svc):
    BaseWorld.apply_config(name='main',
                           config={
                               'app.contact.http': '0.0.0.0',
                               'plugins': ['sandcat', 'stockpile'],
                               'crypt_salt': 'BLAH',
                               'api_key': 'ADMIN123',
                               'encryption_key': 'ADMIN123',
                               'exfil_dir': '/tmp'
                           })
    loop.run_until_complete(
        data_svc.store(
            Ability(ability_id='123',
                    test=BaseWorld.encode_string('curl #{app.contact.http}'),
                    variations=[],
                    executor='psh',
                    platform='windows')))
    adversary = Adversary(adversary_id='123',
                          name='test',
                          description='test',
                          atomic_ordering=[])
    loop.run_until_complete(data_svc.store(adversary))

    agent = Agent(paw='123',
                  sleep_min=2,
                  sleep_max=8,
                  watchdog=0,
                  executors=['pwsh', 'psh'],
                  platform='windows')
    loop.run_until_complete(data_svc.store(agent))

    loop.run_until_complete(
        data_svc.store(
            Planner(planner_id='123',
                    name='test',
                    module='test',
                    params=dict())))

    source = Source(id='123', name='test', facts=[], adjustments=[])
    loop.run_until_complete(data_svc.store(source))

    loop.run_until_complete(
        data_svc.store(
            Operation(name='test',
                      agents=[agent],
                      adversary=adversary,
                      id='123',
                      source=source)))

    loop.run_until_complete(
        data_svc.store(
            Obfuscator(
                name='plain-text',
                description=
                'Does no obfuscation to any command, instead running it in plain text',
                module='plugins.stockpile.app.obfuscators.plain_text')))
Exemple #20
0
    def test_operation(self):
        adversary = self.run_async(self.data_svc.store(
            Adversary(adversary_id='123', name='test', description='test adversary', phases=dict())
        ))
        self.run_async(self.data_svc.store(Operation(name='my first op', agents=[], adversary=adversary)))

        operations = self.run_async(self.data_svc.locate('operations'))
        self.assertEqual(1, len(operations))
        for x in operations:
            json.dumps(x.display)
 def setUp(self):
     self.initialize()
     self.ability = self.run_async(
         self.data_svc.store(
             Ability(ability_id='123',
                     tactic='discovery',
                     technique_id='T1033',
                     technique='Find',
                     name='test',
                     test='d2hvYW1pCg==',
                     description='find active user',
                     cleanup='',
                     executor='sh',
                     platform='darwin',
                     payload='wifi.sh',
                     parsers=[],
                     requirements=[],
                     privilege=None)))
     self.operation = Operation(name='sample', agents=None, adversary=None)
     self.run_async(self.data_svc.store(self.operation))
Exemple #22
0
 async def create_operation(self, source, op_type):
     planner = (await self.get_service('data_svc').locate('planners', match=dict(name='batch')))[0]
     await self.get_service('data_svc').store(source)
     blue_op_name = self.get_config(prop='op_name', name='response')
     access = self.Access.BLUE if op_type == 'visible' else self.Access.HIDDEN
     self.ops[op_type] = Operation(name=blue_op_name, agents=self.agents, adversary=self.adversary,
                                   source=source, access=access, planner=planner, state='running',
                                   auto_close=False, jitter='1/4')
     obj = await self.get_service('data_svc').locate('objectives', match=dict(name='default'))
     self.ops[op_type].objective = deepcopy(obj[0])
     self.ops[op_type].set_start_details()
Exemple #23
0
 async def _create_detection_operation(self, red_op_name, red_op_id,
                                       red_op_access):
     planner = (await self.get_service('data_svc').locate(
         'planners', match=dict(name='atomic')))[0]
     adversary_id = self.get_config(prop='adversary', name='gameboard')
     adversary = (await self.data_svc.locate(
         'adversaries', match=dict(adversary_id=adversary_id)))[0]
     obj = (await self.data_svc.locate('objectives',
                                       match=dict(name='default')))[0]
     agent = Agent(0, 0, 0, paw='gameboard_detection')
     access = self.Access.BLUE
     detection_operation = Operation(name=red_op_name + '_' +
                                     str(red_op_id) +
                                     self.blue_op_name_modifier,
                                     agents=[agent],
                                     adversary=adversary,
                                     access=access,
                                     planner=planner,
                                     group='blue')
     detection_operation.objective = obj
     detection_operation.set_start_details()
     return [await self.data_svc.store(detection_operation)]
Exemple #24
0
    def test_operation(self, loop, data_svc):
        adversary = loop.run_until_complete(
            data_svc.store(
                Adversary(adversary_id='123',
                          name='test',
                          description='test adversary',
                          phases=dict())))
        loop.run_until_complete(
            data_svc.store(
                Operation(name='my first op', agents=[], adversary=adversary)))

        operations = loop.run_until_complete(data_svc.locate('operations'))
        assert len(operations) == 1
        for x in operations:
            json.dumps(x.display)
Exemple #25
0
def setup_rest_svc_test(loop, data_svc):
    BaseWorld.apply_config(name='main', config={'app.contact.http': '0.0.0.0',
                                                'plugins': ['sandcat', 'stockpile'],
                                                'crypt_salt': 'BLAH',
                                                'api_key': 'ADMIN123',
                                                'encryption_key': 'ADMIN123',
                                                'exfil_dir': '/tmp'})
    loop.run_until_complete(data_svc.store(
        Ability(ability_id='123', name='testA', executors=[
            Executor(name='psh', platform='windows', command='curl #{app.contact.http}')
        ])
    ))
    loop.run_until_complete(data_svc.store(
        Ability(ability_id='456', name='testB', executors=[
            Executor(name='sh', platform='linux', command='whoami')
        ])
    ))
    loop.run_until_complete(data_svc.store(
        Ability(ability_id='789', name='testC', executors=[
            Executor(name='sh', platform='linux', command='hostname')
        ])
    ))
    adversary = Adversary(adversary_id='123', name='test', description='test', atomic_ordering=[])
    loop.run_until_complete(data_svc.store(adversary))

    agent = Agent(paw='123', sleep_min=2, sleep_max=8, watchdog=0, executors=['pwsh', 'psh'], platform='windows')
    loop.run_until_complete(data_svc.store(agent))

    loop.run_until_complete(data_svc.store(
        Objective(id='495a9828-cab1-44dd-a0ca-66e58177d8cc', name='default', goals=[Goal()])
    ))

    loop.run_until_complete(data_svc.store(
        Planner(planner_id='123', name='test', module='test', params=dict())
    ))

    source = Source(id='123', name='test', facts=[], adjustments=[])
    loop.run_until_complete(data_svc.store(source))

    loop.run_until_complete(data_svc.store(
        Operation(name='test', agents=[agent], adversary=adversary, id='123', source=source)
    ))

    loop.run_until_complete(data_svc.store(
        Obfuscator(name='plain-text',
                   description='Does no obfuscation to any command, instead running it in plain text',
                   module='plugins.stockpile.app.obfuscators.plain_text')
    ))
Exemple #26
0
 async def _build_operation_object(self, data):
     name = data.pop('name')
     planner = await self.get_service('data_svc').locate(
         'planners', match=dict(name=data.pop('planner')))
     adversary = await self.get_service('data_svc').locate(
         'adversaries', match=dict(adversary_id=data.pop('adversary_id')))
     agents = await self.get_service('data_svc').locate(
         'agents', match=dict(group=data.pop('group')))
     sources = await self.get_service('data_svc').locate(
         'sources', match=dict(name=data.pop('source')))
     return Operation(name=name,
                      planner=planner[0],
                      agents=agents,
                      adversary=adversary[0],
                      jitter=data.pop('jitter'),
                      source=next(iter(sources), None),
                      state=data.pop('state'),
                      allow_untrusted=int(data.pop('allow_untrusted')),
                      autonomous=int(data.pop('autonomous')))
Exemple #27
0
def op_with_learning_and_seeded(ability, adversary, operation_agent,
                                parse_datestring):
    sc = Source(id='3124',
                name='test',
                facts=[Fact(trait='domain.user.name', value='bob')])
    op = Operation(id='6789',
                   name='testC',
                   agents=[],
                   adversary=adversary,
                   source=sc,
                   use_learning_parsers=True)
    # patch operation to make it 'realistic'
    op.start = parse_datestring(OP_START_TIME)
    op.adversary = op.adversary()
    op.planner = Planner(planner_id='12345',
                         name='test_planner',
                         module='not.an.actual.planner',
                         params=None)
    op.objective = Objective(id='6428', name='not_an_objective')
    t_operation_agent = operation_agent
    t_operation_agent.paw = '123456'
    op.agents = [t_operation_agent]
    return op
Exemple #28
0
 def test_no_state_change_event_on_instantiation(
         self, mock_emit_state_change_method, fake_event_svc, adversary):
     Operation(name='test', agents=[], adversary=adversary)
     mock_emit_state_change_method.assert_not_called()
Exemple #29
0
class ResponseService(BaseService):
    def __init__(self, services):
        self.log = self.add_service('response_svc', self)
        self.data_svc = services.get('data_svc')
        self.rest_svc = services.get('rest_svc')
        self.agents = []
        self.adversary = None
        self.abilities = []
        self.op = None

    @template('response.html')
    async def splash(self, request):
        abilities = [
            a for a in await self.data_svc.locate('abilities')
            if await a.which_plugin() == 'response'
        ]
        adversaries = [
            a for a in await self.data_svc.locate('adversaries')
            if await a.which_plugin() == 'response'
        ]
        return dict(abilities=abilities, adversaries=adversaries)

    @staticmethod
    async def register_handler(event_svc):
        await event_svc.observe_event('link/completed', handle_link_completed)

    async def respond_to_pid(self, pid, agent):
        available_agents = await self.get_available_agents(agent)
        if not available_agents:
            return
        total_facts = []
        total_links = []

        for blue_agent in available_agents:
            agent_facts, agent_links = await self.run_abilities_on_agent(
                blue_agent, pid)
            total_facts.extend(agent_facts)
            total_links.extend(agent_links)

        await self.save_to_operation(total_facts, total_links)

    async def get_available_agents(self, agent_to_match):
        await self.refresh_blue_agents_abilities()
        available_agents = [
            a for a in self.agents if a.host == agent_to_match.host
        ]

        if not available_agents:
            self.log.debug('No available blue agents to respond to red action')
            return []

        return available_agents

    async def refresh_blue_agents_abilities(self):
        self.agents = await self.data_svc.locate(
            'agents', match=dict(access=self.Access.BLUE))
        self.adversary = (await self.data_svc.locate(
            'adversaries', match=dict(adversary_id=BLUE_ADVERSARY)))[0]

        self.abilities = []
        for a in self.adversary.atomic_ordering:
            if a not in self.abilities:
                self.abilities.append(a)

    async def run_abilities_on_agent(self, blue_agent, original_pid):
        facts = [Fact(trait='host.process.id', value=original_pid)]
        links = []
        for ability_id in self.abilities:
            ability_facts, ability_links = await self.run_ability_on_agent(
                blue_agent, ability_id, facts, original_pid)
            links.extend(ability_links)
            facts.extend(ability_facts)
        return facts, links

    async def run_ability_on_agent(self, blue_agent, ability_id, agent_facts,
                                   original_pid):
        links = await self.rest_svc.task_agent_with_ability(
            blue_agent.paw, ability_id, agent_facts)
        await self.wait_for_link_completion(links, blue_agent)
        ability_facts = []
        for link in links:
            link.pin = int(original_pid)
            unique_facts = link.facts[1:]
            ability_facts.extend(unique_facts)
        return ability_facts, links

    @staticmethod
    async def wait_for_link_completion(links, agent):
        for link in links:
            while not link.finish or link.can_ignore():
                await asyncio.sleep(3)
                if not agent.trusted:
                    break

    async def create_fact_source(self, facts):
        source_id = str(uuid.uuid4())
        source_name = 'blue-pid-{}'.format(source_id)
        return Source(id=source_id, name=source_name, facts=facts)

    async def save_to_operation(self, facts, links):
        if not self.op or await self.op.is_finished():
            source = await self.create_fact_source(facts)
            await self.create_operation(links=links, source=source)
        else:
            await self.update_operation(links)
        await self.get_service('data_svc').store(self.op)

    async def create_operation(self, links, source):
        planner = (await self.get_service('data_svc').locate(
            'planners', match=dict(name='sequential')))[0]
        await self.get_service('data_svc').store(source)
        self.op = Operation(name=BLUE_OP_NAME,
                            agents=self.agents,
                            adversary=self.adversary,
                            source=source,
                            access=self.Access.BLUE,
                            planner=planner,
                            state='running',
                            auto_close=False,
                            jitter='1/4')
        self.op.set_start_details()
        await self.update_operation(links)

    async def update_operation(self, links):
        for link in links:
            link.operation = self.op.id
            self.op.add_link(link)
Exemple #30
0
 def _generate_operation(name, agents, adversary, *args, **kwargs):
     return Operation(name=name,
                      agents=agent,
                      adversary=adversary,
                      *args,
                      **kwargs)