Object tags instead of named resources look like a neat and flexible concept, and is something I hadn't considered before. It is quite jarring transitioning from the filesystem example to the introduction of tags though, as something quite important appears to be lost in the translation.
In the filesystem example I can visit any node in thee tree and set an ACL on it, optionally recursively. This gives me a lot of flexibility to slice and dice permissions in a complex potentially-multi-tenant resource model. Tags appear to lead to a flattened view of resources - all resources with tag foo are treated the same, regardless of their location in the model. It would be nice to see the author acknowledge this and expand on their examples to see how they might incorporate relational data models.
You can think of tags as folders. The big different being an object (e.g. file) can be in multiple "folders" (tags) at the same time if you do that. But it would probably mean you don't have nested folders.
The article is a good start. I can add what's helpful in my experience: Core RBAC includes users, assignments, roles, permissions, operations, objects, and sessions.
For a system that implements RBAC, the objects can represent information containers e.g. files/directories within an operating system, locks on columns/rows/tables within a database management system, tags on resources within an application, exhaustible system resources such as storage or CPU cycles, etc.
RBAC can get you a long way, but there comes a time when you need even more granular permissions that are context aware (eg is the user an owner of the thing they are accessing and are they accessing from an internal IP address)
I think that's what the article was describing as ABAC, and explicitly declared (paraphrasing, not quoting) "temporarily out of scope because this blog post is long enough".
But yeah, ephemeral/contextual stuff can be really important too, though getting as far as a decent RBAC system does tend to buy you a lot over most statuses quo.
Having wasted a couple of engineers time a year on building and managing permissioning systems, the challenge and complexity really rings true
This is especially painful in B2B businesses where your customers have their own set of requirements and access controls (this department can do X, but these 3 people also have access to these other 2 departments etc). The hidden cost of supporting this plus the audit overhead really stacks up [1]
Not being one for building the same system over and over, we are now working on an open-source, self-hosted access control service - https://cerbos.dev
Theory is great, but everywhere I've worked managing permissions becomes a nightmare that either ends up with everybody having too much access or not having the access they need.
People who gravitate to being in charge of permissions are anal retentive micromanaging types. They get a kick out of making others come to them to beg permission to access whatever it is, and making them get permission from their manager and his director. They are insufferable so people develop workarounds, shadow systems, or try to accumulate as much permission as they can so they can avoid future dealings with the permissions bureaucracy.
I hear you! Ended up building such a system so many times, so much we've built an open-source, self-hosted system to do it out of the box! https://cerbos.dev
This model makes a ton of sense for abstracting away individual file permissions to higher level RBAC concepts. I really like the concept that an expandable set of tags gets compiled down to lower level ACLs
The follow up question I have is: who decides the group members? That becomes the new point of failure. In the examples here it appears to be HR. How can one secure deciding those group members so that say, Joe in HR doesn't install some malware, adds himself to Eng + Executive, and then go wild?
It sounds like an incomplete model if groups aren't themselves controllable objects. I think they are punting to host MAC for that?
Fun factoid: Even if roles aren't explicitly compiled to ACLs -- which is really an arbitrary implementation artifact, not a design requirement -- a lot of ABAC systems (and their policies) like these can be provably converted on-the-fly. This matters bc (1) it frees up implementations to be things like in-DB RLS policies (so you don't need to leave the DB for authorization decisions, as recent Google-clones and auth startups slow your app down with), and (2) you can send the policies (vs ACL 'binaries') to friendly verifiers like Z3 for fast and easy interactive analysis/querying/auditing/verification. We wrote a paper showing XACML -> BDDs for that ("Margrave") in what now feels like the stone age, and AWS more recently redid it for IAM via Z3.
IMO, getting this into postgres could be a pillar for a really awesome DBaaS/PaaS startup: imagine Django or Rails w built-in scale-to-zero multitenancy & rich collaboration, which are normally a PITA
The article kept saying HR was responsible but I don't understand why this wouldn't be split organisationally. A manager knows who is on their team (and when they leave), it seems to me it would make the most sense to split the "groups" into teams and make the managers responsible for keeping their group up to date.
Isn't SELinux turned on by default in most mainstream distros these days? I think it's not "nightmarishly difficult" as it is "nightmarishly difficult" to use with the most complicated scenarios you can come up with but the system will let you be as permissive or restrictive as you like. I really wish more would be invested in making SELinux more convenient because it appears to me to be the best solution when dealing with virus', malware and so on.
I've always considered SELinux a RHEL/Fedora thing.
It's not very inconvenient these days, and those distros include tools that will write policies for you.
Debian and Ubuntu distros use AppArmor.
OpenSUSE MicroOS/Kubic also seem to have SELinux enabled by default, but I believe Leap and Tumbleweed use AppArmor by default.
Other than that, I don't think it's hugely popular. Alpine, Arch, and Slackware have neither enabled by default. NixOS has a working group for SELinux but I'm not sure what state it's in.
Coincidentally, We have designed somewhat similar Entitlement System for our use case. We narrowed down our requirement in one simple sentence - "A group of users can be given permission to do something on group of resources."
We just need 3 entities here:
- UserGroup
- ResourceGroup
- Entitlement (Which is basically a mapping of userGroupId and resourceGroupId along with permissions like Widget.CREATE, Report.DOWNLOAD etc etc)
All the entitlements will be granted at Group level and no nesting of groups.
The theory looks very promising. Separations of tags and roles and the ability to decide who can grant what looks very flexible (at least if I compare it to some systems that I worked on). But I think that there is one implmentation detail that will make or break system with such powerfull security model. And it is the performance cost.
Has anybody seen any real implementations of this model that are applied on the lowest possible level and still meets performance requirements for whole system?
I'm asking because I have seen few simpler ACL system, which when applied to Full Text Search Systems with power users enabled to define and modify security schemas, brought the system to its knees.
I think the problem is that reading search results from any kind of search engine with dynamic read (entry visibility) rules applied on top seems like very hard problem to solve in performant way (while preserving theoretical flexibility).
Maybe a really dumb question, but wouldn't the least complex way of doing something like this be to just attach the ACLs to folders instead of files/objects?
So if you want to grant access to reports to a role, you would set the ACLs on the reports folder, not on individual reports.
Object-level permissions feels too fine-grained for me in many cases. We probably need this for actual file systems, but those are quite different from something like an enterprise application. The file system has lots of "irrelevant" files for the user that might need specific permissions, and you can't arbitrarily reorganize files without breaking stuff.
I think that sort of gets you back to DAC. The downside is that I have a file at path /foo/bar, and I want bar only accessible in one way. I move it to /baz/bar and now it's accessible in another way, even though 'bar' has not really changed.
This works for a lot of use cases. ACLs aren't zero-sum, so it's fine to layer them. As an example, Dropbox Paper has some interesting security properties.
A Document can have ACLs that are tied to the Document itself. Things like "Only let these specific people read / edit the document" or "Only users within our organization". There are also directories - your private directory isn't browsable by others, but you can have organization-wide directories.
And then finally there are document capabilities. I can share a URL to a Document and, regardless of its directory (even private) that Document can be viewed. The article calls this MAC, which I guess could be correct? I've never heard the terms conflated.
Also, existing file systems are built around DAC so it's hard to really think of exactly how you'd apply object level permissions. Apparmor, a MAC, lets you specify interesting things like 'owner'. SELinux gives you object tagging, RBAC, etc. They have their tradeoffs.
The system described in the article is pretty good. But why restrict tags to have only users and not let include groups ( all users of a group)? Also the issue with tags is that if you don't tied them to another structuring object there are too much of them and it starts being difficult to choose and manage them.
I actually had to write a permission system for a collaborative b2b tool, and the answer for tags was to tied them to a folder.
When you add nested folders, things become easier to maintain. You have rights on folders or files and, and you have tags on folders which can grant rights too
> But why restrict tags to have only users and not let include groups
? Tags are associated with a role. Someone in the "Engineering" role can apply a "source-code" tag to a file. There's no such thing as a group, but rather everyone fills a role.
Sorry I meant role instead of group. Ah so tags are tied to a role, all good then. But you could still give permissions for a role through a tag. Like Someone in "Engineering" role can apply a "source-code" tag to a file, which will grant permission to person A, person B, person C but also to people of Role 1 and Role 2
Someone in the "engineering" role can apply the "source-code" tag to a file, which will grant people in the "engineering" role read-write permissions, and the "dev-ops" role read permissions. Users don't have tags associated with them, so they don't get permissions from having a tag assigned. They can't because the policy doesn't allow you to stick a bare user into the (role,tag,permission) tuple.
So when you're auditing permissions, you can check to see if the tags have the appropriate permissions, the roles have appropriate tags, and users have appropriate roles.
ZeroTier has a rules engine with tags and capabilities, but currently editing it requires some low-level knowledge of TCP/IP and manual management of tags and what they mean. It needs a higher level editor.
There's also some things you can do here for security that are unique, like sending copies of select traffic to security monitoring nodes or transparently redirecting traffic.
In the filesystem example I can visit any node in thee tree and set an ACL on it, optionally recursively. This gives me a lot of flexibility to slice and dice permissions in a complex potentially-multi-tenant resource model. Tags appear to lead to a flattened view of resources - all resources with tag foo are treated the same, regardless of their location in the model. It would be nice to see the author acknowledge this and expand on their examples to see how they might incorporate relational data models.