spicedb
spicedb copied to clipboard
Support for wildcard query (computed_usersets with prefixes)
This stuff looks awesome! I want to know whether there is plan to support the LIKE operator, which is very important in my use case.
For example, salesrep_* is allowed to edit broucher_*.doc will allow usernames with prefix salesrep_ to edit docs that match wildcard pattern broucher_*.doc.
This is really useful in cases where you have many apis in your app that follows some kind of naming pattern, and specifying each of them explicitly becomes tedious.
This is an interesting idea, so I'd like to understand a bit more about the type of data you're working with.
Typically, we'd recommend writing a schema where users can have a relation "salesrep" or documents can have a "broucher". Relationships are SpiceDB's way to avoid having forced hierarchies like string-prefixes.
Aha I see. I've just started reading up on Zanzibar this week, so pls bear with me.
A typical scenario is where I want access control to an API endpoint. I will design my API such that I can parse out the "action" from the url prefix. For example, /api/DeleteFile/lalala.txt will have the action DeleteFile. Now since the user is already authenticated, I will want the authz engine to answer something like "can Johnny performance action delete file on file lalala.txt".
Now alongside DeleteFile, the reality is there will often be dozens or even hundreds of "action" in an API endpoint. If my understanding of spicedb is correct, an end-user/operators writing their own ACL will need to first define an action set (permission in authzed) by explicitly stating its members (DeleteFile, DeleteFolder, DeleteTimestamp, ...), and then establish the relationship between Johnny and file lalala.txt as that action set. Now, I want a query to the engine for DeleteFile, etc. to match a wildcard relation label Delete*, i.e. I can define a permission named Delete*, and all defined relationships that match this wildcard will be auto included.
Sometimes it is not only an issue of tediousness. The resource itself may not be ascertainable beforehand, so it is impossible to define its set. For instance, how do I say "Johnny can delete file lalala.*"? The only solution I can think of is to use the expand API and then filter in code.
@imacks Are the list of actions known ahead of time in your applicable or are they fully dynamic? Likewise, is the mapping between an action and a "class" of user known ahead of time, or is it also dynamic?
Fully dynamic permissions systems can be represented using a static schema and relationships. For example, let's say you wanted to issue a check like within your first example (salesrep_* is allowed to edit broucher_*.doc). One option is to have your code parse the prefix of the file to get broucher and the prefix of the user to get salesrep. Then, you could issue the following check:
check('broucher', 'edit', 'salerep')
The goal would be to then define a schema that allows for this check to succeed, from the file "type" to the user "class". An example might be:
definition userclass {}
definition filetype {
relation editor: userclass
permission edit = editor
}
To enable the above check to succeed, you'd write a relationship of the form:
Relationship(
resource: {
object_type: 'filetype',
object_id: 'broucher'
},
relation: 'editor',
subject: {
object: {
object_type: 'userclass',
object_id: 'salesrep',
}
})
Now, the above assumes that the filetype and userclass are fully dynamic and based on parsing in your client code. If you, instead, wanted to issue a check on the file itself, along with the user itself, then you'd also need to add relationships linking each file to its filetype, and each userclass to its users.
@josephschorr tks for the clarification. My issue is that I cannot parse code in the scenario. Let me describe the bigger picture: I have a web drive app that allow operator users to create other users, groups, and files. User, group and file names are arbitrary.
User/group can perform an action on a file. Actions are predefined (EditTag, EditFilename, etc.) and I can parse out the action from the request URL. I want operators to be able to self-service create acls like group:salesreps can webdrv:Edit* on file:broucher_*.doc.
Query to authzed for a request may look like check(file:broucher_foo.doc, webdrv:EditTag, user:johnny). This will not work unless I predefine permission webdrv:Edit* = EditTag + EditFilename. A wildcard capability I propose is like an automatic relationship that will match the existing webdrv:Edit* when I check for webdrv:EditWhatever.
To illustrate further, consider user have files broucher_foo.doc and broucher_bar.doc. Without wildcard, he would have to manually specify that both files to belong to set broucher_*.doc in authzed. When he creates a new file broucher_baz.doc, he will have to update the set too.
@imacks in your design, the operator is calling the Authzed API directly, or is it going through your application?
It is through my application, but I won't for instance be able to know to check for Edit* when the request is for EditTag.
This is equivalent to a computed_userset with some sort of prefix-matching rule definition