Fix infinite loop when enhanced policy check

- Fix so that infinite loop don't occurred in _pre_enhanced_policy_check
  when targets and credentials is set to special role.
- And add check whether targets is set to special role
  in _pre_enhanced_policy_check

Closes-Bug: #2078012
Change-Id: I410f8422b0be44cf84ffe0a6d9edef0f699d10f7
This commit is contained in:
Takahiro Miyajima
2024-08-28 05:44:52 +00:00
parent 611cd1fa9c
commit e9036cdf7f
9 changed files with 395 additions and 10 deletions

View File

@@ -121,6 +121,9 @@ attributes.
As "all" is treated as a special value, the above attribute of resource
cannot use "all" as the attribute value.
If the attribute of resource is set to "all" by mistake, only users with
the admin role or special roles can access the resource, and other users
cannot access it.
Conversion rules

View File

@@ -129,6 +129,10 @@ class PolicyCheckError(TackerException):
message = _("Failed to check policy %(policy)s because %(reason)s")
class PolicyTargetCheckError(Forbidden):
message = _("Failed to check policy about target because %(reason)s")
class InUse(TackerException):
message = _("The resource is in use")

View File

@@ -77,7 +77,7 @@ def init(conf=cfg.CONF, policy_file=None, suppress_deprecation_warnings=False):
_ENFORCER.load_rules()
def _pre_enhanced_policy_check(target, credentials):
def _pre_enhanced_policy_check(target, credentials, target_chk=True):
"""Preprocesses target and credentials for enhanced tacker policy.
This method does the following things:
@@ -105,14 +105,28 @@ def _pre_enhanced_policy_check(target, credentials):
'vendor': ['*', 'company_A'],
'tenant: ['*', 'default']
}
2) Convert special value `all` to the corresponding attribute value in
2) Check whether using special role(ex: `all`) in target
As not assume using such in the further procedure, this method return here
in case check is NG.
However, once a object with the special role set as an attribute has been
registered, this check will prevent access to that object.
Therefore, for only user who has credentials with admin role or special
role(ex: `Tenant_all`) this check is skipped.
3) Convert special value `all` to the corresponding attribute value in
target.
:param target: a dictionary of the attributes of the object
being accessed.
:param credentials: The information about the user performing the action.
:param target_chk: boolean
True: execute check of 2)
False: skip check of 2)
:return tgt: The preprocessed target is returned.
:return user_attrs: The preprocessed credentials is returned.
:raises tacker.common.exceptions.PolicyTargetCheckError
if check of 2) is NG
"""
if not cfg.CONF.oslo_policy.enhanced_tacker_policy:
return target, credentials
@@ -124,6 +138,7 @@ def _pre_enhanced_policy_check(target, credentials):
LOG.debug(f'target: {target}')
special_roles = {'area': r'all@\w+', 'vendor': 'all', 'tenant': 'all'}
convert_map = {
'area_': 'area',
'vendor_': 'vendor',
@@ -134,7 +149,7 @@ def _pre_enhanced_policy_check(target, credentials):
'vendor': ['*'],
'tenant': ['*']
}
# Convert special roles to enhanced policy attributes in credentials.
# 1) Convert special roles to enhanced policy attributes in credentials.
for role in credentials.get('roles'):
role = role.lower()
for prefix, key in convert_map.items():
@@ -143,9 +158,33 @@ def _pre_enhanced_policy_check(target, credentials):
if attr:
user_attrs[key].append(attr)
# 2) Check whether using special role(ex: `all`) in target,
if target_chk and not credentials.get('is_admin', False):
for k, v in tgt.items():
if (k in special_roles and
re.match(special_roles[k], v)):
chk_all = False
# Not NG in case credentials has special role
for uv in user_attrs[k]:
if re.match(special_roles[k], uv):
# In case 'area':
# OK case1 : credential is all@all and
# target is all@region_A
# OK case2 : credential is all@region_A and
# target is all@region_A
# NG case : credential is all@region_A and
# target is all@region_B
if k == 'area' and uv != 'all@all' and uv != v.lower():
continue
chk_all = True
if not chk_all:
msg = f'`{v}` of {k} in target is special role'
LOG.error(msg)
raise exceptions.PolicyTargetCheckError(reason=msg)
common_keys = user_attrs.keys() & tgt.keys()
# Convert special value `all` to the corresponding attribute value in
# 3) Convert special value `all` to the corresponding attribute value in
# target.
for key in common_keys:
tgt[key] = tgt[key].lower()
@@ -153,10 +192,11 @@ def _pre_enhanced_policy_check(target, credentials):
if tgt.get(key) == '*':
continue
to_remove = []
orig_attrs = copy.deepcopy(attrs)
if 'area' == key:
if not is_valid_area(tgt.get(key)):
continue
for attr in attrs:
for attr in orig_attrs:
if not is_valid_area(attr):
continue
if 'all@all' == attr:
@@ -183,7 +223,7 @@ def _pre_enhanced_policy_check(target, credentials):
# 'all@region_A' -> to be removed.
else:
for attr in attrs:
for attr in orig_attrs:
if 'all' == attr:
# example:
# target = {'vendor': 'company_A'}
@@ -217,9 +257,16 @@ def authorize(context, action, target, do_raise=True, exc=None):
# readable way.
if context.system_scope:
credentials['system'] = context.system_scope
target, credentials = _pre_enhanced_policy_check(target, credentials)
if not exc:
exc = exceptions.PolicyNotAuthorized
try:
target, credentials = _pre_enhanced_policy_check(target, credentials)
except exceptions.PolicyTargetCheckError:
LOG.error('Policy check for %(action)s failed with target check '
'%(target)s', {'action': action, 'target': target})
raise exc(action=action)
try:
result = _ENFORCER.authorize(action, target, credentials,
do_raise=do_raise, exc=exc, action=action)
@@ -554,7 +601,12 @@ def check(context, action, target, plugin=None, might_not_exist=False,
target.update({'area': area})
if 'tenant_id' in target:
target['project_id'] = target['tenant_id']
target, credentials = _pre_enhanced_policy_check(target, credentials)
try:
target, credentials = _pre_enhanced_policy_check(target, credentials)
except exceptions.PolicyTargetCheckError:
LOG.error('Policy check for %(action)s failed with target check '
'%(target)s', {'action': action, 'target': target})
return False
result = _ENFORCER.enforce(match_rule,
target,
@@ -602,8 +654,21 @@ def enforce(context, action, target, plugin=None, pluralized=None,
target.update({'area': area})
if 'tenant_id' in target:
target['project_id'] = target['tenant_id']
target, credentials = _pre_enhanced_policy_check(target, credentials)
# About target_chk:
# Set target_chk=False, as not execute target check.
# The reason is that matching with the behavior of other APIs
# that pass through the 'authorize' method.
# ex:
# 1 openstack vim register with area set special role
# (this method is passed through, for policy check)
# -> target_chk=True, policy check `NG`
# 2 instantiate with request parameter area set special role
# (`authorize` method is passed through, for policy check)
# -> target_chk=True, policy check `OK`
# -> There is a difference in the behavior of 1 and 2
target, credentials = _pre_enhanced_policy_check(
target, credentials, target_chk=False)
try:
result = _ENFORCER.enforce(rule, target, credentials, action=action,
do_raise=True, exc=exc)

View File

@@ -766,6 +766,36 @@ class VimAPIsTest(BaseTackerTest, BaseEnhancedPolicyTest):
# step 9 VIM-Delete, Resource Group C / User Group admin
self._step_vim_delete('user_admin', vim_c, 204)
def _test_vim_apis_enhanced_policy_special_role(self, vim_type, local_vim):
# step 1 VIM-Register, Area special role / User Group A
vim_a_1 = self._step_vim_register(
'user_a', vim_type, local_vim, 'vim_a_1', 'all@region_A', 201)
# step 2 VIM-Register, Area special role / User Group A
vim_a_2 = self._step_vim_register(
'user_a', vim_type, local_vim, 'vim_a_2', 'all@all', 201)
# step 3 VIM-Show, Area special role / User Group A
self._step_vim_show('user_a', vim_a_1, 404)
# step 4 VIM-Show, Area special role / User Group A
self._step_vim_show('user_a', vim_a_2, 404)
# step 5 VIM-Show, Area special role / User Group All
self._step_vim_show('user_all', vim_a_1, 200)
# step 6 VIM-Show, Area special role / User Group Admin
self._step_vim_show('user_admin', vim_a_2, 200)
# step 7 VIM-Delete, Area special role / User Group A
self._step_vim_delete('user_a', vim_a_1, 404)
# step 8 VIM-Delete, Area special role / User Group All
self._step_vim_delete('user_all', vim_a_1, 204)
# step 9 VIM-Delete, Area special role / User Group Admin
self._step_vim_delete('user_admin', vim_a_2, 204)
class VnflcmAPIsV1Base(vnflcm_base.BaseVnfLcmTest, BaseEnhancedPolicyTest):

View File

@@ -23,3 +23,7 @@ class VimAPIsOpenstackTest(VimAPIsTest):
def test_vim_apis_vim_without_area_openstack(self):
self._test_vim_apis_vim_without_area_attribute(
'openstack', 'local-vim.yaml')
def test_vim_apis_vim_with_area_openstack_special_role(self):
self._test_vim_apis_enhanced_policy_special_role(
'openstack', 'local-vim.yaml')

View File

@@ -228,12 +228,37 @@ class BaseVnfPackageAPIsTest(BaseTackerTest, BaseEnhancedPolicyTest):
# step 29 PKG-Delete, Resource Group B / User Group all
self._step_pkg_delete('user_all', pkg_b, 204)
def _test_vnf_package_apis_enhanced_policy_special_role(self, csar_name):
# step 1 PKG-Create, Resource Group A / User Group A
pkg_a = self._step_pkg_create('user_a')
# step 2 PKG-Upload-content, Vendor Special Role / User Group A
self._step_pkg_upload_content(
'user_a', pkg_a, csar_name, 'all', 403)
# step 3 PKG-Upload-content, Vendor Special Role / User Group all
self._step_pkg_upload_content(
'user_all', pkg_a, csar_name, 'all', 202)
# step 4 PKG-Update, Vendor Special Role / User Group A
self._step_pkg_update('user_a', pkg_a, 403)
# step 5 PKG-Update, Vendor Special Role / User Group all
self._step_pkg_update('user_all', pkg_a, 200)
# step 6 PKG-Delete, Vendor Special Role / User Group all
self._step_pkg_delete('user_all', pkg_a, 204)
class VnfPackageAPIsTest(BaseVnfPackageAPIsTest):
def test_vnf_package_apis_enhanced_policy_vnf(self):
self._test_vnf_package_apis_enhanced_policy('test_enhanced_policy')
def test_vnf_package_apis_enhanced_policy_vnf_special_role(self):
self._test_vnf_package_apis_enhanced_policy_special_role(
'test_enhanced_policy')
class CnfPackageAPIsTest(BaseVnfPackageAPIsTest):

View File

@@ -41,6 +41,8 @@ class VnflcmAPIsV2VNFBase(CommonVnfLcmTest, BaseEnhancedPolicyTest):
'TENANT_tenant_B', 'manager'],
'user_c': ['VENDOR_company_C', 'AREA_area_C@region_C',
'TENANT_tenant_C', 'manager'],
'user_c_1': ['VENDOR_all', 'AREA_all@all',
'TENANT_tenant_C', 'manager'],
'user_all': ['VENDOR_all', 'AREA_all@all',
'TENANT_all', 'manager'],
'user_admin': ['admin']
@@ -49,6 +51,7 @@ class VnflcmAPIsV2VNFBase(CommonVnfLcmTest, BaseEnhancedPolicyTest):
'user_a': 'tenant_A',
'user_b': 'tenant_B',
'user_c': 'tenant_C',
'user_c_1': 'all',
'user_all': 'tenant_B',
'user_admin': 'tenant_C'
}
@@ -119,6 +122,10 @@ class VnflcmAPIsV2VNFBase(CommonVnfLcmTest, BaseEnhancedPolicyTest):
change_vnfpkg_from_image_to_image_path_2, image_path=image_path,
provider='company_C')
# for Vendor Special Role
cls.vnf_pkg_sr, cls.vnfd_id_sr = cls.create_vnf_package(
basic_lcms_min_path, image_path=image_path, provider='all')
@classmethod
def tearDownClass(cls):
cls.delete_vnf_package(cls.vnf_pkg_a)
@@ -130,6 +137,7 @@ class VnflcmAPIsV2VNFBase(CommonVnfLcmTest, BaseEnhancedPolicyTest):
cls.delete_vnf_package(cls.vnf_pkg_c)
cls.delete_vnf_package(cls.vnf_pkg_c_1)
cls.delete_vnf_package(cls.vnf_pkg_c_2)
cls.delete_vnf_package(cls.vnf_pkg_sr)
BaseEnhancedPolicyTest.tearDownClass()
super(VnflcmAPIsV2VNFBase, cls).tearDownClass()
@@ -739,6 +747,63 @@ class VnflcmAPIsV2VNFInstantiateWithArea(VnflcmAPIsV2VNFBase):
sub_id, inst_id_a, inst_id_b, zone_name_list, glance_image,
flavour_vdu_dict)
def test_vnflcm_apis_v2_vnf_with_area_in_vim_conn_info_sr_area(self):
# test in case area is special role, including vendor is special role
glance_image = None
flavour_vdu_dict = None
zone_name_list = None
# step 1 LCM-CreateV2, Vendor Special Role / User Group A
self._step_lcm_create('user_a', self.vnfd_id_sr, 403)
# step 2 LCM-CreateV2, Resource Group A / User Group A
inst_id_a = self._step_lcm_create('user_a', self.vnfd_id_a, 201)
# step 3 LCM-InstantiateV2, Area Special Role / User Group A
self._step_lcm_instantiate('user_a', inst_id_a, 'tenant_A',
glance_image, flavour_vdu_dict,
zone_name_list, 202, area='all@all')
# step 4 LCM-ShowV2, Area Special Role / User Group A
self._step_lcm_show('user_a', inst_id_a, 403)
# step 5 LCM-ShowV2, Area Special Role / User Group Admin
self._step_lcm_show('user_admin', inst_id_a, 200)
# step 6 LCM-TerminateV2, Area Special Role / User Group Admin
self._step_lcm_terminate('user_admin', inst_id_a, 202)
# step 7 LCM-DeleteV2, Resource Group A / User Group Admin
self._step_lcm_delete('user_admin', inst_id_a, 204)
def test_vnflcm_apis_v2_vnf_with_area_in_vim_conn_info_sr_tenant(self):
# test in case tenant: special role
glance_image = None
flavour_vdu_dict = None
zone_name_list = None
# step 1 LCM-CreateV2, Resource Group C / User Group C-1
inst_id_c = self._step_lcm_create('user_c_1', self.vnfd_id_c, 201)
# step 2 LCM-InstantiateV2, Tenant Special Role / User Group C-1
self._step_lcm_instantiate('user_c_1', inst_id_c, 'all',
glance_image, flavour_vdu_dict,
zone_name_list, 202, area='area_C@region_C')
# step 3 LCM-ShowV2, Tenant Special Role / User Group C_1
self._step_lcm_show('user_c_1', inst_id_c, 403)
# step 4 LCM-ShowV2, Tenant Special Role / User Group Admin
self._step_lcm_show('user_admin', inst_id_c, 200)
# step 5 LCM-TerminateV2, Tenant Special Role / User Group Admin
self._step_lcm_terminate('user_admin', inst_id_c, 202)
# step 6 LCM-DeleteV2, Resource Group C / User Group Admin
self._step_lcm_delete('user_admin', inst_id_c, 204)
class VnflcmAPIsV2VNFInstantiateWithAreaInRegisteredVim(VnflcmAPIsV2VNFBase):

