Пример #1
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)
Пример #2
0
class OperationSchema(ma.Schema):
    id = ma.fields.Integer()
    name = ma.fields.String()
    host_group = ma.fields.List(ma.fields.Nested(AgentSchema()), attribute='agents')
    adversary = ma.fields.Nested(AdversarySchema())
    jitter = ma.fields.String()
    planner = ma.fields.Nested(PlannerSchema())
    start = ma.fields.DateTime(format='%Y-%m-%d %H:%M:%S')
    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()

    @ma.post_load
    def build_planner(self, data, **_):
        return Operation(**data)
Пример #3
0
class AgentApi(BaseObjectApi):
    def __init__(self, services):
        super().__init__(description='agent',
                         obj_class=Agent,
                         schema=AgentSchema,
                         ram_key='agents',
                         id_property='paw',
                         auth_svc=services['auth_svc'])
        self._api_manager = AgentApiManager(data_svc=services['data_svc'],
                                            file_svc=services['file_svc'])

    def add_routes(self, app: web.Application):
        router = app.router
        router.add_get('/agents', self.get_agents)
        router.add_get('/agents/{paw}', self.get_agent_by_id)
        router.add_post('/agents', self.create_agent)
        router.add_patch('/agents/{paw}', self.update_agent)
        router.add_put('/agents/{paw}', self.create_or_update_agent)
        router.add_delete('/agents/{paw}', self.delete_agent)

        router.add_get('/deploy_commands', self.get_deploy_commands)
        router.add_get('/deploy_commands/{ability_id}',
                       self.get_deploy_commands_for_ability)

    @aiohttp_apispec.docs(tags=['agents'],
                          summary="Retrieves all agents",
                          description="Retrieves all stored agents.")
    @aiohttp_apispec.querystring_schema(BaseGetAllQuerySchema)
    @aiohttp_apispec.response_schema(
        AgentSchema(many=True, partial=True),
        description="Returns a list of all agents.")
    async def get_agents(self, request: web.Request):
        agents = await self.get_all_objects(request)
        return web.json_response(agents)

    @aiohttp_apispec.docs(
        tags=['agents'],
        summary="Retrieve Agent by paw",
        description=
        "Retrieve information about a specific agent using its ID (paw). Use "
        "the paw field in the URL to specify matching criteria for the agent to "
        "obtain information about.",
        parameters=[{
            'in':
            'path',
            'name':
            'paw',
            'schema': {
                'type': 'string'
            },
            'required':
            'true',
            'description':
            'ID of the Agent to retrieve information about'
        }])
    @aiohttp_apispec.querystring_schema(BaseGetOneQuerySchema)
    @aiohttp_apispec.response_schema(AgentSchema(partial=True),
                                     description="Returns JSON response with "
                                     "specified Agent")
    async def get_agent_by_id(self, request: web.Request):
        agent = await self.get_object(request)
        return web.json_response(agent)

    @aiohttp_apispec.docs(
        tags=['agents'],
        summary="Create a new agent",
        description="Creates a new agent using the format from 'AgentSchema'.")
    @aiohttp_apispec.request_schema(AgentSchema)
    @aiohttp_apispec.response_schema(
        AgentSchema,
        description="Returns a single agent in 'AgentSchema' format")
    async def create_agent(self, request: web.Request):
        agent = await self.create_object(request)
        return web.json_response(agent.display)

    @aiohttp_apispec.docs(
        tags=['agents'],
        summary="Update an Agent",
        description=
        "Update the attributes of a specific Agent using its ID (paw). Use the paw "
        "field in the URL to specify matching criteria and the fields from the "
        "AgentSchema in the request body to specify updated field values.",
        parameters=[{
            'in': 'path',
            'name': 'paw',
            'schema': {
                'type': 'string'
            },
            'required': 'true',
            'description': 'ID of the Agent to update'
        }])
    @aiohttp_apispec.request_schema(
        AgentSchema(partial=True,
                    only=[
                        'group', 'trusted', 'sleep_min', 'sleep_max',
                        'watchdog', 'pending_contact'
                    ]))
    @aiohttp_apispec.response_schema(
        AgentSchema,
        description="Returns JSON response with updated Agent fields")
    async def update_agent(self, request: web.Request):
        agent = await self.update_object(request)
        return web.json_response(agent.display)

    @aiohttp_apispec.docs(
        tags=['agents'],
        summary="Create or Update an Agent",
        description=
        "Update an agent, or if a existing agent match cannot be found, "
        "create one. Use the paw field in the URL to specify matching "
        "criteria and the fields from the AgentSchema in the request body"
        " to specify new field values.",
        parameters=[{
            'in': 'path',
            'name': 'paw',
            'schema': {
                'type': 'string'
            },
            'required': 'true',
            'description': 'paw of the Agent to be retrieved'
        }])
    @aiohttp_apispec.request_schema(AgentSchema(partial=True))
    @aiohttp_apispec.response_schema(
        AgentSchema,
        description="Json dictionary representation of the created or "
        "updated Agent")
    async def create_or_update_agent(self, request: web.Request):
        agent = await self.create_or_update_object(request)
        return web.json_response(agent.display)

    @aiohttp_apispec.docs(
        tags=['agents'],
        summary="Delete an Agent",
        description=
        "Delete an agent. Use the paw field in the URL to specify matching "
        "criteria for the agent(s) to delete.",
        parameters=[{
            'in': 'path',
            'name': 'paw',
            'schema': {
                'type': 'string'
            },
            'required': 'true',
            'description': 'paw of the Agent to be deleted'
        }])
    @aiohttp_apispec.response_schema(AgentSchema(only=[]),
                                     description="Returns HTTP 200")
    async def delete_agent(self, request: web.Request):
        await self.delete_object(request)
        return web.HTTPNoContent()

    @aiohttp_apispec.docs(
        tags=['agents'],
        summary="Retrieve deploy commands",
        description=
        "Retrieve the deploy commands currently configured within Caldera.")
    @aiohttp_apispec.response_schema(
        DeployCommandsSchema,
        description="Json dictionary representation of deploy "
        "commands, sorted by Ability ID")
    async def get_deploy_commands(self, request: web.Request):
        deploy_commands = await self._api_manager.get_deploy_commands()
        return web.json_response(deploy_commands)

    @aiohttp_apispec.docs(
        tags=['agents'],
        summary="Retrieve deploy commands for an Ability",
        description=
        "Retrieve the deploy commands associated with a given ability ID. "
        "Use the 'ability_id' field in the URL specify which ability to "
        "retrieve deploy commands for.",
        parameters=[{
            'in':
            'path',
            'name':
            'ability_id',
            'schema': {
                'type': 'string'
            },
            'required':
            'true',
            'description':
            'ID of the ability to retrieve deploy commands for'
        }])
    @aiohttp_apispec.response_schema(
        DeployCommandsSchema,
        description="Json dictionary representation of deploy "
        "commands for the specified Ability ID")
    async def get_deploy_commands_for_ability(self, request: web.Request):
        ability_id = request.match_info.get('ability_id')
        deploy_commands = await self._api_manager.get_deploy_commands(
            ability_id)
        return web.json_response(deploy_commands)
