You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by cl...@apache.org on 2013/09/04 21:27:02 UTC

svn commit: r1520114 - in /jena/site/trunk/content/documentation/security: ./ assembler.mdtext evaluator.mdtext index.mdtext

Author: claude
Date: Wed Sep  4 19:27:02 2013
New Revision: 1520114

URL: http://svn.apache.org/r1520114
Log:
Added documentation for jena-security module.

Added:
    jena/site/trunk/content/documentation/security/
    jena/site/trunk/content/documentation/security/assembler.mdtext
    jena/site/trunk/content/documentation/security/evaluator.mdtext
    jena/site/trunk/content/documentation/security/index.mdtext

Added: jena/site/trunk/content/documentation/security/assembler.mdtext
URL: http://svn.apache.org/viewvc/jena/site/trunk/content/documentation/security/assembler.mdtext?rev=1520114&view=auto
==============================================================================
--- jena/site/trunk/content/documentation/security/assembler.mdtext (added)
+++ jena/site/trunk/content/documentation/security/assembler.mdtext Wed Sep  4 19:27:02 2013
@@ -0,0 +1,21 @@
+Title: Jena Security - Assembler For a Secured Model
+
+Jena Security provides a standard Jena assembler making it easy to use the SecuredModel in an Assembler based 
+environment.  To use the security assembler the assembler file must contain the lines:
+
+    <>; ja:loadClass "org.apache.jena.security.SecuredAssembler" .
+    sec:Model rdfs:subClassOf ja:NamedModel .
+    
+and a model definition something like:
+
+    [] a ja:Model ;
+       sec:baseModel jena:model ;
+       ja:modelName "modelName";
+       sec:evaluatorFactory "javaclass";
+       .
+where:
+- `jena:model` is a model defined in the assembler file.  In this example there would be a like in the file
+something like `jena:model a ja:Model`.  
+- `modelName` is the name of the model as identified in the security manager.
+- `javaclass` is the java class name that implements an Evaluator Factory.  The Factory must have static method 
+`getInstance()` that returns a SecurityEvaluator instance.

