You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2018/11/17 17:20:57 UTC

[31/34] jena git commit: Refine access control features.

Refine access control features.

Command line --auth
Command line --passwd and imply at least server access control.


Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/14491b86
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/14491b86
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/14491b86

Branch: refs/heads/master
Commit: 14491b8637cf0784766410f4ac8d637e74d0ca29
Parents: 9c6bdf0
Author: Andy Seaborne <an...@apache.org>
Authored: Wed Nov 14 17:05:11 2018 +0000
Committer: Andy Seaborne <an...@apache.org>
Committed: Wed Nov 14 17:05:11 2018 +0000

----------------------------------------------------------------------
 .../sparql/core/DatasetGraphFilteredView.java   |  2 +
 .../access/AssemblerSecurityRegistry.java       | 18 +++++++-
 .../fuseki/access/TestSecurityRegistry.java     | 31 +++++++-------
 .../org/apache/jena/fuseki/jetty/JettyLib.java  | 16 +++----
 .../apache/jena/fuseki/main/FusekiServer.java   | 44 +++++++++++++-------
 .../jena/fuseki/main/cmds/FusekiMain.java       | 21 +++++++---
 .../jena/fuseki/main/cmds/ServerConfig.java     |  2 +
 7 files changed, 88 insertions(+), 46 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jena/blob/14491b86/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphFilteredView.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphFilteredView.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphFilteredView.java
index ec61b04..504fc80 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphFilteredView.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphFilteredView.java
@@ -83,6 +83,8 @@ public class DatasetGraphFilteredView extends DatasetGraphReadOnly implements Da
     }
 
     private Iterator<Quad> filter(Iterator<Quad> iter) {
+        if ( this.quadFilter == null )
+            return iter;
         return Iter.filter(iter, this::filter);
     }
     

http://git-wip-us.apache.org/repos/asf/jena/blob/14491b86/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AssemblerSecurityRegistry.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AssemblerSecurityRegistry.java b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AssemblerSecurityRegistry.java
index 93c4cdb..c0ef33c 100644
--- a/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AssemblerSecurityRegistry.java
+++ b/jena-fuseki2/jena-fuseki-access/src/main/java/org/apache/jena/fuseki/access/AssemblerSecurityRegistry.java
@@ -28,6 +28,7 @@ import org.apache.jena.assembler.Assembler;
 import org.apache.jena.assembler.Mode;
 import org.apache.jena.assembler.assemblers.AssemblerBase;
 import org.apache.jena.assembler.exceptions.AssemblerException;
+import org.apache.jena.atlas.logging.Log;
 import org.apache.jena.ext.com.google.common.collect.ArrayListMultimap;
 import org.apache.jena.ext.com.google.common.collect.Multimap;
 import org.apache.jena.graph.Node;
@@ -139,10 +140,13 @@ public class AssemblerSecurityRegistry extends AssemblerBase {
         return x;
     }
     