View File

@@ -124,6 +124,8 @@ CONF = config.CONF
def get_test_data_policy_instantiate():
rules = {POLICY_NAME.format('instantiate'): "vendor:%(vendor)s"}
rules_admin = {POLICY_NAME.format('instantiate'):
"(vendor:%(vendor)s or role:admin)"}
test_data = [
# 'expected_status_code': http_client.ACCEPTED
{
@@ -138,6 +140,18 @@ def get_test_data_policy_instantiate():
'roles': ['VENDOR_all'],
'expected_status_code': http_client.ACCEPTED
},
{
'vnf_instance_updates': {'vnfProvider': 'all'},
'rules': rules,
'roles': ['VENDOR_all'],
'expected_status_code': http_client.ACCEPTED
},
{
'vnf_instance_updates': {'vnfProvider': 'all'},
'rules': rules_admin,
'roles': ['admin'],
'expected_status_code': http_client.ACCEPTED
},
# 'expected_status_code': http_client.FORBIDDEN
{
'vnf_instance_updates': {'vnfProvider': 'provider_A'},
@@ -151,6 +165,12 @@ def get_test_data_policy_instantiate():
'roles': ['VENDOR_provider_B'],
'expected_status_code': http_client.FORBIDDEN
},
{
'vnf_instance_updates': {'vnfProvider': 'all'},
'rules': rules,
'roles': ['VENDOR_provider_A'],
'expected_status_code': http_client.FORBIDDEN
},
]
return test_data
@@ -163,6 +183,20 @@ def get_test_data_policy_vnf_instantiated(action, success_status_code):
access_info={"key1": 'value1', "key2": 'value2'},
extra={'area': 'area_A@region_A'}
)
vim_connection_info_area_all_region_a = objects.VimConnectionInfo(
id='f8c35bd0-4d67-4436-9f11-14b8a84c92aa',
vimId='f8c35bd0-4d67-4436-9f11-14b8a84c92aa',
vimType='openstack',
access_info={"key1": 'value1', "key2": 'value2'},
extra={'area': 'all@region_A'} # special role
)
vim_connection_info_area_all_region_all = objects.VimConnectionInfo(
id='f8c35bd0-4d67-4436-9f11-14b8a84c92aa',
vimId='f8c35bd0-4d67-4436-9f11-14b8a84c92aa',
vimType='openstack',
access_info={"key1": 'value1', "key2": 'value2'},
extra={'area': 'all@all'} # special role
)
vim_connection_info_without_area = objects.VimConnectionInfo(
id='f8c35bd0-4d67-4436-9f11-14b8a84c92aa',
vimId='f8c35bd0-4d67-4436-9f11-14b8a84c92aa',
@@ -177,11 +211,24 @@ def get_test_data_policy_vnf_instantiated(action, success_status_code):
'vnfProvider': 'provider_A',
'vimConnectionInfo': {'vim1': vim_connection_info_without_area}
}
vnf_instance_updates_area_all_region_a = {
'vnfProvider': 'provider_A',
'vimConnectionInfo': {'vim1': vim_connection_info_area_all_region_a}
}
vnf_instance_updates_area_all_region_all = {
'vnfProvider': 'provider_A',
'vimConnectionInfo': {'vim1': vim_connection_info_area_all_region_all}
}
rule_area_vendor_tenant = {
POLICY_NAME.format(action):
"area:%(area)s and vendor:%(vendor)s and "
"tenant:%(tenant)s"
}
rule_area_vendor_tenant_admin = {
POLICY_NAME.format(action):
"area:%(area)s and vendor:%(vendor)s and "
"tenant:%(tenant)s or role:admin"
}
rule_vendor = {
POLICY_NAME.format(action): "vendor:%(vendor)s"
}
@@ -227,6 +274,62 @@ def get_test_data_policy_vnf_instantiated(action, success_status_code):
],
'expected_status_code': success_status_code
},
{
'vnf_instance_updates': vnf_instance_updates_area_all_region_a,
'tenant': 'tenant_A',
'rules': rule_area_vendor_tenant,
'roles': [
'AREA_all@region_A',
'VENDOR_provider_A',
'TENANT_tenant_A'
],
'expected_status_code': success_status_code
},
{
'vnf_instance_updates': vnf_instance_updates_area_all_region_a,
'tenant': 'tenant_A',
'rules': rule_area_vendor_tenant,
'roles': [
'AREA_all@all',
'VENDOR_provider_A',
'TENANT_tenant_A'
],
'expected_status_code': success_status_code
},
{
'vnf_instance_updates': vnf_instance_updates_area_all_region_all,
'tenant': 'tenant_A',
'rules': rule_area_vendor_tenant,
'roles': [
'AREA_all@all',
'VENDOR_provider_A',
'TENANT_tenant_A'
],
'expected_status_code': success_status_code
},
{
'vnf_instance_updates': vnf_instance_updates_area_all_region_all,
'tenant': 'tenant_A',
'rules': rule_area_vendor_tenant_admin,
'roles': [
'AREA_all@region_A',
'VENDOR_provider_A',
'TENANT_tenant_A',
'admin'
],
'expected_status_code': success_status_code
},
{
'vnf_instance_updates': vnf_instance_updates,
'tenant': 'all', # special role
'rules': rule_area_vendor_tenant,
'roles': [
'AREA_area_A@region_A',
'VENDOR_provider_A',
'TENANT_all'
],
'expected_status_code': success_status_code
},
# 'expected_status_code': http_client.FORBIDDEN
{
'vnf_instance_updates': vnf_instance_updates,
@@ -395,7 +498,40 @@ def get_test_data_policy_vnf_instantiated(action, success_status_code):
'VENDOR_provider_B',
],
'expected_status_code': http_client.FORBIDDEN
}
},
{
'vnf_instance_updates': vnf_instance_updates_area_all_region_all,
'tenant': 'tenant_A',
'rules': rule_area_vendor_tenant,
'roles': [
'AREA_all@region_A',
'VENDOR_provider_A',
'TENANT_tenant_A'
],
'expected_status_code': http_client.FORBIDDEN
},
{
'vnf_instance_updates': vnf_instance_updates_area_all_region_a,
'tenant': 'tenant_A',
'rules': rule_area_vendor_tenant,
'roles': [
'AREA_all@region_B',
'VENDOR_provider_A',
'TENANT_tenant_A'
],
'expected_status_code': http_client.FORBIDDEN
},
{
'vnf_instance_updates': vnf_instance_updates,
'tenant': 'all', # special role
'rules': rule_area_vendor_tenant,
'roles': [
'AREA_area_A@region_A',
'VENDOR_provider_A',
'TENANT_tenant_A'
],
'expected_status_code': http_client.FORBIDDEN
},
]
return test_data
@@ -416,6 +552,12 @@ def get_test_data_policy_delete():
'roles': ['VENDOR_all'],
'expected_status_code': http_client.NO_CONTENT
},
{
'vnf_instance_updates': {'vnfProvider': 'all'}, # special role
'rules': rules,
'roles': ['VENDOR_all'],
'expected_status_code': http_client.NO_CONTENT
},
# 'expected_status_code': http_client.FORBIDDEN
{
'vnf_instance_updates': {'vnfProvider': 'provider_A'},
@@ -429,6 +571,12 @@ def get_test_data_policy_delete():
'roles': ['VENDOR_provider_B'],
'expected_status_code': http_client.FORBIDDEN
},
{
'vnf_instance_updates': {'vnfProvider': 'all'}, # special role
'rules': rules,
'roles': ['VENDOR_provider_B'],
'expected_status_code': http_client.FORBIDDEN
},
]
return test_data
@@ -1995,6 +2143,8 @@ class TestVnflcmV2EnhancedPolicy(TestVnflcmV2):
request = requests.Request()
ctx = context.Context('fake', 'fake', roles=roles)
ctx.api_version = api_version.APIVersion("2.0.0")
if 'admin' in roles:
ctx.is_admin = True
request.context = ctx
return request

