diff options
| author | Jamie Lennox <jamielennox@redhat.com> | 2013-11-22 11:14:49 +1000 |
|---|---|---|
| committer | Jamie Lennox <jamielennox@redhat.com> | 2013-12-20 14:02:48 +1000 |
| commit | 35aed518a9a8c0049512910219ca6fea4f35f2b8 (patch) | |
| tree | 93c0583b976d2f5ec0c47eb4d65dc2fb48cc04e5 /keystoneclient | |
| parent | 6ad5f2f4cc99b4d76cf0839cad09f9f8912d0542 (diff) | |
| download | python-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.py | 19 | ||||
| -rw-r--r-- | keystoneclient/tests/v2_0/test_auth.py | 64 | ||||
| -rw-r--r-- | keystoneclient/tests/v2_0/utils.py | 4 | ||||
| -rw-r--r-- | keystoneclient/tests/v3/test_auth.py | 64 | ||||
| -rw-r--r-- | keystoneclient/tests/v3/utils.py | 4 |
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" }], |
