r17 - 06 Feb 2008 - 11:47:39 - RandyLetnessYou are here: OSAF >  Journal Web  >  ContributorNotes > RandyLetnessNotes > CosmoAccessControlNotes

Access Control Notes

Whats the problem?

In short, items in multiple collections. Now that an item can exist in multiple collections and its not a copy, it becomes complicated in determining permissions for that item. For example:

  1. User 1 publishes collection A with item aaa
  2. User 2 subscribes to collection A using a read-write ticket issued by User 1
  3. User 2 publishes collection B
  4. User 2 adds item aaa to collection B

On the server, item aaa already exists, as it was created by User 1. When User 2 updates collection B with aaa, the server sees that aaa exists and needs to determine if User 2 has the correct permissions to add it to collection B. Today the server just allows it without checking, hence the security hole. This didn't happen before items in multiple collections because each collection had a separate copy of the item.

Assuming the server can determine if User 2 has access, there is now another problem. Item aaa exists in two collections, with each collection having its own set of permissions. Let's say User 1 wants to revoke the read-write ticket on collection A, preventing User 2 from updating item aaa. What happens now is the ticket is revoked on collection A, and User 2 is unable to update item aaa through collection A. But item aaa exists in collection B, which User 2 owns so she can still update item aaa through collection B.

So the question is, what is the desired behavior? If an item has been added to multiple collections using a ticket, and that ticket is revoked, should access be denied to that item through all collections, or just the one collection?

Are there any examples (apps or systems) that have similar problems with securing items in multiple collections?

UNIX file system - files exist in single directory, possible to create links in other directories, mimicking a file existing in multiple "collections". When link is removed, file is untouched. When file is removed, link becomes broken. One set of permissions assigned to file, not able to assign different permissions to link.

Google Calendar - events can be copied to other calendars, but a new event (copy) is created, so no analog here

Others?? I can't find an example of securing access to items that exist in multiple collections or directories. Maybe because its such a pain!

One collection per item, copies of items

The whole idea of allowing items in multiple collections came about because the client supports it. Before the server supported it, the client would publish the same item into different collections on the server, resulting in copies of the item. This forced synchronizing the items onto the client. If you think about it, it worked great because the owner of a collection had full control of that collection. For example:

  1. User 1 publishes collection A with item aaa
  2. User 2 subscribes to collection A using a read-write ticket issued by User 1
  3. User 2 publishes collection B
  4. User 2 adds item aaa to collection B
  5. User 3 subscribes to collection B using a read-write ticket issued by User 2
  6. User 3 publishes collection C, adds item aaa

In order for changes that User 3 makes to aaa to make it to collection A, User 3 must update collection B, and then User 2 must receive those changes and update collection A. So User 3 never updates collection A directly. If User 1 revokes the read-write ticket, then User 2 can't update collection A, meaning User 3 can't update it either. Works great.

The problem is that an item can have many different states on the server if it exists in multiple collections and the client is responsible for synchronizing. Although Chandler handles this fine, the web ui can't. Consider this case:

  • User 1 publishes collection A with item aaa
  • User 1 publishes collection B with item aaa

Two collections, same item. On the server this would be represented as two collections and two items, with the items having the same uuid. On the client its represented as two collections, single item. When a change is made to item aaa on the client, the client makes two update requests to the server, one for collection A, and one for collection B. This is how the client works today so there is no change here.

What about the webui? The webui doesn't have an item repository like Chandler nor does it have conflict resolution. So how can the webui handle the case of an item that exists in multiple collections, and more specifically, the case where the item differs between collections? The server would have to provide some extra smarts to keep copies of items in sync and manage conflicts, but that could be done at a later time if we assume the desktop will take care of this in the mean time.

What about caldav? Same problem. Maybe we can live with this as caldav doesn't support items in multiple collections.

More notes: CosmoC18NNotes

Ticket required to add to collection

Another option would be to keep the model the way it is now, but require that in order to add an existing item to another collection you need:

1. write access to the collection (either owner or read-write ticket) 2. write access to any of the collections that the item is currently in (either owner or read-write ticket)

At the protocol level this assumes the request includes tickets for any existing items that are to be added to the collection.

Once the item has been added to another collection, it inherits all permissions (tickets) assigned to that collection.


  • model stays the same, allowing items in multiple collection support in web widgets down the road with little server work (no synchronization issues with copies of items)
  • no change to web ui
  • no mixed permissions in collection (we discussed yesterday to eliminate read-only, so that might be an option)
  • desktop work required to keep track and include tickets in morse code requests and maybe handle authorization errors

Ticket per item

A collection has a set of items and a set of item tickets, meaning for each item the collection has an entry that relates the item with a ticket, which is the ticket that was used to add the item to the collection. The collection ticket essentially encapsulates all item tickets. So the work flow would be:

  1. User 1 publishes collection A with item aaa
  2. User 2 subscribes to collection A using a read-write ticket issued by User 1
  3. User 2 publishes collection B
  4. User 2 adds item aaa to collection B
  5. User 3 subscribes to collection B using a read-write ticket issued by User 2
  6. User 3 publishes collection C, adds item aaa

Add true ACL support

One possible solution to the above limitations is to add ACL (access control list) support in the model. This means each resource would have an ACL which is a list of ACEs (access control entites). An ACE grants a principal a set of privileges for that resource. What is a principal?

A principal would be one of:

  • User
  • Ticket
  • Group

An account on cosmo. Nothing really different here.

A principal that has access to a single resource. Again, nothing really different here. Tickets provide a mechanism for gaining access to a resource without having an account, which is what the casual collaborator is all about. A ticket is basically an anonymous user with privileges to a single resource (most likely a collection).

A set of principals. This would be a new concept to cosmo. Groups would allow privileges to be assigned to a group of users. A users can be a remember of multiple groups and a group could include other groups.

In order to do anything, you must be authenticated as a principal. You can't authenticate directly as a group, as the set of groups is determined from the authenticated user. So every request must be authenticated as a User or a Ticket. When you authenticate as a Ticket, you only have access to the resource that the ticket was assigned to. This is because when a ticket is created, an entry for the ticket with the specified permissions is added to the ACL of the resource. When you authenticate as a User, you are authenticating as a User plus any groups that the user belongs to.

In order to determine if the request is authorized for the target resource(s), the server checks the authenticated principal against each resource's ACL.

For example:

Collection A 's ACL has an entry that gives group B write access. User Joe is a member of group B. When user Joe authenticates and attempts to update A, the server allows it because it finds the entry in A's ACL for group B, and because Joe is in group B, access is granted.

Collection A's ACL has an entry that gives Ticket X read-write access. An anonymous user uses ticket X to add an item to A. The server allows this because it finds an entry for ticket X in A's ACL.

Items in multiple collections
What does this mean with ACLs? It means an item could exist in multiple collections, with each collection having a different ACL. How does ACL evaluation work in this case? Does the first matching ACE win, or does the most restrictive win, or least restrictive? As you can see, ACLs don't solve the items in multiple collections problem. Assuming we have ACL support in the model, we still need to figure out how to secure items in multiple collections.

Per Collection ACL

Permissions are defined on the collection, and item permissions are inherited from the collection. This implies all updates are done in the context of a collection, and the permissions that apply for an item are determined from this context. How does this work with the two problems defined above?

Adding existing items to collections:
A principal may add an item to another collection if they have read-write access to that item through any other collection it is in.

Revoking access to shared collection:
This is tricky. Because ACLs are collection oriented, when you deny access to a collection, you are only denying access to items in that collection when accessed through that collection. If anyone has published items to other collections, you don't have any control of those items when accessed through other collections. This doesn't seem to solve the problem.

