use of won.auth.WonAclEvaluator in project webofneeds by researchstudio-sat.
the class AclChecker method process.
@Override
public void process(Exchange exchange) throws Exception {
URI recipientAtomUri = WonCamelHelper.getRecipientAtomURIRequired(exchange);
WonMessage message = WonCamelHelper.getMessageRequired(exchange);
if (message.getMessageType().isCreateAtom()) {
// no checks required for a create message
return;
}
if (message.getMessageType().isHintMessage()) {
// no checks required for a hint message
return;
}
URI signer = message.getSignerURIRequired();
URI sender = message.getSenderAtomURIRequired();
URI senderNode = message.getSenderNodeURIRequired();
WonMessageDirection direction = WonCamelHelper.getDirectionRequired(exchange);
if (direction.isFromExternal() || direction.isFromSystem()) {
if (signer.equals(senderNode)) {
// nodes are allowed to messages on behalf of an atom (for now)
return;
}
}
Atom atom = atomService.getAtomForMessageRequired(message, direction);
Optional<Graph> aclGraph = atom.getAclGraph();
if (aclGraph.isEmpty()) {
// no checks if no acl present
if (!sender.equals(signer)) {
throw new IllegalMessageSignerException(String.format("%s must not be signer of %s message %s", signer, message.getMessageTypeRequired(), message.getMessageURIRequired()));
}
return;
}
boolean isMessageOnBehalf = false;
URI requestor = sender;
if (direction.isFromOwner()) {
if (signer.equals(sender)) {
// no checks if the owner is the signer
return;
} else {
isMessageOnBehalf = true;
requestor = signer;
}
}
OperationRequest operationRequest = OperationRequest.builder().setReqAtom(atom.getAtomURI()).setReqAtomState(AuthUtils.toAuthAtomState(atom.getState())).setRequestor(requestor).build();
if (message.getMessageType().isConnectionSpecificMessage()) {
if (direction.isFromOwner() || direction.isFromSystem()) {
Optional<Socket> s = socketService.getSocket(message.getSenderSocketURIRequired());
operationRequest.setReqSocketType(s.get().getTypeURI());
operationRequest.setReqSocket(s.get().getSocketURI());
} else if (direction.isFromExternal()) {
Optional<Socket> s = socketService.getSocket(message.getRecipientSocketURIRequired());
operationRequest.setReqSocketType(s.get().getTypeURI());
operationRequest.setReqSocket(s.get().getSocketURI());
}
} else {
operationRequest.setReqPosition(POSITION_ROOT);
}
Optional<Connection> con = WonCamelHelper.getConnection(exchange, connectionService);
if (con.isPresent()) {
operationRequest.setReqPosition(POSITION_CONNECTION);
Connection c = con.get();
operationRequest.setReqConnection(c.getConnectionURI());
operationRequest.setReqConnectionTargetAtom(c.getTargetAtomURI());
operationRequest.setReqConnectionState(AuthUtils.toAuthConnectionState(c.getState()));
// we already set these values, but now that we know we have a connection, make
// sure these values match the connection's
operationRequest.setReqSocketType(c.getTypeURI());
operationRequest.setReqSocket(c.getSocketURI());
} else {
operationRequest.setReqPosition(POSITION_SOCKET);
}
if (isMessageOnBehalf) {
operationRequest.setOperationMessageOperationExpression(MessageOperationExpression.builder().addMessageOnBehalfsMessageType(AuthUtils.toAuthMessageType(message.getMessageType())).build());
} else {
operationRequest.setOperationMessageOperationExpression(MessageOperationExpression.builder().addMessageTosMessageType(AuthUtils.toAuthMessageType(message.getMessageType())).build());
}
WonAclEvaluator evaluator = wonAclEvaluatorFactory.create(aclGraph.get());
if (message.getMessageType().isReplace()) {
// decision for replace messages is deferred to where replacement actually
// happens
} else {
AclEvalResult result = evaluator.decide(operationRequest);
if (DecisionValue.ACCESS_DENIED.equals(result.getDecision())) {
throw new ForbiddenMessageException(String.format("Message not allowed"));
}
}
WonCamelHelper.putWonAclEvaluator(exchange, evaluator);
WonCamelHelper.putWonAclOperationRequest(exchange, operationRequest);
}
use of won.auth.WonAclEvaluator in project webofneeds by researchstudio-sat.
the class WonAclAccessDecisionVoter method voteForNonMessageRequest.
public int voteForNonMessageRequest(String webId, AuthToken authToken, URI resourceUri, FilterInvocation filterInvocation, Supplier<Integer> legacyImpl) {
URI atomUri = uriService.getAtomURIofSubURI(resourceUri);
if (atomUri == null) {
logger.debug("Cannot process ACL for resource {}", resourceUri);
return ACCESS_DENIED;
}
if (!uriService.isAtomURI(atomUri)) {
logger.debug("Not an atom URI: {}", atomUri);
return ACCESS_DENIED;
}
Optional<Atom> atom = atomService.getAtom(atomUri);
if (!atom.isPresent()) {
return ACCESS_DENIED;
}
Optional<Graph> aclGraph = atom.get().getAclGraph();
if (aclGraph.isEmpty()) {
// fall back to legacy implementation
WonAclRequestHelper.setWonAclEvaluationContext(filterInvocation.getRequest(), WonAclEvalContext.allowAll());
return legacyImpl.get();
}
WonAclEvaluator wonAclEvaluator = wonAclEvaluatorFactory.create(aclGraph.get());
// set up request object
OperationRequest request = new OperationRequest();
request.setReqAtom(atomUri);
if (authToken != null) {
request.addBearsToken(authToken);
}
request.setReqAtomState(toAuthAtomState(atom.get().getState()));
if (webId != null) {
request.setRequestor(URI.create(webId));
}
request.setOperationSimpleOperationExpression(OP_READ);
if (uriService.isAtomURI(resourceUri)) {
request.setReqPosition(POSITION_ROOT);
// we are going to need the acl evaluator to choose the graphs we can show
// this can only be done by the logic that assembles the response dataset
// approach: allow the request for now, then check acl for each subgraph
WonAclRequestHelper.setWonAclEvaluationContext(filterInvocation.getRequest(), WonAclEvalContext.contentFilter(request, wonAclEvaluator));
return ACCESS_GRANTED;
} else if (uriService.isAtomMessagesURI(resourceUri)) {
request.setReqPosition(POSITION_ATOM_MESSAGES);
} else if (uriService.isConnectionMessagesURI(resourceUri)) {
request.setReqPosition(POSITION_CONNECTION_MESSAGES);
Optional<Connection> con = connectionRepository.findOneByConnectionURI(uriService.getConnectionURIofConnectionMessagesURI(resourceUri));
if (!con.isPresent()) {
return ACCESS_DENIED;
}
request.setReqSocketType(con.get().getTypeURI());
request.setReqSocket(con.get().getSocketURI());
request.setReqConnection(con.get().getConnectionURI());
request.setReqConnectionState(toAuthConnectionState(con.get().getState()));
request.setReqConnectionTargetAtom(con.get().getTargetAtomURI());
} else if (uriService.isConnectionURI(resourceUri)) {
request.setReqPosition(POSITION_CONNECTION);
Optional<Connection> con = connectionRepository.findOneByConnectionURI(uriService.getConnectionURIofConnectionMessagesURI(resourceUri));
if (!con.isPresent()) {
if (logger.isDebugEnabled()) {
logger.debug("request to inexistent connection denied: {}", resourceUri);
}
return ACCESS_DENIED;
}
request.setReqSocketType(con.get().getTypeURI());
request.setReqSocket(con.get().getSocketURI());
request.setReqConnection(con.get().getConnectionURI());
request.setReqConnectionState(toAuthConnectionState(con.get().getState()));
request.setReqConnectionTargetAtom(con.get().getTargetAtomURI());
} else if (uriService.isConnectionContainerURI(resourceUri)) {
// We want to enable requesting connections per socket but haven't got
// the LD service implementation for that, yet. Moreover, a lot of code relies
// on the legacy implementation. So, we'll process requests
// to the atom's connection container as a special case: prepare the
// operationRequest now but evaluate it only when we are processing the
// results. Then, we have to group the connections by socket/socket type,
// generate the corresponding operationRequests, evaluate them and
// remove all connections the requestor is not allowed to read.
request.setReqPosition(POSITION_CONNECTIONS);
// consequence: allow now, check later
WonAclRequestHelper.setWonAclEvaluationContext(filterInvocation.getRequest(), WonAclEvalContext.contentFilter(request, wonAclEvaluator));
return ACCESS_GRANTED;
} else if (uriService.isTokenEndpointURI(resourceUri)) {
// token request
request.setReqPosition(POSITION_ROOT);
String scopeParam = WonAclRequestHelper.getRequestParamScope(filterInvocation.getRequest());
Set<OperationRequest> opReqs = new HashSet<>();
if (scopeParam == null || scopeParam.trim().length() == 0) {
TokenSpecification tokenSpec = new TokenSpecification();
TokenOperationExpression opex = new TokenOperationExpression();
opex.setRequestToken(tokenSpec);
request.setOperationSimpleOperationExpression(null);
request.setOperationTokenOperationExpression(opex);
opReqs.add(request);
} else {
String[] scopes = scopeParam.split("\\s+");
for (int i = 0; i < scopes.length; i++) {
TokenSpecification tokenSpec = new TokenSpecification();
URI tokenScopeUri = null;
try {
tokenScopeUri = new URI(scopes[i]);
} catch (URISyntaxException e) {
}
if (tokenScopeUri != null && tokenScopeUri.getScheme() != null) {
tokenSpec.setTokenScopeURI(tokenScopeUri);
} else {
tokenSpec.setTokenScopeString(scopes[i]);
}
TokenOperationExpression opex = new TokenOperationExpression();
opex.setRequestToken(tokenSpec);
OperationRequest clonedRequest = cloneShallow(request);
clonedRequest.setOperationTokenOperationExpression(opex);
clonedRequest.setOperationSimpleOperationExpression(null);
opReqs.add(clonedRequest);
}
Set<AclEvalResult> evalResults = new HashSet<>();
for (OperationRequest req : opReqs) {
AclEvalResult result = wonAclEvaluator.decide(req);
evalResults.add(result);
}
AclEvalResult finalResult = evalResults.stream().reduce(WonAclEvaluator::mergeAclEvalResults).get();
if (DecisionValue.ACCESS_GRANTED.equals(finalResult.getDecision())) {
Set<String> tokens = finalResult.getIssueTokens().stream().map(token -> AuthUtils.toJWT(token, cryptographyService.getDefaultPrivateKey(), cryptographyService.getDefaultPrivateKeyAlias())).collect(Collectors.toSet());
WonAclRequestHelper.setGrantedTokens(filterInvocation.getRequest(), tokens);
}
setAuthInfoIfDenied(filterInvocation, finalResult);
return toAccessDecisionVote(finalResult);
}
} else if (uriService.isGrantsEndpointURI(resourceUri)) {
// the LinkedDataWebController will return the grants
WonAclRequestHelper.setWonAclEvaluationContext(filterInvocation.getRequest(), WonAclEvalContext.contentFilter(request, wonAclEvaluator));
return ACCESS_GRANTED;
} else {
// default
request.setReqPosition(POSITION_ROOT);
}
AclEvalResult result = wonAclEvaluator.decide(request);
setAuthInfoIfDenied(filterInvocation, result);
return toAccessDecisionVote(result);
}
use of won.auth.WonAclEvaluator in project webofneeds by researchstudio-sat.
the class WonAclAccessDecisionVoter method voteForMessageRequest.
public int voteForMessageRequest(String webId, AuthToken authToken, URI resourceUri, FilterInvocation filterInvocation, Supplier<Integer> legacyImpl) {
// if we're requesting a message, we have to check access for each message
// container
// that it is in
Map<URI, Set<OperationRequest>> opReqs = new HashMap<>();
Map<URI, Graph> aclGraphs = new HashMap<>();
Map<URI, Integer> legacyResults = new HashMap<>();
URI messageUri = WonMessageUriHelper.toGenericMessageURI(resourceUri, uriService.getMessageResourceURIPrefix());
List<MessageEvent> msgs = messageEventRepository.findByMessageURI(messageUri);
for (MessageEvent msg : msgs) {
URI parent = msg.getParentURI();
URI atomUri = uriService.getAtomURIofSubURI(parent);
Optional<Atom> atom = atomService.getAtom(atomUri);
if (!atom.isPresent()) {
return ACCESS_DENIED;
}
if (!aclGraphs.containsKey(atomUri)) {
Optional<Graph> aclGraph = atom.get().getAclGraph();
if (aclGraph.isEmpty()) {
legacyResults.put(atomUri, legacyImpl.get());
continue;
}
aclGraphs.put(atomUri, aclGraph.get());
}
if (!atom.isPresent()) {
continue;
}
OperationRequest operationRequest = new OperationRequest();
if (authToken != null) {
operationRequest.addBearsToken(authToken);
}
operationRequest.setRequestor(URI.create(webId));
operationRequest.setReqAtomState(toAuthAtomState(atom.get().getState()));
operationRequest.setReqAtom(atomUri);
operationRequest.setOperationSimpleOperationExpression(OP_READ);
if (uriService.isConnectionURI(parent)) {
Optional<Connection> con = connectionRepository.findOneByConnectionURI(parent);
if (con == null) {
continue;
}
operationRequest.setReqPosition(POSITION_CONNECTION_MESSAGE);
operationRequest.setReqConnectionMessage(msg.getMessageURI());
operationRequest.setReqConnection(con.get().getConnectionURI());
operationRequest.setReqSocket(con.get().getSocketURI());
operationRequest.setReqSocketType(con.get().getTypeURI());
operationRequest.setReqConnectionState(toAuthConnectionState(con.get().getState()));
operationRequest.setReqConnectionTargetAtom(con.get().getTargetAtomURI());
} else if (uriService.isAtomURI(parent)) {
operationRequest.setReqPosition(POSITION_ATOM_MESSAGE);
} else {
legacyResults.put(atomUri, legacyImpl.get());
continue;
}
if (!opReqs.containsKey(atomUri)) {
Set<OperationRequest> ors = new HashSet<>();
ors.add(operationRequest);
opReqs.put(atomUri, ors);
} else {
opReqs.get(atomUri).add(operationRequest);
}
}
Set<AclEvalResult> aclEvalResults = new HashSet<>();
for (URI atomUri : aclGraphs.keySet()) {
Graph aclGraph = aclGraphs.get(atomUri);
for (OperationRequest opReq : opReqs.get(atomUri)) {
aclEvalResults.add(wonAclEvaluatorFactory.create(aclGraph).decide(opReq));
}
}
Optional<AclEvalResult> aclEvalResult = aclEvalResults.stream().reduce(WonAclEvaluator::mergeAclEvalResults);
Integer legacyResult = legacyResults.values().stream().reduce((left, right) -> {
if (left.equals(right)) {
return left;
}
if (left.equals(ACCESS_GRANTED) || right.equals(ACCESS_GRANTED)) {
return ACCESS_GRANTED;
} else if (left.equals(ACCESS_ABSTAIN) || right.equals(ACCESS_ABSTAIN)) {
return ACCESS_ABSTAIN;
}
return ACCESS_DENIED;
}).orElse(ACCESS_ABSTAIN);
if (legacyResult.equals(ACCESS_GRANTED) || (aclEvalResult.isPresent() && aclEvalResult.get().getDecision().equals(DecisionValue.ACCESS_GRANTED))) {
return ACCESS_GRANTED;
} else {
if (aclEvalResult.isPresent()) {
setAuthInfoIfDenied(filterInvocation, aclEvalResult.get());
}
return ACCESS_DENIED;
}
}
Aggregations