Persist User Domain for role validation in Heat
Heat must have the domain of the user in order to validate the user for role assignment. Regardless of if roles are being changed or assigned, heat always requires and validates this data when heat receives a project template. This work persists the user domain when calls are made to CMS so that RDS can add this data to project heat templates. Change-Id: I5a8e72241e68dac730c3522d820a17d926fa3be8
This commit is contained in:
parent
058c534796
commit
23b9d62dc5
@ -134,7 +134,6 @@ def authorize(action, request, app_conf, keystone_ep=None):
|
||||
|
||||
keystone_ep = keystone_ep if keystone_ep else (
|
||||
request.headers.get('Keystone-Endpoint'))
|
||||
|
||||
try:
|
||||
if _is_authorization_enabled(app_conf):
|
||||
try:
|
||||
@ -145,6 +144,7 @@ def authorize(action, request, app_conf, keystone_ep=None):
|
||||
request.headers['X-RANGER-Client'] = user.user['name']
|
||||
request.headers['X-RANGER-Owner'] = user.tenant['id']
|
||||
request.headers['Keystone-Endpoint'] = user.auth_url
|
||||
request.headers['User-Domain'] = user.domain
|
||||
keystone_ep = user.auth_url
|
||||
except Exception as ex:
|
||||
user = None
|
||||
|
@ -89,6 +89,9 @@ class RdsProxy(object):
|
||||
headers['X-Auth-Token'] = request.headers[
|
||||
'X-Auth-Token'] if 'X-Auth-Token' in \
|
||||
request.headers else ''
|
||||
headers['User-Domain'] = request.headers[
|
||||
'User-Domain'] if 'User-Domain' in \
|
||||
request.headers else ''
|
||||
|
||||
LOG.debug("Wrapper JSON before sending action: {0} to Rds "
|
||||
"Proxy\n{1}".format(method, pretty_text))
|
||||
|
@ -170,7 +170,7 @@ class CreateNewResource(rest.RestController):
|
||||
"""Handle HTTP POST request.
|
||||
|
||||
:param Customer (json in request body):
|
||||
:return: result (json format ... {'Cusetomer':{'id':'',
|
||||
:return: result (json format ... {'Customer':{'id':'',
|
||||
'links':{'own':'how host url'},'created':'1234567890'}}
|
||||
the response will be 201 created if success
|
||||
:return 409 for conflict
|
||||
@ -179,17 +179,20 @@ class CreateNewResource(rest.RestController):
|
||||
"""
|
||||
my_logger.info("create resource")
|
||||
jsondata = resource.service_template.model
|
||||
my_logger.debug("parse json & get yaml file!!! {}".format(jsondata))
|
||||
my_logger.debug("parse json & retrieve yaml file {}".format(jsondata))
|
||||
uuid = resource.service_template.tracking.tracking_id
|
||||
resource_type = resource.service_template.resource.resource_type
|
||||
base_url = pecan.request.application_url
|
||||
user_domain = None
|
||||
if resource_type == 'customer':
|
||||
user_domain = pecan.request.headers['User-Domain']
|
||||
jsondata = ast.literal_eval(jsondata)
|
||||
|
||||
try:
|
||||
resource_id = ResourceService.main(jsondata,
|
||||
uuid,
|
||||
resource_type,
|
||||
'create')
|
||||
'create',
|
||||
user_domain)
|
||||
site_link = "%s/v1/rds/%s/%s" % (base_url,
|
||||
resource_type,
|
||||
resource_id)
|
||||
@ -208,7 +211,7 @@ class CreateNewResource(rest.RestController):
|
||||
@wsexpose(Result, body=Resource, status_code=201,
|
||||
rest_content_types='json')
|
||||
def put(self, resource):
|
||||
"""Handle HTTP POST request.
|
||||
"""Handle HTTP PUT request.
|
||||
|
||||
:param Customer (json in request body):
|
||||
:return: result (json format ... {'Cusetomer':{'id':'',
|
||||
@ -225,13 +228,17 @@ class CreateNewResource(rest.RestController):
|
||||
resource_type = resource.service_template.resource.resource_type
|
||||
base_url = pecan.request.application_url
|
||||
jsondata = ast.literal_eval(jsondata)
|
||||
user_domain = None
|
||||
if resource_type == 'customer':
|
||||
user_domain = pecan.request.headers['User-Domain']
|
||||
|
||||
try:
|
||||
resource_id = ResourceService.main(jsondata,
|
||||
uuid,
|
||||
resource_type,
|
||||
'modify')
|
||||
my_logger.debug("data sent!.")
|
||||
'modify',
|
||||
user_domain)
|
||||
my_logger.debug("data sent")
|
||||
site_link = "%s/v1/rds/%s/%s" % (base_url,
|
||||
resource_type,
|
||||
resource_id)
|
||||
@ -266,6 +273,9 @@ class CreateNewResource(rest.RestController):
|
||||
jsondata = ast.literal_eval(jsondata)
|
||||
resource_uuid = resource.service_template.tracking.tracking_id
|
||||
resource_type = resource.service_template.resource.resource_type
|
||||
user_domain = None
|
||||
if resource_type == 'customer':
|
||||
user_domain = pecan.request.headers['User-Domain']
|
||||
if resource_type not in resources_operation_list or operation not in \
|
||||
resources_operation_list[resource_type]:
|
||||
raise NotAllowedError("delete Not allowed for this"
|
||||
@ -274,7 +284,8 @@ class CreateNewResource(rest.RestController):
|
||||
resource_id = ResourceService.main(jsondata,
|
||||
resource_uuid,
|
||||
resource_type,
|
||||
operation)
|
||||
operation,
|
||||
user_domain)
|
||||
return resource_id
|
||||
except ConflictValue as e:
|
||||
my_logger.error("the request blocked need to wait"
|
||||
|
@ -126,7 +126,8 @@ def _create_template_data(input_data):
|
||||
if target['action'] == "delete":
|
||||
yamldata = "delete"
|
||||
elif input_data.resource_type == "customer":
|
||||
yamldata = yaml_customer_builder.yamlbuilder(jsondata, target)
|
||||
yamldata = yaml_customer_builder.yamlbuilder(jsondata, target,
|
||||
input_data.user_domain)
|
||||
elif input_data.resource_type == "group":
|
||||
yamldata = yaml_group_builder.yamlbuilder(jsondata, target)
|
||||
elif input_data.resource_type == "flavor":
|
||||
@ -256,11 +257,14 @@ def _generate_resource_data(input_data):
|
||||
input_data.resource_id))
|
||||
targetslist = _create_template_data(input_data)
|
||||
my_logger.debug("submit yaml to ranger-agent...")
|
||||
_submit_template_data(input_data.resource_id, input_data.transaction_id,
|
||||
_submit_template_data(input_data.resource_id,
|
||||
input_data.transaction_id,
|
||||
targetslist)
|
||||
|
||||
|
||||
def main(jsondata, external_transaction_id, resource_type, operation):
|
||||
# User domain is only used in the case that a customer template is being generated,
|
||||
# as certain builds of heat require user_domain in order to validate roles
|
||||
def main(jsondata, external_transaction_id, resource_type, operation, user_domain=None):
|
||||
"""main function handle resource operation."""
|
||||
my_logger.info("got %s for %s resource" % (operation, resource_type))
|
||||
try:
|
||||
@ -273,6 +277,7 @@ def main(jsondata, external_transaction_id, resource_type, operation):
|
||||
my_logger.debug("iterate through the regions see if none in submitted")
|
||||
_check_resource_status(input_data)
|
||||
my_logger.debug("get uuid from uuid generator")
|
||||
input_data.user_domain = user_domain
|
||||
input_data.transaction_id = uuid_utils.get_random_uuid()
|
||||
my_logger.debug("uuid ={}".format(input_data.transaction_id))
|
||||
# add regions status from rms (to check if it down)
|
||||
|
@ -2,6 +2,7 @@
|
||||
import logging
|
||||
|
||||
from orm.services.resource_distributor.rds.services.helpers import create_final_yaml
|
||||
|
||||
from pecan import conf
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@ -25,7 +26,7 @@ def _metadata_to_tags(metadata):
|
||||
str(k) + '=' + str(v) for i in metadata for k, v in i.items()) + ']'
|
||||
|
||||
|
||||
def yamlbuilder(alldata, region):
|
||||
def yamlbuilder(alldata, region, user_domain):
|
||||
logger.info("building customer yaml")
|
||||
logger.debug("start building flavor yaml for region %s" % region['name'])
|
||||
"""build cstomer yaml.
|
||||
@ -79,7 +80,6 @@ def yamlbuilder(alldata, region):
|
||||
# create the output for roles
|
||||
# outputs['outputs']["%s_id" % role] =\
|
||||
# {"value": {"get_resource": "%s" % role}}
|
||||
|
||||
# no support for group when type is ldap
|
||||
if yaml_type != 'ldap':
|
||||
# create one group for user
|
||||
@ -107,7 +107,7 @@ def yamlbuilder(alldata, region):
|
||||
else:
|
||||
resources['resources'][user['id']] = \
|
||||
{'type': 'OS::Keystone::UserRoleAssignment\n',
|
||||
'properties': {'user': (user['id'] + "{%s}" % domain),
|
||||
'properties': {'user': (user['id'] + "{%s}" % user_domain),
|
||||
'roles': user_roles}}
|
||||
|
||||
# create the output for users
|
||||
|
@ -10,7 +10,8 @@ class TestCreateResource(FunctionalTest):
|
||||
@patch.object(root.ResourceService, 'main', return_value="12345")
|
||||
def test_create_resource_success(self, input):
|
||||
"""test create resource as it succeed."""
|
||||
response = self.app.post_json('/v1/rds/resources', good_data)
|
||||
headers = {'User-Domain': 'default'}
|
||||
response = self.app.post_json('/v1/rds/resources', good_data, headers=headers)
|
||||
assert response.json['customer']['id'] == '12345'
|
||||
assert response.status_int == 201
|
||||
|
||||
@ -32,22 +33,26 @@ class TestCreateResource(FunctionalTest):
|
||||
side_effect=Exception("general exception"))
|
||||
def test_create_resource_gen_except(self, input):
|
||||
"""test creatte resource to catch general exception."""
|
||||
response = self.app.post_json('/v1/rds/resources',
|
||||
good_data, expect_errors=True)
|
||||
headers = {'User-Domain': 'default'}
|
||||
response = self.app.post_json('/v1/rds/resources', good_data,
|
||||
headers=headers, expect_errors=True)
|
||||
assert response.status_int == 400
|
||||
|
||||
@patch.object(root.ResourceService, 'main',
|
||||
side_effect=root.ConflictValue("region"))
|
||||
def test_create_resource_conflict_except(self, input):
|
||||
"""test creatte resource to catch ConflictValue exception."""
|
||||
response = self.app.post_json('/v1/rds/resources',
|
||||
good_data, expect_errors=True)
|
||||
headers = {'User-Domain': 'default'}
|
||||
response = self.app.post_json('/v1/rds/resources', good_data,
|
||||
headers=headers, expect_errors=True)
|
||||
assert response.status_int == 409
|
||||
|
||||
@patch.object(root.ResourceService, 'main', return_value="12345")
|
||||
def test_delete_resource_flavor(self, input):
|
||||
"""test delete flavor."""
|
||||
response = self.app.delete_json('/v1/rds/resources', flavor_data)
|
||||
headers = {'User-Domain': 'default'}
|
||||
response = self.app.delete_json('/v1/rds/resources', flavor_data,
|
||||
headers=headers)
|
||||
assert response.status_int == 200
|
||||
|
||||
@patch.object(root.ResourceService, 'main', return_value="12345")
|
||||
@ -55,8 +60,9 @@ class TestCreateResource(FunctionalTest):
|
||||
"""test delete resource not flavor."""
|
||||
flavor_data["service_template"]["resource"]['resource_type'] = \
|
||||
"customer"
|
||||
headers = {'User-Domain': 'default'}
|
||||
response = self.app.delete_json('/v1/rds/resources', flavor_data,
|
||||
expect_errors=True)
|
||||
headers=headers, expect_errors=True)
|
||||
assert response.status_int == 405
|
||||
flavor_data["service_template"]["resource"]['resource_type'] = "flavor"
|
||||
|
||||
@ -64,8 +70,10 @@ class TestCreateResource(FunctionalTest):
|
||||
side_effect=root.ConflictValue("region"))
|
||||
def test_delete_resource_flavor_con(self, input):
|
||||
"""test delete flavor while previous process still in progress."""
|
||||
headers = {'User-Domain': 'default'}
|
||||
try:
|
||||
response = self.app.delete_json('/v1/rds/resources', flavor_data)
|
||||
response = self.app.delete_json('/v1/rds/resources', flavor_data,
|
||||
headers=headers)
|
||||
except Exception as e:
|
||||
if '409 Conflict' not in str(e):
|
||||
self.fail('error')
|
||||
@ -74,8 +82,10 @@ class TestCreateResource(FunctionalTest):
|
||||
side_effect=Exception("unknown error"))
|
||||
def test_delete_resource_flavor_exce(self, input):
|
||||
"""test delete flavor with general; exception."""
|
||||
headers = {'User-Domain': 'default'}
|
||||
try:
|
||||
response = self.app.delete_json('/v1/rds/resources', flavor_data)
|
||||
response = self.app.delete_json('/v1/rds/resources',
|
||||
flavor_data, headers=headers)
|
||||
except Exception as e:
|
||||
if 'unknown error' not in str(e):
|
||||
self.fail('error')
|
||||
@ -84,7 +94,9 @@ class TestCreateResource(FunctionalTest):
|
||||
def test_update_resource_success(self, input):
|
||||
updated = False
|
||||
"""test update resource as it succeed."""
|
||||
response = self.app.put_json('/v1/rds/resources', good_data)
|
||||
headers = {'User-Domain': 'default'}
|
||||
response = self.app.put_json('/v1/rds/resources', good_data,
|
||||
headers=headers)
|
||||
if 'updated' in response.json['customer']:
|
||||
updated = True
|
||||
assert response.json['customer']['id'] == '12345'
|
||||
@ -95,8 +107,10 @@ class TestCreateResource(FunctionalTest):
|
||||
side_effect=Exception("unknown error"))
|
||||
def test_put_resource_gen_exce(self, input):
|
||||
"""test customer put with general; exception."""
|
||||
headers = {'User-Domain': 'default'}
|
||||
try:
|
||||
response = self.app.put_json('/v1/rds/resources', good_data)
|
||||
response = self.app.put_json('/v1/rds/resources', good_data,
|
||||
headers=headers)
|
||||
except Exception as e:
|
||||
if 'unknown error' not in str(e):
|
||||
self.fail('error')
|
||||
@ -105,8 +119,9 @@ class TestCreateResource(FunctionalTest):
|
||||
side_effect=root.ConflictValue("region"))
|
||||
def test_modify_resource_conflict_except(self, input):
|
||||
"""test modify resource to catch ConflictValue exception."""
|
||||
response = self.app.put_json('/v1/rds/resources',
|
||||
good_data, expect_errors=True)
|
||||
headers = {'User-Domain': 'default'}
|
||||
response = self.app.put_json('/v1/rds/resources', good_data,
|
||||
headers=headers, expect_errors=True)
|
||||
assert response.status_int == 409
|
||||
|
||||
good_data = {
|
||||
|
@ -83,6 +83,7 @@ class CreateResource(unittest.TestCase):
|
||||
operation='create',
|
||||
targets=targets
|
||||
)
|
||||
input_data.user_domain = 'default'
|
||||
status_model = StatusModel(status=[result])
|
||||
status_model.regions = None
|
||||
result.return_value = status_model
|
||||
|
@ -287,7 +287,7 @@ class CreateResource(unittest.TestCase):
|
||||
ver = mock_conf.yaml_configs.customer_yaml.yaml_version = '2015-1-1'
|
||||
domain = mock_conf.yaml_configs.customer_yaml.customer_domain = 'default'
|
||||
mock_conf.yaml_configs.customer_yaml.yaml_options.quotas = False
|
||||
yamlfile = CustomerBuild.yamlbuilder(alldata, region_quotas)
|
||||
yamlfile = CustomerBuild.yamlbuilder(alldata, region_quotas, user_domain='default')
|
||||
yamlfile_as_json = yaml.safe_load(yamlfile)
|
||||
self.assertEqual(yamlfile_as_json['heat_template_version'], ver)
|
||||
self.assertEqual(yaml.safe_load(yamlfile), yaml.safe_load(fullyaml_no_users_quotasoff))
|
||||
@ -298,7 +298,7 @@ class CreateResource(unittest.TestCase):
|
||||
ver = mock_conf.yaml_configs.customer_yaml.yaml_version = '2015-1-2'
|
||||
domain = mock_conf.yaml_configs.customer_yaml.customer_domain = 'default'
|
||||
mock_conf.yaml_configs.customer_yaml.yaml_options.quotas = False
|
||||
yamlfile = CustomerBuild.yamlbuilder(alldata, region_users)
|
||||
yamlfile = CustomerBuild.yamlbuilder(alldata, region_users, user_domain='default')
|
||||
yamlfile_as_json = yaml.safe_load(yamlfile)
|
||||
self.assertEqual(yamlfile_as_json['heat_template_version'], ver)
|
||||
self.assertEqual(yaml.safe_load(yamlfile), yaml.safe_load(fullyaml_with_users_quotasoff))
|
||||
@ -309,7 +309,7 @@ class CreateResource(unittest.TestCase):
|
||||
ver = mock_conf.yaml_configs.customer_yaml.yaml_version = '2015-1-1'
|
||||
domain = mock_conf.yaml_configs.customer_yaml.customer_domain = 'default'
|
||||
mock_conf.yaml_configs.customer_yaml.yaml_options.quotas = True
|
||||
yamlfile = CustomerBuild.yamlbuilder(alldata, region_users)
|
||||
yamlfile = CustomerBuild.yamlbuilder(alldata, region_users, user_domain='default')
|
||||
yamlfile_as_json = yaml.safe_load(yamlfile)
|
||||
self.assertEqual(yamlfile_as_json['heat_template_version'], ver)
|
||||
self.assertEqual(yaml.safe_load(yamlfile), yaml.safe_load(full_yaml_default_quotas))
|
||||
@ -320,7 +320,7 @@ class CreateResource(unittest.TestCase):
|
||||
ver = mock_conf.yaml_configs.customer_yaml.yaml_version = '2015-1-1'
|
||||
domain = mock_conf.yaml_configs.customer_yaml.customer_domain = 'default'
|
||||
mock_conf.yaml_configs.customer_yaml.yaml_options.quotas = True
|
||||
yamlfile = CustomerBuild.yamlbuilder(alldata, region_quotas)
|
||||
yamlfile = CustomerBuild.yamlbuilder(alldata, region_quotas, user_domain='default')
|
||||
yamlfile_as_json = yaml.safe_load(yamlfile)
|
||||
self.assertEqual(yamlfile_as_json['heat_template_version'], ver)
|
||||
self.assertEqual(yaml.safe_load(yamlfile), yaml.safe_load(full_yaml_quotas))
|
||||
@ -334,7 +334,7 @@ class CreateResource(unittest.TestCase):
|
||||
mock_conf.authentication.user_domain_name = 'default'
|
||||
mock_conf.yaml_configs.customer_yaml.yaml_options.quotas = False
|
||||
mock_conf.yaml_configs.customer_yaml.yaml_options.type = "ldap"
|
||||
yamlfile = CustomerBuild.yamlbuilder(alldata, region_users)
|
||||
yamlfile = CustomerBuild.yamlbuilder(alldata, region_users, user_domain='default')
|
||||
yamlfile_as_json = yaml.safe_load(yamlfile)
|
||||
self.assertEqual(yamlfile_as_json['heat_template_version'], ver)
|
||||
|
||||
@ -345,7 +345,7 @@ class CreateResource(unittest.TestCase):
|
||||
ver = mock_conf.yaml_configs.customer_yaml.yaml_version = '2015-1-2'
|
||||
domain = mock_conf.yaml_configs.customer_yaml.customer_domain = 'default'
|
||||
mock_conf.yaml_configs.customer_yaml.yaml_options.quotas = True
|
||||
yamlfile = CustomerBuild.yamlbuilder(alldata, region_users_v4)
|
||||
yamlfile = CustomerBuild.yamlbuilder(alldata, region_users_v4, user_domain='default')
|
||||
yamlfile_as_json = yaml.safe_load(yamlfile)
|
||||
self.assertEqual(yamlfile_as_json['heat_template_version'], ver)
|
||||
self.assertEqual(yaml.safe_load(yamlfile), yaml.safe_load(fullyaml_aic4))
|
||||
|
@ -16,3 +16,4 @@ keystonemiddleware>=4.17.0 # Apache-2.0
|
||||
python-keystoneclient>=3.8.0 # Apache-2.0
|
||||
mysqlclient>=1.4.0
|
||||
psutil>=3.2.2 # BSD
|
||||
setuptools>=40.0.0
|
||||
|
Loading…
x
Reference in New Issue
Block a user