diff --git a/glance/policies/base.py b/glance/policies/base.py index ef908eae27..77d023414b 100644 --- a/glance/policies/base.py +++ b/glance/policies/base.py @@ -54,16 +54,9 @@ PROJECT_READER_OR_PUBLIC_NAMESPACE = ( # # These check strings do not support tenancy with the `admin` role. This means # anyone with the `admin` role on any project can execute a policy, which is -# typical in OpenStack services. Eventually, these check strings will be -# superseded by check strings that implement scope checking and system-scope -# for applicable APIs (e.g., making an image public). But, we have a lot of -# cleanup to do in different parts of glance to sweep all the authorization -# code into a single layer before we can safely consume system-scope and -# implement scope checking. This refactoring also needs significant API testing -# to ensure we don't leave doors open to unintended users, or expose -# authoritative regressions. In the mean time, we can use the following check -# strings to offer formal support for project membership and a read-only -# variant consistent with other OpenStack services. +# typical in OpenStack services. But following check strings offer formal +# support for project membership and a read-only variant consistent with +# other OpenStack services. ADMIN_OR_PROJECT_MEMBER = f'role:admin or ({PROJECT_MEMBER})' ADMIN_OR_PROJECT_READER = f'role:admin or ({PROJECT_READER})' ADMIN_OR_PROJECT_READER_GET_IMAGE = ( diff --git a/glance/policies/discovery.py b/glance/policies/discovery.py index 3273a48ecb..50a4213304 100644 --- a/glance/policies/discovery.py +++ b/glance/policies/discovery.py @@ -19,7 +19,7 @@ discovery_policies = [ policy.DocumentedRuleDefault( name="stores_info_detail", check_str='role:admin', - scope_types=['system', 'project'], + scope_types=['project'], description='Expose store specific information', operations=[ {'path': '/v2/info/stores/detail', diff --git a/glance/policies/image.py b/glance/policies/image.py index 4bddd62d3a..c4400ec0bd 100644 --- a/glance/policies/image.py +++ b/glance/policies/image.py @@ -24,7 +24,7 @@ image_policies = [ policy.DocumentedRuleDefault( name="add_image", check_str=base.ADMIN_OR_PROJECT_MEMBER_CREATE_IMAGE, - scope_types=['system', 'project'], + scope_types=['project'], description='Create new image', operations=[ {'path': '/v2/images', @@ -38,7 +38,7 @@ image_policies = [ policy.DocumentedRuleDefault( name="delete_image", check_str=base.ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + scope_types=['project'], description='Deletes the image', operations=[ {'path': '/v2/images/{image_id}', @@ -52,7 +52,7 @@ image_policies = [ policy.DocumentedRuleDefault( name="get_image", check_str=base.ADMIN_OR_PROJECT_READER_GET_IMAGE, - scope_types=['system', 'project'], + scope_types=['project'], description='Get specified image', operations=[ {'path': '/v2/images/{image_id}', @@ -66,7 +66,7 @@ image_policies = [ policy.DocumentedRuleDefault( name="get_images", check_str=base.ADMIN_OR_PROJECT_READER, - scope_types=['system', 'project'], + scope_types=['project'], description='Get all available images', operations=[ {'path': '/v2/images', @@ -80,7 +80,7 @@ image_policies = [ policy.DocumentedRuleDefault( name="modify_image", check_str=base.ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + scope_types=['project'], description='Updates given image', operations=[ {'path': '/v2/images/{image_id}', @@ -94,7 +94,7 @@ image_policies = [ policy.DocumentedRuleDefault( name="publicize_image", check_str='role:admin', - scope_types=['system', 'project'], + scope_types=['project'], description='Publicize given image', operations=[ {'path': '/v2/images/{image_id}', @@ -104,7 +104,7 @@ image_policies = [ policy.DocumentedRuleDefault( name="communitize_image", check_str=base.ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + scope_types=['project'], description='Communitize given image', operations=[ {'path': '/v2/images/{image_id}', @@ -119,7 +119,7 @@ image_policies = [ policy.DocumentedRuleDefault( name="download_image", check_str=base.ADMIN_OR_PROJECT_MEMBER_DOWNLOAD_IMAGE, - scope_types=['system', 'project'], + scope_types=['project'], description='Downloads given image', operations=[ {'path': '/v2/images/{image_id}/file', @@ -133,7 +133,7 @@ image_policies = [ policy.DocumentedRuleDefault( name="upload_image", check_str=base.ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + scope_types=['project'], description='Uploads data to specified image', operations=[ {'path': '/v2/images/{image_id}/file', @@ -148,7 +148,7 @@ image_policies = [ policy.DocumentedRuleDefault( name="delete_image_location", check_str="role:admin", - scope_types=['system', 'project'], + scope_types=['project'], description='Deletes the location of given image', operations=[ {'path': '/v2/images/{image_id}', @@ -162,7 +162,7 @@ image_policies = [ policy.DocumentedRuleDefault( name="get_image_location", check_str=base.ADMIN_OR_PROJECT_READER, - scope_types=['system', 'project'], + scope_types=['project'], description='Reads the location of the image', operations=[ {'path': '/v2/images/{image_id}', @@ -176,7 +176,7 @@ image_policies = [ policy.DocumentedRuleDefault( name="set_image_location", check_str=base.ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + scope_types=['project'], description='Sets location URI to given image', operations=[ {'path': '/v2/images/{image_id}', @@ -191,7 +191,7 @@ image_policies = [ policy.DocumentedRuleDefault( name="add_member", check_str=base.ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + scope_types=['project'], description='Create image member', operations=[ {'path': '/v2/images/{image_id}/members', @@ -205,7 +205,7 @@ image_policies = [ policy.DocumentedRuleDefault( name="delete_member", check_str=base.ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + scope_types=['project'], description='Delete image member', operations=[ {'path': '/v2/images/{image_id}/members/{member_id}', @@ -219,7 +219,7 @@ image_policies = [ policy.DocumentedRuleDefault( name="get_member", check_str=base.ADMIN_OR_PROJECT_READER_OR_SHARED_MEMBER, - scope_types=['system', 'project'], + scope_types=['project'], description='Show image member details', operations=[ {'path': '/v2/images/{image_id}/members/{member_id}', @@ -233,7 +233,7 @@ image_policies = [ policy.DocumentedRuleDefault( name="get_members", check_str=base.ADMIN_OR_PROJECT_READER_OR_SHARED_MEMBER, - scope_types=['system', 'project'], + scope_types=['project'], description='List image members', operations=[ {'path': '/v2/images/{image_id}/members', @@ -247,7 +247,7 @@ image_policies = [ policy.DocumentedRuleDefault( name="modify_member", check_str=base.ADMIN_OR_SHARED_MEMBER, - scope_types=['system', 'project'], + scope_types=['project'], description='Update image member', operations=[ {'path': '/v2/images/{image_id}/members/{member_id}', @@ -262,17 +262,14 @@ image_policies = [ policy.RuleDefault( name="manage_image_cache", check_str='role:admin', - # NOTE(lbragstad): Remove 'project' from the list below when glance - # fully supports system-scope and this policy is updated to reflect - # that in the check string. - scope_types=['system', 'project'], + scope_types=['project'], description='Manage image cache' ), policy.DocumentedRuleDefault( name="deactivate", check_str=base.ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + scope_types=['project'], description='Deactivate image', operations=[ {'path': '/v2/images/{image_id}/actions/deactivate', @@ -286,7 +283,7 @@ image_policies = [ policy.DocumentedRuleDefault( name="reactivate", check_str=base.ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + scope_types=['project'], description='Reactivate image', operations=[ {'path': '/v2/images/{image_id}/actions/reactivate', @@ -301,11 +298,10 @@ image_policies = [ policy.DocumentedRuleDefault( name="copy_image", check_str='role:admin', - # Eventually, we need to make sure we update the check string here to - # be scope-aware, but for now this is restricted to system-admins and - # project-admins. That might change in the future if we decide to push + # For now this is restricted to project-admins. + # That might change in the future if we decide to push # this functionality down to project-members. - scope_types=['system', 'project'], + scope_types=['project'], description='Copy existing image to other stores', operations=[ {'path': '/v2/images/{image_id}/import', diff --git a/glance/policies/metadef.py b/glance/policies/metadef.py index 862e12e230..d1feaaed84 100644 --- a/glance/policies/metadef.py +++ b/glance/policies/metadef.py @@ -27,7 +27,7 @@ metadef_policies = [ policy.DocumentedRuleDefault( name="get_metadef_namespace", check_str=base.ADMIN_OR_PROJECT_READER_GET_NAMESPACE, - scope_types=['system', 'project'], + scope_types=['project'], description="Get a specific namespace.", operations=[ {'path': '/v2/metadefs/namespaces/{namespace_name}', @@ -42,7 +42,7 @@ metadef_policies = [ policy.DocumentedRuleDefault( name="get_metadef_namespaces", check_str=base.ADMIN_OR_PROJECT_READER, - scope_types=['system', 'project'], + scope_types=['project'], description="List namespace.", operations=[ {'path': '/v2/metadefs/namespaces', @@ -57,7 +57,7 @@ metadef_policies = [ policy.DocumentedRuleDefault( name="modify_metadef_namespace", check_str="rule:metadef_admin", - scope_types=['system', 'project'], + scope_types=['project'], description="Modify an existing namespace.", operations=[ {'path': '/v2/metadefs/namespaces/{namespace_name}', @@ -67,7 +67,7 @@ metadef_policies = [ policy.DocumentedRuleDefault( name="add_metadef_namespace", check_str="rule:metadef_admin", - scope_types=['system', 'project'], + scope_types=['project'], description="Create a namespace.", operations=[ {'path': '/v2/metadefs/namespaces', @@ -77,7 +77,7 @@ metadef_policies = [ policy.DocumentedRuleDefault( name="delete_metadef_namespace", check_str="rule:metadef_admin", - scope_types=['system', 'project'], + scope_types=['project'], description="Delete a namespace.", operations=[ {'path': '/v2/metadefs/namespaces/{namespace_name}', @@ -88,7 +88,7 @@ metadef_policies = [ policy.DocumentedRuleDefault( name="get_metadef_object", check_str=base.ADMIN_OR_PROJECT_READER_GET_NAMESPACE, - scope_types=['system', 'project'], + scope_types=['project'], description="Get a specific object from a namespace.", operations=[ {'path': '/v2/metadefs/namespaces/{namespace_name}/objects' @@ -104,7 +104,7 @@ metadef_policies = [ policy.DocumentedRuleDefault( name="get_metadef_objects", check_str=base.ADMIN_OR_PROJECT_READER_GET_NAMESPACE, - scope_types=['system', 'project'], + scope_types=['project'], description="Get objects from a namespace.", operations=[ {'path': '/v2/metadefs/namespaces/{namespace_name}/objects', @@ -119,7 +119,7 @@ metadef_policies = [ policy.DocumentedRuleDefault( name="modify_metadef_object", check_str="rule:metadef_admin", - scope_types=['system', 'project'], + scope_types=['project'], description="Update an object within a namespace.", operations=[ {'path': '/v2/metadefs/namespaces/{namespace_name}/objects' @@ -130,7 +130,7 @@ metadef_policies = [ policy.DocumentedRuleDefault( name="add_metadef_object", check_str="rule:metadef_admin", - scope_types=['system', 'project'], + scope_types=['project'], description="Create an object within a namespace.", operations=[ {'path': '/v2/metadefs/namespaces/{namespace_name}/objects', @@ -140,7 +140,7 @@ metadef_policies = [ policy.DocumentedRuleDefault( name="delete_metadef_object", check_str="rule:metadef_admin", - scope_types=['system', 'project'], + scope_types=['project'], description="Delete an object within a namespace.", operations=[ {'path': '/v2/metadefs/namespaces/{namespace_name}/objects' @@ -152,7 +152,7 @@ metadef_policies = [ policy.DocumentedRuleDefault( name="list_metadef_resource_types", check_str=base.ADMIN_OR_PROJECT_READER_GET_NAMESPACE, - scope_types=['system', 'project'], + scope_types=['project'], description="List meta definition resource types.", operations=[ {'path': '/v2/metadefs/resource_types', @@ -168,7 +168,7 @@ metadef_policies = [ policy.DocumentedRuleDefault( name="get_metadef_resource_type", check_str=base.ADMIN_OR_PROJECT_READER_GET_NAMESPACE, - scope_types=['system', 'project'], + scope_types=['project'], description="Get meta definition resource types associations.", operations=[ {'path': '/v2/metadefs/namespaces/{namespace_name}/resource_types', @@ -184,7 +184,7 @@ metadef_policies = [ policy.DocumentedRuleDefault( name="add_metadef_resource_type_association", check_str="rule:metadef_admin", - scope_types=['system', 'project'], + scope_types=['project'], description="Create meta definition resource types association.", operations=[ {'path': '/v2/metadefs/namespaces/{namespace_name}/resource_types', @@ -194,7 +194,7 @@ metadef_policies = [ policy.DocumentedRuleDefault( name="remove_metadef_resource_type_association", check_str="rule:metadef_admin", - scope_types=['system', 'project'], + scope_types=['project'], description="Delete meta definition resource types association.", operations=[ {'path': '/v2/metadefs/namespaces/{namespace_name}/resource_types' @@ -206,7 +206,7 @@ metadef_policies = [ policy.DocumentedRuleDefault( name="get_metadef_property", check_str=base.ADMIN_OR_PROJECT_READER_GET_NAMESPACE, - scope_types=['system', 'project'], + scope_types=['project'], description="Get a specific meta definition property.", operations=[ {'path': '/v2/metadefs/namespaces/{namespace_name}/properties' @@ -223,7 +223,7 @@ metadef_policies = [ policy.DocumentedRuleDefault( name="get_metadef_properties", check_str=base.ADMIN_OR_PROJECT_READER_GET_NAMESPACE, - scope_types=['system', 'project'], + scope_types=['project'], description="List meta definition properties.", operations=[ {'path': '/v2/metadefs/namespaces/{namespace_name}/properties', @@ -239,7 +239,7 @@ metadef_policies = [ policy.DocumentedRuleDefault( name="modify_metadef_property", check_str="rule:metadef_admin", - scope_types=['system', 'project'], + scope_types=['project'], description="Update meta definition property.", operations=[ {'path': '/v2/metadefs/namespaces/{namespace_name}/properties' @@ -250,7 +250,7 @@ metadef_policies = [ policy.DocumentedRuleDefault( name="add_metadef_property", check_str="rule:metadef_admin", - scope_types=['system', 'project'], + scope_types=['project'], description="Create meta definition property.", operations=[ {'path': '/v2/metadefs/namespaces/{namespace_name}/properties', @@ -260,7 +260,7 @@ metadef_policies = [ policy.DocumentedRuleDefault( name="remove_metadef_property", check_str="rule:metadef_admin", - scope_types=['system', 'project'], + scope_types=['project'], description="Delete meta definition property.", operations=[ {'path': '/v2/metadefs/namespaces/{namespace_name}/properties' @@ -272,7 +272,7 @@ metadef_policies = [ policy.DocumentedRuleDefault( name="get_metadef_tag", check_str=base.ADMIN_OR_PROJECT_READER_GET_NAMESPACE, - scope_types=['system', 'project'], + scope_types=['project'], description="Get tag definition.", operations=[ {'path': '/v2/metadefs/namespaces/{namespace_name}/tags' @@ -288,7 +288,7 @@ metadef_policies = [ policy.DocumentedRuleDefault( name="get_metadef_tags", check_str=base.ADMIN_OR_PROJECT_READER_GET_NAMESPACE, - scope_types=['system', 'project'], + scope_types=['project'], description="List tag definitions.", operations=[ {'path': '/v2/metadefs/namespaces/{namespace_name}/tags', @@ -303,7 +303,7 @@ metadef_policies = [ policy.DocumentedRuleDefault( name="modify_metadef_tag", check_str="rule:metadef_admin", - scope_types=['system', 'project'], + scope_types=['project'], description="Update tag definition.", operations=[ {'path': '/v2/metadefs/namespaces/{namespace_name}/tags' @@ -314,7 +314,7 @@ metadef_policies = [ policy.DocumentedRuleDefault( name="add_metadef_tag", check_str="rule:metadef_admin", - scope_types=['system', 'project'], + scope_types=['project'], description="Add tag definition.", operations=[ {'path': '/v2/metadefs/namespaces/{namespace_name}/tags' @@ -325,7 +325,7 @@ metadef_policies = [ policy.DocumentedRuleDefault( name="add_metadef_tags", check_str="rule:metadef_admin", - scope_types=['system', 'project'], + scope_types=['project'], description="Create tag definitions.", operations=[ {'path': '/v2/metadefs/namespaces/{namespace_name}/tags', @@ -335,7 +335,7 @@ metadef_policies = [ policy.DocumentedRuleDefault( name="delete_metadef_tag", check_str="rule:metadef_admin", - scope_types=['system', 'project'], + scope_types=['project'], description="Delete tag definition.", operations=[ {'path': '/v2/metadefs/namespaces/{namespace_name}/tags' @@ -346,7 +346,7 @@ metadef_policies = [ policy.DocumentedRuleDefault( name="delete_metadef_tags", check_str="rule:metadef_admin", - scope_types=['system', 'project'], + scope_types=['project'], description="Delete tag definitions.", operations=[ {'path': '/v2/metadefs/namespaces/{namespace_name}/tags', diff --git a/glance/policies/tasks.py b/glance/policies/tasks.py index d4771b8627..42d25a5f6d 100644 --- a/glance/policies/tasks.py +++ b/glance/policies/tasks.py @@ -47,7 +47,7 @@ task_policies = [ # 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'], + scope_types=['project'], description='Get an image task.\n' + TASK_DESCRIPTION, operations=[ {'path': '/v2/tasks/{task_id}', @@ -61,7 +61,7 @@ task_policies = [ policy.DocumentedRuleDefault( name="get_tasks", check_str='rule:default', - scope_types=['system', 'project'], + scope_types=['project'], description='List tasks for all images.\n' + TASK_DESCRIPTION, operations=[ {'path': '/v2/tasks', @@ -75,7 +75,7 @@ task_policies = [ policy.DocumentedRuleDefault( name="add_task", check_str='rule:default', - scope_types=['system', 'project'], + scope_types=['project'], description='List tasks for all images.\n' + TASK_DESCRIPTION, operations=[ {'path': '/v2/tasks', @@ -89,7 +89,7 @@ task_policies = [ policy.DocumentedRuleDefault( name="modify_task", check_str='rule:default', - scope_types=['system', 'project'], + scope_types=['project'], description="This policy is not used.", operations=[ {'path': '/v2/tasks/{task_id}', @@ -102,7 +102,7 @@ task_policies = [ policy.DocumentedRuleDefault( name="tasks_api_access", check_str="role:admin", - scope_types=['system', 'project'], + scope_types=['project'], description=TASK_ACCESS_DESCRIPTION, operations=[ {'path': '/v2/tasks/{task_id}', diff --git a/releasenotes/notes/rbac-updates-ba0fcb886fe4085c.yaml b/releasenotes/notes/rbac-updates-ba0fcb886fe4085c.yaml new file mode 100644 index 0000000000..bcb3eb08f4 --- /dev/null +++ b/releasenotes/notes/rbac-updates-ba0fcb886fe4085c.yaml @@ -0,0 +1,26 @@ +--- +features: + - | + The Glance policies have been modified to drop the system scope. Every + API policy is scoped to project. This means that system scoped users + will get 403 permission denied error. + + Also, the project reader role is ready to use. Users with reader role + can only perform the read-only operations within their project. This + role can be used for the audit purposes. + + For the details on what changed from the existing policy, please refer + to the `RBAC new guidelines`_. We have implemented only phase-1 of the + `RBAC new guidelines`_. + Currently, scope checks and new defaults are disabled by default. You can + enable them by switching the below config option in ``glance.conf`` file:: + + [oslo_policy] + enforce_new_defaults=True + enforce_scope=True + + We recommend to enable the both scope as well new defaults together + otherwise you may experience some late failures with unclear error + messages. + + .. _`RBAC new guidelines`: https://governance.openstack.org/tc/goals/selected/consistent-and-secure-rbac.html#phase-1