Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add role management #117

Merged
merged 2 commits into from
Oct 11, 2023
Merged

add role management #117

merged 2 commits into from
Oct 11, 2023

Conversation

butonic
Copy link
Member

@butonic butonic commented Oct 4, 2023

This is a prerequisite for sharing NG to clarify roles and permissions management.

Permissions are represented as a list of resource actions and conditions that must be met for the action to be allowed.

Resource Actions

Resource actions are a set of tasks that can be performed on a resource.

The following is the schema for resource actions:

  {Namespace}/{Entity}/{PropertySet}/{Action}

For example: libre.graph/applications/credentials/update

  • {Namespace} - The services that exposes the task. For example, all tasks in libre graph use the namespace libre.graph.
  • {Entity} - The logical features or components exposed by the service in libre graph. For example, applications, servicePrincipals, or groups.
  • {PropertySet} - Optional. The specific properties or aspects of the entity for which access is being granted.
    For example, libre.graph/applications/authentication/read grants the ability to read the reply URL, logout URL,
    and implicit flow property on the application object in libre graph. The following are reserved names for common property sets:
    • allProperties - Designates all properties of the entity, including privileged properties.
      Examples include libre.graph/applications/allProperties/read and libre.graph/applications/allProperties/update.
    • basic - Designates common read properties but excludes privileged ones.
      For example, libre.graph/applications/basic/update includes the ability to update standard properties like display name.
    • standard - Designates common update properties but excludes privileged ones.
      For example, libre.graph/applications/standard/read.
  • {Actions} - The operations being granted. In most circumstances, permissions should be expressed in terms of CRUD operations or allTasks. Actions include:
    • create - The ability to create a new instance of the entity.
    • read - The ability to read a given property set (including allProperties).
    • update - The ability to update a given property set (including allProperties).
    • delete - The ability to delete a given entity.
    • allTasks - Represents all CRUD operations (create, read, update, and delete).

The most interesting part IMO is how we will represent CS3 permissions. I took the liberty to map them to unifiedRolePermissions:

CS3 ResourcePermission action comment
stat libre.graph/driveItem/basic/read basic because it does not include versions or trashed items
get_quota libre.graph/driveItem/quota/read read only the quota property
get_path libre.graph/driveItem/path/read read only the path property
move libre.graph/driveItem/path/update allows updating the path property of a CS3 resource
delete libre.graph/driveItem/standard/delete standard because deleting is a common update operation
list_container libre.graph/driveItem/children/read
create_container libre.graph/driveItem/children/create
initiate_file_download libre.graph/driveItem/content/read content is the property read when initiating a download
initiate_file_upload libre.graph/driveItem/upload/create uploads are a separate property. postprocessing creates the content
add_grant libre.graph/driveItem/permissions/create
list_grant libre.graph/driveItem/permissions/read
update_grant libre.graph/driveItem/permissions/update
remove_grant libre.graph/driveItem/permissions/delete
deny_grant libre.graph/driveItem/permissions/deny uses a non CRUD action deny
list_file_versions libre.graph/driveItem/versions/read versions is a driveItemVersion collection
restore_file_version libre.graph/driveItem/versions/update the only update action is restore
list_recycle libre.graph/driveItem/deleted/read reading a driveItem deleted property implies listing
restore_recycle_item libre.graph/driveItem/deleted/update the only update action is restore
purge_recycle libre.graph/driveItem/deleted/delete allows purging deleted driveItems

This is in fact a 1:1 mapping of the CS3 Resource permissions to unifiedRolePermission actions as they are used in ms graph.

Conditions

Optional constraints that must be met for the permission to be effective.

Conditions define constraints that must be met. For example, a requirement that the principal be an owner of the target resource.
The following are the supported conditions:

  • Self: @Subject.objectId == @Resource.objectId
  • Owner: @Subject.objectId Any_of @Resource.owners
  • Grantee: @Subject.objectId Any_of @Resource.grantee - does not exist in MS Graph, but we use it to express permissions on shared resources.

Permissions

The following is an example of a role permission for a Viewer role on shared resources.

{
      "id": "7ccc2a61-9615-4063-a80a-eb7cd8e59d8",
      "description": "Allows reading the shared file or folder",
      "displayName": "Viewer",
      "rolePermissions": [
        {
          "allowedResourceActions": [
            "libre.graph/driveItem/basic/read",
            "libre.graph/driveItem/permissions/read"
          ],
          "condition": "@Subject.objectId Any_of @Resource.grantee"
        }
      ]
    },

