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

Ideas for access modes and corresponding operations in the Protocol #253

Open
kjetilk opened this issue Aug 30, 2021 · 53 comments
Open

Ideas for access modes and corresponding operations in the Protocol #253

kjetilk opened this issue Aug 30, 2021 · 53 comments

Comments

@kjetilk
Copy link
Member

kjetilk commented Aug 30, 2021

It is welcome that the authorization-panel wants to propose that the protocol needs to define the access modes in a universal way. It has been on my agenda for a while to propose it, as it is important to ease the tensions between the authorization systems.

I have read Authorization UCR and I note that its access modes definitions are incompatible with WAC, and so with Solid as currently defined. I take it as a requirement that the Protocol must be compatible with WAC as defined, and I believe my this thinking does that, as well as satisfies the panel's requirements. I propose a structure where certain access modes grant rights that are a strict subset of others.

However, for the purpose of the Protocol spec, I suggest that we define in terms of operations rather than access modes, and then attach access modes to operations. It is understood that the requirements in the following are on the server, in case I don't include that in every sentence. Thus, there isn't a one-to-one correspondence between the work of this panel and my suggestion, mine is more constrained by Solid as currently defined.

So, here are some ideas for discussion:

Read operation

The server MUST return a representation of the target resource as a response to a read operation.

State changes in existing resources

The server MUST NOT change the state of any resource as a result of a read operation.

Implementation

A request MUST use GET, HEAD or OPTIONS for read operations, as defined.

Access Mode

To execute a read operation, an agent is required to be authorized with a Read access mode. Read is a top level access mode, mutually exclusive with Write and Control.

List operation

  • The existence of a resource MUST be acknowledged in a response to a list operation.
  • When the target resource is a container, the containment triples MUST be returned. Other data MUST NOT be in the representation.

State changes in existing resources

A list operation MUST NOT change the state of any resource.

Implementation

To confirm the existence of a resource, the server MUST respond with a 204.

A server implementing this access mode MUST also implement the Prefer Request Header of LDP. A client requests a list operation by using the include parameter with a value of http://www.w3.org/ns/ldp#PreferContainment. A server MUST respond with 403 if the header is not present and the requesting agent has List permission.

Issue: The Expect header is possibly closer to what we want here, and it could be defined analogous to the Prefer header.

Access Mode

List (aka File Scan) is an access mode that is a subset of Read that allows only list operations to be executed.

Write operation

A Write operation MAY make any change to the target resource. The server MAY perform validation and filtering steps on the request. As a result of a write operation, the server will change the parent container by adding or removing containment.

State changes in existing resources

A write operation may change the state of the target resource or its parent container.

Implementation

PUT, PATCH, POST as defined.

Access Mode

To execute a write operation, an agent is required to be authorized with a Write access mode on the target resource. If the write operation results in a change of state of the parent container, the agent is also required to be authorized to perform the resulting operation on that container. Write is a top level access mode, mutually exclusive with Read and Control.

Modify operation

  • Add and subtract data to the representation of the target resource.
  • Create a representation of the target resource if it does not already exist.
  • If the target resource is an existing container resource, create a representation as a child resource of the target resource.

State changes in existing resources

A modify operation MUST NOT change the state of any other resource than the target resource, except when a new resource is created, then the server will change the parent container by adding or removing containment.

Implementation

Mostly as defined.

Access Mode

To execute a modify operation, an agent is required to be authorized with a Modify or Write access mode on the target resource. If the modify operation results in a change of state of the parent container, the agent is also required to be authorized to perform the resulting operation on that container. Modify is an access mode that is a subset of Write. It is mutually exclusive with Delete.

Append operation

  • Only add data to the representation of the target resource.
  • Create a representation of the target resource if it does not already exist.
  • If the target resource is an existing container resource, create a representation as a child resource of the target resource.

State changes in existing resources

An append operation MUST NOT change the state of any other resource than the target resource, except when a new resource is created, then the server will change the parent container adding containment.

Implementation

The special characteristics of append operations aren't well defined currently, it would need to be improved in a separate effort.

Access Mode

To execute an append operation, an agent is required to be authorized with a Append, Modify or Write access mode on the target resource. If the modify operation results in a change of state of the parent container, the agent is also required to be authorized to perform the resulting operation on that container. Append is an access mode that is a subset of Modify.

Create operation

  • Create a representation of the target resource if it does not already exist.
  • If the target resource is an existing container resource, create a representation as a child resource of the target resource.

State changes in existing resources

Changes the state of the parent container.

Implementation

As defined

It is an error to attempt a create operation on an existing non-container resource (in practice, this would currently not happen, since the server can't in such cases distinguish a create operation from a modify operation).

Access Mode

To execute a create operation, an agent is required to be authorized with a Create, Append, Modify or Write access mode on target resource if it is an existing container, or on the parent container if it does not. Append is an access mode that is a subset of Modify.

Delete operation

A delete operation removes the representation of the target resource.

State changes in existing resources

A delete operation changes the state of the target resource and the parent container.

Implementation

As defined.

Access Mode

To execute a delete operation, an agent is required to be authorized with a Delete or Write access mode on the target resource. Since the delete operation results in a change of state of the parent container, the agent is also required to be authorized to perform the resulting operation on that container, in this case, it needs a Write or Modify access mode on the parent container.
Delete is an access mode that is a subset of Write. It is mutually exclusive with Modify.

Control operation

A control operation includes read, create, modify or delete the resource containing a representation of authorizations.

State changes in existing resources

A control operation only changes the state of the target resource.

Implementation

As defined.

Access Mode

To execute a control operation, an agent is required to be authorized with a Control access mode on the target resource. Control is a top level access mode, mutually exclusive with Write and Read.

Read Permissions operation

A read permissions operation can read the resource containing a representation of authorizations.

State changes in existing resources

A read permissions operation MUST NOT change the state of any resource.

Implementation

GET on a access control resource.

Access Mode

To execute a read permissions operation, an agent is required to be authorized with a ReadPermissions access mode.
ReadPermissions is an access mode that is a subset of Control.

Some considerations

Minimal requirement on a Solid Server

We need to determine which access modes MUST be supported by a Solid server. WAC's set of Read, Write, Append and Control seems like a good starting point, with the rest defined to be MAY.

Break compatibility by disallowing append to create resources?

From the principle of least privilege, it seems, at least intuitively, to be attractive that a modify operation should not include the create operation, and so more a hierarchy like this:

It is however clear that the append operation is a subset of the modify operation and so that would break the current definition of the Append access mode. Moreover, if we keep WACs current access modes as the minimum, it would mean that you'd need Write to create a resource, which is also not good seen from the principle of least privilege.

Linking and propagation of access control

Control may need to change the state of many other resources depending on the outcome of current work regarding propagation and/or linking of resources to their access controls. This is a breaking change relative to current Solid. In general, I'm a bit divided on what we should do about the impact of state changes done as a side effect by the server.

Definition of terms

It seems to me that "Access Control Resource" should be a generic term for any such resource, including WAC's ACL resources and ACP's ACRs. Thus, the latter will have to give that up for the greater good. :-)

Audit logs, etc

At some point, I'd like to see an auxiliary resource that is an audit log, in which case all operations may append to the audit log, and so all methods would be changing the state of that resource as a side effect. This would then need to be added.

No corresponding WritePermission

Offhand, I couldn't see a use case for a corresponding WritePermission or AppendPermission. It seems that you would always need to read the authorizations to be able to change them meaningfully, and therefore, I didn't put in an analog. I also acknowledge the interesting idea in solid/specification#303 .

Operations discussions

There have been similar discussions in the protocol, notably a series of issues solid/specification#126 , solid/specification#149 , solid/specification#165 and solid/specification#118

I have also felt that the protocol needs an editorial overhaul that should make it easier for others to reference it. My thinking is that an emphasis on various operations should do that.

@csarven
Copy link
Member

csarven commented Aug 30, 2021

solid/specification#235
solid/web-access-control-spec#85

The WAC ED spec in fact already approaches this from the point of operations.

@justinwb
Copy link
Member

Great work putting this together @kjetilk - this is a really good, thoughtful breakdown. Also very glad that @csarven pointed out solid/web-access-control-spec#85. We're also having similar discussions in the interoperability panel. Lets pick one place to work through this topic (I'm happy to continue it here).

A modify operation MUST NOT change the state of any other resource than the target resource, except when a new resource is created, then the server will change the parent container by adding or removing containment.

I don't believe there's an advantage to having modify encompass create

From the principle of least privilege, it seems, at least intuitively, to be attractive that a modify operation should not include the create operation

+1

Since the delete operation results in a change of state of the parent container, the agent is also required to be authorized to perform the resulting operation on that container, in this case, it needs a Write or Modify access mode on the parent container.

What would be the use of a delete mode if you need another mode to complete a deletion?

Generally I believe that we should try to make any new modes as simple and intuitive as possible, or we run the risk of misinterpretation, which could then end up in rules being created incorrectly, and data being exposed as a consequence. In the simplest terms for me, that would be:

  • if you want to create a resource, you need acl:create on the parent
  • if you want to delete a resource, you need acl:delete on it, or acl:delete inherited from the parent (and not overridden on the resource)
  • if you want to modify an existing resource (not create or delete it) - you need acl:modify
  • if you want to append to a resource - you need acl:extend permission (note: see point below on why this isn't acl:append related to backwards compatibility)

I do appreciate the path to backwards compatibility with existing modes, which to me would be:

  • retain acl:write but deprecate its use, and for a container resource make that equivalent to acl:create, acl:modify, and acl:delete. for a non-container resource make that equivalent to acl:modify and acl:delete.
  • retain acl:append but deprecate its use. while i think append is the most fitting mode name for this operation, we'd need to determine how we want to reconcile append modes on a container moving forward, since it has also been used for creating child resources. With that context, let acl:append on a container be equivalent to acl:create and acl:extend, and acl:append on a non-container resource be equivalent to acl:extend. Note that I wouldn't be totally against changing the behavior of acl:append to line up with what i'm proposing for acl:extend - but that would be a non-backwards compatible breaking change - and it would probably be easier on everyone to avoid that.

@elf-pavlik
Copy link
Member

A control operation includes read, create, modify or delete the resource containing a representation of authorizations.

I think we should reconsider need for Control and any further spin-offs. Besides solid/specification#303 I would also like to point out new use case 2.6.1. Delegating subset of received access to another agent which mentions fact that anyone already effectively can 'share' their access (or restricted subset) if they use any of pretty straight forward approaches based on impersonation. Given that it might be worth to properly support alternative approach based on delegation.

In that case only owner of the storage would have initial implicit right to grant access, any other agent who was granted access by the owner uses delegation chain (preferably with a trail) to further propagate their access.


It seems to me that "Access Control Resource" should be a generic term for any such resource, including WAC's ACL resources and ACP's ACRs. Thus, the latter will have to give that up for the greater good. :-)

