From 08fd95de147675ad84d55bc53c142954f92d25da Mon Sep 17 00:00:00 2001 From: Brant Knudson Date: Mon, 15 Dec 2014 17:57:25 -0600 Subject: [PATCH] Add validate token for v2.0 There was no API to validate a token using v2.0. bp auth-token-use-client Change-Id: I22223f546e750457a0c9d851ef389f7983e5c205 --- keystoneclient/tests/v2_0/test_tokens.py | 39 ++++++++++++++++++++++++ keystoneclient/v2_0/tokens.py | 32 +++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/keystoneclient/tests/v2_0/test_tokens.py b/keystoneclient/tests/v2_0/test_tokens.py index 335127390..f1a3b3493 100644 --- a/keystoneclient/tests/v2_0/test_tokens.py +++ b/keystoneclient/tests/v2_0/test_tokens.py @@ -12,6 +12,8 @@ import uuid +from keystoneclient import access +from keystoneclient import exceptions from keystoneclient import fixture from keystoneclient.tests.v2_0 import utils from keystoneclient.v2_0 import client @@ -161,6 +163,43 @@ class TokenTests(utils.TestCase): self.assertEqual(token_fixture.token_id, token_ref.id) self.assertEqual(token_fixture.expires_str, token_ref.expires) + def test_validate_token(self): + id_ = uuid.uuid4().hex + token_fixture = fixture.V2Token(token_id=id_) + self.stub_url('GET', ['tokens', id_], json=token_fixture) + + token_ref = self.client.tokens.validate(id_) + self.assertIsInstance(token_ref, tokens.Token) + self.assertEqual(id_, token_ref.id) + + def test_validate_token_invalid_token(self): + # If the token is invalid, typically a NotFound is raised. + + id_ = uuid.uuid4().hex + # The server is expected to return 404 if the token is invalid. + self.stub_url('GET', ['tokens', id_], status_code=404) + self.assertRaises(exceptions.NotFound, + self.client.tokens.validate, id_) + + def test_validate_token_access_info_with_token_id(self): + # Can validate a token passing a string token ID. + token_id = uuid.uuid4().hex + token_fixture = fixture.V2Token(token_id=token_id) + self.stub_url('GET', ['tokens', token_id], json=token_fixture) + access_info = self.client.tokens.validate_access_info(token_id) + self.assertIsInstance(access_info, access.AccessInfoV2) + self.assertEqual(token_id, access_info.auth_token) + + def test_validate_token_access_info_with_access_info(self): + # Can validate a token passing an access info. + token_id = uuid.uuid4().hex + token_fixture = fixture.V2Token(token_id=token_id) + self.stub_url('GET', ['tokens', token_id], json=token_fixture) + token = access.AccessInfo.factory(body=token_fixture) + access_info = self.client.tokens.validate_access_info(token) + self.assertIsInstance(access_info, access.AccessInfoV2) + self.assertEqual(token_id, access_info.auth_token) + def test_get_revoked(self): sample_revoked_response = {'signed': '-----BEGIN CMS-----\nMIIB...'} self.stub_url('GET', ['tokens', 'revoked'], diff --git a/keystoneclient/v2_0/tokens.py b/keystoneclient/v2_0/tokens.py index ed1c07e33..670d65b1c 100644 --- a/keystoneclient/v2_0/tokens.py +++ b/keystoneclient/v2_0/tokens.py @@ -10,6 +10,7 @@ # License for the specific language governing permissions and limitations # under the License. +from keystoneclient import access from keystoneclient import auth from keystoneclient import base from keystoneclient import exceptions @@ -73,6 +74,37 @@ class TokenManager(base.Manager): def endpoints(self, token): return self._get("/tokens/%s/endpoints" % base.getid(token), "token") + def validate(self, token): + """Validate a token. + + :param token: Token to be validated. + + :rtype: :py:class:`.Token` + + """ + return self._get('/tokens/%s' % base.getid(token), 'access') + + def validate_access_info(self, token): + """Validate a token. + + :param token: Token to be validated. This can be an instance of + :py:class:`keystoneclient.access.AccessInfo` or a string + token_id. + + :rtype: :py:class:`keystoneclient.access.AccessInfoV2` + + """ + + def calc_id(token): + if isinstance(token, access.AccessInfo): + return token.auth_token + return base.getid(token) + + url = '/tokens/%s' % calc_id(token) + resp, body = self.client.get(url) + access_info = access.AccessInfo.factory(resp=resp, body=body) + return access_info + def get_revoked(self): """Returns the revoked tokens response.