The following is an example of a role permission for a Space Editor role on (co-)owned resources.

{
      "id": "7ccc2a61-9615-4063-a80a-eb7cd8e59d8",
      "description": "Allows editing the co-owned file or folder",
      "displayName": "Space Editor",
      "rolePermissions": [
        {
          "allowedResourceActions": [
            "libre.graph/driveItem/basic/read",
            "libre.graph/driveItem/permissions/read",
            "libre.graph/driveItem/upload/create"
          ],
          "condition": "@Subject.objectId Any_of @Resource.owners"
        }
      ]
    },

@butonic butonic force-pushed the role-management branch 3 times, most recently from b5207de to ea9fd26 Compare October 4, 2023 13:33
Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>
@butonic
Copy link
Member Author

butonic commented Oct 5, 2023

aces are currently hardcoded to a CS3 permissions set:

// grantPermissionSet returns the set of CS3 resource permissions representing the ACE
func (e *ACE) grantPermissionSet() *provider.ResourcePermissions {
	p := &provider.ResourcePermissions{}
	// r
	if strings.Contains(e.permissions, "r") {
		p.Stat = true
		p.GetPath = true
		p.InitiateFileDownload = true
		p.ListContainer = true
	}
	// w
	if strings.Contains(e.permissions, "w") {
		p.InitiateFileUpload = true
		if p.InitiateFileDownload {
			p.Move = true
		}
	}
	// a
	if strings.Contains(e.permissions, "a") {
		// TODO append data to file permission?
		p.CreateContainer = true
	}
	// x
	// if strings.Contains(e.Permissions, "x") {
	// TODO execute file permission?
	// TODO change directory permission?
	// }
	// d
	if strings.Contains(e.permissions, "d") {
		p.Delete = true
	}
	// D ?

	// sharing
	if strings.Contains(e.permissions, "C") {
		p.AddGrant = true
	}
	if strings.Contains(e.permissions, "c") {
		p.ListGrants = true
	}
	if strings.Contains(e.permissions, "o") { // missuse o = write-owner
		p.RemoveGrant = true
		p.UpdateGrant = true
	}
	if strings.Contains(e.permissions, "O") {
		p.DenyGrant = true
	}

	// trash
	if strings.Contains(e.permissions, "u") { // u = undelete
		p.ListRecycle = true
	}
	if strings.Contains(e.permissions, "U") {
		p.RestoreRecycleItem = true
	}
	if strings.Contains(e.permissions, "P") {
		p.PurgeRecycle = true
	}

	// versions
	if strings.Contains(e.permissions, "v") {
		p.ListFileVersions = true
	}
	if strings.Contains(e.permissions, "V") {
		p.RestoreFileVersion = true
	}

	// ?
	if strings.Contains(e.permissions, "q") {
		p.GetQuota = true
	}
	// TODO set quota permission?
	return p
}

@micbar
Copy link
Contributor

micbar commented Oct 9, 2023

@butonic My only question "should we use a dot in the namespace of the permissions or not?"

@butonic
Copy link
Member Author

butonic commented Oct 9, 2023

The 'action' is just a string that follows the same pattern as the ms graph api. They use microsoft.graph as the namespace, so I chose to mimic it as libre.graph. I don't see the action string being part of object properties.

Copy link
Contributor

@micbar micbar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a weight property. Rest looks fine.

@butonic
Copy link
Member Author

butonic commented Oct 11, 2023

@micbar I would add the weight property to the @libre.graph.permissions.roles.allowedValues annotation, which is part of listing permissions:

{
  "@libre.graph.permissions.roles.allowedValues": {
    { "name":"read", "displayname":"Viewer", "weight":30 },
    { "name":"write", "displayname":"Editor", "weight":20 },
    { "name":"owner", "displayname":"Manager",  "weight":10 },
    { "name":"foo", "displayname":"Fooer", "description":"Can foo things, but not bar them.", "weight":5 }
  },
  "value": [
    {
      "id": "67445fde-a647-4dd4-b015-fc5dafd2821d",
      "roles": [
        "read"
      ],
...

but that is not part of this role management PR

@butonic
Copy link
Member Author

butonic commented Oct 11, 2023

ah got it ... yeah we also need a way to set the weight.

@butonic butonic merged commit 36bd0fa into main Oct 11, 2023
1 check passed
@delete-merged-branch delete-merged-branch bot deleted the role-management branch October 11, 2023 12:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants