Skip to content

Commit 2a4782a

Browse files
committed
docs: Explain asset collection implementation
1 parent cd4a56f commit 2a4782a

File tree

2 files changed

+189
-0
lines changed

2 files changed

+189
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ You can then execute the following flows:
2929
- `yarn script:uma-ucp`: `PUT` some text to the private `/alice/other/resource.txt`, protected by a UCP enforcer checking WebIDs according to policies in `packages/uma/config/rules/policy/`.
3030
- `yarn script:collection`: `POST`, `GET` and `DELETE` some text to/from `/alice/public/resource.txt` to test the correct creation and deletion of resource registrations on the UMA server.
3131
An AssetCollection policy is used to create `/alice/public/`.
32+
More information on the collection implementation can be found in [documentation/collections.md](documentation/collections.md).
3233

3334
`yarn script:flow` runs all flows in sequence.
3435

documentation/collections.md

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
# ODRL policies targeting collections
2+
3+
This document describes how this UMA server supports ODRL collections.
4+
The implementation is based on the [A4DS specification](https://spec.knows.idlab.ugent.be/A4DS/L1/latest/).
5+
Much of the information in this document can also be found there.
6+
7+
## WAC / ACP
8+
9+
The initial idea for implementing collections is that we want to be able
10+
to create policies that target the contents of a container,
11+
similar to how WAC and ACP do this.
12+
We do not want the UMA server to be tied to the LDP interface though,
13+
so the goal is to have a generic solution that can handle any kind of relationship between resources.
14+
15+
## New resource description fields
16+
17+
To support collections, the RS now includes two additional fields when registering a resource,
18+
in addition to those defined in the UMA specification.
19+
20+
* `resource_defaults`: A key/value map describing the scopes of collections having the registered resource as a source.
21+
The keys are the relations where the resource is the subject,
22+
and the values are the scopes that the Authorization Server should support for the corresponding collections.
23+
* `resource_relations`: A key/value map linking this resource to others through relations.
24+
The keys are the relations and the values are the UMA IDs of the relation targets.
25+
The resource itself is the object of the relations,
26+
and the values in the arrays are the subject.
27+
Note that this is the reverse of the `resource_defaults` fields.
28+
29+
For both of the above, one of the keys can be `@reverse`,
30+
which takes as value a similar key/value object,
31+
but reverses how the relations should be interpreted.
32+
E.g., in the case of `resource_defaults`,
33+
the resource would be the object instead of the subject of those relations.
34+
35+
An example of such an extended resource description:
36+
```json
37+
{
38+
"resource_scopes": [ "read", "write" ],
39+
"resource_defaults": {
40+
"http://www.w3.org/ns/ldp#contains": [ "read" ]
41+
},
42+
"resource_relations": {
43+
"http://www.w3.org/ns/ldp#contains": [ "assets:1234" ],
44+
"@reverse": { "my:other:relation": [ "assets:5678" ] }
45+
}
46+
}
47+
```
48+
49+
The above example tells the UMA server that the available scopes for this new resource are `read` and `write`,
50+
as defined in the UMA specification.
51+
The new field `resource_defaults` tells the server that all containers for
52+
the `http://www.w3.org/ns/ldp#contains` relation
53+
that have this resource as the source,
54+
have `read` as an available scope.
55+
The `resource_relations` field indicates that this resource
56+
has the `http://www.w3.org/ns/ldp#contains` relation with as target `assets:5678`,
57+
while the other entry indicates it is the target of the `my:other:relation` with `assets:5678` as subject.
58+
59+
## Generating collection triples
60+
61+
When registering a resource,
62+
the UMA server immediately generates all necessary triples to keep track of all collections a resource is part of.
63+
First it generates the necessary asset collections based on the `resource_defaults` field,
64+
and then generate the relation triples based on the `resource_relations` field.
65+
With the example above, the following triples would be generated:
66+
67+
```ttl
68+
@prefix odrl: <http://www.w3.org/ns/odrl/2/>.
69+
@prefix odrl_p: <https://w3id.org/force/odrl3proposal#>.
70+
71+
<urn:1:2:3> a odrl:AssetCollection ;
72+
odrl:source <my:new:resource> ;
73+
odrl_p:relation <http://www.w3.org/ns/ldp#contains> .
74+
75+
<my:new:resource> odrl:partOf <collection:12345> ;
76+
odrl:partOf <collection:5678:reverse> .
77+
```
78+
This assumes that the collection IDs used above, `collection:12345` and `collection:5678:reverse`, already exist.
79+
If these collections were not yet generated,
80+
the registration request would fail with an error.
81+
All these triples then get passed to the ODRL evaluator when policies need to be processed.
82+
Any policy that targets a collection ID will apply to all resources that are part of that collection.
83+
If the relation was reversed, the relation object would be `[ owl:inverseOf <http://www.w3.org/ns/ldp#contains> ]`.
84+
85+
## Updating collection triples
86+
87+
Every time a resource is updated, the corresponding collection triples are updated accordingly.
88+
If an update removes some of the `resource_relations` entries,
89+
the relevant `odrl:partOf` triples will be removed.
90+
If entries are removed from `resource_defaults`,
91+
the triples that define the corresponding asset collection are removed.
92+
The latter can only happen if the asset collection is empty.
93+
In case there are still `odrl:partOf` triples linking to it,
94+
the update will fail with an error.
95+
96+
It is possible to generate the same relation in two different ways:
97+
in the description of the source, and in the description of the target.
98+
Since updates to one resource can remove relations,
99+
this can potentially cause some confusion and/or inconsistencies.
100+
E.g., if resource A is registered with relation L to resource B,
101+
and B is registered with the reverse of L to resource A.
102+
Both these statements apply to the same relation.
103+
If resource A is then updated without that relation,
104+
it would be removed while the description of B still contains it.
105+
For this reason it is advised to always describe relations in only one of the two resources.
106+
107+
## Known issues/workarounds
108+
109+
Below are some of the issues encountered while implementing this,
110+
that might need more robust solutions.
111+
112+
### UMA identifiers
113+
114+
The UMA server is only aware of the UMA identifiers;
115+
it does not know the resource identifiers.
116+
Those are also the identifiers that need to be used when writing policies.
117+
Eventually, there should be an API an interface so users know which identifiers they need to use.
118+
To make things easier until that is resolved,
119+
the servers are configured so the generated UMA identifiers correspond to the actual resource identifiers.
120+
The Resource Server informs the UMA server of the identifiers by using the `name` field when registering a resource.
121+
122+
### Asset Collection identifiers
123+
124+
For asset collections, there is a similar problem where the user doesn't know which identifiers to use.
125+
To work around this,
126+
users can create their own asset collections and add them to policies.
127+
Take the following policy for example:
128+
129+
```ttl
130+
@prefix ex: <http://example.org/> .
131+
@prefix ldp: <http://www.w3.org/ns/ldp#>.
132+
@prefix odrl: <http://www.w3.org/ns/odrl/2/>.
133+
@prefix odrl_p: <https://w3id.org/force/odrl3proposal#>.
134+
135+
<urn:uuid:e30bcd34-0d5c-43d1-b229-bf68afcae5ae> a odrl:Set ;
136+
odrl:uid <urn:uuid:e30bcd34-0d5c-43d1-b229-bf68afcae5ae> ;
137+
odrl:permission <urn:uuid:f4cb5007-e834-4a9c-a62a-091891350c04> .
138+
139+
<urn:uuid:f4cb5007-e834-4a9c-a62a-091891350c04> a odrl:Permission ;
140+
odrl:assignee ex:alice ;
141+
odrl:action odrl:read ;
142+
odrl:target ex:assetCollection .
143+
144+
ex:assetCollection a odrl:AssetCollection ;
145+
odrl:source <http://localhost:3000/container/> ;
146+
odrl_p:relation ldp:contains .
147+
```
148+
149+
The above policy gives Alice read permission on all resources in `http://localhost:3000/container/`.
150+
Here the user chose the identifier `ex:assetCollection` for the collection with the given parameters.
151+
When new resources are registered,
152+
the UMA server will detect that this collection already exists,
153+
and use that identifier for the new metadata triples.
154+
It is important that this definition already exists in the policies before any resources get registered to it,
155+
so this solution is better for static policy solutions,
156+
where all policies are already defined on server initialization.
157+
The server will error if there are multiple asset collections with the same parameters,
158+
so make sure to only define identifier per combination.
159+
160+
### Parent containers not yet registered
161+
162+
Resource registration happens asynchronously.
163+
As a consequence, it is possible when registering a resource,
164+
that the registration of its parent container was not yet completed.
165+
This is a problem since the UMA ID of this parent is necessary to link to the correct relation.
166+
To work around this, resources get updated when the relevant information becomes available.
167+
If the parent is not yet registered, a resource will be registered without the relevant relation fields.
168+
Then, when the parent is registered, an event will trigger a registration update for the child resource,
169+
where the registration is updated with the now available parent UMA ID.
170+
171+
### Accessing resources before they are registered
172+
173+
An additional consequence of asynchronous resource registration,
174+
is that a client might try to access a resource before its registration is finished.
175+
This would cause an error as the Resource Server needs the UMA ID to request a ticket,
176+
but doesn't know it yet.
177+
To prevent issues, the RS will wait until registration of the corresponding resource is finished,
178+
or even start registration should it not have happened yet for some reason.
179+
A timeout is added to prevent the connection from getting stuck should something go wrong.
180+
181+
### Policies for resources that do not yet exist
182+
183+
When creating a new resource on the RS, using PUT for example,
184+
it is necessary to know if that action is allowed.
185+
It is not possible to generate a ticket with this potentially new resource as a target though,
186+
as it does not have an UMA ID yet.
187+
The current implementation instead generates a ticket targeting the first existing (grand)parent container,
188+
and requests the `create` scope.

0 commit comments

Comments
 (0)