Search in sources :

Example 1 with WonAclEvaluator

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);
}
Also used : Optional(java.util.Optional) OperationRequest(won.auth.model.OperationRequest) Connection(won.protocol.model.Connection) WonAclEvaluator(won.auth.WonAclEvaluator) AclEvalResult(won.auth.model.AclEvalResult) URI(java.net.URI) Atom(won.protocol.model.Atom) Graph(org.apache.jena.graph.Graph) ForbiddenMessageException(won.protocol.exception.ForbiddenMessageException) WonMessage(won.protocol.message.WonMessage) IllegalMessageSignerException(won.protocol.exception.IllegalMessageSignerException) WonMessageDirection(won.protocol.message.WonMessageDirection) Socket(won.protocol.model.Socket)

Example 2 with WonAclEvaluator

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);
}
Also used : WonAclEvaluator(won.auth.WonAclEvaluator) Connection(won.protocol.model.Connection) URISyntaxException(java.net.URISyntaxException) URI(java.net.URI) Atom(won.protocol.model.Atom) Graph(org.apache.jena.graph.Graph)

Example 3 with WonAclEvaluator

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;
    }
}
Also used : AtomNodeChecker(won.auth.check.AtomNodeChecker) java.util(java.util) Connection(won.protocol.model.Connection) WonMessageUriHelper(won.protocol.util.WonMessageUriHelper) URISyntaxException(java.net.URISyntaxException) LoggerFactory(org.slf4j.LoggerFactory) won.auth.model(won.auth.model) Autowired(org.springframework.beans.factory.annotation.Autowired) Supplier(java.util.function.Supplier) Graph(org.apache.jena.graph.Graph) WonAclEvaluator(won.auth.WonAclEvaluator) WonAclEvaluatorFactory(won.auth.WonAclEvaluatorFactory) AuthUtils(won.auth.AuthUtils) AccessDecisionVoter(org.springframework.security.access.AccessDecisionVoter) MessageEventRepository(won.protocol.repository.MessageEventRepository) WebIdUserDetails(won.node.springsecurity.userdetails.WebIdUserDetails) Individuals(won.auth.model.Individuals) WonDefaultAccessControlRules(won.node.springsecurity.WonDefaultAccessControlRules) WebIdKeyLoader(won.cryptography.rdfsign.WebIdKeyLoader) URI(java.net.URI) ConnectionRepository(won.protocol.repository.ConnectionRepository) URIService(won.node.service.nodeconfig.URIService) ConfigAttribute(org.springframework.security.access.ConfigAttribute) Atom(won.protocol.model.Atom) Logger(org.slf4j.Logger) Transactional(javax.transaction.Transactional) MethodHandles(java.lang.invoke.MethodHandles) ConnectionTargetCheckEvaluator(won.auth.check.ConnectionTargetCheckEvaluator) DatasetHolderRepository(won.protocol.repository.DatasetHolderRepository) StopWatch(org.springframework.util.StopWatch) Collectors(java.util.stream.Collectors) CryptographyService(won.cryptography.service.CryptographyService) GrantedAuthority(org.springframework.security.core.GrantedAuthority) PreAuthenticatedAuthenticationToken(org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken) FilterInvocation(org.springframework.security.web.FilterInvocation) MessageEvent(won.protocol.model.MessageEvent) Authentication(org.springframework.security.core.Authentication) AtomService(won.node.service.persistence.AtomService) MessageEvent(won.protocol.model.MessageEvent) Connection(won.protocol.model.Connection) WonAclEvaluator(won.auth.WonAclEvaluator) URI(java.net.URI) Atom(won.protocol.model.Atom) Graph(org.apache.jena.graph.Graph)

Aggregations

URI (java.net.URI)3 Graph (org.apache.jena.graph.Graph)3 WonAclEvaluator (won.auth.WonAclEvaluator)3 Atom (won.protocol.model.Atom)3 Connection (won.protocol.model.Connection)3 URISyntaxException (java.net.URISyntaxException)2 MethodHandles (java.lang.invoke.MethodHandles)1 java.util (java.util)1 Optional (java.util.Optional)1 Supplier (java.util.function.Supplier)1 Collectors (java.util.stream.Collectors)1 Transactional (javax.transaction.Transactional)1 Logger (org.slf4j.Logger)1 LoggerFactory (org.slf4j.LoggerFactory)1 Autowired (org.springframework.beans.factory.annotation.Autowired)1 AccessDecisionVoter (org.springframework.security.access.AccessDecisionVoter)1 ConfigAttribute (org.springframework.security.access.ConfigAttribute)1 Authentication (org.springframework.security.core.Authentication)1 GrantedAuthority (org.springframework.security.core.GrantedAuthority)1 FilterInvocation (org.springframework.security.web.FilterInvocation)1