Ejemplo n.º 1
0
class FactSourceApi(BaseObjectApi):
    def __init__(self, services):
        super().__init__(description='fact source',
                         obj_class=Source,
                         schema=SourceSchema,
                         ram_key='sources',
                         id_property='id',
                         auth_svc=services['auth_svc'])
        self._api_manager = BaseApiManager(data_svc=services['data_svc'],
                                           file_svc=services['file_svc'])

    def add_routes(self, app: web.Application):
        router = app.router
        router.add_get('/sources', self.get_fact_sources)
        router.add_get('/sources/{id}', self.get_fact_source_by_id)
        router.add_post('/sources', self.create_fact_source)
        router.add_patch('/sources/{id}', self.update_fact_source)
        router.add_put('/sources/{id}', self.create_or_update_source)

    @aiohttp_apispec.docs(tags=['sources'])
    @aiohttp_apispec.querystring_schema(BaseGetAllQuerySchema)
    @aiohttp_apispec.response_schema(SourceSchema(many=True, partial=True))
    async def get_fact_sources(self, request: web.Request):
        sources = await self.get_all_objects(request)
        return web.json_response(sources)

    @aiohttp_apispec.docs(tags=['sources'])
    @aiohttp_apispec.querystring_schema(BaseGetOneQuerySchema)
    @aiohttp_apispec.response_schema(SourceSchema(partial=True))
    async def get_fact_source_by_id(self, request: web.Request):
        source = await self.get_object(request)
        return web.json_response(source)

    @aiohttp_apispec.docs(tags=['sources'])
    @aiohttp_apispec.request_schema(SourceSchema)
    @aiohttp_apispec.response_schema(SourceSchema)
    async def create_fact_source(self, request: web.Request):
        source = await self.create_on_disk_object(request)
        return web.json_response(source.display)

    @aiohttp_apispec.docs(tags=['sources'])
    @aiohttp_apispec.request_schema(SourceSchema(partial=True))
    @aiohttp_apispec.response_schema(SourceSchema)
    async def update_fact_source(self, request: web.Request):
        source = await self.update_on_disk_object(request)
        return web.json_response(source.display)

    @aiohttp_apispec.docs(tags=['sources'])
    @aiohttp_apispec.request_schema(SourceSchema(partial=True))
    @aiohttp_apispec.response_schema(SourceSchema)
    async def create_or_update_source(self, request: web.Request):
        source = await self.create_or_update_on_disk_object(request)
        return web.json_response(source.display)
Ejemplo n.º 2
0
class OperationSchema(ma.Schema):
    id = ma.fields.String()
    name = ma.fields.String(required=True)
    host_group = ma.fields.List(ma.fields.Nested(AgentSchema()),
                                attribute='agents',
                                dump_only=True)
    adversary = ma.fields.Nested(AdversarySchema())
    jitter = ma.fields.String()
    planner = ma.fields.Nested(PlannerSchema())
    start = ma.fields.DateTime(format=BaseObject.TIME_FORMAT, dump_only=True)
    state = ma.fields.String()
    obfuscator = ma.fields.String()
    autonomous = ma.fields.Integer()
    chain = ma.fields.Function(lambda obj: [lnk.display for lnk in obj.chain])
    auto_close = ma.fields.Boolean()
    visibility = ma.fields.Integer()
    objective = ma.fields.Nested(ObjectiveSchema())
    use_learning_parsers = ma.fields.Boolean()
    group = ma.fields.String(missing='')
    source = ma.fields.Nested(SourceSchema())

    @ma.pre_load()
    def remove_properties(self, data, **_):
        data.pop('host_group', None)
        data.pop('start', None)
        data.pop('chain', None)
        data.pop('objective', None)
        return data

    @ma.post_load
    def build_operation(self, data, **kwargs):
        return None if kwargs.get('partial') is True else Operation(**data)
Ejemplo n.º 3
0
 async def _construct_and_dump_source(self, source_id: str):
     source = await self.services['data_svc'].locate(
         'sources', match=dict(id=source_id))
     if not source:
         source = (await self.services['data_svc'].locate(
             'sources', match=dict(name='basic')))
     return SourceSchema().dump(source[0])
Ejemplo n.º 4
0
def expected_replaced_source_dump(replaced_source_payload, mocker, mock_time):
    with mocker.patch(
            'app.objects.secondclass.c_fact.datetime') as mock_datetime:
        mock_datetime.return_value = mock_datetime
        mock_datetime.now.return_value = mock_time
        source = SourceSchema().load(replaced_source_payload)
        dumped_obj = source.display_schema.dump(source)
        dumped_obj['relationships'][0]['unique'] = mock.ANY
        return dumped_obj
Ejemplo n.º 5
0
def test_operation(test_adversary, test_planner, test_source):
    expected_operation = {
        'name': '123',
        'adversary': AdversarySchema().dump(test_adversary),
        'state': 'paused',
        'id': '123',
        'group': 'red',
        'autonomous': 0,
        'planner': PlannerSchema().dump(test_planner),
        'source': SourceSchema().dump(test_source),
        'jitter': '2/8',
        'visibility': 50,
        'auto_close': False,
        'obfuscator': 'plain-text',
        'use_learning_parsers': False
    }
    return expected_operation
