From a72b397f7cc807cd21012124e80e1ddd0f2a60d8 Mon Sep 17 00:00:00 2001 From: Hampapur Ajay Date: Wed, 8 Oct 2014 16:51:48 -0700 Subject: [PATCH] Validate for blacklist chars in name at create Closes-Bug: 1379066 Change-Id: I9d289076b5c929d9137c795f60a0892175e4b5e5 --- src/api-lib/vnc_api.py | 2 ++ .../api-server/tests/test_crud_basic.py | 32 ++++++++++++++++++- src/config/api-server/vnc_cfg_api_server.py | 23 +++++++++++++ src/config/common/exceptions.py | 12 +++++++ .../vnc_openstack/neutron_plugin_db.py | 2 +- 5 files changed, 69 insertions(+), 2 deletions(-) diff --git a/src/api-lib/vnc_api.py b/src/api-lib/vnc_api.py index 7e2302959b3..a1e8cfffe1e 100644 --- a/src/api-lib/vnc_api.py +++ b/src/api-lib/vnc_api.py @@ -377,6 +377,8 @@ def _request_server(self, op, url, data=None, retry_on_error=True, time.sleep(1) continue + elif status == 400: + raise BadRequest(status, content) else: # Unknown Error raise HttpError(status, content) # end while True diff --git a/src/config/api-server/tests/test_crud_basic.py b/src/config/api-server/tests/test_crud_basic.py index 9c38c1eb18b..af850a61be8 100644 --- a/src/config/api-server/tests/test_crud_basic.py +++ b/src/config/api-server/tests/test_crud_basic.py @@ -691,7 +691,7 @@ def err_rabbitq_put(*args, **kwargs): logger.info("Creating objects to hit max rabbit pending.") # every create updates project quota - test_objs = self._create_test_objects(count=max_pend_upd/2+1) + test_objs = self._create_test_objects(count=max_pend_upd) def asserts_on_max_pending(): self.assertEqual(e.status_code, 500) @@ -857,6 +857,36 @@ def test_floatingip_as_instanceip(self): instance_ip_address=ip_allocated, virtual_network_refs=[vn_fixt.getObj()])) # end test_floatingip_as_instanceip + + def test_name_with_blacklist_char(self): + vn_name = self.id()+'-vn<1>' + vn_obj = VirtualNetwork(vn_name) + self._add_detail('Creating network with name %s expecting failure' %(vn_name)) + with ExpectedException(BadRequest) as e: + self._vnc_lib.virtual_network_create(vn_obj) + + vn_name = self.id()+'-vn' + vn_obj = VirtualNetwork(vn_name) + self._add_detail('Creating network with name %s expecting success' %(vn_name)) + self._vnc_lib.virtual_network_create(vn_obj) + self.assertTill(self.ifmap_has_ident, obj=vn_obj) + + rt_name = self.id()+'-route-target<1>' + rt_obj = RouteTarget(rt_name) + self._add_detail('Creating network with name %s expecting failure' %(rt_name)) + with ExpectedException(BadRequest) as e: + self._vnc_lib.route_target_create(rt_obj) + + rt_name = self.id()+'-route-target:1' + rt_obj = RouteTarget(rt_name) + self._add_detail('Creating network with name %s expecting success' %(rt_name)) + self._vnc_lib.route_target_create(rt_obj) + self.assertTill(self.ifmap_has_ident, obj=rt_obj) + + self._vnc_lib.virtual_network_delete(id=vn_obj.uuid) + self._vnc_lib.route_target_delete(id=rt_obj.uuid) + # end test_name_with_blacklist_char + # end class TestVncCfgApiServer class TestLocalAuth(test_case.ApiServerTestCase): diff --git a/src/config/api-server/vnc_cfg_api_server.py b/src/config/api-server/vnc_cfg_api_server.py index a949d592c40..f7755c7a8fd 100644 --- a/src/config/api-server/vnc_cfg_api_server.py +++ b/src/config/api-server/vnc_cfg_api_server.py @@ -202,6 +202,8 @@ class VncApiServer(VncApiServerGen): """ This is the manager class co-ordinating all classes present in the package """ + _INVALID_NAME_CHARS = set('<>:') + def __new__(cls, *args, **kwargs): obj = super(VncApiServer, cls).__new__(cls, *args, **kwargs) bottle.route('/', 'GET', obj.homepage_http_get) @@ -235,6 +237,7 @@ def __init__(self, args_str=None): self._get_common = self._http_get_common self._put_common = self._http_put_common self._delete_common = self._http_delete_common + self._post_validate = self._http_post_validate self._post_common = self._http_post_common # Type overrides from generated code @@ -1280,6 +1283,26 @@ def _http_delete_common(self, request, obj_type, uuid, parent_type): return self._permissions.check_perms_write(request, parent_uuid) # end _http_delete_common + def _http_post_validate(self, obj_type=None, obj_dict=None): + if not obj_dict: + return + + def _check_field_present(fname): + fval = obj_dict.get(fname) + if not fval: + bottle.abort(400, "Bad Request, no %s in POST body" %(fname)) + return fval + fq_name = _check_field_present('fq_name') + if obj_type[:].replace('-','_') == 'route_target': + invalid_chars = self._INVALID_NAME_CHARS - set(':') + else: + invalid_chars = self._INVALID_NAME_CHARS + if any((c in invalid_chars) for c in fq_name[-1]): + bottle.abort(400, + "Bad Request, name has one of invalid chars %s" + %(invalid_chars)) + # end _http_post_validate + def _http_post_common(self, request, obj_type, obj_dict): # If not connected to zookeeper do not allow operations that # causes the state change diff --git a/src/config/common/exceptions.py b/src/config/common/exceptions.py index db739107dee..8d5f1d98b35 100644 --- a/src/config/common/exceptions.py +++ b/src/config/common/exceptions.py @@ -19,6 +19,18 @@ def __str__(self): # end class TimeOutError +class BadRequest(Exception): + def __init__(self, status_code, content): + self.status_code = status_code + self.content = content + # end __init__ + + def __str__(self): + return 'HTTP Status: %s Content: %s' % (self.status_code, self.content) + # end __str__ +# end class BadRequest + + class NoIdError(VncError): def __init__(self, unknown_id): diff --git a/src/config/vnc_openstack/vnc_openstack/neutron_plugin_db.py b/src/config/vnc_openstack/vnc_openstack/neutron_plugin_db.py index 7e2ffc7341e..9fd6c5ca488 100644 --- a/src/config/vnc_openstack/vnc_openstack/neutron_plugin_db.py +++ b/src/config/vnc_openstack/vnc_openstack/neutron_plugin_db.py @@ -307,7 +307,7 @@ def _resource_create(self, resource_type, obj): obj.name += '-' + obj.uuid obj.fq_name[-1] += '-' + obj.uuid obj_uuid = create_method(obj) - except PermissionDenied as e: + except (PermissionDenied, BadRequest) as e: self._raise_contrail_exception('BadRequest', resource=resource_type, msg=str(e))