/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.jena.permissions; import java.util.Arrays; import java.util.Collection; import java.util.LinkedHashSet; import java.util.Set; import org.apache.jena.graph.Node; import org.apache.jena.graph.Triple; import org.apache.jena.graph.NodeFactory; import org.apache.jena.shared.AuthenticationRequiredException; /** * SecurityEvaluator. * <p> * The security evaluator is the link between the graph security system and an * external security system. This interface specifies the methods that are * required by the graph security system. It is assumed that the implementation * will handle tracking the current user and will query some underlying data * source to determine what actions the user can and can not take. * </p> * <p> * All questions of white listing or black listing will be handled in the * concrete implementation. * </p> * <p> * Implementations of this class should probably cache any evaluate calculations * as the evaluate methods are called frequently. However, the underlying * classes do cache results within a single method check. * </p> * <p> * <dl> * <dt>Secured operations</dt> * <dd>The security system recognizes and secures each of the CRUD (Create, * Read, Update and Delete) operations as represented by the Action enumeration. * </dd> * </dl> * <dl> * <dt>Levels of security</dt> * <dd>The security interfaces operates at two (2) levels: graph (or Model) and * triple. * <p> * At the the graph level the security evaluator may restrict CRUD access to the * graph or model as a whole. When evaluating the restriction, if the user it * not permitted to perform the operation on the graph or model access is * denied. If the user is permitted any triple restrictions are evaluated. * </p> * <p> * At the triple level the security evaluator may restrict CRUD access to * specific triples. In order to skip potentially expensive triple security * checks the system will generally ask if the user is permitted the CRUD action * on any triple. This is represented by the SecTriple * <code>(ANY, ANY, ANY)</code>. * <ul> * <li> * If the system does not support triple level security the system should always * return <code>true</code>.</li> * If the system does support triple level security and is unable to verify that * the user can execute the CRUD action against any arbitrary triple the system * should return <code>false</code>. </li> * <li>See <code>Node.ANY</code>, <code>SecurityEvaluator.FUTURE</code>, and * <code>SecurityEvaluator.VARIABLE</code> for discussion of specifics of their * respective usages.</li> * </ul> * </p> * </dd> * </dl> * <dl> * <dt> * * </p> */ public interface SecurityEvaluator { /** * Identifies a sepcific CRUD actions. */ static enum Action { /** * Allow creation of the object in question. */ Create, /** * Allow the user to read the object in question. */ Read, /** * Allow the user to update the object in question */ Update, /** * Allow the user to delete the object in question. */ Delete } /** * A collection of utility functions for the SecurityEvaluator * implementations. */ public static class Util { /** * Return an array of actions as a set. * <p> * The order of the collection is preserved * </p> * * @param actions * The actions. * @return The set of actions. */ public static Set<Action> asSet(final Action[] actions) { return Util.asSet(Arrays.asList(actions)); } /** * Return a collection of actions as a set. * <p> * The order of the collection is preserved * </p> * * @param actions * The collection of actions. * @return The set of actions. */ public static Set<Action> asSet(final Collection<Action> actions) { if (actions instanceof Set) { return (Set<Action>) actions; } else { return new LinkedHashSet<Action>(actions); } } } /** * Indicates a variable in the triple. * <p> * </p> * This differs from <code>ANY</code> in that the system is asking if there * are any prohibitions not if the user may perform. Thus queries with the * VARIABLE type node should return <code>true</code> where <code>ANY</code> * returns <code>false</code>. In general this type is used in the query to * determine if triple level filtering of results must be performed. * <p> * </p> * <p> * <dl> * <dt><code>(VARIABLE, X, Y )</code></dt> * <dd> * Asks if there are any prohibitions against the user seeing all subjects * that have property X and object Y.</dd> * <dt> * <code>(X, VARIABLE, Y )</code></dt> * <dd> * Asks if there are any prohibitions against the user seeing all predicates * that have subject X and object Y.</dd> * <dt> * <code>(X, Y, VARIABLE)</code></dt> * <dd> * Asks if there are any prohibitions against the user seeing all objects * that have subject X and predicate Y.</dd> * </dl> * The <code>VARIABLE</code> may occur multiple times and may occur with the * <code>ANY</code> node. * </p> * */ public static final Node VARIABLE = NodeFactory .createBlankNode("urn:jena-permissions:VARIABLE"); /** * This is a blank (anonymous) node that will be created in the future. * <p> * FUTURE is used to check that a blank node may be created in as specific * position in a triple. * </p> * <p> * <dl> * <dt><code>(FUTURE, X, Y )</code></dt> * <dd> * Asks if there the user may create a blank node that has property X and * object Y.</dd> * <dt> * <code>(X, Y, FUTURE)</code></dt> * <dd> * Asks if there the user may create a blank node that has subject X and * property Y.</dd> * </dl> * The <code>FUTURE</code> may occur multiple times and may occur with the * <code>ANY</code> node. * </p> */ public static final Node FUTURE = NodeFactory .createBlankNode("urn:jena-permissions:FUTURE"); /** * Determine if the action is allowed on the graph. * * @param principal * The principal that is attempting the action. * * @param action * The action to perform * @param graphIRI * The IRI of the graph to check * @return true if the action is allowed, false otherwise. * @throws AuthenticationRequiredException * if user is not authenticated and is required to be. */ public boolean evaluate(Object principal, Action action, Node graphIRI) throws AuthenticationRequiredException; /** * Determine if the action is allowed on the triple within the graph. * <p> * The evaluation should be performed in the following order: * <ol> * <li> * If the triple contains a <code>VARIABLE</code> then this method must * return <code>true</code> if there are any restrictions where the * remaining nodes are either constants or <code>ANY</code> nodes. This will * force the system to use subsequent checks to verify access by * substituting the value of the <code>VARIABLE</code>s. * <em>If the system can not quickly verify the solution * it is always acceptable to return <code>true</code>.</em> * <li> * Except as specified in the above check, if the triple contains an * <code>ANY</code> then this method must return <code>false</code> if there * are any restrictions where the remaining nodes are held constant and the * ANY node is allowed to vary. This checks is used to avoid subsequent * explicit triple checks. * <em>If the system can not quickly verify the solution it is always * acceptable to return <code>false</code>.</em></li> * <li>All other triples are explict triples and the system must determine * if the user is permitted to perform the action on the triple. If the * triple contains a <code>FUTURE</code> node that node should be considered * as an anonymous or blank node that is not yet created. It should only be * used with <code>Create</code> actions and is asking if the user may * create a blank node in that position in the triple.</li> * </ol> * </p> * * @param principal * The principal that is attempting the action. * * @param action * The action to perform * @param graphIRI * The IRI of the graph to the action is being taken upon. May be * <code>ANY</code>. * @param triple * The triple to check * @return true if the action is allowed, false otherwise. * @throws IllegalArgumentException * if any argument is null. * @throws AuthenticationRequiredException * if user is not authenticated and is required to be. */ public boolean evaluate(Object principal, Action action, Node graphIRI, Triple triple) throws AuthenticationRequiredException; /** * Determine if all actions are allowed on the graph. * * @param principal * The principal that is attempting the action. * * @param actions * The set of actions to perform * @param graphIRI * The IRI of the graph to the action is being taken upon. May be * <code>ANY</code>. * @return true if all the actions are allowed, false otherwise. * @throws IllegalArgumentException * if any argument is null. * @throws AuthenticationRequiredException * if user is not authenticated and is required to be. */ public boolean evaluate(Object principal, Set<Action> actions, Node graphIRI) throws AuthenticationRequiredException; /** * Determine if all the actions are allowed on the triple within the graph. * <p> * See evaluate( Action, Node, Triple ) for discussion of evaluation * strategy. * </p> * * @param actions * The actions to perform. * @param graphIRI * The IRI of the graph to the action is being taken upon. May be * <code>ANY</code>. * @param triple * The triple to check * @return true if all the actions are allowed, false otherwise. * @throws IllegalArgumentException * if any argument is null. * @throws AuthenticationRequiredException * if user is not authenticated and is required to be. */ public boolean evaluate(Object principal, Set<Action> actions, Node graphIRI, Triple triple) throws AuthenticationRequiredException; /** * Determine if any of the actions are allowed on the graph. * * @param principal * The principal that is attempting the action. * * @param actions * The actions to perform * @param graphIRI * The IRI of the graph to the action is being taken upon. May be * <code>ANY</code>. * @return true true if any the actions are allowed, false otherwise. * @throws IllegalArgumentException * if any argument is null. * @throws AuthenticationRequiredException * if user is not authenticated and is required to be. */ public boolean evaluateAny(Object principal, Set<Action> actions, Node graphIRI) throws AuthenticationRequiredException; /** * Determine if any of the actions are allowed on the triple within the * graph. * <p> * See evaluate( Action, Node, Triple ) for discussion of evaluation * strategy. * </p> * * @param principal * The principal that is attempting the action. * * @param actions * The actions to check. * @param graphIRI * The IRI of the graph to the action is being taken upon. May be * <code>ANY</code>. * @param triple * The triple to check * @return true if any the actions are allowed, false otherwise. * @throws IllegalArgumentException * if any argument is null. * @throws AuthenticationRequiredException * if user is not authenticated and is required to be. */ public boolean evaluateAny(Object principal, Set<Action> actions, Node graphIRI, Triple triple) throws AuthenticationRequiredException; /** * Determine if the user is allowed to update the "from" triple to the "to" * triple. * <p> * Update is a special case since it modifies one triple to be another. So * the user must have permissions to change the "from" triple into the "to" * triple. * * @param principal * The principal that is attempting the action. * @param graphIRI * The IRI of the graph to the action is being taken upon. May be * <code>ANY</code>. * @param from * The triple to be changed * @param to * The value to change it to. * @return true if the user may make the change, false otherwise. * @throws IllegalArgumentException * if any argument is null. * @throws AuthenticationRequiredException * if user is not authenticated and is required to be. */ public boolean evaluateUpdate(Object principal, Node graphIRI, Triple from, Triple to) throws AuthenticationRequiredException; /** * returns the current principal or null if there is no current principal. * * All security evaluation methods use this method to determine who the call * is being executed as. This allows subsystems (like the listener system) * to capture the current user and evaluate later calls in terms of that * user. * * @return The current principal */ public Object getPrincipal(); /** * Returns true if the principal is recognized as an authenticated principal * by the underlying authentication mechanism. * * This is to handle the case where an authentication mechanism returns a * non-null object to indicate a non-authenticated principal. (e.g. Shiro). * * The principal is guaranteed to have been the return value from an earlier * getPrincipal() call. * * @param principal * The principal to check. * @return true if authenticated, false if not. */ public boolean isPrincipalAuthenticated(Object principal); }