solid / authorization-panel

Github repository for the Solid Authorization Panel
MIT License
19 stars 20 forks source link

ACLs on ACLs for WAC #189

Open bblfish opened 3 years ago

bblfish commented 3 years ago

Overview

Here is a proposal that extends WAC without changing its default behavior as deployed, which currently is that only users with acl:Control mode rights can view and edit the ACL document. It is also compatible with ACP and could be used there too.

This proposal allows organizations with the need to make ACLs more widely readable, to make those available as they wish -- at their own risk. This feature is needed for the Minimal Credential Disclosure use case, and for a use case on the principle of least privilege which is not yet part of the UCR document. (hoping @justinwb will add such a use case)

In this description I build on the wac:authorizes relation discussed in issue 184: Limitations: re-using policies , but that is not a requirement for this proposal. (If you don't like that proposal just remove the authorizes relations from the diagram and turn the dotted lines into solid ones.)

Description

I illustrate this with the following diagram of a public organization (the W3C) that must show transparency in its workings. Note, that in the first comment below I show how this can work with more complicated cases where parts of the contents of the Access Control statements are protected.

@timbl has a public foaf card with a link to the its acl resource in the HTTP Link: <card.acl>; rel="acl" header. This card.acl document states that anyone can view the card resource and that Tim Berners-Lee also has write privileges to, via his WebID Profile card. On existing deployed systems the <card.acl> would not be readable by anyone, apart from Tim.

To help read the diagram here is the content of card.acl:

<#> wac:authorizes <personal#A1>;
    wac:authorizes  [ acl:agentClass foaf:Agent;
                      acl:mode acl:Read ].

it links to the <personal#A1> authorization which gives access to Tim in read and write mode.

<#A1> acl:mode acl:Read, acl:Write,
      acl:agent <card#i> .

In both those cases as developed in issue 184 the client and server can deduce the acl:accessTo relation from the existence of the accessControl Link header followed by the wac:authorizes relation. That is an idea taken from ACP which adds a lot of flexibility to the system, but is not central to the argument here.

ACLonACL

The Proposal here is that if the ACL document X itself has a HTTP Link header relation of type acl (or acl:accessControl) to Y, then the Y ACL sets the access control rules on X. So here the card.acl is readable by any authenticated agent because it has an accessControl Link header (show in double lines) to the </People/Default.acl> resource which says (after authorizes reasoning is applied) that all Authenticated Agents can read the card. This is a very lax restriction - any type of authentication is allowed here - which is used here for illustration purposes to show that one can have different access control restrictions.

[] acl:agentClass acl:AuthenticatedAgent;
   acl:mode acl:Read;
   acl:accessTo </BernersLee/card.acl> .

And indeed because the W3C wishes to be fully transparent, that resource also has an acl to itself, making itself readable by anyone who is authenticated too.

This extension should be completely compatible with the current WAC spec, in so far as it does not change the behavior of existing systems. But as it allows ACLs to be restricted in the same way other documents can be - using exactly the same ontology - we can be more flexible. It may affect how test systems are written though (cc @michielbdejong ).

I proposed something very similar for ACP in use 151 for which it work the same way too. This means that people really worried about readability of ACLs (as per Allow ACL doc discovery without acl:Control) can be as secure-by-default as is reasonable, but others that want to be more transparent can be so too.

bblfish commented 3 years ago

Let us look at a more complicated case next. We want to make information publicly visible on who can access a resource without revealing who has access, so that those who can access know what type of Credential they need to present to gain access.

We have two protected resources:

RFC 7235 requires a server to return a 401 to a client that has not presented a credential (or the provided credential was refused).
WAC enriches this 401 response with a Link: <event.acl>; rel="acl" header. But that linked-to resource can currently only be read by those who have acl:Control rights it, ie those who can edit it (but see PR 250).

This presents a problem in the case where Alice is a member of <invitees#G> and knows it, but is not an organizer of the party, so cannot see the linked-to acl and does not know that the <event> is in any way connected to that group. If her user agent reached <event> by following a link from somewhere else on the World Wide Web, it would not know what credential, if any, to show in order to see the contents.

This example would be clearer if both documents had UUID generated names such as <15263626-8352-11eb-8dcd-0242ac130003> or if the group were on a different server. But for the sake of making it easier to follow the exposition, I'll stick to easy to understand names here. Here is the view she would have:

Alice view of an event on current specs

What the ACLs on ACLs proposal enables is for both <event> and <invitees> to be protected resource visible only to members of the group <invitees#G>, but for Alice to be able to discover what Credential she needs to present to access them. This is illustrated in the picture below, which makes a lot more visible, without leaking any unnecessary information.

Both the grayed out resources are still only visible to members of <invitees#G>but the ACL for <event> and the acl for <invitees> which a client can discover on a 401 by following the accessControl Link header (shown in doubled blue lines), are public.

PartyTimetable

To help read the illustration I show the turtle here:

  1. <event.acl> is the acl for <event> and contains

    <#> :authorizes <invitees.acl#P1> .

    The authorization links to a "policy" description #P1 in <invitees.acl>, since it can be re-used.

  2. <invitees.acl> is the ACL for <invitees>. It contains

    <#> :authorizes <#P1> .
    <#P1>  acl:agentClass <invitees#G>;
      :mode :Read  .

This refers to the group of invitees <#G>.
Since the accessControl relation from <invitees> to the acl (shown in double stroke) followed by the :authorizes relation implies

<invitees.acl#P1> :accessTo <invitees> .

we have that <#P1> gives access to the resource <invitees> to the group <#G> in :Read mode. So the group <#G> can only be seen by members of the group.

Similarly because the accessControl Link header relation from <event> to <event.acl#> is followed by the authorizes relation from <event.acl#> to <invitees.acl#P1> the client or server guard can deduce the relation:

<invitees.acl#P1> :accessTo <event> .

As such the event is also only readable to members of the group <#G>.

  1. We then have ACLs on both those ACLs pointing to <Default.acl#> which gives read access to anyone to those ACLs.

How would you then know you are a member of the group? You'd need to be invited using Linked Data Notification or something similar.

If you know you are a member of the group, then you will know what identity to use to authenticate, if you are not then you should probably not bother, though you may follow a ldn:inbox link to find a box to ask to be added to the list.

matthieubosquet commented 3 years ago

I do like the idea of ACLs on ACLs from an aesthetics perspective. However, I think that introducing a layer of recursion there is a minefield and in any case a huge departure from how Solid works at the moment.

A few questions that come to mind would be:

bblfish commented 3 years ago

A few questions that come to mind would be: a. How do you manage the lifecycle of such ACLs (make sure there's no orphans)

These would be server managed resources. An obvious first answer would be: If a resource is deleted all acls for it recursively are deleted too?

b. Where do you store them?

On the Pod? If the naming is the problem then one option is card.acl.acl for an acl for an acl. Or perhaps <card?acl=2>.

c. How does it affect inheritance logic?

Can you explain this in more detail? What problem do you see here?

matthieubosquet commented 3 years ago

a. How do you manage the lifecycle of such ACLs (make sure there's no orphans)

These would be server managed resources. An obvious first answer would be: If a resource is deleted all acls for it recursively are deleted too?

What I read from the proposal is:

This means in order to delete an Access Control Resource, you need to make sure that it's not the effective ACR for any resource. It also means that when deleting a Resource, you need to make sure that the chain of effective ACRs doesn't leave an orphan up the tree.

That doesn't solve Access Control Resource creation or:

b. Where do you store them?

Because then, the ACLs on ACL don't really work like the rest of Solid anymore, they are on this multi level meta layer which doesn't currently exist (it's currently flat). Sure we could come up with something there, but once again, it's a significant departure from where we're at.

And:

c. How does it affect inheritance logic?

Do we completely forego the notion of hierarchy in ACLs on ACLs? Are they not stored in containers? If not where are they stored? ...

All I'm saying is it is a big departure from what we have in Solid where there is to my knowledge no notion of metadata resources on metadata resources. Remaining flat is not the worst restriction one could think of to foster simplicity.

bblfish commented 3 years ago

Thanks for those clarifications. That is really helping the discussion move along.

As to whether it is a big departure from acls currently, it all depends on how it is done. If one thinks that by default all acls are their own acls, perhaps that covers the current situation.

It may suggest we don't really need Control at all. One could just have the resource.acl specify:

<#aclOnAcl> a :Authorization;
   :mode :Read, :Write;
   :accessTo <> ;
   :agent </#owner> .

That would simplify the ontology, and I think there is a good reason to do so, as I feel the "Control" mode is doing something very different from Read and Write modes: it is giving access not to the object of accessTo, but to the document linked to that object via a header, which happens to be the same document it is written in!! Why such contortions?

But yes, the problem I have not yet worked out is how a client would add an acl to a specific acl using HTTP. (server wide is easy to imagine). Good ideas welcome.

A long time ago, we discussed having Link: <.meta>; rel="meta" header, which could have been a place to add such links. I would love to hear @timbl's ideas on this. Could one edit such a document to create a new acl as a triple?

Thinking of an acl as some form of container does not seem quite right, as we really only want one acl on an acl at most... (certainly not more than 2 or 3)

matthieubosquet commented 3 years ago

It may suggest we don't really need Control at all. One could just have the resource.acl specify:

<#aclOnAcl> a :Authorization;
   :mode :Read, :Write;
   :accessTo <> ;
   :agent </#owner> .

I really like this suggestion and completely agree that the "Control" mode is doing something different to other access modes, which I find incoherent with the whole Solid resource based access control system paradigm.

So in an effective Access Control Resource (ACR), you could have Authorizations targeted at:

  1. Itself via :accessTo <>
  2. The resource for which the ACR is directly effective via :accessTo <ResourceIRI>
  3. The resources contained by that resource for which the ACR is effective if the resource is a container via :default <ContainerResourceIRI>
  4. Potentially to the resources down the hierarchy if acl:accessTo and acl:default are relaxed (as per @woutermont's proposal)

I would be very much in favour of that.

cc @csarven


Now, maybe it is worth explaining an element of ACP's design here which doesn't use the ACL on ACLs approach, but might provide answers to some of the problem space without introducing too many questions.

In ACP, you can reference regular resources from within an ACR. So you could use best practices to separate parts of your access control rules across different resources each with their own permissions level fitting your needs:

# Note: Mimicking your first example
# Resource: </card.acl>
<>
    acp:accessControl </acp/personal#AC1> ; # Not represented for brevity. Gives read and write to Tim.
    acp:accessControl <#AC1> .

<#AC1>
    a acp:AccessControl ;
    acp:access </acp/UniversalReadPolicy#> . # Not represented for brevity. Gives read permission to everyone.

# Resource: </acp/UniversalReadPolicy.acl> (effective ACR for </acp/UniversalReadPolicy> also universally readable)
<>
    acp:accessControl <#AC1> .

<#AC1>
    a acp:AccessControl ;
    acp:apply </acp/UniversalReadPolicy#> ;
    acp:access </acp/UniversalReadPolicy#> .

# Resource: </acp/personal.acl> (effective ACR for </acp/personal> not universally readable)
<>
    acp:accessControl <#AC1> .

<#AC1>
    a acp:AccessControl ;
    acp:apply <#TimFullAccessModesPolicy> ; # Not represented for brevity. Gives Tim full permissions to the resource </acp/personal>.
    acp:access <#TimFullAccessModesPolicy> . # Gives Tim full permissions to the ACR </acp/personal.acl>.
bblfish commented 3 years ago

@matthieubosquet wrote

I really like this suggestion and completely agree that the "Control" mode is doing something different to other access modes, which I find incoherent with the whole Solid resource based access control system paradigm.

Thanks Matthieu. I opened an issue deprecate acl:Control, replace with... on the web-access-control repo.

matthieubosquet commented 3 years ago

Thanks for writing it up so clearly and concisely and for formulating the suggestion @bblfish! This makes a lot of sense to me.