Merge "Use service catalog from authentication response"
This commit is contained in:
commit
5452662928
@ -76,7 +76,6 @@ class MistralContext(BaseContext):
|
|||||||
"project_id",
|
"project_id",
|
||||||
"auth_token",
|
"auth_token",
|
||||||
"service_catalog",
|
"service_catalog",
|
||||||
"target_service_catalog",
|
|
||||||
"user_name",
|
"user_name",
|
||||||
"project_name",
|
"project_name",
|
||||||
"roles",
|
"roles",
|
||||||
@ -85,6 +84,7 @@ class MistralContext(BaseContext):
|
|||||||
"redelivered",
|
"redelivered",
|
||||||
"expires_at",
|
"expires_at",
|
||||||
"trust_id",
|
"trust_id",
|
||||||
|
"is_target",
|
||||||
])
|
])
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
@ -108,18 +108,19 @@ def set_ctx(new_ctx):
|
|||||||
|
|
||||||
def context_from_headers_and_env(headers, env):
|
def context_from_headers_and_env(headers, env):
|
||||||
params = _extract_auth_params_from_headers(headers)
|
params = _extract_auth_params_from_headers(headers)
|
||||||
|
|
||||||
auth_cacert = params['auth_cacert']
|
auth_cacert = params['auth_cacert']
|
||||||
auth_token = params['auth_token']
|
auth_token = params['auth_token']
|
||||||
auth_uri = params['auth_uri']
|
auth_uri = params['auth_uri']
|
||||||
project_id = params['project_id']
|
project_id = params['project_id']
|
||||||
user_id = params['user_id']
|
user_id = params['user_id']
|
||||||
user_name = params['user_name']
|
user_name = params['user_name']
|
||||||
target_service_catalog = params['target_service_catalog']
|
is_target = params['is_target']
|
||||||
|
|
||||||
token_info = env.get('keystone.token_info')
|
token_info = env.get('keystone.token_info', {})
|
||||||
|
|
||||||
if token_info and target_service_catalog is None:
|
service_catalog = (params['service_catalog'] if is_target
|
||||||
target_service_catalog = token_info['token']
|
else token_info.get('token', {}))
|
||||||
|
|
||||||
return MistralContext(
|
return MistralContext(
|
||||||
auth_uri=auth_uri,
|
auth_uri=auth_uri,
|
||||||
@ -127,7 +128,8 @@ def context_from_headers_and_env(headers, env):
|
|||||||
user_id=user_id,
|
user_id=user_id,
|
||||||
project_id=project_id,
|
project_id=project_id,
|
||||||
auth_token=auth_token,
|
auth_token=auth_token,
|
||||||
target_service_catalog=target_service_catalog,
|
is_target=is_target,
|
||||||
|
service_catalog=service_catalog,
|
||||||
user_name=user_name,
|
user_name=user_name,
|
||||||
project_name=headers.get('X-Project-Name'),
|
project_name=headers.get('X-Project-Name'),
|
||||||
roles=headers.get('X-Roles', "").split(","),
|
roles=headers.get('X-Roles', "").split(","),
|
||||||
@ -137,7 +139,7 @@ def context_from_headers_and_env(headers, env):
|
|||||||
|
|
||||||
|
|
||||||
def _extract_auth_params_from_headers(headers):
|
def _extract_auth_params_from_headers(headers):
|
||||||
target_service_catalog = None
|
service_catalog = None
|
||||||
|
|
||||||
if headers.get("X-Target-Auth-Uri"):
|
if headers.get("X-Target-Auth-Uri"):
|
||||||
params = {
|
params = {
|
||||||
@ -148,13 +150,17 @@ def _extract_auth_params_from_headers(headers):
|
|||||||
'project_id': headers.get('X-Target-Project-Id'),
|
'project_id': headers.get('X-Target-Project-Id'),
|
||||||
'user_id': headers.get('X-Target-User-Id'),
|
'user_id': headers.get('X-Target-User-Id'),
|
||||||
'user_name': headers.get('X-Target-User-Name'),
|
'user_name': headers.get('X-Target-User-Name'),
|
||||||
|
'is_target': True
|
||||||
}
|
}
|
||||||
if not params['auth_token']:
|
if not params['auth_token']:
|
||||||
raise (exc.MistralException(
|
raise (exc.MistralException(
|
||||||
'Target auth URI (X-Target-Auth-Uri) target auth token '
|
'Target auth URI (X-Target-Auth-Uri) target auth token '
|
||||||
'(X-Target-Auth-Token) must be present'))
|
'(X-Target-Auth-Token) must be present'))
|
||||||
|
|
||||||
target_service_catalog = _extract_service_catalog_from_headers(
|
# It's possible that target service catalog is not provided, in this
|
||||||
|
# case, Mistral needs to get target service catalog dynamically when
|
||||||
|
# talking to target openstack deployment later on.
|
||||||
|
service_catalog = _extract_service_catalog_from_headers(
|
||||||
headers
|
headers
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@ -165,9 +171,10 @@ def _extract_auth_params_from_headers(headers):
|
|||||||
'project_id': headers.get('X-Project-Id'),
|
'project_id': headers.get('X-Project-Id'),
|
||||||
'user_id': headers.get('X-User-Id'),
|
'user_id': headers.get('X-User-Id'),
|
||||||
'user_name': headers.get('X-User-Name'),
|
'user_name': headers.get('X-User-Name'),
|
||||||
|
'is_target': False
|
||||||
}
|
}
|
||||||
|
|
||||||
params['target_service_catalog'] = target_service_catalog
|
params['service_catalog'] = service_catalog
|
||||||
|
|
||||||
return params
|
return params
|
||||||
|
|
||||||
|
@ -12,7 +12,8 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
from mistral import config
|
from mistral import context as auth_context
|
||||||
|
from mistral import exceptions
|
||||||
from mistral.tests.unit import base
|
from mistral.tests.unit import base
|
||||||
from mistral.utils.openstack import keystone
|
from mistral.utils.openstack import keystone
|
||||||
|
|
||||||
@ -23,10 +24,6 @@ class KeystoneUtilsTest(base.BaseTest):
|
|||||||
|
|
||||||
self.values = {'id': 'my_id'}
|
self.values = {'id': 'my_id'}
|
||||||
|
|
||||||
def override_config(self, name, override, group=None):
|
|
||||||
config.CONF.set_override(name, override, group)
|
|
||||||
self.addCleanup(config.CONF.clear_override, name, group)
|
|
||||||
|
|
||||||
def test_format_url_dollar_sign(self):
|
def test_format_url_dollar_sign(self):
|
||||||
url_template = "http://host:port/v1/$(id)s"
|
url_template = "http://host:port/v1/$(id)s"
|
||||||
|
|
||||||
@ -46,3 +43,14 @@ class KeystoneUtilsTest(base.BaseTest):
|
|||||||
expected,
|
expected,
|
||||||
keystone.format_url(url_template, self.values)
|
keystone.format_url(url_template, self.values)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_get_endpoint_for_project_noauth(self):
|
||||||
|
# service_catalog is not set by default.
|
||||||
|
auth_context.set_ctx(base.get_context())
|
||||||
|
self.addCleanup(auth_context.set_ctx, None)
|
||||||
|
|
||||||
|
self.assertRaises(
|
||||||
|
exceptions.UnauthorizedException,
|
||||||
|
keystone.get_endpoint_for_project,
|
||||||
|
'keystone'
|
||||||
|
)
|
||||||
|
@ -20,8 +20,10 @@ from keystoneclient.v3 import client as ks_client
|
|||||||
from keystoneclient.v3 import endpoints as ks_endpoints
|
from keystoneclient.v3 import endpoints as ks_endpoints
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_utils import timeutils
|
from oslo_utils import timeutils
|
||||||
|
import six
|
||||||
|
|
||||||
from mistral import context
|
from mistral import context
|
||||||
|
from mistral import exceptions
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
|
|
||||||
@ -76,30 +78,29 @@ def get_endpoint_for_project(service_name=None, service_type=None):
|
|||||||
|
|
||||||
service_catalog = obtain_service_catalog(ctx)
|
service_catalog = obtain_service_catalog(ctx)
|
||||||
|
|
||||||
catalog = service_catalog.get_endpoints(
|
service_endpoints = service_catalog.get_endpoints(
|
||||||
service_name=service_name,
|
service_name=service_name,
|
||||||
service_type=service_type
|
service_type=service_type
|
||||||
)
|
)
|
||||||
|
|
||||||
endpoint = None
|
endpoint = None
|
||||||
for service_type in catalog:
|
for endpoints in six.itervalues(service_endpoints):
|
||||||
service = catalog.get(service_type)
|
for ep in endpoints:
|
||||||
for interface in service:
|
|
||||||
# is V3 interface?
|
# is V3 interface?
|
||||||
if 'interface' in interface:
|
if 'interface' in ep:
|
||||||
interface_type = interface['interface']
|
interface_type = ep['interface']
|
||||||
if CONF.os_actions_endpoint_type in interface_type:
|
if CONF.os_actions_endpoint_type in interface_type:
|
||||||
endpoint = ks_endpoints.Endpoint(
|
endpoint = ks_endpoints.Endpoint(
|
||||||
None,
|
None,
|
||||||
interface,
|
ep,
|
||||||
loaded=True
|
loaded=True
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
# is V2 interface?
|
# is V2 interface?
|
||||||
if 'publicURL' in interface:
|
if 'publicURL' in ep:
|
||||||
endpoint_data = {
|
endpoint_data = {
|
||||||
'url': interface['publicURL'],
|
'url': ep['publicURL'],
|
||||||
'region': interface['region']
|
'region': ep['region']
|
||||||
}
|
}
|
||||||
endpoint = ks_endpoints.Endpoint(
|
endpoint = ks_endpoints.Endpoint(
|
||||||
None,
|
None,
|
||||||
@ -122,6 +123,7 @@ def get_endpoint_for_project(service_name=None, service_type=None):
|
|||||||
|
|
||||||
def obtain_service_catalog(ctx):
|
def obtain_service_catalog(ctx):
|
||||||
token = ctx.auth_token
|
token = ctx.auth_token
|
||||||
|
|
||||||
if ctx.is_trust_scoped and is_token_trust_scoped(token):
|
if ctx.is_trust_scoped and is_token_trust_scoped(token):
|
||||||
if ctx.trust_id is None:
|
if ctx.trust_id is None:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
@ -134,22 +136,29 @@ def obtain_service_catalog(ctx):
|
|||||||
include_catalog=True
|
include_catalog=True
|
||||||
)['token']
|
)['token']
|
||||||
else:
|
else:
|
||||||
if not ctx.target_service_catalog:
|
response = ctx.service_catalog
|
||||||
|
|
||||||
|
# Target service catalog may not be passed via API.
|
||||||
|
if not response and ctx.is_target:
|
||||||
response = client().tokens.get_token_data(
|
response = client().tokens.get_token_data(
|
||||||
token,
|
token,
|
||||||
include_catalog=True)['token']
|
include_catalog=True
|
||||||
else:
|
)['token']
|
||||||
response = ctx.target_service_catalog
|
|
||||||
|
if not response:
|
||||||
|
raise exceptions.UnauthorizedException()
|
||||||
|
|
||||||
service_catalog = ks_service_catalog.ServiceCatalog.factory(response)
|
service_catalog = ks_service_catalog.ServiceCatalog.factory(response)
|
||||||
|
|
||||||
return service_catalog
|
return service_catalog
|
||||||
|
|
||||||
|
|
||||||
def get_keystone_endpoint_v2():
|
def get_keystone_endpoint_v2():
|
||||||
return get_endpoint_for_project('keystone')
|
return get_endpoint_for_project('keystone', service_type='identity')
|
||||||
|
|
||||||
|
|
||||||
def get_keystone_url_v2():
|
def get_keystone_url_v2():
|
||||||
return get_endpoint_for_project('keystone').url
|
return get_endpoint_for_project('keystone', service_type='identity').url
|
||||||
|
|
||||||
|
|
||||||
def format_url(url_template, values):
|
def format_url(url_template, values):
|
||||||
|
Loading…
Reference in New Issue
Block a user