Merge "Correctly determine keystone v3 endpoint"
This commit is contained in:
commit
27525fb0e4
@ -14,6 +14,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from keystoneclient import discover as ks_discover
|
||||
from oslo_config import cfg
|
||||
from oslo_utils import importutils
|
||||
from webob import exc
|
||||
@ -33,10 +34,18 @@ class AuthUrlFilter(wsgi.Middleware):
|
||||
if 'auth_uri' in self.conf:
|
||||
return self.conf['auth_uri']
|
||||
else:
|
||||
# Import auth_token to have keystone_authtoken settings setup.
|
||||
auth_token_module = 'keystonemiddleware.auth_token'
|
||||
importutils.import_module(auth_token_module)
|
||||
return cfg.CONF.keystone_authtoken.auth_uri
|
||||
# Look for the keystone auth_uri in the configuration. First we
|
||||
# check the [clients_keystone] section, and if it is not set we
|
||||
# look in [keystone_authtoken]
|
||||
if cfg.CONF.clients_keystone.auth_uri:
|
||||
discover = ks_discover.Discover(
|
||||
auth_url=cfg.CONF.clients_keystone.auth_uri)
|
||||
return discover.url_for('3.0')
|
||||
else:
|
||||
# Import auth_token to have keystone_authtoken settings setup.
|
||||
auth_token_module = 'keystonemiddleware.auth_token'
|
||||
importutils.import_module(auth_token_module)
|
||||
return cfg.CONF.keystone_authtoken.auth_uri
|
||||
|
||||
def _validate_auth_url(self, auth_url):
|
||||
"""Validate auth_url to ensure it can be used."""
|
||||
|
@ -287,6 +287,12 @@ heat_client_opts = [
|
||||
help=_('Optional heat url in format like'
|
||||
' http://0.0.0.0:8004/v1/%(tenant_id)s.'))]
|
||||
|
||||
keystone_client_opts = [
|
||||
cfg.StrOpt('auth_uri',
|
||||
default='',
|
||||
help=_('Unversioned keystone url in format like'
|
||||
' http://0.0.0.0:5000.'))]
|
||||
|
||||
client_http_log_debug_opts = [
|
||||
cfg.BoolOpt('http_log_debug',
|
||||
default=False,
|
||||
@ -344,6 +350,7 @@ def list_opts():
|
||||
yield client_specific_group, clients_opts
|
||||
|
||||
yield 'clients_heat', heat_client_opts
|
||||
yield 'clients_keystone', keystone_client_opts
|
||||
yield 'clients_nova', client_http_log_debug_opts
|
||||
yield 'clients_cinder', client_http_log_debug_opts
|
||||
|
||||
|
@ -15,6 +15,7 @@ from keystoneclient import access
|
||||
from keystoneclient.auth.identity import access as access_plugin
|
||||
from keystoneclient.auth.identity import v3
|
||||
from keystoneclient.auth import token_endpoint
|
||||
from keystoneclient import discover as ks_discover
|
||||
from oslo_config import cfg
|
||||
from oslo_context import context
|
||||
from oslo_log import log as logging
|
||||
@ -121,14 +122,29 @@ class RequestContext(context.RequestContext):
|
||||
return cls(**values)
|
||||
|
||||
@property
|
||||
def _keystone_v3_endpoint(self):
|
||||
def keystone_v3_endpoint(self):
|
||||
if self.auth_url:
|
||||
auth_uri = self.auth_url
|
||||
auth_uri = self.auth_url.replace('v2.0', 'v3')
|
||||
else:
|
||||
importutils.import_module('keystonemiddleware.auth_token')
|
||||
auth_uri = cfg.CONF.keystone_authtoken.auth_uri
|
||||
|
||||
return auth_uri.replace('v2.0', 'v3')
|
||||
# Look for the keystone auth_uri in the configuration. First we
|
||||
# check the [clients_keystone] section, and if it is not set we
|
||||
# look in [keystone_authtoken]
|
||||
if cfg.CONF.clients_keystone.auth_uri:
|
||||
discover = ks_discover.Discover(
|
||||
auth_url=cfg.CONF.clients_keystone.auth_uri)
|
||||
auth_uri = discover.url_for('3.0')
|
||||
else:
|
||||
# Import auth_token to have keystone_authtoken settings setup.
|
||||
importutils.import_module('keystonemiddleware.auth_token')
|
||||
if cfg.CONF.keystone_authtoken.auth_uri:
|
||||
auth_uri = cfg.CONF.keystone_authtoken.auth_uri.replace(
|
||||
'v2.0', 'v3')
|
||||
else:
|
||||
LOG.error('Keystone API endpoint not provided. Set '
|
||||
'auth_uri in section [clients_keystone] '
|
||||
'of the configuration file.')
|
||||
raise exception.AuthorizationFailure()
|
||||
return auth_uri
|
||||
|
||||
def _create_auth_plugin(self):
|
||||
if self.trust_id:
|
||||
@ -139,14 +155,14 @@ class RequestContext(context.RequestContext):
|
||||
return v3.Password(username=username,
|
||||
password=password,
|
||||
user_domain_id='default',
|
||||
auth_url=self._keystone_v3_endpoint,
|
||||
auth_url=self.keystone_v3_endpoint,
|
||||
trust_id=self.trust_id)
|
||||
|
||||
if self.auth_token_info:
|
||||
auth_ref = access.AccessInfo.factory(body=self.auth_token_info,
|
||||
auth_token=self.auth_token)
|
||||
return access_plugin.AccessInfoPlugin(
|
||||
auth_url=self._keystone_v3_endpoint,
|
||||
auth_url=self.keystone_v3_endpoint,
|
||||
auth_ref=auth_ref)
|
||||
|
||||
if self.auth_token:
|
||||
@ -154,7 +170,7 @@ class RequestContext(context.RequestContext):
|
||||
# only have a token but don't load a service catalog then
|
||||
# url_for wont work. Stub with the keystone endpoint so at
|
||||
# least it might be right.
|
||||
return token_endpoint.Token(endpoint=self._keystone_v3_endpoint,
|
||||
return token_endpoint.Token(endpoint=self.keystone_v3_endpoint,
|
||||
token=self.auth_token)
|
||||
|
||||
if self.password:
|
||||
@ -162,7 +178,7 @@ class RequestContext(context.RequestContext):
|
||||
password=self.password,
|
||||
project_id=self.tenant_id,
|
||||
user_domain_id='default',
|
||||
auth_url=self._keystone_v3_endpoint)
|
||||
auth_url=self.keystone_v3_endpoint)
|
||||
|
||||
LOG.error(_LE("Keystone v3 API connection failed, no password "
|
||||
"trust or auth_token!"))
|
||||
|
@ -76,14 +76,7 @@ class KeystoneClientV3(object):
|
||||
self._domain_admin_client = None
|
||||
|
||||
self.session = session.Session.construct(self._ssl_options())
|
||||
|
||||
if self.context.auth_url:
|
||||
self.v3_endpoint = self.context.auth_url.replace('v2.0', 'v3')
|
||||
else:
|
||||
# Import auth_token to have keystone_authtoken settings setup.
|
||||
importutils.import_module('keystonemiddleware.auth_token')
|
||||
self.v3_endpoint = cfg.CONF.keystone_authtoken.auth_uri.replace(
|
||||
'v2.0', 'v3')
|
||||
self.v3_endpoint = self.context.keystone_v3_endpoint
|
||||
|
||||
if self.context.trust_id:
|
||||
# Create a client with the specified trust_id, this
|
||||
|
@ -41,9 +41,27 @@ class AuthUrlFilterTest(common.HeatTestCase):
|
||||
self.config = {'auth_uri': 'foobar'}
|
||||
self.middleware = auth_url.AuthUrlFilter(self.app, self.config)
|
||||
|
||||
@mock.patch.object(auth_url.cfg, 'CONF')
|
||||
def test_adds_default_auth_url_from_clients_keystone(self, mock_cfg):
|
||||
self.config = {}
|
||||
mock_cfg.clients_keystone.auth_uri = 'foobar'
|
||||
mock_cfg.keystone_authtoken.auth_uri = 'this-should-be-ignored'
|
||||
mock_cfg.auth_password.multi_cloud = False
|
||||
with mock.patch('keystoneclient.discover.Discover') as discover:
|
||||
class MockDiscover(object):
|
||||
def url_for(self, endpoint):
|
||||
return 'foobar/v3'
|
||||
discover.return_value = MockDiscover()
|
||||
self.middleware = auth_url.AuthUrlFilter(self.app, self.config)
|
||||
req = webob.Request.blank('/tenant_id/')
|
||||
self.middleware(req)
|
||||
self.assertIn('X-Auth-Url', req.headers)
|
||||
self.assertEqual('foobar/v3', req.headers['X-Auth-Url'])
|
||||
|
||||
@mock.patch.object(auth_url.cfg, 'CONF')
|
||||
def test_adds_default_auth_url_from_keystone_authtoken(self, mock_cfg):
|
||||
self.config = {}
|
||||
mock_cfg.clients_keystone.auth_uri = ''
|
||||
mock_cfg.keystone_authtoken.auth_uri = 'foobar'
|
||||
mock_cfg.auth_password.multi_cloud = False
|
||||
self.middleware = auth_url.AuthUrlFilter(self.app, self.config)
|
||||
|
@ -17,6 +17,7 @@ import mock
|
||||
from oslo_config import cfg
|
||||
from oslo_middleware import request_id
|
||||
from oslo_policy import opts as policy_opts
|
||||
from oslo_utils import importutils
|
||||
import webob
|
||||
|
||||
from heat.common import context
|
||||
@ -112,6 +113,66 @@ class TestRequestContext(common.HeatTestCase):
|
||||
ctx = context.RequestContext(roles=['notadmin'])
|
||||
self.assertFalse(ctx.is_admin)
|
||||
|
||||
def test_keystone_v3_endpoint_in_context(self):
|
||||
"""Ensure that the context is the preferred source for the
|
||||
auth_uri.
|
||||
"""
|
||||
cfg.CONF.set_override('auth_uri', 'http://xyz',
|
||||
group='clients_keystone')
|
||||
policy_check = 'heat.common.policy.Enforcer.check_is_admin'
|
||||
with mock.patch(policy_check) as pc:
|
||||
pc.return_value = False
|
||||
ctx = context.RequestContext(
|
||||
auth_url='http://example.com:5000/v2.0')
|
||||
self.assertEqual(ctx.keystone_v3_endpoint,
|
||||
'http://example.com:5000/v3')
|
||||
|
||||
def test_keystone_v3_endpoint_in_clients_keystone_config(self):
|
||||
"""Ensure that the [clients_keystone] section of the configuration is
|
||||
the preferred source when the context does not have the auth_uri.
|
||||
"""
|
||||
cfg.CONF.set_override('auth_uri', 'http://xyz',
|
||||
group='clients_keystone')
|
||||
importutils.import_module('keystonemiddleware.auth_token')
|
||||
cfg.CONF.set_override('auth_uri', 'http://abc/v2.0',
|
||||
group='keystone_authtoken')
|
||||
policy_check = 'heat.common.policy.Enforcer.check_is_admin'
|
||||
with mock.patch(policy_check) as pc:
|
||||
pc.return_value = False
|
||||
with mock.patch('keystoneclient.discover.Discover') as discover:
|
||||
class MockDiscover(object):
|
||||
def url_for(self, endpoint):
|
||||
return 'http://xyz/v3'
|
||||
discover.return_value = MockDiscover()
|
||||
|
||||
ctx = context.RequestContext(auth_url=None)
|
||||
self.assertEqual(ctx.keystone_v3_endpoint, 'http://xyz/v3')
|
||||
|
||||
def test_keystone_v3_endpoint_in_keystone_authtoken_config(self):
|
||||
"""Ensure that the [keystone_authtoken] section of the configuration
|
||||
is used when the auth_uri is not defined in the context or the
|
||||
[clients_keystone] section.
|
||||
"""
|
||||
importutils.import_module('keystonemiddleware.auth_token')
|
||||
cfg.CONF.set_override('auth_uri', 'http://abc/v2.0',
|
||||
group='keystone_authtoken')
|
||||
policy_check = 'heat.common.policy.Enforcer.check_is_admin'
|
||||
with mock.patch(policy_check) as pc:
|
||||
pc.return_value = False
|
||||
ctx = context.RequestContext(auth_url=None)
|
||||
self.assertEqual(ctx.keystone_v3_endpoint, 'http://abc/v3')
|
||||
|
||||
def test_keystone_v3_endpoint_not_set_in_config(self):
|
||||
"""Ensure an exception is raised when the auth_uri cannot be obtained
|
||||
from any source.
|
||||
"""
|
||||
policy_check = 'heat.common.policy.Enforcer.check_is_admin'
|
||||
with mock.patch(policy_check) as pc:
|
||||
pc.return_value = False
|
||||
ctx = context.RequestContext(auth_url=None)
|
||||
self.assertRaises(exception.AuthorizationFailure, getattr, ctx,
|
||||
'keystone_v3_endpoint')
|
||||
|
||||
|
||||
class RequestContextMiddlewareTest(common.HeatTestCase):
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user