Following train of thought is still in it's early stage but I might already bring it up. I think ACR might be an artifact of specific authorization system, like WAC or ACP and different system might manage policies differently.

It might be useful to only focus on common access modes that apply to data in general. If specific authorization system uses ACRs, it could define additional modes specific to that system. Later when resource server (storage) needs to allow/disallow operation on ACR, authorization system would provide it with common access mode that should be applied to that ACR, only using any additional access mode internally to the authorization system itself.

@bblfish
Copy link
Contributor

bblfish commented Sep 1, 2021

I like the diagram with top level concepts and subconcepts below them. It helps a lot.

First it identifies two main interaction types: Read and Write. I think we have definitively very very strong mathematical underpinnings for those interactions as being fundamental. The mathematics of dynamical systems are based on two types of functions on a state S.

  1. a observation function get: S -> A
  2. a change function put: S -> A -> S which from a state and a value returns a new state.

This was found in the 1990ies as part of the work on Caolgebras, such as Bart Jacobs' Objects and Classes Coalgebraically. Later Functional Programming rediscovered this as Lenses which are Monadic versions of the above. And recent mathematical work shows that these fall into a general conception of lenses which can model dynamical systems. For many more resources see this twitter thread. Note that these polynomials are essentially also essentially composed of getters and setters.

So Read and Write is I am pretty sure set in stone.

Control is something completely different, which should not be there along side those two other modes. For one it is not needed, which gives a pretty big clue :-)
Secondly control in the space of access control was introduced by Abadi, Burrows and Needham around 1990 with A Calculus for Access Control in Distributed Systems where A controls p is a short for if A says p then p. That is why I think it is actually better modelled as being the Link: <doc.acl>; rel="acl" header. Arguable that should be "controlledBy" .

I am writing up the mathematical ideas on this on the web-cats issue 28.

@kjetilk
Copy link
Member Author

kjetilk commented Sep 1, 2021

Thank for the thoughtful responses!

I will need to write a more lengthy discussion later, but let me just briefly touch on the topic of permissions on the container for deleting a resource, that stems from a general principle that I think is important:

If a resource changes state, that is an operation that should always be subject to authorization. No state changes without authorization. I think that principle makes it clearer for server implementors, but I realize there is a cost. Moreover, with the introduction of a audit log, for example, the idea got into trouble, because the client would certainly not have append permission on the audit log.

After I posted this, I started to think that perhaps the authorization doesn't need to be on the client, as the state change on the container is done by the server. Perhaps we instead should ensure that the server is an agent, and that that agent needs to have Modify permission on the container to delete a resource. But that creates another cost; to delete, the server will first need to check the authorization of the client on the resource, and then the authorization of the server on the container, and fail the client request unless both are in place.

It may seem contrived, but it isn't given that the server has authority to change a resource. If we introduce end-to-end crypto, the server will only see the state changes, it will not see a representation, and so to change the representation, it would need to have authorization to access the keys to do so.

In the trivial cases, however, this would reduce to a more familiar situation, the server will carry default access rules that gives it Modify on all server-managed resources, and the client will only need Delete on the resource to actually delete it.

@elf-pavlik
Copy link
Member

If we introduce end-to-end crypto, the server will only see the state changes, it will not see a representation, and so to change the representation, it would need to have authorization to access the keys to do so.

I think in this case containment triples would need to be separated from the description of the container. I actually like this approach for more reasons than just end-to-end crypto. Resource with containment statements would be considered Server Managed. It might be better to discuss it in separate issue, for the sake of this issue I just don't think we have to box ourselves in by making assumption that containment triples couldn't be managed in a separate (SM) resource.

@kjetilk
Copy link
Member Author

kjetilk commented Sep 1, 2021

@elf-pavlik :

It might be better to discuss it in separate issue, for the sake of this issue I just don't think we have to box ourselves in by making assumption that containment triples couldn't be managed in a separate (SM) resource.

I have to disagree with that. This issue is for what we can have in the Protocol in the short term, it is not for a complete green-field design. For now, containment triples are where they are, in the representation of the container. There is a difficult balance between what we think in the long term, and what can be achieved in the short term to make truly useful stuff for people right now. I'm trying to be conscious about not cutting off future directions and enabling creativity and to allow possible upgrade paths. We may find an upgrade path from containment triples represented in the container to something else, but for the purpose of formulating operations in the Protocol, I strongly suspect moving the containment triples elsewhere isn't position that is viable in the time frame this has.

The panel is of course free to pursue a broader vision.

@kjetilk
Copy link
Member Author

kjetilk commented Sep 2, 2021

And now for the longer discussion :-) I am as indicated rather reluctant to spend much time on issues that are not compatible with "current Solid", but I also feel it is important to have this discussion in this panel to make the ideas and the text that will be written around it more mature, with the objective to open an issue on the specification board that is something that the Solid Editors are likely to accept for inclusion in the Protocol spec RSN.

What we could do is flesh out the opportunity space a bit and then quickly narrow it down to what is likely to be formulated in the Protocol.

