summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLance Bragstad <lbragstad@gmail.com>2021-02-25 22:22:20 +0000
committerDan Smith <dansmith@redhat.com>2021-03-08 09:32:06 -0800
commit165cce6d6e11504c85a71449fdca9608c7fd1d6c (patch)
treecd75da9011f4cdff4fda09e1f0ae21abf7c26a54
parent31414b9f61ac4c923ede30a3c7e32662e9c14e1a (diff)
downloadglance-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.py3
-rw-r--r--glance/policies/tasks.py87
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'}
+ ],
+ )
]