def test_token_auth_session_invalid_memory_token(self, mocked_decode_token): """ Test token_auth_session to throw TokenExpiredException when memory token is expired """ auth = {'token_auth': {'initial_token': "asdfg"}} status = CheckData() # load a token in memory for validation status.data['http://testhost:8089token'] = 'memorytokenpresent' persistence_check_name = "splunk_metric" config = FakeInstanceConfig() helper = SplunkHelper(config) helper.requests_session.headers.update( {'Authorization': "Bearer memorytokenpresent"}) helper._current_time = mock.MagicMock() helper._current_time.return_value = datetime.datetime( 2020, 06, 16, 15, 44, 51) check = False try: helper.token_auth_session(auth, config.base_url, status, persistence_check_name) except TokenExpiredException: check = True msg = "Current in use authentication token is expired. Please provide a valid token in the YAML " \ "and restart the Agent" self.assertTrue(check, msg)
def test_dispatch_with_ignore_saved_search_errors_true(self): """ Test dispatch method to get value None in case of flag ignore_saved_search_errors=True """ path = '/servicesNS/%s/%s/saved/searches/%s/dispatch' % ( "admin", "search", "component") helper = SplunkHelper(FakeInstanceConfig()) # Mock the post response of request_session helper.requests_session.post = mock.MagicMock() helper.requests_session.post.return_value = MockResponse({ "reason": "Not Found", "status_code": 404, "url": path }) res = helper.dispatch( mocked_saved_search(), "admin", "search", helper.instance_config.ignore_saved_search_errors, None) self.assertEqual(res, None)
def test_token_auth_session(self, mocked_decode_token): """ Test token_auth_session when memory token is valid and doesn't need renewal """ auth = {'token_auth': {'initial_token': "asdfg"}} # load a token in memory for validation status = CheckData() status.data['http://testhost:8089token'] = 'memorytokenpresent' persistence_check_name = "splunk_metric" config = FakeInstanceConfig() helper = SplunkHelper(config) # update headers with memory token helper.requests_session.headers.update( {'Authorization': "Bearer memorytokenpresent"}) helper._current_time = mock.MagicMock() helper._current_time.return_value = datetime.datetime( 2020, 05, 14, 15, 44, 51) helper.token_auth_session(auth, config.base_url, status, persistence_check_name) # Header should be still with the memory token expected_header = helper.requests_session.headers.get("Authorization") self.assertEqual(expected_header, "Bearer {}".format("memorytokenpresent"))
def test_token_auth_session_need_renewal_memory_token( self, mocked_decode_token, moccked_post): """ Test token_auth_session when memory token about to expire and need to be refreshed """ new_token = json.loads(mocked_token_create_response()).get( 'entry')[0].get('content').get('token') auth = {'token_auth': {'initial_token': "asdfg"}} status = CheckData() # load a token in memory for validation status.data['http://testhost:8089token'] = 'memorytokenpresent' persistence_check_name = "splunk_metric" config = FakeInstanceConfig() helper = SplunkHelper(config) helper.requests_session.headers.update( {'Authorization': "Bearer memorytokenpresent"}) helper._current_time = mock.MagicMock() helper._current_time.return_value = datetime.datetime( 2020, 06, 5, 15, 44, 51) helper.token_auth_session(auth, config.base_url, status, persistence_check_name) # Header should be updated with the new token expected_header = helper.requests_session.headers.get("Authorization") self.assertEqual(expected_header, "Bearer {}".format(new_token)) # persistence data will have new token as well self.assertEqual(status.data.get('http://testhost:8089token'), new_token) status.data.clear()
def test_create_auth_token(self, mocked_response): """ Test token creation method for initial token """ new_token = json.loads(mocked_token_create_response()).get( 'entry')[0].get('content').get('token') helper = SplunkHelper(FakeInstanceConfig()) generated_token = helper.create_auth_token("test") username = helper.instance_config.username audience = helper.instance_config.audience expiry_days = helper.instance_config.token_expiration_days payload = { 'name': username, 'audience': audience, 'expires_on': "+{}d".format(str(expiry_days)) } mocked_response.assert_called_with( "/services/authorization/tokens?output_mode=json", payload, 10) mocked_response.assert_called_once() # New token from response and generated token should be same self.assertEqual(generated_token, new_token) # Initial token and new token should differ self.assertNotEqual("test", new_token)
def test_decode_token_util_when_exp_set_never(self, mocked_decode_token): """ Should return 999 days if first initial token expiration set to never """ helper = SplunkHelper(FakeInstanceConfig()) helper._current_time = mock.MagicMock() helper._current_time.return_value = datetime.datetime( 2020, 05, 14, 15, 44, 51) days = helper._decode_token_util("test", True) self.assertEqual(days, 999)
def test_decode_token_util(self, mocked_decode_token): """ Test token decoding utility """ helper = SplunkHelper(FakeInstanceConfig()) helper._current_time = mock.MagicMock() helper._current_time.return_value = datetime.datetime( 2020, 05, 14, 15, 44, 51) days = helper._decode_token_util("test", False) self.assertEqual(days, 27)
def test_need_renewal_false(self, mocked_decode_token): """ Test need renewal method when is_initial_token is false and should return False """ helper = SplunkHelper(FakeInstanceConfig()) helper._current_time = mock.MagicMock() helper._current_time.return_value = datetime.datetime( 2020, 05, 14, 15, 44, 51) valid = helper.need_renewal("test") # Need renewal should return True since flag is true self.assertFalse(valid)
def test_is_token_expired_false(self, mocked_decode_token): """ Test token validation method for invalid token """ helper = SplunkHelper(FakeInstanceConfig()) helper._current_time = mock.MagicMock() helper._current_time.return_value = datetime.datetime( 2020, 05, 14, 15, 44, 51) valid = helper.is_token_expired("test") # Token is not expired self.assertFalse(valid) self.assertEqual(valid, False)
def test_splunk_dispatch(self): username = "******" appname = "myapp" instance_config = SplunkInstanceConfig( { 'url': 'dummy', 'authentication': { 'basic_auth': { 'username': "******", 'password': "******" } } }, {}, { 'default_request_timeout_seconds': 5, 'default_search_max_retry_count': 3, 'default_search_seconds_between_retries': 1, 'default_verify_ssl_certificate': False, 'default_batch_size': 1000, 'default_saved_searches_parallel': 3, 'default_unique_key_fields': ["_bkt", "_cd"], 'default_app': 'default', 'default_parameters': {} }) splunk_helper = SplunkHelper(instance_config) saved_search = SplunkSavedSearch(instance_config, { "name": "search", "parameters": {} }) params = {"key1": "val1", "key2": "val2"} def _mocked_do_post(*args, **kwargs): self.assertEquals(args, ('/servicesNS/%s/%s/saved/searches/%s/dispatch' % (username, appname, quote(saved_search.name)), params, 5, 'true')) class MockedResponse(): def json(self): return {"sid": "zesid"} return MockedResponse() setattr(splunk_helper, "_do_post", _mocked_do_post) res = splunk_helper.dispatch(saved_search, username, appname, 'true', params) self.assertEquals(res, "zesid")
def __init__(self, current_time, instance, instance_config, saved_searches): self.instance_config = instance_config self.splunkHelper = SplunkHelper(instance_config) # no saved searches may be configured if not isinstance(instance['saved_searches'], list): instance['saved_searches'] = [] self.saved_searches = saved_searches self.saved_searches_parallel = int( instance.get( 'saved_searches_parallel', self.instance_config.get_or_default( 'default_saved_searches_parallel'))) self.tags = instance.get('tags', []) self.initial_delay_seconds = int( instance.get( 'initial_delay_seconds', self.instance_config.get_or_default( 'default_initial_delay_seconds'))) self.launch_time_seconds = current_time self.unique_key_fields = instance.get( 'unique_key_fields', self.instance_config.get_or_default('default_unique_key_fields'))
def test_auth_session_fallback(self, mocked_do_post): """ Test request authentication on fallback Authentication header retrieve auth session key, set it to the requests session, and see whether the outgoing request contains the expected HTTP header The expected HTTP header is Authentication when Set-Cookie is not present """ helper = SplunkHelper(FakeInstanceConfig()) helper.auth_session() mocked_do_post.assert_called_with("/services/auth/login?output_mode=json", "username=username&password=password&cookie=1", 10) mocked_do_post.assert_called_once() expected_header = helper.requests_session.headers.get("Authentication") self.assertEqual(expected_header, "Splunk MySessionKeyForThisSession")
def test_finalize_sid(self): """ Test finalize_sid method to successfully pass """ url = FakeInstanceConfig().base_url helper = SplunkHelper(FakeInstanceConfig()) helper.requests_session.post = mock.MagicMock() helper.requests_session.post.return_value = FakeResponse( status_code=200, text="done") # return None when response is 200 self.assertEqual( helper.finalize_sid("admin_comp1", mocked_saved_search()), None) helper.requests_session.post.return_value = MockResponse({ "reason": "Unknown Sid", "status_code": 404, "url": url }) # return None when sid not found because we want to continue self.assertEqual( helper.finalize_sid("admin_comp1", mocked_saved_search()), None) helper.requests_session.post.return_value = MockResponse({ "reason": "Internal Server error", "status_code": 500, "url": url }) # return finalize exception when api returns 500 self.assertRaises(FinalizeException, helper.finalize_sid, "admin_comp1", mocked_saved_search()) helper.requests_session.post = mock.MagicMock(side_effect=Timeout()) # return finalize exception when timeout occurs self.assertRaises(FinalizeException, helper.finalize_sid, "admin_comp1", mocked_saved_search()) helper.requests_session.post = mock.MagicMock( side_effect=ConnectionError()) # return finalize exception when connection error occurs self.assertRaises(FinalizeException, helper.finalize_sid, "admin_comp1", mocked_saved_search())
def test_splunk_helper(self): instance_config = SplunkInstanceConfig( { 'url': 'dummy', 'authentication': { 'basic_auth': { 'username': "******", 'password': "******" } } }, {}, { 'default_request_timeout_seconds': 5, 'default_search_max_retry_count': 3, 'default_search_seconds_between_retries': 1, 'default_verify_ssl_certificate': False, 'default_batch_size': 1000, 'default_saved_searches_parallel': 3, 'default_unique_key_fields': ["_bkt", "_cd"], 'default_app': 'default', 'default_parameters': {} }) splunk_helper = SplunkHelper(instance_config) saved_search = SplunkSavedSearch(instance_config, { "name": "search", "parameters": {} }) search_offsets = [] def _mocked_search_chunk(*args, **kwargs): search_offsets.append(args[2]) if args[2] == 4000: return {"messages": [], "results": []} else: return { "messages": [], "results": list(itertools.repeat(None, 1000)) } setattr(splunk_helper, "_search_chunk", _mocked_search_chunk) res = splunk_helper.saved_search_results("id", saved_search) self.assertEquals(len(res), 5) self.assertEquals(search_offsets, [0, 1000, 2000, 3000, 4000])
def test_splunk_saved_searches(self): instance_config = SplunkInstanceConfig( { 'url': 'dummy', 'authentication': { 'basic_auth': { 'username': "******", 'password': "******" } } }, {}, { 'default_request_timeout_seconds': 5, 'default_search_max_retry_count': 3, 'default_search_seconds_between_retries': 1, 'default_verify_ssl_certificate': False, 'default_batch_size': 1000, 'default_saved_searches_parallel': 3, 'default_unique_key_fields': ["_bkt", "_cd"], 'default_app': 'default', 'default_parameters': {} }) splunk_helper = SplunkHelper(instance_config) def _mocked_do_get(*args, **kwargs): class MockedResponse(): def json(self): return { "entry": [{ "name": "components" }, { "name": "relations" }] } return MockedResponse() setattr(splunk_helper, "_do_get", _mocked_do_get) res = splunk_helper.saved_searches() self.assertEquals(res, ["components", "relations"])
def __init__(self, instance, init_config): self.instance_config = InstanceConfig(instance, init_config) self.splunkHelper = SplunkHelper(self.instance_config) self.snapshot = bool(instance.get('snapshot', True)) # no saved searches may be configured if not isinstance(instance['component_saved_searches'], list): instance['component_saved_searches'] = [] if not isinstance(instance['relation_saved_searches'], list): instance['relation_saved_searches'] = [] # transform component and relation saved searches to SavedSearch objects components = [ SavedSearch("component", self.instance_config, saved_search_instance) for saved_search_instance in instance['component_saved_searches'] ] relations = [ SavedSearch("relation", self.instance_config, saved_search_instance) for saved_search_instance in instance['relation_saved_searches'] ] self.saved_searches = SavedSearches(components + relations) self.instance_key = { "type": self.INSTANCE_TYPE, "url": self.instance_config.base_url } self.tags = instance.get('tags', []) self.splunk_ignore_saved_search_errors = instance.get( 'ignore_saved_search_errors', False) self.polling_interval_seconds = int( instance.get( 'polling_interval_seconds', self.instance_config.default_polling_interval_seconds)) self.saved_searches_parallel = int( instance.get('saved_searches_parallel', self.instance_config.default_saved_searches_parallel)) self.last_successful_poll_epoch_seconds = None