It seems to me that WAC originally found a pretty good balance between complexity and the principle of least privilege, especially with the Append access mode, which made it possible to have very limited access to write. An Update access mode without Append would have been much worse in that respect.

It is also worth noting that PUT is a method that can be used in create, modify and append operations. It makes an awful lot of sense from an implementation perspective when you base something on HTTP to lump these together with a Write access mode, and then put DELETE into the same group to keep the authorization system simple. Now, a create operation can be distinguished from a modify operation using If-None-Match: *, we have that in the spec now, but it still shines some appropriate light on that we are designing this from the starting point of a Web technology, not from access control systems.

Also, I don't see the need to deprecate Write, to the contrary, it seems to be very nice to have for a lot of people who just want to do a simple thing and where trust between agents are established through meatspace relationships, but I also think it is worthwhile examining the subsets.

Now, I understand that there are real-world cases where this simplicity is not sufficient, so we need to talk about extensions. We could in principle have something like:

Here, Update and Extend is similar to Modify and Append but cannot be used to create new resources.

That would retain the semantics of WAC and so backwards compatibility, but also add the stuff that's desired. I'm not saying that this is what should come out of this discussion, I believe something has to be cut from this diagram. The question is what.

The issue of Control is very interesting, and but I believe we should treat it as a separate issue, through 303.

@csarven
Copy link
Member

csarven commented Sep 6, 2021

solid/web-access-control-spec#85 (comment)

@elf-pavlik
Copy link
Member

elf-pavlik commented Sep 6, 2021

I think it might be easier to discuss access modes in one issue. Since we seem to converge on spec defining mapping between access modes returned from authorization system (WAC, ACP, etc.) to server operations we could just transfer this issue to specification repository already and focus conversation there.

@elf-pavlik
Copy link
Member

PUT /C/R Create?, Update acl:Write [2][3] Resource

In this case End-user (via Client) doesn't really update the container. They just create new contained resource and the server updates a server managed contained triples. I think Create on the container should be enough here.

I would see it a different case where End-user (via Client) would want to change client managed triple. For example add/change rdfs:label providing human readable name for the container. This would require Update on the container
since here server isn't the one being in control of making the update.

BTW is there consensus in the spec for PUT that

  • creating new resource via PUT uses If-None-Match: *
  • updating existing resource via PUTuses If-Match: xyz

? (As explained in MDN: Conditional requests )

Myself I would be 👍 for making those together with Etags a requirement.

@bblfish
Copy link
Contributor

bblfish commented Sep 6, 2021

It may be worth converting this to a Discussions, as I can see it being quite a branching topic, and then gather the consensus that arises there to form them into some issues that can be voted on.

If I can consider just one topic|: Should DELETE on a resource require rights on the container? I think I can see merit to @justinwb's argument that that may be overly complicated.

Let me try to see how one could have come to that conclusion. Creation of a resource requires rights to the container, either when using POST or when using PUT. That seems to clearly make sense: there can be no other place for a Creation right to be placed, and creating a resource does change the state of the container.

Deleting a resource also changes its container, but that could be considered a server managed effect, along with creating ACRs, logging, etc...

@elf-pavlik
Copy link
Member

Deleting a resource also changes its container, but that could be considered a server managed effect, along with creating ACRs, logging, etc...

I suggested that Creating a resource changes a container but it's what you called 'server managed effect' as much as when Deleting a resource. Do you see difference in 'server managed effect' of removing containment triple and adding containment triple?

I agree that Create needs to be associated with an existing container, of course it can't mean creating that already existing container itself. At the same time just like Delete I wouldn't see Create requiring Update operation on the container.

@csarven
Copy link
Member

csarven commented Sep 6, 2021

In this case End-user (via Client) doesn't really update the container. They just create new contained resource and the server updates a server managed contained triples. I think Create on the container should be enough here.

RFC 7231 describes creating and replacing resource state with PUT. That's analogous to "Create" and "Update" in the table. Create precedes Update.

@elf-pavlik
Copy link
Member

RFC 7231: 4.3.4. PUT

A PUT request applied to the target resource can have side effects on
other resources. For example, an article might have a URI for
identifying "the current version" (a resource) that is separate from
the URIs identifying each particular version (different resources
that at one point shared the same state as the current version
resource). A successful PUT request on "the current version" URI
might therefore create a new version resource in addition to changing
the state of the target resource, and might also cause links to be
added between the related resources.

I think this is similar to Creating new resource with PUT. Adding server managed containment triple on other resource, the container, shouldn't require Update permission on the container. Client doesn't directly do the update and if containment triples have to be added (or removed on Delete) by the server, giving client permission to Create on a container or Delete on contained resource should already take into account that server will take care of those side effects.

@kjetilk
Copy link
Member Author

kjetilk commented Sep 6, 2021

We're now in The Battle of the Bugs! :-) Over here in authz panel, @kjetilk stands firm, over in the other corner, ready to duke it out on the WAC repo, stands @csarven ! ;-D

Anyway, we're drifting from where I was hoping to take us. I feel strongly that we should first talk about the operations that we need to do. Operations are really what clients will perform, and operations are what servers implement. I shall not comply with @csarven 's assertion that it is nitpicking to cry foul over a choice of CRUD, it is not nitpicking, it is the very crux of the matter :-) What operations we have has potentially tremendous implications on people's ability to control access to their data the way they want, especially in light of the principle of least privilege. I think it is well illustrated by the Update operation vs the Append operation, with CRUD, you do not have a way to to have a resource that people can write to, but not to change. This is exactly why it is so important to first understand the implications of operations.