So one out of two. This would remove the security hole we have now, but it makes managing access to items a pain, because an item can have multiple set's of permissions depending on what collections it is in. In this case, which set of permissions win? Since most operations are done in the context of a collection (morse code/dav), it seems logical for that collection's permissions to apply. But what about protocols that allow updating an item outside the context of a collection (atom)? How would permissions be determined? What about revoking permission to a shared item when that item has been added to other collections?

Per Item ACL

Instead of items inheriting permissions from the collection, each item has its own ACL, which is initialized from the ACL of the parent collection being updated. When an item is created, its ACL is initialized with the ACL of the collection. When an item is added to another collection, that item's ACL is updated with the ACL of the target collection.

Adding existing items to collections:
A principal may add an item to another collection if they have read-write access to that item (if an ACE exists and gives write access to that item).

Revoking access to a shared collection:
ACL for collection is updated and ACL for each item in collection is updated. Each item's ACL must be updated because items could exist in other non-restrictive collections. This seems like a pain, but might work.

The problem with per-item ACLs is that a single collection may include items with different permissions, which is confusing because one user may have write access to items and another may not even though they are sharing the same collection.

The more I think about it, the more I believe access control should be at the collection level, and if you have access to a collection, that access applies to all items in the collection, otherwise we are asking for trouble.

Original Collection

Bcm brought up the concept of "originality", meaning that the initial collection that an item is added to is important and the permissions on that collection should take precedence over other permissions. This means if the principal only has read access to the original collection, they can't assign write access to an item through another collection. So what if we stored an "original collection" property along with each item. The authorization logic would be something like:

  1. Does principal have write access to current collection? If no, deny
  2. Is current collection the original collection of item to be updated? If yes, accept
  3. Does original collection grant write access to principal? If no, deny, if yes, accept

The problem is how do we evaluate #3 for principals that aren't explicitly granted access to the original collection (this will be the case for users granted access to the new collection)? Do these users have write access to these items?

How would this work for the items in multiple collections cases:

Adding existing items to collections:
A principal may add an item to another collection if they have read-write access to the original collection.

Revoking access to a shared collection:
Permissions on original collection are updated. All items that exist in other collections with read-write access become either read-only or have no permissions. Now we have a read-write collection that contains items that aren't read-write, which can be confusing to the client. What happens to these items?

What happens when an item is removed from its original collection? Is the item removed from all collections or is the item assigned a new original collection? How will the client know what the original collection is for an item? The client would have to account for the fact that the order in which an item is published to multiple collections matters.


Its obvious that the ACL model is better than what we have now, but we still have the problem of how to secure items that exist in multiple collections. There are two ways to model items in multiple colelctions:

Single item, multiple collections
By allowing users to publish an existing item into another collection once a user has read-write access to an item, they essentially have super-user control over that item because they can grant additional principals access to that item through the new collection. The owner of the original collection can revoke access to the original collection, but not the new collection, so the owner has lost full control of the item because it now exists in two collections. Even if the user deletes the item from their collection, it won't be deleted from the server because it exists in another collection.

If the owner of the original collection can revoke access to a shared item in another collection, we have the problem of collections containing items with different permissions, which can get complicated. What happens when a client updates one of these items (that has been revoked in the orginal collection) in a read-write collection? Are they denied access to that one item? What would the client do? Remove that item from the collection. What if the permissions were set to read-only, would the item stay in the collection but only as read-only while the rest of the collection is read-write? What is the user going to think when they subscribe to a collection read-write and they have an item that is read-only?

Multiple items, multiple collections
The problem with this is it forces a lot of synchronization logic on the client. What about a simpler client like the web ui? If an item exists in multiple collections, changes to the item in one collection won't propagate to other collections until the Chandler clients sync. Its possible this could be handled on the server side some how (update all collections that an item is in and that the principal has write access to).

So if we change the model to store a copies of items that exist in multiple collection, access control is easy, but we have synchronization problems with clients other than Chandler.

