Don't call the Keystone client if the token is None

There are certain cases the user.Token constructor is called with
the default unscoped_token value of None. When this happens using
PKI, an unexpected error occurs. If the token is None, we know it's
not pki and should not make an extra call to the Keystone client to
check.

A test is provided to demonstrate the issue, and the test fails
without the included code change.

Change-Id: Ie8e93eda4cf8e8285785335126624781470be19c
Closes-Bug: #1551977
This commit is contained in:
Brad Pokorny
2016-02-29 23:01:46 -08:00
parent 9de5d87bec
commit 75a6b9721e
3 changed files with 27 additions and 2 deletions

View File

@@ -17,6 +17,7 @@ import uuid
from django.utils import datetime_safe from django.utils import datetime_safe
from keystoneauth1.access import access from keystoneauth1.access import access
from keystoneauth1.access import service_catalog from keystoneauth1.access import service_catalog
from keystoneclient.common import cms
from keystoneclient.v3 import domains from keystoneclient.v3 import domains
from keystoneclient.v3 import projects from keystoneclient.v3 import projects
from keystoneclient.v3 import roles from keystoneclient.v3 import roles
@@ -54,7 +55,7 @@ class TestResponse(requests.Response):
return self._text return self._text
def generate_test_data(): def generate_test_data(pki=False):
'''Builds a set of test_data data as returned by Keystone V2.''' '''Builds a set of test_data data as returned by Keystone V2.'''
test_data = TestDataContainer() test_data = TestDataContainer()
@@ -177,7 +178,13 @@ def generate_test_data():
# Tokens # Tokens
tomorrow = datetime_safe.datetime.now() + datetime.timedelta(days=1) tomorrow = datetime_safe.datetime.now() + datetime.timedelta(days=1)
expiration = datetime_safe.datetime.isoformat(tomorrow) expiration = datetime_safe.datetime.isoformat(tomorrow)
auth_token = uuid.uuid4().hex if pki:
# We don't need a real PKI token, but just the prefix to make the
# keystone client treat it as a PKI token
auth_token = cms.PKI_ASN1_PREFIX + uuid.uuid4().hex
else:
auth_token = uuid.uuid4().hex
auth_response_headers = { auth_response_headers = {
'X-Subject-Token': auth_token 'X-Subject-Token': auth_token
} }

View File

@@ -29,7 +29,9 @@ from keystoneclient.v2_0 import client as client_v2
from keystoneclient.v3 import client as client_v3 from keystoneclient.v3 import client as client_v3
import mock import mock
from mox3 import mox from mox3 import mox
import sys
from testscenarios import load_tests_apply_scenarios # noqa from testscenarios import load_tests_apply_scenarios # noqa
import unittest
from openstack_auth import policy from openstack_auth import policy
from openstack_auth.tests import data_v2 from openstack_auth.tests import data_v2
@@ -1156,3 +1158,17 @@ class UtilsTestCase(test.TestCase):
] ]
for src, expected in test_urls: for src, expected in test_urls:
self.assertEqual(expected, utils.fix_auth_url_version(src)) self.assertEqual(expected, utils.fix_auth_url_version(src))
class UserTestCase(test.TestCase):
def setUp(self):
self.data = data_v3.generate_test_data(pki=True)
@unittest.skipIf(sys.version_info >= (3, 0), "Bug #1552443")
def test_unscoped_token_is_none(self):
created_token = user.Token(self.data.domain_scoped_access_info,
unscoped_token=None)
self.assertTrue(created_token._is_pki_token(
self.data.domain_scoped_access_info.auth_token))
self.assertFalse(created_token._is_pki_token(None))

View File

@@ -117,6 +117,8 @@ class Token(object):
def _is_pki_token(self, token): def _is_pki_token(self, token):
"""Determines if this is a pki-based token (pki or pkiz)""" """Determines if this is a pki-based token (pki or pkiz)"""
if token is None:
return False
return (keystone_cms.is_ans1_token(token) return (keystone_cms.is_ans1_token(token)
or keystone_cms.is_pkiz(token)) or keystone_cms.is_pkiz(token))