With that, we can add access modes to operations, and then define how operations are implemented. Obviously, it is not a waterfall here, since the protocol can possibly make different operations practically indistinguishable from each other.

BTW, @elf-pavlik : Conditional request are in the spec, so there has been consensus around that, even though ETags aren't mandatory in the the RFC.

@bblfish consensus was reached on the delete requires write on container was reached in solid/specification#197 I think to change that, we should see if we can derive it from some greater principle. As I tried to say above, we could introduce the server as an agent in its own right, and so the server could be the agent having Modify on the container, so the client wouldn't need to have their own Modify access mode. That would have the same effect, but still retain the principle that every state change must be authorized.

@csarven
Copy link
Member

csarven commented Sep 6, 2021

For example, an article might have a URI for

Cool that you've brought that up because I've actually implemented what's described in that example in dokieli (introduced in 2017) where updating mem:OriginalResource creates a mem:Memento with a rel:latest-version and rel:predecessor-version links..


Adding server managed containment triple on other resource, the container, shouldn't require Update permission on the container.

And? 1) I was talking about operations not permissions. 2) Again, update was about replacing the resource state. I'll quote from that comment:

[2] Requires Append (or Write) on /C/ and Write on /C/R to Create.
[3] Requires Write on /C/R to Update.

I think you've also missed my point about create and replace of resource state. For example, creating resource /C/R entails that server could generate a representation for it when requested. A subsequent request to update the resource state with a particular representation replaces what exists.

Now, when /C/R is created, server can give an updated description of /C/ when requested i.e., including /C/R. This is an effect that is described by Solid Protocol - partly borrowed from LDP.

You could continue to "think Create on the container should be enough" but then you're out of luck to update /C/R. Need an Update "permission" in addition so that PUT works. The way you're using that Create permission is equivalent to acl:Append on /C/ which would only work with POST.

@csarven
Copy link
Member

csarven commented Sep 6, 2021

@kjetilk Wow, okay. If you actually read the very next sentence:

Happy to switch to use a different variation, RFC terms, or introduce 50 very specific terms.

So, I'm not sure why you feel the need to corner me on this.. as if I'm saying CRUD terms is the only way or if it even maps perfectly to HTTP or WAC's access modes. I'm well aware of what the actual operations are... The Solid Protocol's operations are informed by WAC's access modes in context of HTTP operations. We've authored that together, as you well know.

And the whole solid/web-access-control-spec#85 (comment) -- which predates this issue here -- is an attempt to collect and understand access modes that are under consideration based on common operations.

What I'm actually sensing in this thread is that people are:

  • observing operations in a vacuum
  • conflating operations and access modes
  • conflating resource and content level operations
  • not seeing the constrained list of operations that an HTTP request entails

If people want super specific operations or access modes or whatever, consider going through the RFCs for the terms and see also the semantics that the Solid Protocol puts on certain types of resources. That's being grounded on an actual range. In parallel, develop and share an actual application that experiments with the proposed/hypothetical. It can look great on paper but why go through that whole exercise if the UI is going to be bloatware or incomprehensible. Not everything is green-field for very good reasons.

@csarven
Copy link
Member

csarven commented Sep 6, 2021

I just don't think we have to box ourselves in by making assumption that containment triples couldn't be managed in a separate (SM) resource.

Cool. Will the server you will develop take on that behaviour?

By the way - this is a tangent - here is some "out of the box" thinking: solid/specification#230 (comment) .. note that it mentions:

what introducing pagination does is moves the server-managed triples (like containment statements, whether it is ldp:contains or as:items is besides the point right now) into its own resource eg. /foo/?p=1.

See also implementation in mayktso server and deployment:

curl -iH'Accept: text/turtle' https://linkedresearch.org/inbox/linkedresearch.org/cloud/

curl -iH'Accept: text/turtle' https://linkedresearch.org/inbox/linkedresearch.org/cloud/?p=1

curl -iH'Accept: application/ld+json; profile="https://www.w3.org/ns/activitystreams"' https://linkedresearch.org/inbox/linkedresearch.org/cloud/

curl -iH'Accept: application/ld+json; profile="https://www.w3.org/ns/activitystreams"' https://linkedresearch.org/inbox/linkedresearch.org/cloud/?p=1

it is not for a complete green-field design.

Why not? We are not thinking out of the box enough.. we should perhaps get rid of the whole containers thing which would actually solve a lot of problems..

@kjetilk
Copy link
Member Author

kjetilk commented Sep 6, 2021

@kjetilk Wow, okay. If you actually read the very next sentence:

Happy to switch to use a different variation, RFC terms, or introduce 50 very specific terms.

So, I'm not sure why you feel the need to corner me on this..

I tried to frame it in humorous language in an attempt to not make it confrontational. The point that I was trying to make is that I felt that in spite of that disclaimer, it seemed to discount what I thought we agreed on the need to look into the operations as the basis. I'm sorry if it felt like an attack, it was not intended. I guess we are feeling the effects of not having met in person for two years, we are suffering from insufficient emotional bandwidth.

@csarven
Copy link
Member

csarven commented Sep 10, 2021

I was thinking about documenting "Remove (to subtract information from resource state)" operation in solid/web-access-control-spec#85 (comment) (recently updated) as complement to the Append operation - more like entertaining the idea what that might entail. It is intended to be content-level. It is certainly possible with for example HTTP PATCH and SPARQL Update's DELETE in payload. (Aside: currently we need read to remove information via PATCH but that's beside the point.) The Remove operation is generally covered by the Update operation (add or remove information). I'm not sure if there are compelling use cases where remove-only is needed.

Thinking further, another way to look at this is whether operations are or should be exclusively resource- or content-level operations, or can they be both depending on the request's characteristics. So perhaps that's something we can explore further. I definitely do think we need to tell them apart whether they are used or not. For instance, the Delete operation, depending on what the request entails could be to delete resource - this is the common thinking - or to delete information in resource state (which may be equivalent to the Remove operation above).

@bblfish
Copy link
Contributor

bblfish commented Sep 10, 2021

@bblfish consensus was reached on the delete requires write on container was reached in solid/specification#197 I think to change that, we should see if we can derive it from some greater principle.

Yesterday I spent a day to implement DELETE for the lens based server and wrote up the details of it on gitlab issue 28. Essentially I get all of CRUD to work with Lenses (i.e. setters and getters).

The result is that yes, one is changing the container on DELETE, but one is also changing the state of the whole web server in a way too... So I don't think this is yet helping make a decision about whether DELETE needs rights to the parent container. I think that may become clearer by thinking of the role of the guard.

Still the fact that we can get all of CRUD (and Append by adding monoid actions I think) shows that this is the right mathematical space.

@kjetilk
Copy link
Member Author

kjetilk commented Sep 10, 2021

@csarven :

Thinking further, another way to look at this is whether operations are or should be exclusively resource- or content-level operations, or can they be both depending on the request's characteristics.

Indeed, that could be done. I think that the reason why you see these things conflated is that this distinction hasn't been done thus far. I suppose to keep the number of access modes down, which is good for simplicity, but not for avoiding overpermissioning.

I think the most critical tradeoff we have to make is between those two, actually (simplicity and principle of least privilege). Whether we should make the distinction between resource and content-level operations depends on that trade-off, I think.

@kjetilk
Copy link
Member Author

kjetilk commented Sep 21, 2021

Just one question: Why does each comment need to be individual resources in the story container? That seems to be a requirement that isn't motivated from the use case.

@kjetilk
Copy link
Member Author

kjetilk commented Sep 22, 2021

This scenario just illustrates something. If we would just have an rdf:label on the container and would just want to allow colleagues to create new comments, update and/or delete a comment if they created it but not change the rdf:label on the container, can we support that?

Yup. You would simply create a container per user, and let them store their comments in there. That'll be a general pattern to follow, I suppose. It is important not to introduce arbitrary requirements that just complicates things.

@bblfish
Copy link
Contributor

bblfish commented Sep 22, 2021

I think we should really have moved this topic to github discussions as that supports threading. Discussions here become impossible to follow quite quickly, or very tedious to do so.

@bblfish
Copy link
Contributor

bblfish commented Sep 22, 2021

@kjetilk

Yup. You would simply create a container per user, and let them store their comments in there.

I think there is a good use case for comments on blog posts, where one wants one container for all comments. The space of agents that can comment could be very large and having a container per user, where each user would only have perhaps one entry, seems very much overkill.

Users could either POST their content to the comments container directly, or POST a link to content on their own pod, blockchain or whatever.

The use case that the a person may later want to delete that statement makes sense, and so does it make sense that a user should only be allowed to delete their own content but not anyone else's; be that content a chunk of html or a link to content elsewhere.

@justinwb
Copy link
Member

Yup. You would simply create a container per user, and let them store their comments in there.

Who exactly would create that? If Alice - in this scenario not only does she need to manage access control rules, but now she needs to manage a hierarchy and give special rights to each container. If the individual colleague, then we have the same problem in the original case (the ability to create or delete resources you create, and only read others). This also wouldn't work if the "group" of users is represented by a general credential (e.g. colleague), and so you don't have advanced knowledge of their individual identity.

It is important not to introduce arbitrary requirements that just complicates things.

Creating a container in advance per colleague for their comments seems like an arbitrary requirement that complicates things 🙂 😉

and there has been broad agreement that users should write to their own pod, and then notify the story pod

That is one pattern, but not the only one (as @bblfish points out). Our job is to provide something flexible so the appropriate pattern can be used for the appropriate scenario. Just because one might be legitimate does not render the others illegitimate.

@elf-pavlik
Copy link
Member

elf-pavlik commented Sep 22, 2021

I really would like to understand what problems do you see with defining Create and Delete for contained elements in a way that it doesn't include access to Update client-managed triples of the container. Does it relate to the side effect, where the server manages adding/removing containment triples?

@TallTed
Copy link
Contributor

TallTed commented Sep 22, 2021

github discussions as that supports threading

Not really. One level of thread depth is insufficient for even basic "discussions". GitHub could have bolted on NNTP, phpBB, LiveJournal, or any of many other possibilities, to better results.

As they stand, GitHub Discussions are worse than Issues, because you can't get a straight time-series view of posts (for those of us who just want to see all the comments made since the last time we looked at that Discussion); and comments are either "primary" on the initial post or "secondary" on one of those "primary" comments — there's no third-level for subsequent branching.

Yay, Microsoft UX... bleah

