summaryrefslogtreecommitdiff
path: root/keystoneclient
diff options
context:
space:
mode:
authorJamie Lennox <jamielennox@redhat.com>2013-11-22 11:14:49 +1000
committerJamie Lennox <jamielennox@redhat.com>2013-12-20 14:02:48 +1000
commit35aed518a9a8c0049512910219ca6fea4f35f2b8 (patch)
tree93c0583b976d2f5ec0c47eb4d65dc2fb48cc04e5 /keystoneclient
parent6ad5f2f4cc99b4d76cf0839cad09f9f8912d0542 (diff)
downloadpython-keystoneclient-35aed518a9a8c0049512910219ca6fea4f35f2b8.tar.gz
Correctly handle auth_url/token authentication
Previously the client assumed that if a user passed a token then this token should be used for everything. This assumption is correct for the endpoint/token case but not in the auth_url/token case where you will want to fetch a new token. This is needed in the case where you want to use an existing token to fetch a token that is re-scoped or activate a trust. There are still problems such as if you use auth_url/token authentication then when the token expires it will try to refresh it, but authenticating with a token will not extend the token expiry. Closes-Bug: #1257541 Change-Id: I1c35600ca5437da44071dcea5361bfb42f6b72a3
Diffstat (limited to 'keystoneclient')
-rw-r--r--keystoneclient/httpclient.py19
-rw-r--r--keystoneclient/tests/v2_0/test_auth.py64
-rw-r--r--keystoneclient/tests/v2_0/utils.py4
-rw-r--r--keystoneclient/tests/v3/test_auth.py64
-rw-r--r--keystoneclient/tests/v3/utils.py4
5 files changed, 148 insertions, 7 deletions
diff --git a/keystoneclient/httpclient.py b/keystoneclient/httpclient.py
index a0dcf24..9f901cd 100644
--- a/keystoneclient/httpclient.py
+++ b/keystoneclient/httpclient.py
@@ -161,7 +161,7 @@ class HTTPClient(object):
self.project_domain_id = self.auth_ref.project_domain_id
self.auth_url = self.auth_ref.auth_url[0]
self._management_url = self.auth_ref.management_url[0]
- self.auth_token = self.auth_ref.auth_token
+ self.auth_token_from_user = self.auth_ref.auth_token
self.trust_id = self.auth_ref.trust_id
if self.auth_ref.has_service_catalog():
self.region_name = self.auth_ref.service_catalog.region_name
@@ -223,6 +223,7 @@ class HTTPClient(object):
self._endpoint = endpoint.rstrip('/')
if region_name:
self.region_name = region_name
+ self._auth_token = None
if not session:
verify = cacert or True
@@ -265,20 +266,28 @@ class HTTPClient(object):
@property
def auth_token(self):
- if self.auth_token_from_user:
- return self.auth_token_from_user
+ if self._auth_token:
+ return self._auth_token
if self.auth_ref:
if self.auth_ref.will_expire_soon(self.stale_duration):
self.authenticate()
return self.auth_ref.auth_token
+ if self.auth_token_from_user:
+ return self.auth_token_from_user
@auth_token.setter
def auth_token(self, value):
- self.auth_token_from_user = value
+ """Override the auth_token.
+
+ If an application sets auth_token explicitly then it will always be
+ used and override any past or future retrieved token.
+ """
+ self._auth_token = value
@auth_token.deleter
def auth_token(self):
- del self.auth_token_from_user
+ self._auth_token = None
+ self.auth_token_from_user = None
@property
def service_catalog(self):
diff --git a/keystoneclient/tests/v2_0/test_auth.py b/keystoneclient/tests/v2_0/test_auth.py
index 94333ea..98a3380 100644
--- a/keystoneclient/tests/v2_0/test_auth.py
+++ b/keystoneclient/tests/v2_0/test_auth.py
@@ -18,6 +18,7 @@ import json
import httpretty
from keystoneclient import exceptions
+from keystoneclient.openstack.common import jsonutils
from keystoneclient.openstack.common import timeutils
from keystoneclient.tests.v2_0 import utils
from keystoneclient.v2_0 import client
@@ -158,6 +159,27 @@ class AuthenticateAgainstKeystoneTests(utils.TestCase):
self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY)
@httpretty.activate
+ def test_auth_url_token_authentication(self):
+ fake_token = 'fake_token'
+ fake_url = '/fake-url'
+ fake_resp = {'result': True}
+
+ self.stub_auth(json=self.TEST_RESPONSE_DICT)
+ self.stub_url('GET', [fake_url], json=fake_resp,
+ base_url=self.TEST_ADMIN_IDENTITY_ENDPOINT)
+
+ cl = client.Client(auth_url=self.TEST_URL,
+ token=fake_token)
+ body = jsonutils.loads(httpretty.last_request().body)
+ self.assertEqual(body['auth']['token']['id'], fake_token)
+
+ resp, body = cl.get(fake_url)
+ self.assertEqual(fake_resp, body)
+
+ self.assertEqual(httpretty.last_request().headers.get('X-Auth-Token'),
+ self.TEST_TOKEN)
+
+ @httpretty.activate
def test_authenticate_success_token_scoped(self):
del self.TEST_REQUEST_BODY['auth']['passwordCredentials']
self.TEST_REQUEST_BODY['auth']['token'] = {'id': self.TEST_TOKEN}
@@ -206,3 +228,45 @@ class AuthenticateAgainstKeystoneTests(utils.TestCase):
self.TEST_RESPONSE_DICT["access"]["token"]["id"])
self.assertFalse('serviceCatalog' in cs.service_catalog.catalog)
self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY)
+
+ @httpretty.activate
+ def test_allow_override_of_auth_token(self):
+ fake_url = '/fake-url'
+ fake_token = 'fake_token'
+ fake_resp = {'result': True}
+
+ self.stub_auth(json=self.TEST_RESPONSE_DICT)
+ self.stub_url('GET', [fake_url], json=fake_resp,
+ base_url=self.TEST_ADMIN_IDENTITY_ENDPOINT)
+
+ cl = client.Client(username='exampleuser',
+ password='password',
+ tenant_name='exampleproject',
+ auth_url=self.TEST_URL)
+
+ self.assertEqual(cl.auth_token, self.TEST_TOKEN)
+
+ # the token returned from the authentication will be used
+ resp, body = cl.get(fake_url)
+ self.assertEqual(fake_resp, body)
+
+ self.assertEqual(httpretty.last_request().headers.get('X-Auth-Token'),
+ self.TEST_TOKEN)
+
+ # then override that token and the new token shall be used
+ cl.auth_token = fake_token
+
+ resp, body = cl.get(fake_url)
+ self.assertEqual(fake_resp, body)
+
+ self.assertEqual(httpretty.last_request().headers.get('X-Auth-Token'),
+ fake_token)
+
+ # if we clear that overriden token then we fall back to the original
+ del cl.auth_token
+
+ resp, body = cl.get(fake_url)
+ self.assertEqual(fake_resp, body)
+
+ self.assertEqual(httpretty.last_request().headers.get('X-Auth-Token'),
+ self.TEST_TOKEN)
diff --git a/keystoneclient/tests/v2_0/utils.py b/keystoneclient/tests/v2_0/utils.py
index 6716527..238543f 100644
--- a/keystoneclient/tests/v2_0/utils.py
+++ b/keystoneclient/tests/v2_0/utils.py
@@ -31,6 +31,8 @@ class UnauthenticatedTestCase(utils.TestCase):
class TestCase(UnauthenticatedTestCase):
+ TEST_ADMIN_IDENTITY_ENDPOINT = "http://127.0.0.1:35357/v2.0"
+
TEST_SERVICE_CATALOG = [{
"endpoints": [{
"adminURL": "http://cdn.admin-nets.local:8774/v1.0",
@@ -60,7 +62,7 @@ class TestCase(UnauthenticatedTestCase):
"name": "glance"
}, {
"endpoints": [{
- "adminURL": "http://127.0.0.1:35357/v2.0",
+ "adminURL": TEST_ADMIN_IDENTITY_ENDPOINT,
"region": "RegionOne",
"internalURL": "http://127.0.0.1:5000/v2.0",
"publicURL": "http://127.0.0.1:5000/v2.0"
diff --git a/keystoneclient/tests/v3/test_auth.py b/keystoneclient/tests/v3/test_auth.py
index c7149a8..9c02970 100644
--- a/keystoneclient/tests/v3/test_auth.py
+++ b/keystoneclient/tests/v3/test_auth.py
@@ -15,6 +15,7 @@
import httpretty
from keystoneclient import exceptions
+from keystoneclient.openstack.common import jsonutils
from keystoneclient.tests.v3 import utils
from keystoneclient.v3 import client
@@ -225,6 +226,27 @@ class AuthenticateAgainstKeystoneTests(utils.TestCase):
self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY)
@httpretty.activate
+ def test_auth_url_token_authentication(self):
+ fake_token = 'fake_token'
+ fake_url = '/fake-url'
+ fake_resp = {'result': True}
+
+ self.stub_auth(json=self.TEST_RESPONSE_DICT)
+ self.stub_url('GET', [fake_url], json=fake_resp,
+ base_url=self.TEST_ADMIN_IDENTITY_ENDPOINT)
+
+ cl = client.Client(auth_url=self.TEST_URL,
+ token=fake_token)
+ body = jsonutils.loads(httpretty.last_request().body)
+ self.assertEqual(body['auth']['identity']['token']['id'], fake_token)
+
+ resp, body = cl.get(fake_url)
+ self.assertEqual(fake_resp, body)
+
+ self.assertEqual(httpretty.last_request().headers.get('X-Auth-Token'),
+ self.TEST_TOKEN)
+
+ @httpretty.activate
def test_authenticate_success_token_domain_scoped(self):
ident = self.TEST_REQUEST_BODY['auth']['identity']
del ident['password']
@@ -301,3 +323,45 @@ class AuthenticateAgainstKeystoneTests(utils.TestCase):
self.TEST_RESPONSE_HEADERS["X-Subject-Token"])
self.assertFalse('catalog' in cs.service_catalog.catalog)
self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY)
+
+ @httpretty.activate
+ def test_allow_override_of_auth_token(self):
+ fake_url = '/fake-url'
+ fake_token = 'fake_token'
+ fake_resp = {'result': True}
+
+ self.stub_auth(json=self.TEST_RESPONSE_DICT)
+ self.stub_url('GET', [fake_url], json=fake_resp,
+ base_url=self.TEST_ADMIN_IDENTITY_ENDPOINT)
+
+ cl = client.Client(username='exampleuser',
+ password='password',
+ tenant_name='exampleproject',
+ auth_url=self.TEST_URL)
+
+ self.assertEqual(cl.auth_token, self.TEST_TOKEN)
+
+ # the token returned from the authentication will be used
+ resp, body = cl.get(fake_url)
+ self.assertEqual(fake_resp, body)
+
+ self.assertEqual(httpretty.last_request().headers.get('X-Auth-Token'),
+ self.TEST_TOKEN)
+
+ # then override that token and the new token shall be used
+ cl.auth_token = fake_token
+
+ resp, body = cl.get(fake_url)
+ self.assertEqual(fake_resp, body)
+
+ self.assertEqual(httpretty.last_request().headers.get('X-Auth-Token'),
+ fake_token)
+
+ # if we clear that overriden token then we fall back to the original
+ del cl.auth_token
+
+ resp, body = cl.get(fake_url)
+ self.assertEqual(fake_resp, body)
+
+ self.assertEqual(httpretty.last_request().headers.get('X-Auth-Token'),
+ self.TEST_TOKEN)
diff --git a/keystoneclient/tests/v3/utils.py b/keystoneclient/tests/v3/utils.py
index 182e947..2965860 100644
--- a/keystoneclient/tests/v3/utils.py
+++ b/keystoneclient/tests/v3/utils.py
@@ -49,6 +49,8 @@ class UnauthenticatedTestCase(utils.TestCase):
class TestCase(UnauthenticatedTestCase):
+ TEST_ADMIN_IDENTITY_ENDPOINT = "http://127.0.0.1:35357/v3"
+
TEST_SERVICE_CATALOG = [{
"endpoints": [{
"url": "http://cdn.admin-nets.local:8774/v1.0/",
@@ -105,7 +107,7 @@ class TestCase(UnauthenticatedTestCase):
"region": "RegionOne",
"interface": "internal"
}, {
- "url": "http://127.0.0.1:35357/v3",
+ "url": TEST_ADMIN_IDENTITY_ENDPOINT,
"region": "RegionOne",
"interface": "admin"
}],