summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Young <ayoung@redhat.com>2014-07-11 20:20:50 -0500
committerayoung <ayoung@redhat.com>2014-09-23 13:47:35 +0000
commita82d4a69219036781a276da4523bbbc242d7a50f (patch)
tree96412425ecc5a95fa222cb2e1756dc473f023a69
parent79d1eec35aad874a7c08ff22c39260884a5524ba (diff)
downloadpython-keystoneclient-a82d4a69219036781a276da4523bbbc242d7a50f.tar.gz
Enumerate Projects with Unscoped Tokens
Creating a client with a session using an Unscoped tokens now sets auth info in client. This Auth Info is necessary in order to enumerate projects. This is the standard login path for Horizon. Change-Id: I688a27cd0e7c98e7cf899ac65bb593a85171813f
-rw-r--r--keystoneclient/base.py30
-rw-r--r--keystoneclient/tests/auth/test_identity_v3.py55
-rw-r--r--keystoneclient/v3/projects.py1
3 files changed, 75 insertions, 11 deletions
diff --git a/keystoneclient/base.py b/keystoneclient/base.py
index f94c16b..a0618f9 100644
--- a/keystoneclient/base.py
+++ b/keystoneclient/base.py
@@ -25,6 +25,7 @@ import functools
import six
from six.moves import urllib
+from keystoneclient import auth
from keystoneclient import exceptions
from keystoneclient.openstack.common.apiclient import base
@@ -337,19 +338,26 @@ class CrudManager(Manager):
return self._head(self.build_url(dict_args_in_out=kwargs))
@filter_kwargs
- def list(self, **kwargs):
+ def list(self, fallback_to_auth=False, **kwargs):
url = self.build_url(dict_args_in_out=kwargs)
- if kwargs:
- query = '?%s' % urllib.parse.urlencode(kwargs)
- else:
- query = ''
- return self._list(
- '%(url)s%(query)s' % {
- 'url': url,
- 'query': query,
- },
- self.collection_key)
+ try:
+ if kwargs:
+ query = '?%s' % urllib.parse.urlencode(kwargs)
+ else:
+ query = ''
+ url_query = '%(url)s%(query)s' % {'url': url, 'query': query}
+ return self._list(
+ url_query,
+ self.collection_key)
+ except exceptions.EmptyCatalog:
+ if fallback_to_auth:
+ return self._list(
+ url_query,
+ self.collection_key,
+ endpoint_filter={'interface': auth.AUTH_INTERFACE})
+ else:
+ raise
@filter_kwargs
def put(self, **kwargs):
diff --git a/keystoneclient/tests/auth/test_identity_v3.py b/keystoneclient/tests/auth/test_identity_v3.py
index ecdc38a..bce4fa7 100644
--- a/keystoneclient/tests/auth/test_identity_v3.py
+++ b/keystoneclient/tests/auth/test_identity_v3.py
@@ -15,7 +15,9 @@ import uuid
from keystoneclient import access
from keystoneclient.auth.identity import v3
+from keystoneclient import client
from keystoneclient import exceptions
+from keystoneclient import fixture
from keystoneclient import session
from keystoneclient.tests import utils
@@ -110,6 +112,11 @@ class V3IdentityPlugin(utils.TestCase):
def setUp(self):
super(V3IdentityPlugin, self).setUp()
+
+ V3_URL = "%sv3" % self.TEST_URL
+ self.TEST_DISCOVERY_RESPONSE = {
+ 'versions': {'values': [fixture.V3Discovery(V3_URL)]}}
+
self.TEST_RESPONSE_DICT = {
"token": {
"methods": [
@@ -138,6 +145,31 @@ class V3IdentityPlugin(utils.TestCase):
"catalog": self.TEST_SERVICE_CATALOG
},
}
+ self.TEST_PROJECTS_RESPONSE = {
+ "projects": [
+ {
+ "domain_id": "1789d1",
+ "enabled": "True",
+ "id": "263fd9",
+ "links": {
+ "self": "https://identity:5000/v3/projects/263fd9"
+ },
+ "name": "Dev Group A"
+ },
+ {
+ "domain_id": "1789d1",
+ "enabled": "True",
+ "id": "e56ad3",
+ "links": {
+ "self": "https://identity:5000/v3/projects/e56ad3"
+ },
+ "name": "Dev Group B"
+ }
+ ],
+ "links": {
+ "self": "https://identity:5000/v3/projects",
+ }
+ }
def stub_auth(self, subject_token=None, **kwargs):
if not subject_token:
@@ -165,6 +197,29 @@ class V3IdentityPlugin(utils.TestCase):
self.assertRequestHeaderEqual('Accept', 'application/json')
self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN)
+ def test_authenticate_with_username_password_unscoped(self):
+ del self.TEST_RESPONSE_DICT['token']['catalog']
+ del self.TEST_RESPONSE_DICT['token']['project']
+
+ self.stub_auth(json=self.TEST_RESPONSE_DICT)
+ self.stub_url(method="GET", json=self.TEST_DISCOVERY_RESPONSE)
+ test_user_id = self.TEST_RESPONSE_DICT['token']['user']['id']
+ self.stub_url(method="GET",
+ json=self.TEST_PROJECTS_RESPONSE,
+ parts=['users', test_user_id, 'projects'])
+
+ a = v3.Password(self.TEST_URL,
+ username=self.TEST_USER,
+ password=self.TEST_PASS)
+ s = session.Session(auth=a)
+ cs = client.Client(session=s, auth_url=self.TEST_URL)
+
+ # As a sanity check on the auth_ref, make sure client has the
+ # proper user id, that it fetches the right project response
+ self.assertEqual(test_user_id, a.auth_ref.user_id)
+ t = cs.projects.list(user=a.auth_ref.user_id)
+ self.assertEqual(2, len(t))
+
def test_authenticate_with_username_password_domain_scoped(self):
self.stub_auth(json=self.TEST_RESPONSE_DICT)
a = v3.Password(self.TEST_URL, username=self.TEST_USER,
diff --git a/keystoneclient/v3/projects.py b/keystoneclient/v3/projects.py
index ffc9f32..2fcd249 100644
--- a/keystoneclient/v3/projects.py
+++ b/keystoneclient/v3/projects.py
@@ -76,6 +76,7 @@ class ProjectManager(base.CrudManager):
return super(ProjectManager, self).list(
base_url=base_url,
domain_id=base.getid(domain),
+ fallback_to_auth=True,
**kwargs)
def get(self, project):