diff --git a/etc/magnum/policy.json b/etc/magnum/policy.json index 58f633f5ff..ad008eb2ee 100644 --- a/etc/magnum/policy.json +++ b/etc/magnum/policy.json @@ -1,12 +1,4 @@ { - "default": "rule:admin_or_owner", - - "quotas:get": "rule:default", - "quotas:get_all": "rule:admin_api", - "quotas:create": "rule:admin_api", - "quotas:update": "rule:admin_api", - "quotas:delete": "rule:admin_api", - "certificate:rotate_ca": "rule:admin_or_owner", "certificate:create": "rule:admin_or_user or rule:cluster_user", "certificate:get": "rule:admin_or_user or rule:cluster_user", diff --git a/magnum/common/policies/__init__.py b/magnum/common/policies/__init__.py index e5f115bb5f..d191625c69 100644 --- a/magnum/common/policies/__init__.py +++ b/magnum/common/policies/__init__.py @@ -19,6 +19,7 @@ from magnum.common.policies import bay from magnum.common.policies import baymodel from magnum.common.policies import cluster from magnum.common.policies import cluster_template +from magnum.common.policies import quota def list_rules(): @@ -27,5 +28,6 @@ def list_rules(): bay.list_rules(), baymodel.list_rules(), cluster.list_rules(), - cluster_template.list_rules() + cluster_template.list_rules(), + quota.list_rules() ) diff --git a/magnum/common/policies/quota.py b/magnum/common/policies/quota.py new file mode 100644 index 0000000000..83e1deaaf3 --- /dev/null +++ b/magnum/common/policies/quota.py @@ -0,0 +1,80 @@ +# All Rights Reserved. +# +# 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. +from oslo_policy import policy + +from magnum.common.policies import base + +QUOTA = 'quotas:%s' + +rules = [ + policy.DocumentedRuleDefault( + name=QUOTA % 'create', + check_str=base.RULE_ADMIN_API, + description='Create quota.', + operations=[ + { + 'path': '/v1/quotas', + 'method': 'POST' + } + ] + ), + policy.DocumentedRuleDefault( + name=QUOTA % 'delete', + check_str=base.RULE_ADMIN_API, + description='Delete quota for a given project_id and resource.', + operations=[ + { + 'path': '/v1/quotas/{project_id}/{resource}', + 'method': 'DELETE' + } + ] + ), + policy.DocumentedRuleDefault( + name=QUOTA % 'get', + check_str=base.RULE_ADMIN_OR_OWNER, + description='Retrieve Quota information for the given project_id.', + operations=[ + { + 'path': '/v1/quotas/{project_id}/{resource}', + 'method': 'GET' + } + ] + ), + policy.DocumentedRuleDefault( + name=QUOTA % 'get_all', + check_str=base.RULE_ADMIN_API, + description='Retrieve a list of quotas.', + operations=[ + { + 'path': '/v1/quotas', + 'method': 'GET' + } + ] + ), + policy.DocumentedRuleDefault( + name=QUOTA % 'update', + check_str=base.RULE_ADMIN_API, + description='Update quota for a given project_id.', + operations=[ + { + 'path': '/v1/quotas/{project_id}/{resource}', + 'method': 'PATCH' + } + ] + ) +] + + +def list_rules(): + return rules diff --git a/magnum/tests/fake_policy.py b/magnum/tests/fake_policy.py index 3fb36bc501..ed765c9f6a 100644 --- a/magnum/tests/fake_policy.py +++ b/magnum/tests/fake_policy.py @@ -15,8 +15,6 @@ policy_data = """ { - "default": "rule:admin_or_owner", - "certificate:create": "", "certificate:get": "", diff --git a/magnum/tests/unit/api/controllers/v1/test_certificate.py b/magnum/tests/unit/api/controllers/v1/test_certificate.py index cf84e0cb61..e65af08a4f 100644 --- a/magnum/tests/unit/api/controllers/v1/test_certificate.py +++ b/magnum/tests/unit/api/controllers/v1/test_certificate.py @@ -201,7 +201,9 @@ class TestRotateCaCertificate(api_base.FunctionalTest): self.conductor_api_class.return_value = self.conductor_api self.addCleanup(conductor_api_patcher.stop) - def test_rotate_ca_cert(self): + @mock.patch("magnum.common.policy.enforce") + def test_rotate_ca_cert(self, mock_policy): + mock_policy.return_value = True fake_cert = api_utils.cert_post_data() mock_cert = mock.MagicMock() mock_cert.as_dict.return_value = fake_cert @@ -227,7 +229,9 @@ class TestRotateCaCertificateNonTls(api_base.FunctionalTest): self.conductor_api_class.return_value = self.conductor_api self.addCleanup(conductor_api_patcher.stop) - def test_rotate_ca_cert_non_tls(self): + @mock.patch("magnum.common.policy.enforce") + def test_rotate_ca_cert_non_tls(self, mock_policy): + mock_policy.return_value = True fake_cert = api_utils.cert_post_data() mock_cert = mock.MagicMock() mock_cert.as_dict.return_value = fake_cert diff --git a/magnum/tests/unit/api/controllers/v1/test_quota.py b/magnum/tests/unit/api/controllers/v1/test_quota.py index b3d776e710..0fe1acd396 100644 --- a/magnum/tests/unit/api/controllers/v1/test_quota.py +++ b/magnum/tests/unit/api/controllers/v1/test_quota.py @@ -36,24 +36,32 @@ class TestQuota(api_base.FunctionalTest): def setUp(self): super(TestQuota, self).setUp() - def test_empty(self): + @mock.patch("magnum.common.policy.enforce") + def test_empty(self, mock_policy): + mock_policy.return_value = True response = self.get_json('/quotas') self.assertEqual([], response['quotas']) - def test_one(self): + @mock.patch("magnum.common.policy.enforce") + def test_one(self, mock_policy): + mock_policy.return_value = True quota = obj_utils.create_test_quota(self.context) response = self.get_json('/quotas') self.assertEqual(quota.project_id, response['quotas'][0]["project_id"]) self._verify_attrs(self._quota_attrs, response['quotas'][0]) - def test_get_one(self): + @mock.patch("magnum.common.policy.enforce") + def test_get_one(self, mock_policy): + mock_policy.return_value = True quota = obj_utils.create_test_quota(self.context) response = self.get_json('/quotas/%s/%s' % (quota['project_id'], quota['resource'])) self.assertEqual(quota.project_id, response['project_id']) self.assertEqual(quota.resource, response['resource']) - def test_get_one_not_found(self): + @mock.patch("magnum.common.policy.enforce") + def test_get_one_not_found(self, mock_policy): + mock_policy.return_value = True response = self.get_json( '/quotas/fake_project/invalid_res', expect_errors=True) @@ -174,7 +182,9 @@ class TestQuota(api_base.FunctionalTest): self.assertEqual(1, len(response['quotas'])) self.assertEqual('proj-id-1', response['quotas'][0]['project_id']) - def test_get_all_non_admin(self): + @mock.patch("magnum.common.policy.enforce") + def test_get_all_non_admin(self, mock_policy): + mock_policy.return_value = True quota_list = [] for i in range(4): quota = obj_utils.create_test_quota(self.context, @@ -186,8 +196,10 @@ class TestQuota(api_base.FunctionalTest): self.assertEqual(1, len(response['quotas'])) self.assertEqual('proj-id-2', response['quotas'][0]['project_id']) + @mock.patch("magnum.common.policy.enforce") @mock.patch.object(clients.OpenStackClients, 'keystone') - def test_create_quota(self, mock_keystone): + def test_create_quota(self, mock_keystone, mock_policy): + mock_policy.return_value = True quota_dict = apiutils.quota_post_data() response = self.post_json('/quotas', quota_dict) self.assertEqual('application/json', response.content_type) @@ -224,8 +236,10 @@ class TestQuota(api_base.FunctionalTest): self.assertEqual(400, response.status_int) self.assertTrue(response.json['errors']) + @mock.patch("magnum.common.policy.enforce") @mock.patch.object(clients.OpenStackClients, 'keystone') - def test_create_quota_no_project_id(self, mock_keystone): + def test_create_quota_no_project_id(self, mock_keystone, mock_policy): + mock_policy.return_value = True quota_dict = apiutils.quota_post_data() del quota_dict['project_id'] response = self.post_json('/quotas', quota_dict, expect_errors=True) @@ -233,8 +247,10 @@ class TestQuota(api_base.FunctionalTest): self.assertEqual(400, response.status_int) self.assertTrue(response.json['errors']) + @mock.patch("magnum.common.policy.enforce") @mock.patch.object(clients.OpenStackClients, 'keystone') - def test_patch_quota(self, mock_keystone): + def test_patch_quota(self, mock_keystone, mock_policy): + mock_policy.return_value = True quota_dict = apiutils.quota_post_data(hard_limit=5) response = self.post_json('/quotas', quota_dict) self.assertEqual('application/json', response.content_type) @@ -248,8 +264,10 @@ class TestQuota(api_base.FunctionalTest): self.assertEqual(202, response.status_int) self.assertEqual(20, response.json['hard_limit']) + @mock.patch("magnum.common.policy.enforce") @mock.patch.object(clients.OpenStackClients, 'keystone') - def test_patch_quota_not_found(self, mock_keystone): + def test_patch_quota_not_found(self, mock_keystone, mock_policy): + mock_policy.return_value = True quota_dict = apiutils.quota_post_data() response = self.post_json('/quotas', quota_dict) self.assertEqual('application/json', response.content_type) @@ -264,8 +282,10 @@ class TestQuota(api_base.FunctionalTest): self.assertEqual(404, response.status_int) self.assertTrue(response.json['errors']) + @mock.patch("magnum.common.policy.enforce") @mock.patch.object(clients.OpenStackClients, 'keystone') - def test_delete_quota(self, mock_keystone): + def test_delete_quota(self, mock_keystone, mock_policy): + mock_policy.return_value = True quota_dict = apiutils.quota_post_data() response = self.post_json('/quotas', quota_dict) self.assertEqual('application/json', response.content_type)