diff --git a/glance/api/policy.py b/glance/api/policy.py index 6c494fd90e..40af5aa677 100644 --- a/glance/api/policy.py +++ b/glance/api/policy.py @@ -449,14 +449,17 @@ class TaskRepoProxy(glance.domain.proxy.TaskRepo): task_proxy_class=TaskProxy, task_proxy_kwargs=proxy_kwargs) + # TODO(lbragstad): Move this to the tasks api itself def get(self, task_id): self.policy.enforce(self.context, 'get_task', {}) return super(TaskRepoProxy, self).get(task_id) + # TODO(lbragstad): Move this to the tasks api itself def add(self, task): self.policy.enforce(self.context, 'add_task', {}) super(TaskRepoProxy, self).add(task) + # TODO(lbragstad): Remove this after Xena def save(self, task): self.policy.enforce(self.context, 'modify_task', {}) super(TaskRepoProxy, self).save(task) diff --git a/glance/policies/tasks.py b/glance/policies/tasks.py index 3dd674ed58..f221af2cea 100644 --- a/glance/policies/tasks.py +++ b/glance/policies/tasks.py @@ -10,15 +10,92 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import versionutils from oslo_policy import policy +TASK_DESCRIPTION = """ +This granular policy controls access to tasks, both from the tasks API as well +as internal locations in Glance that use tasks (like import). Practically this +cannot be more restrictive than the policy that controls import or things will +break, and changing it from the default is almost certainly not what you want. +Access to the external tasks API should be restricted as desired by the +tasks_api_access policy. This may change in the future. +""" + +MODIFY_TASK_DEPRECATION = """ +This policy check has never been honored by the API. It will be removed in a +future release. +""" + +TASK_ACCESS_DESCRIPTION = """ +This is a generic blanket policy for protecting all task APIs. It is not +granular and will not allow you to separate writable and readable task +operations into different roles. +""" + task_policies = [ - policy.RuleDefault(name="get_task", check_str="rule:default"), - policy.RuleDefault(name="get_tasks", check_str="rule:default"), - policy.RuleDefault(name="add_task", check_str="rule:default"), - policy.RuleDefault(name="modify_task", check_str="rule:default"), - policy.RuleDefault(name="tasks_api_access", check_str="role:admin"), + policy.DocumentedRuleDefault( + name="get_task", + # All policies except tasks_api_access are internal policies that are + # only called by glance as a result of some other operation. + check_str='rule:default', + scope_types=['system', 'project'], + description='Get an image task.\n' + TASK_DESCRIPTION, + operations=[ + {'path': '/v2/tasks/{task_id}', + 'method': 'GET'} + ], + ), + policy.DocumentedRuleDefault( + name="get_tasks", + check_str='rule:default', + scope_types=['system', 'project'], + description='List tasks for all images.\n' + TASK_DESCRIPTION, + operations=[ + {'path': '/v2/tasks', + 'method': 'GET'} + ], + ), + policy.DocumentedRuleDefault( + name="add_task", + check_str='rule:default', + scope_types=['system', 'project'], + description='List tasks for all images.\n' + TASK_DESCRIPTION, + operations=[ + {'path': '/v2/tasks', + 'method': 'POST'} + ], + ), + policy.DocumentedRuleDefault( + name="modify_task", + check_str='rule:default', + scope_types=['system', 'project'], + description="This policy is not used.", + operations=[ + {'path': '/v2/tasks/{task_id}', + 'method': 'DELETE'} + ], + deprecated_for_removal=True, + deprecated_reason=MODIFY_TASK_DEPRECATION, + deprecated_since=versionutils.deprecated.WALLABY, + ), + policy.DocumentedRuleDefault( + name="tasks_api_access", + check_str="role:admin", + scope_types=['system', 'project'], + description=TASK_ACCESS_DESCRIPTION, + operations=[ + {'path': '/v2/tasks/{task_id}', + 'method': 'GET'}, + {'path': '/v2/tasks', + 'method': 'GET'}, + {'path': '/v2/tasks', + 'method': 'POST'}, + {'path': '/v2/tasks/{task_id}', + 'method': 'DELETE'} + ], + ) ]