Ejemplo n.º 6
0
 async def test_create_operation_existing_relationships(
         self, api_v2_client, api_cookies,
         test_source_existing_relationships):
     payload = dict(
         name='op_existing_relationships',
         id='456',
         planner={'id': '123'},
         adversary={'adversary_id': '123'},
         source=SourceSchema().dump(test_source_existing_relationships))
     resp = await api_v2_client.post('/api/v2/operations',
                                     cookies=api_cookies,
                                     json=payload)
     assert resp.status == HTTPStatus.OK
     op_data = await resp.json()
     assert op_data['name'] == payload['name']
     assert op_data['start']
     assert op_data['planner']['id'] == payload['planner']['id']
     assert op_data['source']['id'] == payload['source']['id']
     assert len(op_data['source']['relationships']) == len(
         payload['source']['relationships'])
Ejemplo n.º 7
0
class FactSourceApi(BaseObjectApi):
    def __init__(self, services):
        super().__init__(description='Fact Source',
                         obj_class=Source,
                         schema=SourceSchema,
                         ram_key='sources',
                         id_property='id',
                         auth_svc=services['auth_svc'])
        self._api_manager = BaseApiManager(data_svc=services['data_svc'],
                                           file_svc=services['file_svc'])

    def add_routes(self, app: web.Application):
        router = app.router
        router.add_get('/sources', self.get_fact_sources)
        router.add_get('/sources/{id}', self.get_fact_source_by_id)
        router.add_post('/sources', self.create_fact_source)
        router.add_patch('/sources/{id}', self.update_fact_source)
        router.add_put('/sources/{id}', self.create_or_update_source)
        router.add_delete('/sources/{id}', self.delete_source)

    @aiohttp_apispec.docs(
        tags=['sources'],
        summary='Retrieve all Fact Sources.',
        description=
        'Returns a list of all Fact Sources, including custom-created ones.')
    @aiohttp_apispec.querystring_schema(BaseGetAllQuerySchema)
    @aiohttp_apispec.response_schema(
        SourceSchema(many=True, partial=True),
        description=
        'Returns a list of all Sources dumped in SourceSchema format.')
    async def get_fact_sources(self, request: web.Request):
        sources = await self.get_all_objects(request)
        return web.json_response(sources)

    @aiohttp_apispec.docs(
        tags=['sources'],
        summary='Retrieve a Fact Source by its id.',
        description='Returns a Fact Source, given a source id.',
        parameters=[{
            'in': 'path',
            'name': 'id',
            'description': 'The id of the Fact Source',
            'schema': {
                'type': 'string'
            },
            'required': 'true'
        }])
    @aiohttp_apispec.querystring_schema(BaseGetOneQuerySchema)
    @aiohttp_apispec.response_schema(
        SourceSchema(partial=True),
        description='Returns a single Source dumped in SourceSchema format.')
    async def get_fact_source_by_id(self, request: web.Request):
        source = await self.get_object(request)
        return web.json_response(source)

    @aiohttp_apispec.docs(
        tags=['sources'],
        summary='Create a Fact Source.',
        description=
        'Create a new Fact Source using the format provided in the SourceSchema.'
    )
    @aiohttp_apispec.docs(tags=['sources'])
    @aiohttp_apispec.request_schema(SourceSchema)
    @aiohttp_apispec.response_schema(
        SourceSchema,
        description='Returns a single Source dumped in SourceSchema format.')
    async def create_fact_source(self, request: web.Request):
        source = await self.create_on_disk_object(request)
        return web.json_response(source.display)

    @aiohttp_apispec.docs(
        tags=['sources'],
        summary='Update an existing Fact Source.',
        description=
        'Returns an updated Fact Source. All fields in a Fact Source can be updated, except for "id" and "adjustments".',
        parameters=[{
            'in': 'path',
            'name': 'id',
            'description': 'The id of the Fact Source.',
            'schema': {
                'type': 'string'
            },
            'required': 'true'
        }])
    @aiohttp_apispec.request_schema(SourceSchema(partial=True))
    @aiohttp_apispec.response_schema(
        SourceSchema,
        description='Returns a single Source dumped in SourceSchema format.')
    async def update_fact_source(self, request: web.Request):
        source = await self.update_on_disk_object(request)
        return web.json_response(source.display)

    @aiohttp_apispec.docs(
        tags=['sources'],
        summary='Update an existing or create a new Fact Source.',
        description=
        'Use fields from the SourceSchema in the request body to replace an existing Fact Source or create a new Fact Source.',
        parameters=[{
            'in': 'path',
            'name': 'id',
            'description': 'The id of the Fact Source.',
            'schema': {
                'type': 'string'
            },
            'required': 'true'
        }])
    @aiohttp_apispec.request_schema(SourceSchema(partial=True))
    @aiohttp_apispec.response_schema(
        SourceSchema,
        description='Returns a single Source dumped in SourceSchema format.')
    async def create_or_update_source(self, request: web.Request):
        source = await self.create_or_update_on_disk_object(request)
        return web.json_response(source.display)

    @aiohttp_apispec.docs(tags=['sources'],
                          summary='Delete an existing Fact Source.',
                          description='Delete a Fact Source, given its id.',
                          parameters=[{
                              'in': 'path',
                              'name': 'id',
                              'description':
                              'The id of the Fact Source to be deleted.',
                              'schema': {
                                  'type': 'string'
                              },
                              'required': 'true'
                          }])
    @aiohttp_apispec.response_schema(SourceSchema,
                                     description='Returns DELETE status.')
    async def delete_source(self, request: web.Request):
        await self.delete_object(request)
        return web.HTTPNoContent()