-
Notifications
You must be signed in to change notification settings - Fork 45
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
Explain the ACL inheritance algorithm for clients #106
Comments
Why not have the server specify the inherited ACL in a header? Figuring out the parent acl is something the server does on almost every request, it’s a core capability. |
That could be a very nice SHOULD; I'd support that. |
I agree, we should have a |
other than specially-privileged permission management apps that have for a parent/inherited ACL, it might be of interest to know its URI, but you'd presumably also want to know the URI of the parent container it goes with (it could be several levels up), so that if you were a permission management app, the user could make an informed decision as to how to appropriately adjust that container's permissions. i hope and expect it'll be rare for random apps/clients to have |
[Revisiting this proposal even though I was in the original meeting for it.] We currently have consensus on the following:
Hence, it is currently possible for a server to return the effective/inherited ACL of a resource. No algorithm required for a client other than to check rel=acl in resource's Link header. Aside: If I'm not mistaken, there is a historical reason to why the inheritance algorithm exists... It is partly due to the way NSS worked - it happened to automatically associate an ACL to each resource - whether that ACL actually existed as an independent resource or one determined based on an inheritance algorithm was another matter. From that point, we can see why the inheritance algorithm would be required. Proposal: Unless there are security implications we should consider, servers MUST only return the effective ACL for a given resource ie. Link rel=acl as advertised. No new requirements needed for clients. |
How can a client then know how/where to |
In fact, it is worse. If a client treats URIs as opaque, believing that the effective ACL applies only to a particular resource (when in fact it applies to an entire hierarchy of resources), doing a PUT or PATCH on that (effective) ACL resource will affect the ACLs of every other resource that currently inherits from that ACL. Imagine if the effective ACL is the root resource and a client really only wanted to change the ACL of a single child resource. This is fine if that is the intention of a client, but if there is no way of knowing whether such an operation will affect one resource or many resources then the security implications of that change will be terrible. |
As mentioned, shared slash semantics and hierarchical paths limit the possibilities eg. "/foo/bar 's ACL can be /foo/bar.acl , /foo/.acl , /.acl , but not /baz/qux.acl or /baz/.acl." If a client wants to PUT a specific ACL for /foo/bar, it'll have to be under /foo/ or / (but not any other branch). |
You are building a security model on apriori knowledge of this by every current and future client. |
That knowledge is already required by the spec. Figured that what's possible stems from that. Rethinking this.. the issue is not so much of PUTing an ACL but that of associating an ACL with a resource. So, I'm okay to put a pause on that proposal :) It was just another way of not requiring clients to hunt down an ACL or having a server expose yet-another location for an ACL (the "actual" and the "effective") Edit: associating an ACL to a resource can be done with the |
That conflicts with the requirement for clients and servers sharing the slash semantics in URI path. Can't expect clients to conform to that as well as decide to treat URIs as opaque entirely. The latter is currently out of spec behaviour, unless of course exceptions to the requirement are introduced.
True and those are valid concerns. Note however that updating an ACL policy containing I do however see another issues with "servers MUST only return the effective ACL for a given resource": What's on the table:
What's attractive about the client figuring out the inherited/effective ACL is that once a container with an ACL is found, the relation between the container resource and its ACL is clear in conjunction with the policy descriptions in container's ACL. That clarity is lost if "servers MUST only return the effective ACL for a given resource" ie. Resource rel=acl ACL, but when clients read that ACL's policies, relative paths for the values of accessTo and default can potentially mislead the client. Hence, a different link relation (eg using acl:inheritedACL) is needed to make the distinction from rel=acl with a different understanding on handling the inherited ACL. The two approaches are not mutually exclusive (provided that they yield the same ACL). Clients are generally capable of using the inheritance algorithm given the base requirements (Aside: note also the similarity to traversing the URI path to find the controller of a storage as proposed in #153 (comment) and there are some ways to optimise the checks). Servers using two different relations for ACLs seems to be a bit of a bloat but I have no strong objections. In context of server using two ACL relations (rel=acl, rel=acl:inheritedACL) with fixed URLs (as per resource lifecycle and hierarchical containment), updates are a non-issue. It becomes an issue if the target of the link relation is not persistent, and where clients need to associate an ACL to a resource. While that's currently not possible, it can be worked out by adopting LINK and UNLINK methods. |
OK so it seems that I was thrown off by terminology. Am I correct that:
If so, can we call this something like "resource-specific ACL"? |
No. At least I was using "effective ACL" as equivalent to '"ACL currently in effect" (which might be the inherited one)?'
/resource.acl is always the specific ACL for /resource . If HEAD /resource.acl returns 200, it is the effective ACL. If HEAD /resource.acl returns 404, and client finds /.acl, that'd be the effective - the inherited - ACL. |
Ok in that case I am horribly confused, because the initial proposal was
And let's use a deep example So here is what I know think we are saying:
If that understanding is correct, then I would suggest a different phrasing for the proposal (I can help). |
didn't distinguish between specific and inherited. It is literally the only effective ACL using rel=acl. It is "specific" within the context of what's effective. If server determined that /resource.acl exists, that'd be the effective and so it would return that in Link of /resource. If /resource.acl didn't exist, and the server determined that /.acl is inherited (and so effective), then it would only return /.acl in Link of /resource That approach is different than rel=acl strictly being used for resource specific ACL ie. having only /resource.acl target (but never /.acl as you've said above). Links of /resource would be rel=acl /resource.acl and rel=inheritedacl /.acl (if /resource.acl didn't exist). Does that clarify:
|
Understood. Then my Steps:
Unless you tell me that |
PUT is not an issue in and itself because of:
So, yes, you can create /foo/bar/resource.acl (or whatever naming) as long as the hierarchy holds. What's not possible is actually:
because we don't have a way to connect / update the relation with the new ACL that's created. It can be remedied with
if that direction is so desired. ".acl" convention is not part of the spec. |
…or just by always It's so simple and doesn't involve methods that are not really used elsewhere. |
Hierarchy is not relevant here. The examples all presume that acl URIs can be created with (resource URL + ".acl"), which does not hold universally. Using @RubenVerborgh's example, if a client wants to create an ACL for
Or some other server-specific mechanism. The possibilities are endless. The unambiguous way to inform a client where to PUT an acl for the current resource is the mechanism that is currently in use: a Link header. It would be fine to add an additional header to inform a client of the location of the ACL that currently controls access for the resource, but it should be a separate link relation. |
Was not my assumption actually. I would a) link to the most specific ACL, always and b) traverse up and ask every resource for their ACL. |
I was unclear. Some of the examples make that assumption.
Exactly, and that's what I would expect, too (though I like the idea of adding a separate link header to make this traversal easier for clients) |
I'm going to skip further discussions around what the examples use because virtually any example will not hold universally. We have already established that there is no naming convention. ".acl" was just a simple way to denote the ACL. Could've used The slash semantics is the only convention that can be expected because hierarchy is relevant. There wouldn't be an inheritance algorithm for clients if clients threat URIs as opaque. How to PUT the ACL is not the issue as long as it either matches a predetermined location (server exposing Link rel=acl ACL) or the client creates the association at allowed locations.
No. It will simply check /foo/bar/resource's Link rel=acl and PUT to target. If rel=acl is not available, as long as the ACL URL is under /foo/bar/ or /foo/ or / (but no sub-directory other than /foo/ or /foo/bar/) they can create that in whatever naming contention. That's required for the inheritance algorithm to work. Can't PUT the ACL at random locations because it wouldn't be associated with a resource. It requires the client to take an additional step to make that association or possibly have the server figure it out by inspecting the payload of ACL policy's accessTo target and doing it automagically - not completely ridiculous I think. If rel=acl is available, we already know where to PUT - naming is irrelevant.
As I understand it, that's the original proposal for this issue. It is based on NSS's history (as mentioned earlier) in that it associates an ACL to each resource when it is created. Traversal is required because the associated ACL may not actually have a representation. The important bit here is that server has a predetermined and fixed rel=acl with its target ACL when the primary resource is created. The "drawback" was whether a client needs to "hunt down an ACL". That's two calls per parent container (1. container resource 2. its acl) in the hierarchy. I'm not making a judgement. The intention was to contrast with the other options. As said in #106 (comment) I have no strong objection to an additional header but don't consider it to be a great approach either. I think the confusion around PUT was because of having one rel=acl referring to the "effective" ACL (where the target is either the specific ACL or the inherited).. and that if it so happens to be the inherited, how would one create the specific. Again, creating the ACL is not the issue because the server shouldn't care (we follow rel=acl remember?) - unless of course it wants to stick to particular URI Template for ACL resources. Association is the challenge - with two possible solution: 1) LINK method, 2) server inspects payload and creates the association (as mentioned earlier). |
I don't understand. Could you please solve this case for me?
I'd like the steps for 4 with your proposal. It's a common case in Databrowser. |
I assume that /foo/bar/resource doesn't have a Link header with rel=acl .
I assume that ACLs must be valid and so servers must validate ACL payloads. For example, a policy's acl:accessTo must be /foo/bar/resource . Examples with different request targets using Link header with rev=acl (reverse relationship):
The anchor attribute may be another way to associate /foo/bar/resource and /foo/bar/resourceacl . I don't think the LINK method is ideal for ACLs because PUT needs to happen before. PUT without headers indicating that the payload is an ACL will append a resource to container. |
In your example, it seems to be the client choosing the ACL URL. Because the consequence of letting the client do it, is that the server now needs bookkeeping. Whereas otherwise, it could just maintain a simple logic or association. |
Right. Like I said, PUT is not the issue but the association required from client. I wanted to show how it could work with a single relation and assuming that server didn't have a resource specific ACL associated. If server had advertised rel=acl, then updates can happen as usual (still requiring client association). Even in the case of advertising the inherited We have:
eg. both rel=acl (always resource specific) and rel=inheritedacl (always inherited but only need to be revealed if resource specific doesn't have a representation) |
So as it stands, I would still support That way, we can do everything we want without too much trickery. If it's not, then we can always add |
I agree. This is where feedback from multiple independently built implementations will help to determine whether without inheritedacl is sufficient or useful to have as a MAY to encourage use. |
I just added support for this in Trellis. Lacking clarity around the value of In other words, for a resource without its own ACL, the response headers would have this structure: Link: <https://example.com/container/resource?acl>; rel="acl",
<https://example.com/container?acl>; rel="http://www.trellisldp.org/ns/trellis#effectiveAcl" |
Why wouldn't /foo/bar/resource have a Link header with rel=acl? This is the part that's confusing for me.
👍 |
It is important to test the assumptions. If we can expect rel=acl to always be present even while the target may not actually have a representation, I think it is equally important to see what's possible with minimal information. I've demonstrated that it is in fact possible (re Link rev) but it presses on other premises (ie. only server making the association). I've eliminated the LINK method approach along the way. It also shows that the rel=acl being present is not the key bit of information. It actually came down to distinguishing between specific ACL and the inherited ACL in conjunction with only the server making the association. I didn't want to take anything for granted because it is very easy to look over stuff. FWIW, this thread at least shows what's explored and documented. It tried to justify the original proposal! There is useful information here besides the rough consensus IMHO. |
@csarven told me that a Resource does not advertise an ACL in the (He also asked me to bring up such questions here.) |
Yes, most current rough consensus.
You're right that a client may not observe a link relation for the ACL on the root container. I think when this issue got ported, it carried the MUST. The context of the original algorithm is that server certainly has an ACL for the root container and so it'll check that as last option. Note also that the algorithm is framed in a way that a user account is part of the same service has Control access on the root container. Given that a WebID (and associated user account) can be on any system, I think the server inheritance algorithm should be revised and omit "user account" in step 5: The root container MUST have an ACL resource specified. It still holds that the link relation for the ACL is only advertised if client has Control access of a resource (including root container). Steps 3, 4 of ACL inheritance algorithm for clients should be along these lines:
TBD: Check if root Container - #153 (comment) includes proposal to determine Storage/Workspace root eg. URL has |
I vehemently disagree on that. Control access should only limit who can write to the ACL. Not who can read it. |
See also: #252 which corrects the above / what was mistakenly introduced intothe spec. |
Ok, I'll wait. I am implementing this now in Reactive Solid, so that is why I am looking here for guidance. |
Thanks for this issue and discussion. Closing this issue as consensus is deemed to be captured in WAC Editor's Draft: https://solid.github.io/web-access-control-spec/ . See #effective-acl-resource . Please use https://github.com/solid/web-access-control-spec for future discussion. |
No description provided.
The text was updated successfully, but these errors were encountered: