From ecfec61737eb12310aaeb9af73757f0e74da2067 Mon Sep 17 00:00:00 2001 From: Rohan Kanade Date: Tue, 8 Apr 2014 10:35:34 +0200 Subject: [PATCH] Remove use of auth_token for REST API * User username/password for each individual request * Stop using single auth_token for authorizing multiple requests. Closes-launchpad-Bug: #1302828 --- seamicroclient/client.py | 82 ++++------------------------- seamicroclient/tests/test_client.py | 9 ---- seamicroclient/tests/test_http.py | 13 +---- seamicroclient/v2/client.py | 8 +-- 4 files changed, 15 insertions(+), 97 deletions(-) diff --git a/seamicroclient/client.py b/seamicroclient/client.py index 3b25be8..99a6ee0 100644 --- a/seamicroclient/client.py +++ b/seamicroclient/client.py @@ -49,8 +49,6 @@ class HTTPClient(object): self.times = [] # [("item", starttime, endtime), ...] - self.auth_token = None - self._logger = logging.getLogger(__name__) if self.http_log_debug and not self._logger.handlers: # Logging level is already set on the root logger @@ -67,10 +65,6 @@ class HTTPClient(object): # requests within the same session can reuse TCP connections from pool self.http = requests.Session() - def unauthenticate(self): - """Forget all of our authentication information.""" - self.auth_token = None - def get_timings(self): return self.times @@ -150,39 +144,16 @@ class HTTPClient(object): return resp, body def _cs_request(self, url, method, **kwargs): - if self.auth_token: - if method in ['GET', 'DELETE']: - url = "%s?username=%s&password=%s" % (url, self.user, - self.password) - else: - kwargs.setdefault('body', {})['authtoken'] = self.auth_token + if method in ['GET', 'DELETE']: + url = "%s?username=%s&password=%s" % (url, self.user, + self.password) + else: + kwargs.setdefault('body', {}).update({'username': self.user, + 'password': self.password}) - # Perform the request once. If we get a 401 back then it - # might be because the auth token expired, so try to - # re-authenticate and try again. If it still fails, bail. - try: - - resp, body = self._time_request(self.api_endpoint + url, method, - **kwargs) - return resp, body - except (exceptions.Unauthorized, exceptions.BadRequest) as e: - try: - # first discard auth token, to avoid the possibly expired - # token being re-used in the re-authentication attempt - self.unauthenticate() - self.authenticate() - if method in ['GET', 'DELETE']: - url = "%s?username=%s&password=%s" % (url, self.user, - self.password) - else: - kwargs.setdefault( - 'body', {})['authtoken'] = self.auth_token - - resp, body = self._time_request(self.api_endpoint + url, - method, **kwargs) - return resp, body - except exceptions.Unauthorized: - raise e + resp, body = self._time_request(self.api_endpoint + url, method, + **kwargs) + return resp, body def get(self, url, **kwargs): return self._cs_request(url, 'GET', **kwargs) @@ -196,41 +167,6 @@ class HTTPClient(object): def delete(self, url, **kwargs): return self._cs_request(url, 'DELETE', **kwargs) - def authenticate(self): - auth_url = self.auth_url - if self.version == "v2.0": # FIXME(rk): This should be better. - self._v2_auth(auth_url) - - def _v2_auth(self, url): - """Authenticate against a v2.0 auth service.""" - if self.auth_token: - return - else: - body = {"username": self.user, "password": self.password} - - return self._authenticate(url, body) - - def _authenticate(self, url, body, **kwargs): - """Authenticate and extract the service catalog.""" - method = "POST" - token_url = url + "/login" - - # Make sure we follow redirects when trying to reach Keystone - resp, respbody = self._time_request( - token_url, - method, - body=body, - allow_redirects=True, - **kwargs) - - return self._extract_auth_token(url, resp, respbody) - - def _extract_auth_token(self, url, resp, body): - if resp.status_code == 200 or resp.status_code == 201: - if 'OpaqueRef' not in body: - raise exceptions.AuthorizationFailure() - self.auth_token = body - def get_client_class(version): version_map = { diff --git a/seamicroclient/tests/test_client.py b/seamicroclient/tests/test_client.py index 2b3923b..c00a3a0 100644 --- a/seamicroclient/tests/test_client.py +++ b/seamicroclient/tests/test_client.py @@ -14,8 +14,6 @@ # under the License. -import mock - import seamicroclient.client from seamicroclient.tests import utils import seamicroclient.v2.client @@ -33,10 +31,3 @@ class ClientTest(utils.TestCase): def test_get_client_class_v2(self): output = seamicroclient.client.get_client_class('2') self.assertEqual(output, seamicroclient.v2.client.Client) - - @mock.patch.object(seamicroclient.client.HTTPClient, 'authenticate') - def test_authenticate_call_v2(self, mock_authenticate): - cs = seamicroclient.v2.client.Client("user", "password", - auth_url="foo/v2") - cs.authenticate() - self.assertTrue(mock_authenticate.called) diff --git a/seamicroclient/tests/test_http.py b/seamicroclient/tests/test_http.py index 143f0aa..efde575 100644 --- a/seamicroclient/tests/test_http.py +++ b/seamicroclient/tests/test_http.py @@ -68,7 +68,8 @@ class ClientTest(utils.TestCase): 'User-Agent': 'python-seamicroclient'} mock_request.assert_called_with( "GET", - "http://example.com/hi?username=%s&password=%s" % (cl.user, cl.password), + "http://example.com/hi?username=%s&password=%s" % (cl.user, + cl.password), headers=headers) # Automatic JSON parsing self.assertEqual(body, {"hi": "there"}) @@ -93,16 +94,6 @@ class ClientTest(utils.TestCase): test_post_call() - def test_auth_failure(self): - cl = get_client() - - # response must not have x-server-management-url header - @mock.patch.object(requests.Session, "request", mock_request) - def test_auth_call(): - self.assertRaises(exceptions.AuthorizationFailure, cl.authenticate) - - test_auth_call() - def test_connection_refused(self): cl = get_client() diff --git a/seamicroclient/v2/client.py b/seamicroclient/v2/client.py index 47ab331..5652e32 100644 --- a/seamicroclient/v2/client.py +++ b/seamicroclient/v2/client.py @@ -12,17 +12,17 @@ # under the License. from seamicroclient import client -from seamicroclient.v2 import servers -from seamicroclient.v2 import pools -from seamicroclient.v2 import volumes -from seamicroclient.v2 import disks from seamicroclient.v2 import chassis +from seamicroclient.v2 import disks from seamicroclient.v2 import fantrays from seamicroclient.v2 import interfaces +from seamicroclient.v2 import pools from seamicroclient.v2 import powersupplies from seamicroclient.v2 import scards +from seamicroclient.v2 import servers from seamicroclient.v2 import smcards from seamicroclient.v2 import system +from seamicroclient.v2 import volumes class Client(object):