+    // Unfinished.
+    private final static boolean SKIP_ALLGRAPH = true; 
+    
     private void accessEntries(Resource root, Multimap<String, Node> map, String user, List<Node> _graphs) {
         // Convert string names for graphs to URIs. 
         Set<Node> graphs = _graphs.stream().map(n->graphLabel(n, root)).collect(Collectors.toSet());
-        
+
         if ( graphs.contains(SecurityContext.allGraphs) ) {
             map.removeAll(user);
             map.put(user, SecurityContext.allGraphs);
@@ -158,6 +162,18 @@ public class AssemblerSecurityRegistry extends AssemblerBase {
             map.put(user, x);
             return;
         }
+        
+        if ( SKIP_ALLGRAPH ) {
+            if ( graphs.contains(SecurityContext.allGraphs) ) {
+                Log.warn(this, "Graph name '"+SecurityContext.allGraphsStr+"' not supported yet"); 
+                graphs.remove(SecurityContext.allGraphs);
+            }
+            if ( graphs.contains(SecurityContext.allNamedGraphs) ) {
+                Log.warn(this, "Graph name '"+SecurityContext.allNamedGraphsStr+"' not supported yet"); 
+                graphs.remove(SecurityContext.allNamedGraphs);
+            }
+        }
+        
         map.putAll(user, graphs);
     }
 

http://git-wip-us.apache.org/repos/asf/jena/blob/14491b86/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityRegistry.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityRegistry.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityRegistry.java
index d6b7c1b..0e62bd7 100644
--- a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityRegistry.java
+++ b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityRegistry.java
@@ -48,20 +48,20 @@ public class TestSecurityRegistry {
         AuthorizationService authService = (AuthorizationService)AssemblerUtils.build(DIR+"assem-security-registry-2.ttl", VocabSecurity.tSecurityRegistry);
         assertNotNull(authService);
 
-//        {
-//            SecurityContext sCxt = authService.get("user1");
-//            assertEquals(1, sCxt.visibleGraphs().size());
-//            Node x = sCxt.visibleGraphs().stream().findFirst().get();
-//            assertEquals(SecurityContext.allNamedGraphs, x);
-//        }
-//        
-//        {
-//            SecurityContext sCxt = authService.get("user2");
-//            assertEquals(1, sCxt.visibleGraphs().size());
-//            Node x = sCxt.visibleGraphs().stream().findFirst().get();
-//            assertEquals(SecurityContext.allGraphs, x);
-//        }
-//        
+        {
+            SecurityContext sCxt = authService.get("user1");
+            assertEquals(1, sCxt.visibleGraphs().size());
+            Node x = sCxt.visibleGraphs().stream().findFirst().get();
+            assertEquals(SecurityContext.allNamedGraphs, x);
+        }
+        
+        {
+            SecurityContext sCxt = authService.get("user2");
+            assertEquals(1, sCxt.visibleGraphs().size());
+            Node x = sCxt.visibleGraphs().stream().findFirst().get();
+            assertEquals(SecurityContext.allGraphs, x);
+        }
+        
         {
             SecurityContext sCxt = authService.get("user3");
             assertEquals(1, sCxt.visibleGraphs().size());
@@ -75,8 +75,5 @@ public class TestSecurityRegistry {
             String x = sCxt.visibleGraphNames().stream().findFirst().get();
             assertEquals("http://host/graphname1", x);
         }            
-        
-        
     }
-
 }

http://git-wip-us.apache.org/repos/asf/jena/blob/14491b86/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/jetty/JettyLib.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/jetty/JettyLib.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/jetty/JettyLib.java
index f516e80..ae5ce65 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/jetty/JettyLib.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/jetty/JettyLib.java
@@ -60,12 +60,20 @@ public class JettyLib {
 //        return securityHandler;
 //    }
     
+    /**
+     * Digest requires an extra round trip so it is unfriendly to API
+     * or scripts that stream.
+     */
+    public final static AuthScheme dftAuthMode = AuthScheme.DIGEST;
+    /** Current auth mode */
+    public static AuthScheme authMode = dftAuthMode;
+
     /** Create a Jetty {@link SecurityHandler} for basic authentication. 
      * See {@linkplain #addPathConstraint(ConstraintSecurityHandler, String)}
      * for adding the {@code pathspec} to apply it to.
      */
      public static ConstraintSecurityHandler makeSecurityHandler(String realm, UserStore userStore) {
-         return makeSecurityHandler(realm, userStore, "**", dftAuthMode);
+         return makeSecurityHandler(realm, userStore, "**", authMode);
      }
 
      /** Create a Jetty {@link SecurityHandler} for basic authentication. 
@@ -76,12 +84,6 @@ public class JettyLib {
           return makeSecurityHandler(realm, userStore, "**", authMode);
       }
 
-      /**
-     * Digest requires an extra round trip so it is unfriendly to API
-     * or scripts that stream.
-     */
-     public static AuthScheme dftAuthMode = AuthScheme.DIGEST; 
-
       /** Create a Jetty {@link SecurityHandler} for basic authentication. 
      * See {@linkplain #addPathConstraint(ConstraintSecurityHandler, String)}
      * for adding the {@code pathspec} to apply it to.

http://git-wip-us.apache.org/repos/asf/jena/blob/14491b86/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/FusekiServer.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/FusekiServer.java b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/FusekiServer.java
index d465ebe..4f63c84 100644
--- a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/FusekiServer.java
+++ b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/FusekiServer.java
@@ -238,9 +238,9 @@ public class FusekiServer {
         private RequestAuthorization     serverAllowedUsers = null;
         private String                   passwordFile       = null;
         private String                   realm              = null;
-        private AuthScheme                 authMode           = null;
-        private String                   httpsKeystore        = null;
-        private String                   httpsKeystorePasswd  = null;
+        private AuthScheme               authScheme             = null;
+        private String                   httpsKeystore          = null;
+        private String                   httpsKeystorePasswd    = null;
         // Other servlets to add.
         private List<Pair<String, HttpServlet>> servlets    = new ArrayList<>();
         private List<Pair<String, Filter>> filters          = new ArrayList<>();
@@ -249,7 +249,6 @@ public class FusekiServer {
         private String                   staticContentDir   = null;
         private SecurityHandler          securityHandler    = null;
         private Map<String, Object>      servletAttr        = new HashMap<>();
-
         // Builder with standard operation-action mapping.  
         Builder() {
             this.serviceDispatch = new ServiceDispatchRegistry(true);
@@ -485,12 +484,20 @@ public class FusekiServer {
             realm(realm);
             
             String authStr = GraphUtils.getAsStringValue(server, FusekiVocab.pAuth);
-            authMode = AuthScheme.scheme(authStr);
+            authScheme = AuthScheme.scheme(authStr);
             
             serverAllowedUsers = FusekiBuilder.allowedUsers(server);
         }
 
         /**
+         * Choose the HTTP authentication scheme. 
+         */
+        public Builder auth(AuthScheme authScheme) {
+            this.authScheme = authScheme;
+            return this;
+        }
+
+        /**
          * Set the realm used for HTTP digest authentication.
          * The default is "TripleStore". 
          */
@@ -645,18 +652,24 @@ public class FusekiServer {
             
             // See if there are any DatasetGraphAccessControl.
             hasDataAccessControl = 
-                dataAccessPoints.keys().stream().map(name-> dataAccessPoints.get(name).getDataService().getDataset())
-                    .filter(DataAccessCtl::isAccessControlled)
-                    .findFirst()
-                    .isPresent();
+                dataAccessPoints.keys().stream()
+                    .map(name-> dataAccessPoints.get(name).getDataService().getDataset())
+                    .anyMatch(DataAccessCtl::isAccessControlled);
 
             hasAllowedUsers = ( serverAllowedUsers != null );
             if ( ! hasAllowedUsers ) {
                 // Any datasets with allowedUsers?
                 hasAllowedUsers =
-                    dataAccessPoints.keys().stream().map(name-> dataAccessPoints.get(name).getDataService())
+                    dataAccessPoints.keys().stream()
+                        .map(name-> dataAccessPoints.get(name).getDataService())
                         .anyMatch(dSvc->dSvc.allowedUsers() != null);
             }
+            
+            // If only a password file given, and nothing else, set the server to allowedUsers="*" (must log in).  
+            if ( passwordFile != null && ! hasAllowedUsers ) {
+                hasAllowedUsers = true;
+                serverAllowedUsers = RequestAuthorization.policyAllowAuthenticated();
+            }
         }
         
         private void buildFinish() {
@@ -689,7 +702,6 @@ public class FusekiServer {
             DataAccessPointRegistry dapRegistry = new DataAccessPointRegistry(dataAccessPoints);
             ServiceDispatchRegistry svcRegistry = new ServiceDispatchRegistry(serviceDispatch);
             
-            
             ServiceDispatchRegistry.set(cxt, svcRegistry);
             DataAccessPointRegistry.set(cxt, dapRegistry);
             JettyLib.setMimeTypes(handler);
@@ -710,16 +722,16 @@ public class FusekiServer {
             if ( passwordFile == null )
                 return null;
             UserStore userStore = JettyLib.makeUserStore(passwordFile);
-            return JettyLib.makeSecurityHandler(realm, userStore, authMode);
+            return JettyLib.makeSecurityHandler(realm, userStore, authScheme);
         }
         
         private void buildAccessControl(ServletContext cxt) {
             // -- Access control
             if ( securityHandler != null && securityHandler instanceof ConstraintSecurityHandler ) {
                 ConstraintSecurityHandler csh = (ConstraintSecurityHandler)securityHandler;
-               if ( serverAllowedUsers != null )
-                   JettyLib.addPathConstraint(csh, "/*");
-               else {
+                if ( serverAllowedUsers != null )
+                    JettyLib.addPathConstraint(csh, "/*");
+                else {
                     DataAccessPointRegistry.get(cxt).forEach((name, dap)-> {
                         DatasetGraph dsg = dap.getDataService().getDataset();
                         if ( dap.getDataService().allowedUsers() != null ) {
@@ -728,7 +740,7 @@ public class FusekiServer {
                             JettyLib.addPathConstraint(csh, DataAccessPoint.canonical(name)+"/*");
                         }
                     });
-               }
+                }
             }
         }
         

http://git-wip-us.apache.org/repos/asf/jena/blob/14491b86/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/cmds/FusekiMain.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/cmds/FusekiMain.java b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/cmds/FusekiMain.java
index 4a72270..e1505b1 100644
--- a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/cmds/FusekiMain.java
+++ b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/cmds/FusekiMain.java
@@ -38,6 +38,7 @@ import org.apache.jena.atlas.json.JsonObject;
 import org.apache.jena.atlas.lib.DateTimeUtils;
 import org.apache.jena.atlas.lib.FileOps;
 import org.apache.jena.atlas.logging.FmtLog;
+import org.apache.jena.atlas.web.AuthScheme;
 import org.apache.jena.fuseki.Fuseki;
 import org.apache.jena.fuseki.FusekiException;
 import org.apache.jena.fuseki.main.FusekiServer;
@@ -85,13 +86,14 @@ public class FusekiMain extends CmdARQ {
         private static ArgDecl  argGZip         = new ArgDecl(ArgDecl.HasValue, "gzip");
         private static ArgDecl  argBase         = new ArgDecl(ArgDecl.HasValue, "base", "files");
         
+        private static ArgDecl  argAuth         = new ArgDecl(ArgDecl.HasValue, "auth");
+        
         private static ArgDecl  argHttps        = new ArgDecl(ArgDecl.HasValue, "https");
         private static ArgDecl  argHttpsPort    = new ArgDecl(ArgDecl.HasValue, "httpsPort", "httpsport", "sport");
         
         private static ArgDecl  argPasswdFile   = new ArgDecl(ArgDecl.HasValue, "passwd");
         private static ArgDecl  argRealm        = new ArgDecl(ArgDecl.HasValue, "realm");
         
-        
         // Same as --empty --validators --general=/sparql, --files=ARG
         
         private static ArgDecl  argSparqler     = new ArgDecl(ArgDecl.HasValue, "sparqler");
@@ -155,11 +157,12 @@ public class FusekiMain extends CmdARQ {
                 "Run with SPARQLer services Directory for static content");
             add(argValidators, "--validators", "Install validators");
             
+            add(argAuth, "--auth=[basic|Digest]", "Run the server using basic or digest authentication (dft: digest).");
             add(argHttps, "--https=CONF", "https certificate access details. JSON file { \"cert\":FILE , \"passwd\"; SECRET } ");
             add(argHttpsPort, "--httpsPort=NUM", "https port (default port is 3043)");
 
-            // Disable - put in the configuration file.
-//            add(argPasswdFile, "--passwd=FILE", "Password file");
+            add(argPasswdFile, "--passwd=FILE", "Password file");
+            // put in the configuration file
 //            add(argRealm, "--realm=REALM", "Realm name");
 
             super.modVersion.addClass(Fuseki.class);
@@ -196,7 +199,7 @@ public class FusekiMain extends CmdARQ {
                 throw new CmdException("No dataset specified on the command line.");
 
             if ( numDefinitions > 1 )
-                throw new CmdException("Multiple ways providing a dataset. Only one of --mem, --file, --loc or --desc");
+                throw new CmdException("Multiple ways providing a dataset. Only one of --mem, --file, --loc or --conf");
 
             if ( numDefinitions > 0 && allowEmpty )
                 throw new CmdException("Dataset provided but 'no dataset' flag given");
@@ -349,6 +352,7 @@ public class FusekiMain extends CmdARQ {
 
             if ( contains(argPasswdFile) )
                 serverConfig.passwdFile = getValue(argPasswdFile);
+            
             if ( contains(argRealm) )
                 serverConfig.realm =  getValue(argRealm);
             
@@ -368,7 +372,11 @@ public class FusekiMain extends CmdARQ {
                 serverConfig.httpsKeystore = path.getParent().resolve(keystore).toString();
                 
                 serverConfig.httpsKeystorePasswd = httpsConf.get("passwd").getAsString().value();
-              
+            }
+            
+            if ( contains(argAuth) ) {
+                String schemeStr = getValue(argAuth);
+                serverConfig.authScheme = AuthScheme.scheme(schemeStr); 
             }
             
 //            if ( contains(argGZip) ) {
@@ -467,6 +475,9 @@ public class FusekiMain extends CmdARQ {
             if ( serverConfig.httpsKeystore != null )
                 builder.https(serverConfig.httpsPort, serverConfig.httpsKeystore, serverConfig.httpsKeystorePasswd);
            
+            if ( serverConfig.authScheme != null )
+                builder.auth(serverConfig.authScheme);
+            
             return builder.build();
         }
 

http://git-wip-us.apache.org/repos/asf/jena/blob/14491b86/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/cmds/ServerConfig.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/cmds/ServerConfig.java b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/cmds/ServerConfig.java
index 89f991c..447babf 100644
--- a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/cmds/ServerConfig.java
+++ b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/cmds/ServerConfig.java
@@ -18,6 +18,7 @@
 
 package org.apache.jena.fuseki.main.cmds;
 
+import org.apache.jena.atlas.web.AuthScheme;
 import org.apache.jena.sparql.core.DatasetGraph;
 
 /** Setup details (command line, config file) from command line processing.
@@ -50,6 +51,7 @@ class ServerConfig {
     public String contentDirectory    = null;
     
     // Server authentication
+    public AuthScheme authScheme      = null;
     public String passwdFile          = null;
     public String realm               = null;