Пример #4
0
class AgentApi(BaseObjectApi):
    def __init__(self, services):
        super().__init__(description='agent',
                         obj_class=Agent,
                         schema=AgentSchema,
                         ram_key='agents',
                         id_property='paw',
                         auth_svc=services['auth_svc'])
        self._api_manager = AgentApiManager(data_svc=services['data_svc'],
                                            file_svc=services['file_svc'])

    def add_routes(self, app: web.Application):
        router = app.router
        router.add_get('/agents', self.get_agents)
        router.add_get('/agents/{paw}', self.get_agent_by_id)
        router.add_post('/agents', self.create_agent)
        router.add_patch('/agents/{paw}', self.update_agent)
        router.add_put('/agents/{paw}', self.create_or_update_agent)
        router.add_delete('/agents/{paw}', self.delete_agent)

        router.add_get('/deploy_commands/{ability_id}',
                       self.get_deploy_commands)

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

    @aiohttp_apispec.docs(tags=['agents'])
    @aiohttp_apispec.querystring_schema(BaseGetOneQuerySchema)
    @aiohttp_apispec.response_schema(AgentSchema(partial=True))
    async def get_agent_by_id(self, request: web.Request):
        agent = await self.get_object(request)
        return web.json_response(agent)

    @aiohttp_apispec.docs(tags=['agents'])
    @aiohttp_apispec.request_schema(AgentSchema)
    @aiohttp_apispec.response_schema(AgentSchema)
    async def create_agent(self, request: web.Request):
        agent = await self.create_object(request)
        return web.json_response(agent.display)

    @aiohttp_apispec.docs(tags=['agents'])
    @aiohttp_apispec.request_schema(AgentSchema(partial=True))
    @aiohttp_apispec.response_schema(AgentSchema)
    async def update_agent(self, request: web.Request):
        agent = await self.update_object(request)
        return web.json_response(agent.display)

    @aiohttp_apispec.docs(tags=['agents'])
    @aiohttp_apispec.request_schema(AgentSchema(partial=True))
    @aiohttp_apispec.response_schema(AgentSchema)
    async def create_or_update_agent(self, request: web.Request):
        agent = await self.create_or_update_object(request)
        return web.json_response(agent.display)

    @aiohttp_apispec.docs(tags=['agents'])
    @aiohttp_apispec.response_schema(AgentSchema)
    async def delete_agent(self, request: web.Request):
        await self.delete_object(request)
        return web.HTTPNoContent()

    @aiohttp_apispec.docs(tags=['agents'])
    @aiohttp_apispec.response_schema(DeployCommandsSchema)
    async def get_deploy_commands(self, request: web.Request):
        ability_id = request.match_info.get('ability_id')
        deploy_commands = await self._api_manager.get_deploy_commands(
            ability_id)
        return web.json_response(deploy_commands)