proposal: generalise acp:access
Opened this issue · 6 comments
Having determined that acp:access
is the inverse of wac:accessTo
in issue 129: acp/wac diff the ACR document, I end up with the mapping between wac and acp
wac:accessTo owl:inverseOf [
owl:propertyChainAxiom ( wac:accessControl :authorizes )
] .
being equivalent to
acp:access owl:propertyChainAxiom ( wac:accessControl :authorizes )
The idea was that we could infer the inverse of acp:accessTo
from following a wac:accessControl
Link
and an :authorizes
link. Looking at this from the point of view of acp:access
suggests that an ACR is its own ACR as the statement
<> acp:access <#p1> .
then would be equivalent to
<> wac:accessControl <> .
<> :authorizes <#p1> .
But we notice now that we can no longer distinguish Policies that apply to the ldp:Resource
linking to the ACR and those that apply to the ACR itself.
For, let us imagine that every ACR has a Link: rel="acp"
relation to itself (ie <> acp:accessControl <>
) Then the same acp:Policy
s would apply to the ACR as to the Resource that it is meant to protect.
So for example in this picture we have Tim Berners-Lee's foaf profile that links to the ACR. But now there would be no way - with only these tools - to make the ACR readable only to Tim, without also limiting access to his foaf profile... In this case it seems like it's ok, but there will be other use cases where it won't be quite what is needed.
So it seems that we actually can't get rid of the wac:accessTo
relation, and that furthermore ACP does not do it. It just replaces it with the inverse acp:access
.
But then we can now write out what should appear in Tim's profile using just acp:access
were he to want to be the only one to read it.
# this applies to the ACR itself as per current ACP doc dumps
<> acp:access <#TimsPolicy> .
<#TimsPolicy> a acp:Policy;
acp:allow acp:Read, acp:Write;
acp:anyOf <#TimRules> .
# This applies to TimBL's profile
<card> acp:access [ a acp:Policy;
acp:allow acp:Read;
acp:anyOf foaf:Agent ];
acp:access <#TimsPolicy> .
<#TimBLRules> acp:agent </People/Berners-Lee/card#i> .
So why not define acp:access
to just relate a Resource to the Policy that applies to it?
Like this:
acp:access a rdf:Property ;
rdfs:label "access"@en ;
rdfs:comment "The access property identifies the access policies that apply to a resource."@en ;
rdfs:range acp:Policy ;
rdfs:domain gen:InformationResource;
rdfs:isDefinedBy acp: .
Ie we could then have an ACR that looks like this:
In the above it looks like essentially I bypass the need for the acp:AccessControl class, defined as:
acp:AccessControl a rdfs:Class ;
rdfs:comment "Access Control statements associate an AccessControlResource with specific Policy definitions."@en .
The only relations that have acp:AccessControl
as (co)domain are all the acp:apply*
relations which I found to be confusing. This I think explains the confusion: it seems that there is no serious distinction between an acp:AccessControl
and a acp:Policy
.
Looking at the Access Enforcement doc I found the following pseudo-code that gives a hint as to why the distinction is there. Essentially the pseudo code looks for all the acp:AccessControl
statements in the ACR and uses those to evaluate access.
export function isAccessAllowed(agent: Agent, resource: Resource, method: HTTPMethod): boolean {
const acr: ACR = resource.getAccessControlResource();
const accessModes: AccessModes = new AccessModes();
acr.getAccessControls().forEach((ac: AccessControl) => {
accessModes.add(evaluatePolicies(ac.apply, agent, resource));
accessModes.add(evaluatePolicies(ac.applyProtected, agent, resource));
accessModes.add(evaluatePolicies(ac.applyLocked, agent, resource));
});
const requiredMode: string = HTTPMethodToAccessMode.get(method);
if (accessModes.contains(requiredMode)) return true;
return false;
}
So the type AccessControl
is really used to locate the relevant Policies.
The advantages over searching for the resource name as in my proposal above are:
- there may be many content-negotiated resources with different extensions
.ttl
,.rdf
,.jsld
, etc that have anaccessControl
Link relation, and that would require the ACR to keep track of different resources. Eg. a server uprade could suddenly add all kinds of mime types to a server for videos. - It removes a brittleness on the client and server since both just need to start from the
AccessControl
node type in that document for their search.
The disadvantage is in making this distinction between AccessControl
type and Policy
type, where the AccessControl
really just forwards to the Policy
. And also the distinction between Policies about the ACR and Policies that apply to another Resource.
Instead of introducing a new type one could also introduce a new relation that would start off from the document, which should be given, as the client or server need to know in which document these relations appear.
<> acp:access <personal#TimsPolicy> .
<> acp:authorizes </const#PublicRead> .
So here we would say that, as above, acp:access
only applies the policy to the subject,
whereas acp:authorizes applies the policy to linked-to resources (which do not self-link I guess).
It could be that we get rid of one unnecessary class here, and an apply relation. So this would give us the following:
Lots of comments there to reply to :-)
Perhaps I'll start with a couple of high level statements and then I'll try to go through the content in detail and respond to each.
acp:access is used specifically to control access to the ACR whereas acp:apply is used to control access to the resource associated with the ACR. Both refer to policies. Both could refer to the same policies if that was intended. It's more likely that in a lot of cases the restrictions around access to the ACR would be tighter than those around access to the associated resource.
acp:AccessControl simply groups the policies that control access to the resource. In an earlier version of the documentation, individual acp:AccessControl could be protected separately by policies. We removed this is an unnecessary level of complexity. However we left the acp:AccessControl as a way for applications to manage their own access controls. This allows them to set the minimum access required for particular use cases without having to examine other existing access controls .
Looking at this from the point of view of acp:access suggests that an ACR is its own ACR
Well except an ACR doesn't have an ACR. There is a 1-1 relationship between a normal resource and an ACR. But an ACR is not a normal resource in that its lifecycle is managed by the server. Only some of the statements in an ACR can apply to the ACR itself. Both an ACR and a normal resource are protected by policies.
But we notice now that we can no longer distinguish Policies that apply to the ldp:Resource linking to the ACR and those that apply to the ACR itself.
This depends where we start from. If we start from the ACR then we can distinguish between them based on the predicate used i.e.g acp:accessXXX or acp:applyXXX.
If we start from the policy then this is correct. Policies are reusable so a given policy could be used to protect any number of resources and/or ACRs.
So for example in this picture we have Tim Berners-Lee's foaf profile that links to the ACR. But now there would be no way - with only these tools - to make the ACR readable only to Tim, without also limiting access to his foaf profile... In this case it seems like it's ok, but there will be other use cases where it won't be quite what is needed.
Not sure I understand this.
The profile would be protected by the policies specified using acp:applyXXX while the ACR for the profile would be protected by the policies specified using acp:accessXXX . So different policies can be used to protect the resource and the ACR for the resource. But perhaps I'm misunderstanding the point?
Thanks for the feedback @emmettownsend.
I'll move aside the question about whether ACRs should have ACRs to issue 151 as that is a topic by itself, and is confusing things here. As a result the title of this issue is also no longer correct. The question is really now of defining acp:access
a bit more precisely and noticing its relation to acl:accessTo
.
(I should perhaps open a new issue and close this one)
What we notice is that we have two ways of tying a resource to a policy.
- via the
Link: ... rel="acp"...
relation and then finding all the "AccessControl" statements in the document. - via the
acp:access
relation, but only when it applies to the ACR itself
In 2. the acp:access
plays very much the same role as acl:accessTo
. It tells us to which resource the Policy applies to, but restricted to ACRs. So we have precisely (I think).
acp:access rdfs:subPropertyOf [ owl:inverseOf acl:accessTo ] .
acp:access rdfs:domain acp:AccessControlResource .
The acp:AccessControl
type is there to allow one to know which statements apply to a resource followed by an acp:accessControl
relation. Thinking in terms of linked data this led me to propose theacp:authorizes
relation from the ACR to the Policy (as shown in the pictures). Then one can follow the link header, arrive on the graph with a pointer on the node identifying the ACR itself, and continue by following the acp:authorizes
relation to arrive at the Policy.
That allows us to relate ACL and ACP like this I think:
[ owl:propertyChainAxiom ( acp:accessControl acp:authorizes ) ] rdfs:subPropertyOf acl:accessTo .
The subPropertyOf
in both examples means the inference only goes from left to right (avoiding the issue of ACRs of ACRs).