View File

@@ -30,8 +30,11 @@ from tacker.common import exceptions
from tacker import context
from tacker import manager
from tacker import policy
from tacker.sol_refactored.common import config
from tacker.tests import base
CONF = config.CONF
class PolicyFileTestCase(base.BaseTestCase):
def setUp(self):
@@ -555,3 +558,39 @@ class TackerPolicyTestCase(base.BaseTestCase):
{'extension:provider_network:set': 'rule:admin_only'},
dict((policy, 'rule:admin_only') for policy in
expected_policies))
class EnhancedPolicyTestCace(base.BaseTestCase):
def setUp(self):
super(EnhancedPolicyTestCace, self).setUp()
CONF.set_override(
'enhanced_tacker_policy', True, group='oslo_policy')
policy.reset()
self.addCleanup(policy.reset)
policy.init()
rules = {
'manager_and_owner': 'role:manager and project_id:%(project_id)s',
'vim_attrs_cmp': 'area:%(area)s',
'create_vim': 'rule:manager_and_owner or role:admin',
'get_vim': 'rule:vim_attrs_cmp or role:admin'
}
policy.set_rules(common_policy.Rules.from_dict(rules), overwrite=True)
self.context = context.Context('fake', 'fake', roles=['manager'])
self.target = {'project_id': 'fake', 'user_id': 'fake', 'vendor': '*',
'area': '*', 'tenant': '*'}
@mock.patch.object(common_policy.Enforcer, 'enforce')
def test_enforce_with_target_special_role(self, mock_enforce):
self.target['vendor'] = 'all'
action = 'create_vim'
result = policy.enforce(self.context, action, self.target)
self.assertTrue(result)
self.assertTrue(mock_enforce.called)
@mock.patch.object(common_policy.Enforcer, 'enforce')
def test_check_with_target_special_role(self, mock_enforce):
self.target['vendor'] = 'all'
action = 'get_vim'
result = policy.check(self.context, action, self.target)
self.assertFalse(result)
self.assertFalse(mock_enforce.called)