Added: jena/site/trunk/content/documentation/security/evaluator.mdtext
URL: http://svn.apache.org/viewvc/jena/site/trunk/content/documentation/security/evaluator.mdtext?rev=1520114&view=auto
==============================================================================
--- jena/site/trunk/content/documentation/security/evaluator.mdtext (added)
+++ jena/site/trunk/content/documentation/security/evaluator.mdtext Wed Sep  4 19:27:02 2013
@@ -0,0 +1,185 @@
+Title: Jena Security - SecurityEvaluator implementation
+
+## Overview
+
+The SecurityEvaluator interface defines the access control operations. It provides the interface between the 
+authentication (answers the question: "who are you?") and the authorization (answers the question: "what can you
+do?"), as such it provides access to the current principal (user).  The javadocs contain detailed
+requirements for implementations of the SecurityEvaluator interface, short notes are provided below.
+
+**NOTE** The security system caches intermediate results and will only call the evaluator if the answer is not
+already in the cache.  There is little or advantage to implementing caching in the SecurityEvaluator itself.
+
+### Actions
+
+Principals may perform Create, Read, Action or Delete operations on 
+secured resources.  These operations are defined in the `Action` enum in the SecurtyEvaluator interface.
+
+### SecNode
+
+The security node is a class that tracks the type and node value.  SecNodes are one of the four enumerated Types 
+found in the SecNodes class:
+
+- **URI**  A URI node.
+- **Literal**  A Literal node.
+- **Anonymous**  An anonymous node.  Also called a "blank" node.
+- **Any** Any node.  This is a special case used for wild card matching.
+
+SecNode defines three static nodes:
+
+- `SecNode.ANY = new SecNode(Type.Any, "any")`  Matches any node in the security system.
+- `SecNode.VARIABLE = new SecNode(Type.Any, "variable")` Indicates a variable in the triple.
+- `SecNode.FUTURE = new SecNode(Type.Anonymous, "")` This is an anonymous node that will be created in the future.
+
+
+### SecTriple
+
+The security triple is a class that provides a triple of SecNode objects.  SecTriple also defines a single static
+triple:
+
+- `SecTriple.ANY` = new SecTriple(SecNode.ANY, SeccNode.ANY, SecNode.ANY)` Matches any SecTriple.
+
+### Evaluator Methods
+ 
+    public boolean evaluate( Action action, SecNode graphIRI );
+Determine if the action is permitted within the graph.
+
+    public boolean evaluate( Action action, SecNode graphIRI, SecTriple triple );
+Determine if the action is allowed on the triple within the graph.
+
+    public boolean evaluate( Set<Action> actions, SecNode graphIRI );
+Determine if all actions are allowed on the graph.
+    
+    public boolean evaluate( Set<Action> actions, SecNode graphIRI, SecTriple triple );            
+Determine if all the actions are allowed on the triple within the graph.            
+
+    public boolean evaluateAny( Set<Action> actions, SecNode graphIRI );
+Determine if any of the actions are allowed on the graph.
+   
+    public boolean evaluateAny( Set<Action> actions, SecNode graphIRI, SecTriple triple );
+Determine if any of the actions are allowed on the triple within the graph.
+
+    public boolean evaluateUpdate( SecNode graphIRI, SecTriple from, SecTriple to );
+Determine if the user is allowed to update the "from" triple to the "to" triple.            
+
+    public Principal getPrincipal();   
+returns the current principal or null if there is no current principal.    
+
+## Sample Implementation
+
+This sample is for a graph that contains a set of messages, access to the messages are limited to 
+principals that the messages are to or from.  Any triple that is not a message is not affected. This 
+implementation simply has a `setPrincipal(String name)` method.  A real implementation would request the
+user principal or name from the authentication system.  This implementation also requires access to the underlying
+model to determine if the user has access, however, that is not a requirement of the SecurityEvaluator in general.
+Determining access from the information provided is an exercise for the implementer. 
+
+<!-- language: lang-java -->
+    
+    public class ExampleEvaluator implements SecurityEvaluator {
+        
+        private Principal principal;
+        private Model model;
+        private RDFNode msgType = ResourceFactory.createResource( "http://example.com/msg" );
+        private Property pTo = ResourceFactory.createProperty( "http://example.com/to" );
+        private Property pFrom = ResourceFactory.createProperty( "http://example.com/from" );
+        
+        /**
+         * 
+         * @param model The graph we are going to evaluate against.
+         */
+        public ExampleEvaluator( Model model )
+        {
+            this.model = model;
+        }
+        
+        @Override
+        public boolean evaluate(Action action, SecNode graphIRI) {
+            // we allow any action on a graph.
+            return true;
+        }
+    
+        private boolean evaluate( Resource r )
+        {
+            // a message is only available to sender or recipient
+            if (r.hasProperty( RDF.type, msgType ))
+            {
+                return r.hasProperty( pTo, principal.getName() ) ||
+                        r.hasProperty( pFrom, principal.getName());
+            }
+            return true;    
+        }
+        
+        private boolean evaluate( SecNode node )
+        {
+            if (node.equals( SecNode.ANY )) {
+                return false;  // all wild cards are false
+            }
+            
+            if (node.getType().equals( SecNode.Type.URI)) {
+                Resource r = model.createResource( node.getValue() );
+                return evaluate( r );
+            }
+            else if (node.getType().equals( SecNode.Type.Anonymous)) {
+                Resource r = model.getRDFNode( NodeFactory.createAnon( new AnonId( node.getValue()) ) ).asResource();
+                return evaluate( r );
+            }
+            else
+            {
+                return true;
+            }
+    
+        }
+        
+        private boolean evaluate( SecTriple triple ) {
+            return evaluate( triple.getSubject()) &&
+                    evaluate( triple.getObject()) &&
+                    evaluate( triple.getPredicate());
+        }
+        
+        @Override
+        public boolean evaluate(Action action, SecNode graphIRI, SecTriple triple) {
+            return evaluate( triple );
+        }
+    
+        @Override
+        public boolean evaluate(Set<Action> actions, SecNode graphIRI) {
+            return true;
+        }
+    
+        @Override
+        public boolean evaluate(Set<Action> actions, SecNode graphIRI,
+                SecTriple triple) {
+            return evaluate( triple );
+        }
+    
+        @Override
+        public boolean evaluateAny(Set<Action> actions, SecNode graphIRI) {
+            return true;
+        }
+    
+        @Override
+        public boolean evaluateAny(Set<Action> actions, SecNode graphIRI,
+                SecTriple triple) {
+            return evaluate( triple );
+        }
+    
+        @Override
+        public boolean evaluateUpdate(SecNode graphIRI, SecTriple from, SecTriple to) {
+            return evaluate( from ) && evaluate( to );
+        }
+    
+        public void setPrincipal( String userName )
+        {
+            if (userName == null)
+            {
+                principal = null;
+            }
+            principal = new BasicUserPrincipal( userName );
+        }
+        @Override
+        public Principal getPrincipal() {
+            return principal;
+        }
+    
+    }

Added: jena/site/trunk/content/documentation/security/index.mdtext
URL: http://svn.apache.org/viewvc/jena/site/trunk/content/documentation/security/index.mdtext?rev=1520114&view=auto
==============================================================================
--- jena/site/trunk/content/documentation/security/index.mdtext (added)
+++ jena/site/trunk/content/documentation/security/index.mdtext Wed Sep  4 19:27:02 2013
@@ -0,0 +1,51 @@
+Title: Jena Security - A Security (Permissions) wrapper around Jena RDF implementation.
+
+JenaSecurity is a SecurityEvaluator interface and a set of dynamic proxies that apply that interface to Jena Graphs, 
+Models, and associated methods and classes.
+
+## Documentation
+
+- [Overview](#overview)
+- [Usage Notes](#usage-notes)
+- [Security Evaluator](#evaluator.html)
+
+
+## Overview
+
+Jena-security transparently intercepts calls to the Graph or Model interface, evaluates access restrictions and
+either allows or rejects the access.  The system is authentication agnostic and will work with most authentication
+systems.  The system uses dynamic proxies to wrap any Graph or Model implementation.
+The jena-security module includes an Assembler module to extend the standard Assembler to include the ability to
+create secured models and graphs.  A complete example application is also available.
+
+The developer using jena-security is required to implement a SecurityEvaluator that provides access to the Principal
+(User) using the system and also determines if that Principal has the proper access to execute a method.  Through the 
+SecurityEvaluator the developer may apply full CRUD (Create, Read, Update, and Delete) restrictions to graphs and 
+optionally triples within the graphs. 
+
+The javadocs have additional annotations that specify what permissions at graph and triple levels are required for 
+the user to execute the method.
+
+## Usage Notes
+
+When the system is correctly configured the developer creates a SecuredGraph by calling 
+`Factory.getInstance( SecurityEvaluator, String, Graph );`. Once created the resulting graph automatically 
+makes the appropriate calls to the SecurityEvaluator before passing any approved requests to the underlying graph.
+
+Secured models are created by calling `Factory.getInstance( SecurityEvaluator, String, Model );` or 
+`ModelFactory.createModelForGraph( SecuredGraph );`
+
+**NOTE:** when creating a model by wrapping a secured graph (e.g. `ModelFactory.createModelForGraph( SecuredGraph );`) 
+the resulting Model does not have the same security requirements that the standard secured model.  For example 
+When creating a list on a secured model calling `model.createList( RDFNode[] );`, the standard secured 
+model verifies that the user has the right to **update** the triples and allows or denies the entire operation 
+accordingly. The wrapped secured graph does not have visibility to the `createList()` command and can only operate 
+on the instructions issued by the `model.createList()` implementation. In the standard implementation the model 
+requests the graph to delete one triple and then insert another. Thus the user must have **delete** and **add**
+permissions, not the **update** permission.
+
+There are several other cases where the difference in the layer can trip up the security system. In all known cases 
+the result is a tighter security definition than was requested. For simplicity sake we recommend that the wrapped 
+secured graph only be used in cases where access to the graph as a whole is granted/denied. In these cases the user 
+either has all CRUD capabilities or none.
+