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
This commit is contained in:
@@ -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 = {
|
||||
|
@@ -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)
|
||||
|
@@ -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()
|
||||
|
||||
|
@@ -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):
|
||||
|
Reference in New Issue
Block a user