If we continue to manage a single copy, the synchronization problems go away and we have access control problems. One problem I think we want to stay away from is forcing the client to have to deal with collections that have items with different sets of permissions. We want to keep things as simple as possible, which is to assign permissions at the collection level.


(MikeT) Have you looked at how ACL heavy OS's handle file access? If I recall how WinNT?/Win2k does it, when you make a link to a file (i.e. copy an item to another collection) you also inherit the original ACL (since you had to have access to do the copy.) When any change is made to the ACL of the copy it the inherited ACL then changes from a pure link to a persisted change. Think of it like how subversion does branches - it's all virtual until you touch it. My thought is that since in Chandler items in multiple collections are just ref-counted pointers to the original item, why not also do ACL's that way?

(RandyLetness) If we model items in multiple collections as links, with each link possibly having different permissions than the original item, we still have the problem of what permissions apply. For example, if the original item was shared read-write, and then that item was shared read-write by another user, and the original user removes read-write access from the original collection, then what happens to the permissions on the link thats in the other collection? If they are removed too, then we have the problem of a collection containing items with different permissions. If the permissions stick, then we have the problem of the original owner not being able to control access to the item. One thing about ACLs in Windows: they are powerful, but almost too powerful to the point they are complicated and result in a lot of configuration issues.

(RandyLetness) After talking about this issue with Morgen we both came to the conclusion that moving back to storing copies of items (each item has one parent collection) seems to be the best solution. This not only plugs the security hole, but also provides many other benefits such as:

  1. Removes the need for complicated logic on the server to handle recurring events and modifications in multiple collections.
  2. Makes data partitioning easier as all data can be grouped by account.
  3. Prevents uuid hi-jacking because uuid is unique within an account only.
  4. Other Chandler benefits like being able to use the icalUid to map to uid, being able to share different sets of attributes on a per user basis (Morgen can explain better), and being able to support the peer-to-peer sharing model

The drawback of course is that the webui has to deal with this. In the short-term we could live items in multiple collections not being in sync in the webui until Chandler syncs. Eventually the atom protocol could support updating multiple collections in one request, or the webui could make multiple requests.

(MorgenSagen) As Randy noted, there are quite a few advantages to going back to compartmentalized collections, where if an item is in multiple collections, each collection maintains its own copy of the item.

(Instead of typing compartmentalization over and over, I will refer to this as "c18n" from now on.)

  • With c18n, If someone gets a hold of one of your item's UUID (through email or some other means), they can't modify your copy of it unless they also have write access to a collection that you are syncing. And if they do try to slip a change through some other collection you're syncing, Chandler's conflict management will flag it as a pending change for you to approve/decline.
  • Today, without c18n, if someone has one of your UUIDs, they could publish it to the server before you get a chance to, thereby preventing you from publishing your own item!
  • With c18n we could provide users with a way to replicate their collections among their own multiple clients, keeping "read/unread" in sync, etc. By publishing a second copy of a collection to the hub, Chandler could include all the "private" attributes that you wouldn't want to share with others, but which you do want to share with yourself across multiple Chandlers.
  • Without c18n we moved away from deterministically generating an item's UUID from its icalUID, because when multiple users import a public .ics file from somewhere and then publish the calendar to the Hub we want the items to be distinct. I believe this is leading to having multiple UUIDs with the same icalUID as Jared is seeing on the Hub. With c18n, we can go back to generating UUIDs based on icalUID, solving this problem, while still allowing people to publish the same .ics-imported public calendar to the Hub.

-- RandyLetness - 06 Dec 2007

Edit | WYSIWYG | Attach | Printable | Raw View | Backlinks: Web, All Webs | History: r17 < r16 < r15 < r14 < r13 | More topic actions
Open Source Applications Foundation
Except where otherwise noted, this site and its content are licensed by OSAF under an Creative Commons License, Attribution Only 3.0.
See list of page contributors for attributions.