async def test_update_global_agent_config(base_world, data_svc): manager = ConfigApiManager(data_svc, None) await manager.update_global_agent_config(sleep_min=5, sleep_max=10) agent_config = manager.get_filtered_config('agents') assert agent_config['sleep_min'] == 5 assert agent_config['sleep_max'] == 10
async def test_update_global_agent_config_allows_partial_updates( base_world, data_svc): manager = ConfigApiManager(data_svc, None) agent_config = manager.get_filtered_config('agents') await manager.update_global_agent_config( ) # no arguments passed in--should no-op assert manager.get_filtered_config('agents') == agent_config
def test_get_filtered_config_all_sensitive_keys_filtered(base_world, data_svc): sensitive_conf = { key: 'foo' for key in config_api_manager.SENSITIVE_CONFIG_PROPS } base_world.apply_config('test', sensitive_conf) assert base_world.get_config(name='test') == sensitive_conf manager = ConfigApiManager(data_svc, None) filtered = manager.get_filtered_config('test') assert filtered == {}
class ConfigApi(BaseApi): def __init__(self, services): super().__init__(auth_svc=services['auth_svc']) self._api_manager = ConfigApiManager(data_svc=services['data_svc'], file_svc=services['file_svc']) def add_routes(self, app: web.Application): router = app.router router.add_get('/config/{name}', self.get_config_with_name) router.add_patch('/config/main', self.update_main_config) router.add_patch('/config/agents', self.update_agents_config) @aiohttp_apispec.docs(tags=['config']) async def get_config_with_name(self, request): config_name = request.match_info['name'] try: config = self._api_manager.get_filtered_config(config_name) except ConfigNotFound: raise JsonHttpNotFound(f'Config not found: {config_name}') return web.json_response(config) @aiohttp_apispec.docs(tags=['config']) @aiohttp_apispec.request_schema(AgentConfigUpdateSchema) @aiohttp_apispec.response_schema(AgentConfigUpdateSchema) async def update_agents_config(self, request): schema = AgentConfigUpdateSchema() data = await self.parse_json_body(request, schema) await self._api_manager.update_global_agent_config(**data) agents_config = self._api_manager.get_filtered_config('agents') return web.json_response(schema.dump(agents_config)) @aiohttp_apispec.docs(tags=['config']) @aiohttp_apispec.request_schema(ConfigUpdateSchema) async def update_main_config(self, request): data = await self.parse_json_body( request, schema=ConfigUpdateSchema() ) try: self._api_manager.update_main_config( prop=data['prop'], value=data['value'] ) except ConfigUpdateNotAllowed as ex: raise JsonHttpForbidden( error='Update not allowed', details={'property': ex.property} ) return web.json_response(self._api_manager.get_filtered_config('main'))
def test_get_filtered_config_remove_sensitive_keys(base_world, data_svc): test_conf = { 'users': 'this should be filtered', 'host': 'this should be filtered', 'foo': '1', 'bar': '2', 'baz': '3' } base_world.apply_config('test', test_conf) manager = ConfigApiManager(data_svc, None) filtered = manager.get_filtered_config('test') expected = {'foo': '1', 'bar': '2', 'baz': '3'} assert filtered == expected
async def test_update_global_agent_config_updates_list_properties( base_world, ability): stub_data_svc = StubDataService() stub_data_svc.abilities = [ ability('ability-1'), ability('ability-2'), ability('ability-3') ] manager = ConfigApiManager(data_svc=stub_data_svc, file_svc=None) await manager.update_global_agent_config( deadman_abilities=['ability-1', 'ability-2'], bootstrap_abilities=['ability-3']) agent_config = manager.get_filtered_config('agents') assert agent_config['deadman_abilities'] == ['ability-1', 'ability-2'] assert agent_config['bootstrap_abilities'] == ['ability-3']
def test_update_main_config_throws_exception_on_sensitive_field( base_world, data_svc): manager = ConfigApiManager(data_svc, None) with pytest.raises(ConfigUpdateNotAllowed): manager.update_main_config(prop='host', value='this is not allowed')
def test_update_main_config(base_world, data_svc): manager = ConfigApiManager(data_svc, None) manager.update_main_config(prop='foo.bar', value=100) assert manager.get_filtered_config('main')['foo.bar'] == 100
def test_get_filtered_config_throws_exception_on_not_found( base_world, data_svc): manager = ConfigApiManager(data_svc, None) with pytest.raises(ConfigNotFound): manager.get_filtered_config('THIS DOES NOT EXIST')
async def test_update_main_config_throws_validation_error_empty_prop( base_world, data_svc): manager = ConfigApiManager(data_svc, None) with pytest.raises(errors.DataValidationError): await manager.update_main_config(prop='', value=1234)
async def test_update_global_agent_config_throws_validation_error_bad_implant_name( base_world, data_svc): manager = ConfigApiManager(data_svc, None) with pytest.raises(errors.DataValidationError): await manager.update_global_agent_config(implant_name='')
async def test_update_global_agent_config_throws_validation_error_bad_untrusted_timer( base_world, data_svc): manager = ConfigApiManager(data_svc, None) with pytest.raises(errors.DataValidationError): await manager.update_global_agent_config(untrusted_timer=-1)
class ConfigApi(BaseApi): def __init__(self, services): super().__init__(auth_svc=services['auth_svc']) self._api_manager = ConfigApiManager(data_svc=services['data_svc'], file_svc=services['file_svc']) def add_routes(self, app: web.Application): router = app.router router.add_get('/config/{name}', self.get_config_with_name) router.add_patch('/config/main', self.update_main_config) router.add_patch('/config/agents', self.update_agents_config) @aiohttp_apispec.docs( tags=['config'], summary='Retrieve Config', parameters=[{ 'in': 'path', 'name': 'name', 'schema': { 'type': 'string' }, 'required': 'true', 'description': 'Name of the configuration file to be retrieved.' }], description= 'Retrieves configuration by name, as specified by {name} in the request url.' ) async def get_config_with_name(self, request): config_name = request.match_info['name'] try: config = self._api_manager.get_filtered_config(config_name) except ConfigNotFound: raise JsonHttpNotFound(f'Config not found: {config_name}') return web.json_response(config) @aiohttp_apispec.docs( tags=['config'], summary='Update Agent Config', description= 'Use fields from the AgentConfigUpdateSchema in the request body to ' 'update the Agent Configuration file.') @aiohttp_apispec.request_schema(AgentConfigUpdateSchema) @aiohttp_apispec.response_schema( AgentConfigUpdateSchema, description= 'The response consists of data from the Agent configuration file ' 'dumped in the AgentConfigUpdateSchema format.') async def update_agents_config(self, request): schema = AgentConfigUpdateSchema() data = await self.parse_json_body(request, schema) await self._api_manager.update_global_agent_config(**data) agents_config = self._api_manager.get_filtered_config('agents') return web.json_response(schema.dump(agents_config)) @aiohttp_apispec.docs( tags=['config'], summary='Update Main Config', description= 'Use fields from the ConfigUpdateSchema in the request body to ' 'update the main configuration file.') @aiohttp_apispec.request_schema(ConfigUpdateSchema) async def update_main_config(self, request): data = await self.parse_json_body(request, schema=ConfigUpdateSchema()) try: self._api_manager.update_main_config(prop=data['prop'], value=data['value']) except ConfigUpdateNotAllowed as ex: raise JsonHttpForbidden(error='Update not allowed', details={'property': ex.property}) return web.json_response(self._api_manager.get_filtered_config('main'))
def __init__(self, services): super().__init__(auth_svc=services['auth_svc']) self._api_manager = ConfigApiManager(data_svc=services['data_svc'], file_svc=services['file_svc'])
async def test_update_global_agent_config_throws_validation_error_bad_watchdog( base_world, data_svc): manager = ConfigApiManager(data_svc) with pytest.raises(errors.DataValidationError): await manager.update_global_agent_config(watchdog=-1)