diff --git a/horizon/base.py b/horizon/base.py index 5db632730..a373a70df 100644 --- a/horizon/base.py +++ b/horizon/base.py @@ -45,6 +45,7 @@ from horizon.decorators import _current_component # noqa from horizon.decorators import require_auth # noqa from horizon.decorators import require_perms # noqa from horizon import loaders +from horizon.utils import settings as utils_settings # Name of the panel group for panels to be displayed without a group. @@ -144,7 +145,7 @@ class HorizonComponent(object): return self._can_access(context['request']) def _can_access(self, request): - policy_check = getattr(settings, "POLICY_CHECK_FUNCTION", None) + policy_check = utils_settings.import_setting("POLICY_CHECK_FUNCTION") # this check is an OR check rather than an AND check that is the # default in the policy engine, so calling each rule individually diff --git a/horizon/tables/actions.py b/horizon/tables/actions.py index 354e3c04c..3d7af34d0 100644 --- a/horizon/tables/actions.py +++ b/horizon/tables/actions.py @@ -33,6 +33,7 @@ import six from horizon import messages from horizon.utils import functions from horizon.utils import html +from horizon.utils import settings as utils_settings LOG = logging.getLogger(__name__) @@ -129,7 +130,7 @@ class BaseAction(html.HTMLElement): return True def _allowed(self, request, datum): - policy_check = getattr(settings, "POLICY_CHECK_FUNCTION", None) + policy_check = utils_settings.import_setting("POLICY_CHECK_FUNCTION") if policy_check and self.policy_rules: target = self.get_policy_target(request, datum) diff --git a/horizon/utils/settings.py b/horizon/utils/settings.py new file mode 100644 index 000000000..9e9b0c04f --- /dev/null +++ b/horizon/utils/settings.py @@ -0,0 +1,28 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import six + +from django.conf import settings +from django.utils.module_loading import import_string + + +def import_object(name_or_object): + if isinstance(name_or_object, six.string_types): + return import_string(name_or_object) + return name_or_object + + +def import_setting(name): + """Imports an object specified either directly or as a module path.""" + value = getattr(settings, name, None) + return import_object(value) diff --git a/openstack_dashboard/dashboards/identity/projects/tests.py b/openstack_dashboard/dashboards/identity/projects/tests.py index 325d7353e..f47ca3476 100644 --- a/openstack_dashboard/dashboards/identity/projects/tests.py +++ b/openstack_dashboard/dashboards/identity/projects/tests.py @@ -27,7 +27,6 @@ from mox3.mox import IgnoreArg # noqa from mox3.mox import IsA # noqa from horizon.workflows import views -from openstack_auth import policy as policy_backend from openstack_dashboard import api from openstack_dashboard.dashboards.identity.projects import workflows @@ -100,7 +99,7 @@ class TenantsViewTests(test.BaseAdminViewTests): class ProjectsViewNonAdminTests(test.TestCase): - @override_settings(POLICY_CHECK_FUNCTION=policy_backend.check) + @override_settings(POLICY_CHECK_FUNCTION='openstack_auth.policy.check') @test.create_stubs({api.keystone: ('tenant_list', 'domain_lookup')}) def test_index(self): diff --git a/openstack_dashboard/policy.py b/openstack_dashboard/policy.py index 8f8c1733f..da9b49045 100644 --- a/openstack_dashboard/policy.py +++ b/openstack_dashboard/policy.py @@ -12,13 +12,13 @@ # under the License. -from django.conf import settings +from horizon.utils import settings as utils_settings def check(actions, request, target=None): """Wrapper of the configurable policy method.""" - policy_check = getattr(settings, "POLICY_CHECK_FUNCTION", None) + policy_check = utils_settings.import_setting("POLICY_CHECK_FUNCTION") if policy_check: return policy_check(actions, request, target) diff --git a/openstack_dashboard/settings.py b/openstack_dashboard/settings.py index 22f9857a2..2c921b604 100644 --- a/openstack_dashboard/settings.py +++ b/openstack_dashboard/settings.py @@ -305,14 +305,7 @@ THEME_COLLECTION_DIR = 'themes' # Theme Cookie Name THEME_COOKIE_NAME = 'theme' - -def check(actions, request, target=None): - # Note(Itxaka): This is to prevent circular dependencies and apps not ready - # If you do django imports in your settings, you are gonna have a bad time - from openstack_auth import policy - return policy.check(actions, request, target) - -POLICY_CHECK_FUNCTION = check +POLICY_CHECK_FUNCTION = 'openstack_auth.policy.check' CSRF_COOKIE_AGE = None diff --git a/openstack_dashboard/test/api_tests/neutron_tests.py b/openstack_dashboard/test/api_tests/neutron_tests.py index 1f265fe6a..9213ce712 100644 --- a/openstack_dashboard/test/api_tests/neutron_tests.py +++ b/openstack_dashboard/test/api_tests/neutron_tests.py @@ -617,7 +617,7 @@ class NeutronApiTests(test.APITestCase): @override_settings(OPENSTACK_NEUTRON_NETWORK={'enable_distributed_router': True}, - POLICY_CHECK_FUNCTION=policy.check) + POLICY_CHECK_FUNCTION='openstack_auth.policy.check') @test.create_stubs({api.neutron: ('is_extension_supported',)}) def _test_get_dvr_permission_with_policy_check(self, policy_check_allowed, operation): @@ -655,7 +655,7 @@ class NeutronApiTests(test.APITestCase): @override_settings(OPENSTACK_NEUTRON_NETWORK={'enable_distributed_router': True}, - POLICY_CHECK_FUNCTION=policy.check) + POLICY_CHECK_FUNCTION='openstack_auth.policy.check') def test_get_dvr_permission_dvr_unsupported_operation(self): self.assertRaises(ValueError, api.neutron.get_feature_permission, @@ -675,7 +675,7 @@ class NeutronApiTests(test.APITestCase): # above. l3-ha check only checks l3-ha specific code. @override_settings(OPENSTACK_NEUTRON_NETWORK={'enable_ha_router': True}, - POLICY_CHECK_FUNCTION=policy.check) + POLICY_CHECK_FUNCTION='openstack_auth.policy.check') @test.create_stubs({api.neutron: ('is_extension_supported', )}) def _test_get_router_ha_permission_with_policy_check(self, ha_enabled): self.mox.StubOutWithMock(policy, 'check') diff --git a/openstack_dashboard/test/api_tests/policy_rest_tests.py b/openstack_dashboard/test/api_tests/policy_rest_tests.py index 8d1d2ec04..b77077259 100644 --- a/openstack_dashboard/test/api_tests/policy_rest_tests.py +++ b/openstack_dashboard/test/api_tests/policy_rest_tests.py @@ -11,46 +11,45 @@ # limitations under the License. from django.test.utils import override_settings # noqa -from openstack_auth import policy as policy_backend from openstack_dashboard.api.rest import policy from openstack_dashboard.test import helpers as test class PolicyRestTestCase(test.TestCase): - @override_settings(POLICY_CHECK_FUNCTION=policy_backend.check) + @override_settings(POLICY_CHECK_FUNCTION='openstack_auth.policy.check') def test_policy(self, body='{"rules": []}'): request = self.mock_rest_request(body=body) response = policy.Policy().post(request) self.assertStatusCode(response, 200) self.assertEqual({"allowed": True}, response.json) - @override_settings(POLICY_CHECK_FUNCTION=policy_backend.check) + @override_settings(POLICY_CHECK_FUNCTION='openstack_auth.policy.check') def test_rule_alone(self): body = '{"rules": [["compute", "compute:get_all" ]]}' self.test_policy(body) - @override_settings(POLICY_CHECK_FUNCTION=policy_backend.check) + @override_settings(POLICY_CHECK_FUNCTION='openstack_auth.policy.check') def test_multiple_rule(self): body = '{"rules": [["compute", "compute:get_all"],' \ ' ["compute", "compute:start"]]}' self.test_policy(body) - @override_settings(POLICY_CHECK_FUNCTION=policy_backend.check) + @override_settings(POLICY_CHECK_FUNCTION='openstack_auth.policy.check') def test_rule_with_empty_target(self): body = '{"rules": [["compute", "compute:get_all"],' \ ' ["compute", "compute:start"]],' \ ' "target": {}}' self.test_policy(body) - @override_settings(POLICY_CHECK_FUNCTION=policy_backend.check) + @override_settings(POLICY_CHECK_FUNCTION='openstack_auth.policy.check') def test_rule_with_target(self): body = '{"rules": [["compute", "compute:get_all"],' \ ' ["compute", "compute:start"]],' \ ' "target": {"project_id": "1"}}' self.test_policy(body) - @override_settings(POLICY_CHECK_FUNCTION=policy_backend.check) + @override_settings(POLICY_CHECK_FUNCTION='openstack_auth.policy.check') def test_policy_fail(self): # admin only rule, default test case user should fail request = self.mock_rest_request( @@ -59,7 +58,7 @@ class PolicyRestTestCase(test.TestCase): self.assertStatusCode(response, 200) self.assertEqual({"allowed": False}, response.json) - @override_settings(POLICY_CHECK_FUNCTION=policy_backend.check) + @override_settings(POLICY_CHECK_FUNCTION='openstack_auth.policy.check') def test_policy_error(self): # admin only rule, default test case user should fail request = self.mock_rest_request( @@ -69,7 +68,7 @@ class PolicyRestTestCase(test.TestCase): class AdminPolicyRestTestCase(test.BaseAdminViewTests): - @override_settings(POLICY_CHECK_FUNCTION=policy_backend.check) + @override_settings(POLICY_CHECK_FUNCTION='openstack_auth.policy.check') def test_rule_with_target(self): body = '{"rules": [["compute", "compute:unlock_override"]]}' request = self.mock_rest_request(body=body) diff --git a/openstack_dashboard/test/tests/policy.py b/openstack_dashboard/test/tests/policy.py index d8a422a5c..8c2a24fe7 100644 --- a/openstack_dashboard/test/tests/policy.py +++ b/openstack_dashboard/test/tests/policy.py @@ -12,14 +12,13 @@ # under the License. from django.test.utils import override_settings -from openstack_auth import policy as policy_backend from openstack_dashboard import policy from openstack_dashboard.test import helpers as test class PolicyTestCase(test.TestCase): - @override_settings(POLICY_CHECK_FUNCTION=policy_backend.check) + @override_settings(POLICY_CHECK_FUNCTION='openstack_auth.policy.check') def test_policy_check_set(self): value = policy.check((("identity", "admin_required"),), request=self.request) @@ -33,7 +32,7 @@ class PolicyTestCase(test.TestCase): class PolicyBackendTestCaseAdmin(test.BaseAdminViewTests): - @override_settings(POLICY_CHECK_FUNCTION=policy_backend.check) + @override_settings(POLICY_CHECK_FUNCTION='openstack_auth.policy.check') def test_policy_check_set_admin(self): value = policy.check((("identity", "admin_required"),), request=self.request) diff --git a/openstack_dashboard/test/tests/policy_backend.py b/openstack_dashboard/test/tests/policy_backend.py index 23fcf1a11..b1eec4803 100644 --- a/openstack_dashboard/test/tests/policy_backend.py +++ b/openstack_dashboard/test/tests/policy_backend.py @@ -31,14 +31,14 @@ class PolicyBackendTestCase(test.TestCase): policy_backend.reset() self.assertIsNone(policy_backend._ENFORCER) - @override_settings(POLICY_CHECK_FUNCTION=policy_backend.check) + @override_settings(POLICY_CHECK_FUNCTION='openstack_auth.policy.check') def test_check_admin_required_false(self): policy_backend.reset() value = policy.check((("identity", "admin_required"),), request=self.request) self.assertFalse(value) - @override_settings(POLICY_CHECK_FUNCTION=policy_backend.check) + @override_settings(POLICY_CHECK_FUNCTION='openstack_auth.policy.check') def test_check_identity_rule_not_found_false(self): policy_backend.reset() value = policy.check((("identity", "i_dont_exist"),), @@ -47,14 +47,14 @@ class PolicyBackendTestCase(test.TestCase): # identity is admin_required self.assertFalse(value) - @override_settings(POLICY_CHECK_FUNCTION=policy_backend.check) + @override_settings(POLICY_CHECK_FUNCTION='openstack_auth.policy.check') def test_check_nova_context_is_admin_false(self): policy_backend.reset() value = policy.check((("compute", "context_is_admin"),), request=self.request) self.assertFalse(value) - @override_settings(POLICY_CHECK_FUNCTION=policy_backend.check) + @override_settings(POLICY_CHECK_FUNCTION='openstack_auth.policy.check') def test_compound_check_false(self): policy_backend.reset() value = policy.check((("identity", "admin_required"), @@ -62,7 +62,7 @@ class PolicyBackendTestCase(test.TestCase): request=self.request) self.assertFalse(value) - @override_settings(POLICY_CHECK_FUNCTION=policy_backend.check) + @override_settings(POLICY_CHECK_FUNCTION='openstack_auth.policy.check') def test_scope_not_found(self): policy_backend.reset() value = policy.check((("dummy", "default"),), @@ -71,14 +71,14 @@ class PolicyBackendTestCase(test.TestCase): class PolicyBackendTestCaseAdmin(test.BaseAdminViewTests): - @override_settings(POLICY_CHECK_FUNCTION=policy_backend.check) + @override_settings(POLICY_CHECK_FUNCTION='openstack_auth.policy.check') def test_check_admin_required_true(self): policy_backend.reset() value = policy.check((("identity", "admin_required"),), request=self.request) self.assertTrue(value) - @override_settings(POLICY_CHECK_FUNCTION=policy_backend.check) + @override_settings(POLICY_CHECK_FUNCTION='openstack_auth.policy.check') def test_check_identity_rule_not_found_true(self): policy_backend.reset() value = policy.check((("identity", "i_dont_exist"),), @@ -87,7 +87,7 @@ class PolicyBackendTestCaseAdmin(test.BaseAdminViewTests): # identity is admin_required self.assertTrue(value) - @override_settings(POLICY_CHECK_FUNCTION=policy_backend.check) + @override_settings(POLICY_CHECK_FUNCTION='openstack_auth.policy.check') def test_compound_check_true(self): policy_backend.reset() value = policy.check((("identity", "admin_required"), @@ -95,7 +95,7 @@ class PolicyBackendTestCaseAdmin(test.BaseAdminViewTests): request=self.request) self.assertTrue(value) - @override_settings(POLICY_CHECK_FUNCTION=policy_backend.check) + @override_settings(POLICY_CHECK_FUNCTION='openstack_auth.policy.check') def test_check_nova_context_is_admin_true(self): policy_backend.reset() value = policy.check((("compute", "context_is_admin"),),