diff options
author | Lance Bragstad <lbragstad@gmail.com> | 2021-02-25 22:22:20 +0000 |
---|---|---|
committer | Dan Smith <dansmith@redhat.com> | 2021-03-08 09:32:06 -0800 |
commit | 165cce6d6e11504c85a71449fdca9608c7fd1d6c (patch) | |
tree | cd75da9011f4cdff4fda09e1f0ae21abf7c26a54 | |
parent | 31414b9f61ac4c923ede30a3c7e32662e9c14e1a (diff) | |
download | glance-165cce6d6e11504c85a71449fdca9608c7fd1d6c.tar.gz |
Update the task policies
At one point, these policies were used to protect actual task API
endpoints. Since then, they have also been used internally within
glance when spawning a task on behalf of the user for long-running
operations (like import).
These policies should not apply to the internal usage, as doing so
prevents the operator from setting them to restrictive values in order
to provide granular access to some roles. In the future we will fix
that by moving those checks out of "the onion" and into the task API
operations themselves, thus decoupling the internal and external uses.
This adds documentation and scope definitions for these policies, as
well as deprecates the "modify_task" policy which is never used and
will be removed in the future. Control over the actual tasks API
remains coarse with the "tasks_api_access" policy until a future
release completes the above decoupling.
Implements: blueprint secure-rbac
Change-Id: I70a58acd78053b54187dba8e35273366f14c47a4
-rw-r--r-- | glance/api/policy.py | 3 | ||||
-rw-r--r-- | glance/policies/tasks.py | 87 |
2 files changed, 85 insertions, 5 deletions
diff --git a/glance/api/policy.py b/glance/api/policy.py index 6c494fd90..40af5aa67 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 3dd674ed5..f221af2ce 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'} + ], + ) ] |