@elf-pavlik
Copy link
Member

elf-pavlik commented Sep 22, 2021

Trying to refocus on the initial post:

Delete operation

A delete operation removes the representation of the target resource.

State changes in existing resources

A delete operation changes the state of the target resource and the parent container.

Implementation

As defined.

Access Mode

To execute a delete operation, an agent is required to be authorized with a Delete or Write access mode on the target resource. Since the delete operation results in a change of state of the parent container, the agent is also required to be authorized to perform the resulting operation on that container, in this case, it needs a Write or Modify access mode on the parent container.
Delete is an access mode that is a subset of Write. It is mutually exclusive with Modify.

I would like to focus specifically on:

Since the delete operation results in a change of state of the parent container, the agent is also required to be authorized to perform the resulting operation on that container, in this case, it needs a Write or Modify access mode on the parent container.

In the case of Delete, the client doesn't change client-managed triples in the parent container. The server updates server-managed triples in the parent container.
I would like to propose that if an agent has Delete right on the resource, they DO NOT need any rights on parent container.

If we manage to resolve that it should be easier to dive into nuances of Create.

@csarven
Copy link
Member

csarven commented Sep 22, 2021

@kjetilk
Copy link
Member Author

kjetilk commented Sep 22, 2021

In the case of Delete, the client doesn't change client-managed triples in the parent container. The server updates server-managed triples in the parent container.
I would like to propose that if an agent has Delete right on the resource, they DO NOT need any rights on parent container.

As @csarven noted, this has recently been decided with the opposite conclusion, and I think we should not just re-open issues all the time.

However, there is a possible compromise: If we see the server as an Agent, then we might say that it is sufficient for the server to have a Modify access mode on the container.

That would have the effect that the client doesn't need to have it (but it could) and so have the same practical effect, and still be consistent with the principle that no state change should be unauthorized.

@justinwb
Copy link
Member

As @csarven noted, this has recently been decided with the opposite conclusion, and I think we should not just re-open issues all the time.

That issue was specific to WAC. That decision should be input to these discussions, but we shouldn't assume it is settled when the purpose of the panel is to learn from and improve upon shortcomings in WAC and Solid access control in general.

However, there is a possible compromise: If we see the server as an Agent, then we might say that it is sufficient for the server to have a Modify access mode on the container.

