From f5ffb672f2752c791853cf8ae4d1a1abb6d684eb Mon Sep 17 00:00:00 2001 From: akaila-splunk Date: Fri, 1 Apr 2022 10:30:27 +0530 Subject: [PATCH 1/4] added auth token cookie check fix for issue 'splunklib expects any Set-Cookie to be an auth cookie from Splunk. This is a problem when authenticating with a bearer token.' --- splunklib/binding.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/splunklib/binding.py b/splunklib/binding.py index 6bf4f071..71c848a0 100644 --- a/splunklib/binding.py +++ b/splunklib/binding.py @@ -499,13 +499,13 @@ def get_cookies(self): return self.http._cookies def has_cookies(self): - """Returns true if the ``HttpLib`` member of this instance has at least - one cookie stored. + """Returns true if the ``HttpLib`` member of this instance has auth token stored. - :return: ``True`` if there is at least one cookie, else ``False`` + :return: ``True`` if there is auth token present, else ``False`` :rtype: ``bool`` """ - return len(self.get_cookies()) > 0 + auth_token_key = "splunkd_8089" + return auth_token_key in self.get_cookies().keys() # Shared per-context request headers @property From 09d0c0f0ffe65bdd5667689603382cd3c6c05750 Mon Sep 17 00:00:00 2001 From: akaila-splunk Date: Fri, 1 Apr 2022 10:51:09 +0530 Subject: [PATCH 2/4] Updated auth_headers checks fix for issue 'splunklib expects any Set-Cookie to be an auth cookie from Splunk. This is a problem when authenticating with a bearer token.' --- splunklib/binding.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/splunklib/binding.py b/splunklib/binding.py index 71c848a0..000955b0 100644 --- a/splunklib/binding.py +++ b/splunklib/binding.py @@ -518,23 +518,23 @@ def _auth_headers(self): :returns: A list of 2-tuples containing key and value """ - if self.has_cookies(): - return [("Cookie", _make_cookie_header(list(self.get_cookies().items())))] - elif self.basic and (self.username and self.password): - token = 'Basic %s' % b64encode(("%s:%s" % (self.username, self.password)).encode('utf-8')).decode('ascii') - return [("Authorization", token)] - elif self.bearerToken: - token = 'Bearer %s' % self.bearerToken - return [("Authorization", token)] - elif self.token is _NoAuthenticationToken: - return [] - else: - # Ensure the token is properly formatted + if self.token is not _NoAuthenticationToken: if self.token.startswith('Splunk '): token = self.token else: token = 'Splunk %s' % self.token return [("Authorization", token)] + elif self.bearerToken: + token = 'Bearer %s' % self.bearerToken + return [("Authorization", token)] + elif self.basic and (self.username and self.password): + token = 'Basic %s' % b64encode(("%s:%s" % (self.username, self.password)).encode('utf-8')).decode('ascii') + return [("Authorization", token)] + elif self.has_cookies(): + return [("Cookie", _make_cookie_header(list(self.get_cookies().items())))] + else: + # no Authentication token + return [] def connect(self): """Returns an open connection (socket) to the Splunk instance. From 0d873a704a78a3ec5f15b6b1dfe7e9f16e1ce9aa Mon Sep 17 00:00:00 2001 From: akaila-splunk Date: Fri, 1 Apr 2022 17:09:11 +0530 Subject: [PATCH 3/4] added check for auth token in cookie --- splunklib/binding.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/splunklib/binding.py b/splunklib/binding.py index 000955b0..1822b8e7 100644 --- a/splunklib/binding.py +++ b/splunklib/binding.py @@ -504,8 +504,8 @@ def has_cookies(self): :return: ``True`` if there is auth token present, else ``False`` :rtype: ``bool`` """ - auth_token_key = "splunkd_8089" - return auth_token_key in self.get_cookies().keys() + auth_token_key = "splunkd_" + return any(auth_token_key in key for key in self.get_cookies().keys()) # Shared per-context request headers @property From 368f9365341a8429ff9040aba578b46ef2206c0c Mon Sep 17 00:00:00 2001 From: Abhi Shah Date: Fri, 22 Apr 2022 10:37:51 +0530 Subject: [PATCH 4/4] test case refactoring for code change --- splunklib/binding.py | 24 ++++++++++++------------ tests/test_binding.py | 13 ++++++------- tests/test_service.py | 10 ++++------ 3 files changed, 22 insertions(+), 25 deletions(-) diff --git a/splunklib/binding.py b/splunklib/binding.py index 1822b8e7..c6140060 100644 --- a/splunklib/binding.py +++ b/splunklib/binding.py @@ -518,23 +518,23 @@ def _auth_headers(self): :returns: A list of 2-tuples containing key and value """ - if self.token is not _NoAuthenticationToken: - if self.token.startswith('Splunk '): - token = self.token - else: - token = 'Splunk %s' % self.token + if self.has_cookies(): + return [("Cookie", _make_cookie_header(list(self.get_cookies().items())))] + elif self.basic and (self.username and self.password): + token = 'Basic %s' % b64encode(("%s:%s" % (self.username, self.password)).encode('utf-8')).decode('ascii') return [("Authorization", token)] elif self.bearerToken: token = 'Bearer %s' % self.bearerToken return [("Authorization", token)] - elif self.basic and (self.username and self.password): - token = 'Basic %s' % b64encode(("%s:%s" % (self.username, self.password)).encode('utf-8')).decode('ascii') - return [("Authorization", token)] - elif self.has_cookies(): - return [("Cookie", _make_cookie_header(list(self.get_cookies().items())))] - else: - # no Authentication token + elif self.token is _NoAuthenticationToken: return [] + else: + # Ensure the token is properly formatted + if self.token.startswith('Splunk '): + token = self.token + else: + token = 'Splunk %s' % self.token + return [("Authorization", token)] def connect(self): """Returns an open connection (socket) to the Splunk instance. diff --git a/tests/test_binding.py b/tests/test_binding.py index 3bce0de1..c101b19c 100755 --- a/tests/test_binding.py +++ b/tests/test_binding.py @@ -586,23 +586,22 @@ def test_got_updated_cookie_with_get(self): self.assertTrue(found) def test_login_fails_with_bad_cookie(self): - new_context = binding.connect(**{"cookie": "bad=cookie"}) # We should get an error if using a bad cookie try: - new_context.get("apps/local") + new_context = binding.connect(**{"cookie": "bad=cookie"}) self.fail() except AuthenticationError as ae: - self.assertEqual(str(ae), "Request failed: Session is not logged in.") + self.assertEqual(str(ae), "Login failed.") def test_login_with_multiple_cookies(self): - bad_cookie = 'bad=cookie' - new_context = binding.connect(**{"cookie": bad_cookie}) # We should get an error if using a bad cookie + new_context = binding.Context() + new_context.get_cookies().update({"bad": "cookie"}) try: - new_context.get("apps/local") + new_context = new_context.login() self.fail() except AuthenticationError as ae: - self.assertEqual(str(ae), "Request failed: Session is not logged in.") + self.assertEqual(str(ae), "Login failed.") # Bring in a valid cookie now for key, value in self.context.get_cookies().items(): new_context.get_cookies()[key] = value diff --git a/tests/test_service.py b/tests/test_service.py index 127ce75f..81405883 100755 --- a/tests/test_service.py +++ b/tests/test_service.py @@ -214,15 +214,14 @@ def test_login_fails_with_bad_cookie(self): service2 = client.Service() self.assertEqual(len(service2.get_cookies()), 0) service2.get_cookies().update(bad_cookie) - service2.login() self.assertEqual(service2.get_cookies(), {'bad': 'cookie'}) # Should get an error with a bad cookie try: - service2.apps.get() + service2.login() self.fail() except AuthenticationError as ae: - self.assertEqual(str(ae), "Request failed: Session is not logged in.") + self.assertEqual(str(ae), "Login failed.") def test_autologin_with_cookie(self): self.service.login() @@ -264,14 +263,13 @@ def test_login_with_multiple_cookies(self): self.assertIsNotNone(self.service.get_cookies()) service2 = client.Service(**{"cookie": bad_cookie}) - service2.login() # Should get an error with a bad cookie try: - service2.apps.get() + service2.login() self.fail() except AuthenticationError as ae: - self.assertEqual(str(ae), "Request failed: Session is not logged in.") + self.assertEqual(str(ae), "Login failed.") # Add on valid cookies, and try to use all of them service2.get_cookies().update(self.service.get_cookies())