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;