If that was an implicit understanding (meaning access control statements don't have to be created to specify this) then I suppose it would be OK to document this as the rationale. Otherwise I'd worry that we run the risk of confusing people when they're managing their access control statements.

@elf-pavlik
Copy link
Member

However, there is a possible compromise: If we see the server as an Agent, then we might say that it is sufficient for the server to have a Modify access mode on the container.

If that was an implicit understanding (meaning access control statements don't have to be created to specify this) then I suppose it would be OK to document this as the rationale.

I also think this should be implied for the server, otherwise, it simply wouldn't be able to do its job. I would also note that the server is enforcing access policies. Allowing to delete contained resources but not allowing the server to take care of the side effect (removing server-managed containment triple) sounds to me like a self-contradicting policy.

@bblfish
Copy link
Contributor

bblfish commented Sep 23, 2021

github discussions as that supports threading

Not really. One level of thread depth is insufficient for even basic "discussions". GitHub could have bolted on NNTP, phpBB, LiveJournal, or any of many other possibilities, to better results.

As they stand, GitHub Discussions are worse than Issues, because you can't get a straight time-series view of posts (for those of us who just want to see all the comments made since the last time we looked at that Discussion); and comments are either "primary" on the initial post or "secondary" on one of those "primary" comments — there's no third-level for subsequent branching.

Yay, Microsoft UX... bleah

Just one layer of threading makes it better than the 0 level of discussions we have here. So let the perfect not be the enemy of a little improvement.

Btw. Github discussions went out of beta yesterday, so perhaps we should at least try to see what's new
https://twitter.com/github/status/1440723610553884672

@bblfish
Copy link
Contributor

bblfish commented Sep 23, 2021

I opened a discussions on giving rights to the creator of a resource to see how one would need to deal with that part of the use case brought up above. (waiting to see what the new discussions may look like when someone enables it)

@kjetilk
Copy link
Member Author

kjetilk commented Sep 23, 2021

As @csarven noted, this has recently been decided with the opposite conclusion, and I think we should not just re-open issues all the time.

That issue was specific to WAC. That decision should be input to these discussions, but we shouldn't assume it is settled when the purpose of the panel is to learn from and improve upon shortcomings in WAC and Solid access control in general.

There was very little in that discussion that was specific to WAC. Essentially, the comment that turned the discussion was @timbl 's argument that "if I remove Write access to something it won't change." and that is not a WAC-specific argument, it is a general argument about the understanding of the role of access control in Solid.

However, there is a possible compromise: If we see the server as an Agent, then we might say that it is sufficient for the server to have a Modify access mode on the container.

If that was an implicit understanding (meaning access control statements don't have to be created to specify this) then I suppose it would be OK to document this as the rationale. Otherwise I'd worry that we run the risk of confusing people when they're managing their access control statements.

I think the statements would have to be explicit, because if we are to have a system that satisfies @timbl 's argument above, then you need to know whether something can perform a write operation on a resource. However, giving the server modify on all resources could be something done as a matter of configuration, and it could be left open how it is changed.

I think we should have a more principled approach to this. I think @timbl 's statement is also embodied in the principle that "no state change can happen without authorization". Can we agree on such a principle?

We need think ahead too, say that we introduce end-to-end encryption that makes it impossible for the server to modify a resource without authorization. We need to have robust principles that take such scenarios into account, even though they may be more more remote than the use cases we discuss on a daily basis.

@elf-pavlik
Copy link
Member

I think the statements would have to be explicit, because if we are to have a system that satisfies @timbl 's argument above, then you need to know whether something can perform a write operation on a resource. However, giving the server modify on all resources could be something done as a matter of configuration, and it could be left open how it is changed.

Since that would allow the conforming server not to be authorized to change containment triples, it would not be able to conform to LDP Container requirements. Wouldn't we need to make those requirements conditional?

4.2 Resource Containment

[...]
The representation and behaviour of containers in Solid corresponds to LDP Basic Container and MUST be supported.

I seems that server not authorized to update containment statements would stop to be conformant.

5.2 Container

[...]

5.2.3 HTTP POST

[...]
5.2.3.2 When a successful HTTP POST request to a LDPC results in the creation of a LDPR, a containment triple MUST be added to the state of the LDPC whose subject is the LDPC URI, whose predicate is ldp:contains and whose object is the URI for the newly created document (LDPR). [...]

@kjetilk
Copy link
Member Author

kjetilk commented Sep 23, 2021

Since that would allow the conforming server not to be authorized to change containment triples, it would not be able to conform to LDP Container requirements. Wouldn't we need to make those requirements conditional?

5.2 Container

[...]

5.2.3 HTTP POST

[...]
5.2.3.2 When a successful HTTP POST request to a LDPC results in the creation of a LDPR, a containment triple MUST be added to the state of the LDPC whose subject is the LDPC URI, whose predicate is ldp:contains and whose object is the URI for the newly created document (LDPR). [...]

My emphasis. The request would not be successful, it would have been denied with a 403, so it would still be compliant with LDP.

@bblfish
Copy link
Contributor

bblfish commented Sep 28, 2021

In order to help the process along I have opened a discussion giving rights to the creator of a resource to find out how one could create a rule that would satisfy @justinwb and @elf-pavlik's use cases above.

I offered the following way to encode it in WAC+n3

{ ?i a foaf:Agent } => {
   [] a :Authorization;
     :accessToClass [ 
        a owl:Restriction;
        owl:onProperty iana:author
        owl:hasValue ?i ];
     :mode :Write;
     :agent ?i
}

Given this we can look at Delete and Create modes, whilst keeping the use cases proposed.

@elf-pavlik
Copy link
Member

My emphasis. The request would not be successful, it would have been denied with a 403, so it would still be compliant with LDP.

I find it problematic that the access mode on a given resource doesn't have an unambiguous mapping to operations that can be performed on that resource. So to know if resource R contained in container C can be deleted one needs to take into account access mode to container C.

As I mentioned during the last meeting, in the interop panel we need to communicate to an agent who receives access, what they can access, and what operations they can perform (or modes that map to operations). If we think of an access matrix below WAC / ACP collapses it on resources why Data Grants collapse the same access matrix on the Agent (user)

access matrix

We actually quite heavily rely on granting user access to create/update/delete resources in the container but not updating the client-managed triples in the container itself. Of course, the server can still manage the containment triples.

I'd like to see if we can define unambiguous operations on a single resource and see how authorization systems can construct policies using those granular operations. At the same time authorization system would need to ensure that policy is consistent. So if we follow the example we discussed, if resource R in container C has Delete operation allowed to any agent, the container C itself must have Remove containment triple operation allowed to the server itself. Otherwise, the policy would be inconsistent and the authorization system doesn't do its job.

I think having those very granular operations should be enough on the protocol level for authorizations systems to build some higher-level ways to express policies, which can include more abstract access modes. Once again, the authorization system would stay responsible that applied policies stay consistent.

@bblfish
Copy link
Contributor

bblfish commented Sep 29, 2021

I agree with @elf-pavlik, and I think I expressed my support for that in the meetings since the beginning of the month. Now that we have track 315: for the creator metadata, and a potential answer the access control rule needed, we can just write out the request/response exchange.

I guess that having to make two requests to ACLs is going to be costly. So ideally we'd like to have just one. If consistency is the problem, it is true that one could(/should?) require the guard to make consistency checks to the ACL before writing them out.

Is the question to solve now the following:
what is the use case where having a wac:Delete access mode to a resource would be problematic, assuming that right is specified in the resource's ACR itself?

Is it a use case where one wants to give the user control over the resource, which would allow them to set the wac:Delete mode, but the user should only be able to DELETE it if they have wac:Write access to the container? Can one work that out in more detail?

@elf-pavlik
Copy link
Member

Given the conversation in solid/specification#227 it may turn out that containers will have a bunch more server-managed triples. As I understand the logic of coupling the rights for the server to update containment triple when deleting a contained resource. Similar, with last-modified information on all contained resources in the container, the right to update any contained resource would be coupled to the right for the server to update the corresponding last-modified statement about that contained resource in the container.

@elf-pavlik
Copy link
Member

@csarven, is there a more formal place specifying storage operations? solid/web-access-control-spec#85 (comment), I also used that table in solid/notifications#183

For the next STM, I would like to have a canonical reference for storage operations.

We probably also can merge this issue here:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Done
Development

No branches or pull requests

6 participants