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/22 11:51:35 UTC
[3/6] jena git commit: JENA-1623: Endpoint access control lists tests
JENA-1623: Endpoint access control lists tests
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/070fae10
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/070fae10
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/070fae10
Branch: refs/heads/master
Commit: 070fae10908c46508b3454727e4a388640fbdb97
Parents: ca78393
Author: Andy Seaborne <an...@apache.org>
Authored: Tue Nov 20 20:21:43 2018 +0000
Committer: Andy Seaborne <an...@apache.org>
Committed: Tue Nov 20 20:56:50 2018 +0000
----------------------------------------------------------------------
.../java/org/apache/jena/fuseki/auth/Auth.java | 6 +-
.../apache/jena/fuseki/auth/AuthUserList.java | 60 +++
.../jena/fuseki/auth/RequestAuthorization.java | 60 ---
.../apache/jena/fuseki/build/FusekiBuilder.java | 22 +-
.../org/apache/jena/fuseki/jetty/JettyLib.java | 3 +
.../apache/jena/fuseki/server/DataService.java | 4 +
.../jena/fuseki/servlets/ActionService.java | 2 +-
.../apache/jena/fuseki/main/FusekiServer.java | 138 ++++---
.../AbstractTestFusekiSecurityAssembler.java | 2 +-
.../fuseki/main/access/TS_SecurityFuseki.java | 4 +-
.../fuseki/main/access/TestPasswordServer.java | 219 ----------
.../main/access/TestPasswordServices.java | 233 -----------
.../main/access/TestSecurityBuilderSetup.java | 229 +++++++++++
.../fuseki/main/access/TestSecurityConfig.java | 411 +++++++++++++++++++
.../testing/Access/allowedUsers.ttl | 6 +-
.../testing/Access/assem-security-shared.ttl | 3 +
.../testing/Access/assem-security.ttl | 3 +
.../testing/Access/config-server-0.ttl | 61 +++
.../testing/Access/config-server-1.ttl | 3 +
.../testing/Access/config-server-2.ttl | 3 +
.../testing/Access/config-server-3.ttl | 51 +++
.../testing/Access/config-server-4.ttl | 45 ++
22 files changed, 976 insertions(+), 592 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/070fae10/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/auth/Auth.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/auth/Auth.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/auth/Auth.java
index 2e61129..c0b1d52 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/auth/Auth.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/auth/Auth.java
@@ -29,6 +29,8 @@ import org.apache.jena.fuseki.FusekiConfigException;
* See {@link Users} for special user names.
*/
public class Auth {
+ public static final String dftRealm = "TripleStore";
+
/** Any authenticated user. */
public static AuthPolicy ANY_USER = (user) -> user != null;
@@ -42,7 +44,7 @@ public class Auth {
public static AuthPolicy policyAllowSpecific(String... allowedUsers) {
return Auth.policyAllowSpecific(Arrays.asList(allowedUsers));
}
-
+
/**
* A policy that allows specific users.
* <ul>
@@ -65,7 +67,7 @@ public class Auth {
if ( allowedUsers.stream().anyMatch(Objects::isNull) )
throw new FusekiConfigException("null user found : "+allowedUsers);
- return new RequestAuthorization(allowedUsers);
+ return new AuthUserList(allowedUsers);
}
/**
http://git-wip-us.apache.org/repos/asf/jena/blob/070fae10/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/auth/AuthUserList.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/auth/AuthUserList.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/auth/AuthUserList.java
new file mode 100644
index 0000000..55aae72
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/auth/AuthUserList.java
@@ -0,0 +1,60 @@
+/*
+ * 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.fuseki.auth;
+
+import java.util.*;
+
+/**
+ * Policy for allowing users to execute a request.
+ * Assumes the user has been authenticated.
+ */
+class AuthUserList implements AuthPolicy {
+
+ private final Set<String> allowedUsers;
+
+ /*package*/ AuthUserList(Collection<String> allowed) {
+ this.allowedUsers = (allowed == null) ? Collections.emptySet() : new HashSet<>(allowed);
+ }
+
+ @Override
+ public boolean isAllowed(String user) {
+ if ( user == null )
+ return false;
+ if ( contains(allowedUsers, user) )
+ return true;
+ return false;
+ }
+
+ @Override
+ public boolean isDenied(String user) {
+ return !isAllowed(user);
+ }
+
+ static <T> boolean isNullOrEmpty(Collection<T> collection) {
+ if ( collection == null )
+ return true;
+ return collection.isEmpty();
+ }
+
+ static <T> boolean contains(Collection<T> collection, T obj) {
+ if ( collection == null )
+ return false;
+ return collection.contains(obj);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/070fae10/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/auth/RequestAuthorization.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/auth/RequestAuthorization.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/auth/RequestAuthorization.java
deleted file mode 100644
index 2a5d11a..0000000
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/auth/RequestAuthorization.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.fuseki.auth;
-
-import java.util.*;
-
-/**
- * Policy for allowing users to execute a request.
- * Assumes the user has been authenticated.
- */
-class RequestAuthorization implements AuthPolicy {
-
- private final Set<String> allowedUsers;
-
- /*package*/ RequestAuthorization(Collection<String> allowed) {
- this.allowedUsers = (allowed == null) ? Collections.emptySet() : new HashSet<>(allowed);
- }
-
- @Override
- public boolean isAllowed(String user) {
- if ( user == null )
- return false;
- if ( contains(allowedUsers, user) )
- return true;
- return false;
- }
-
- @Override
- public boolean isDenied(String user) {
- return !isAllowed(user);
- }
-
- static <T> boolean isNullOrEmpty(Collection<T> collection) {
- if ( collection == null )
- return true;
- return collection.isEmpty();
- }
-
- static <T> boolean contains(Collection<T> collection, T obj) {
- if ( collection == null )
- return false;
- return collection.contains(obj);
- }
-}
http://git-wip-us.apache.org/repos/asf/jena/blob/070fae10/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiBuilder.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiBuilder.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiBuilder.java
index bfcb3a5..1cb060a 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiBuilder.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiBuilder.java
@@ -32,12 +32,11 @@ import org.apache.jena.fuseki.server.*;
import org.apache.jena.graph.Node;
import org.apache.jena.query.QuerySolution ;
import org.apache.jena.query.ResultSet ;
-import org.apache.jena.rdf.model.Literal;
-import org.apache.jena.rdf.model.Property ;
-import org.apache.jena.rdf.model.RDFNode;
-import org.apache.jena.rdf.model.Resource ;
+import org.apache.jena.rdf.model.*;
import org.apache.jena.rdf.model.impl.Util;
+import org.apache.jena.shared.JenaException;
import org.apache.jena.sparql.core.DatasetGraph ;
+import org.apache.jena.sparql.util.graph.GraphUtils;
/**
* Helper functions use to construct Fuseki servers.
@@ -91,12 +90,17 @@ public class FusekiBuilder
else if ( ep.isResource() ) {
Resource r = (Resource)ep;
try {
- // [AuthAll]
+ // Look for possible:
// [ fuseki:name "" ; fuseki:allowedUsers ( "" "" ) ]
- Resource x = r.getProperty(FusekiVocab.pAllowedUsers).getResource();
- requestAuth = FusekiBuilder.allowedUsers(x);
- epName = ((Literal)r.getProperty(FusekiVocab.pServiceName)).getLexicalForm();
- } catch(Exception x) {}
+ epName = r.getProperty(FusekiVocab.pServiceName).getString();
+ List<RDFNode> x = GraphUtils.multiValue(r, FusekiVocab.pAllowedUsers);
+ if ( x.size() > 1 )
+ throw new FusekiConfigException("Multiple fuseki:"+FusekiVocab.pAllowedUsers.getLocalName()+" for "+r);
+ if ( ! x.isEmpty() )
+ requestAuth = FusekiBuilder.allowedUsers(r);
+ } catch(JenaException | ClassCastException ex) {
+ throw new FusekiConfigException("Failed to parse endpoint: "+r);
+ }
} else {
throw new FusekiConfigException("Unrecognized: "+ep);
}
http://git-wip-us.apache.org/repos/asf/jena/blob/070fae10/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 ae5ce65..005914c 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
@@ -93,6 +93,9 @@ public class JettyLib {
Objects.requireNonNull(userStore);
Objects.requireNonNull(role);
+ if ( authMode == null )
+ authMode = dftAuthMode;
+
ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler();
IdentityService identService = new DefaultIdentityService();
http://git-wip-us.apache.org/repos/asf/jena/blob/070fae10/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/DataService.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/DataService.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/DataService.java
index 8f02877..3759da0 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/DataService.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/DataService.java
@@ -109,6 +109,10 @@ public class DataService {
return endpoints.get(endpointName);
}
+ public Collection<Endpoint> getEndpoints() {
+ return operations.values();
+ }
+
public List<Endpoint> getEndpoints(Operation operation) {
List<Endpoint> x = operations.get(operation);
if ( x == null )
http://git-wip-us.apache.org/repos/asf/jena/blob/070fae10/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionService.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionService.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionService.java
index eb4e540..fe87407 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionService.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ActionService.java
@@ -101,7 +101,7 @@ public abstract class ActionService extends ActionBase {
}
// ---- Auth checking.
- // -- Server-level auhtorization.
+ // -- Server-level authorization.
// Checking was carried out by servlet filter AuthFilter.
// Need to check Data service and endpoint authorization policies.
String user = action.getUser();
http://git-wip-us.apache.org/repos/asf/jena/blob/070fae10/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 3d298e8..794b4b7 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
@@ -236,7 +236,7 @@ public class FusekiServer {
private boolean verbose = false;
private boolean withStats = false;
private boolean withPing = false;
- private AuthPolicy serverAuth = null;
+ private AuthPolicy serverAuth = null; // Server level policy.
private String passwordFile = null;
private String realm = null;
private AuthScheme authScheme = null;
@@ -458,8 +458,7 @@ public class FusekiServer {
Model model = AssemblerUtils.readAssemblerFile(filename);
Resource server = FusekiConfig.findServer(model);
- // [AuthAll]
- processServerLevel(server);
+ processServerLevel(server);
// Process server and services, whether via server ja:services or, if absent, by finding by type.
// Side effect - sets global context.
@@ -477,29 +476,27 @@ public class FusekiServer {
return;
// Extract settings - the server building is done in buildSecurityHandler,
// buildAccessControl. Dataset and graph level happen in assemblers.
- passwordFile = GraphUtils.getAsStringValue(server, FusekiVocab.pPasswordFile);
- if ( passwordFile != null )
- passwordFile(passwordFile);
- realm = GraphUtils.getAsStringValue(server, FusekiVocab.pRealm);
- if ( realm == null )
- realm = "TripleStore";
- realm(realm);
+ String passwdFile = GraphUtils.getAsStringValue(server, FusekiVocab.pPasswordFile);
+ if ( passwdFile != null )
+ passwordFile(passwdFile);
+ String realmStr = GraphUtils.getAsStringValue(server, FusekiVocab.pRealm);
+ if ( realmStr != null )
+ realm(realmStr);
String authStr = GraphUtils.getAsStringValue(server, FusekiVocab.pAuth);
- authScheme = AuthScheme.scheme(authStr);
-
+ if ( authStr != null )
+ auth(AuthScheme.scheme(authStr));
serverAuth = FusekiBuilder.allowedUsers(server);
}
- /** Process password file, auth and rela settings on the server description. **/
+ /** Process password file, auth and realm settings on the server description. **/
private void processAuthentication(Resource server) {
- passwordFile = GraphUtils.getAsStringValue(server, FusekiVocab.pPasswordFile);
- if ( passwordFile != null )
- passwordFile(passwordFile);
- realm = GraphUtils.getAsStringValue(server, FusekiVocab.pRealm);
- if ( realm == null )
- realm = "TripleStore";
- realm(realm);
+ String passwdFile = GraphUtils.getAsStringValue(server, FusekiVocab.pPasswordFile);
+ if ( passwdFile != null )
+ passwordFile(passwdFile);
+ String realmStr = GraphUtils.getAsStringValue(server, FusekiVocab.pRealm);
+ if ( realmStr != null )
+ realm(realmStr);
}
/**
@@ -512,7 +509,6 @@ public class FusekiServer {
/**
* Set the realm used for HTTP digest authentication.
- * The default is "TripleStore".
*/
public Builder realm(String realm) {
this.realm = realm;
@@ -645,23 +641,31 @@ public class FusekiServer {
}
if ( networkLoopback )
applyLocalhost(server);
- boolean accessCtlRequest = securityHandler != null;
- boolean accessCtlData = false;
return new FusekiServer(serverPort, serverHttpsPort, server, handler.getServletContext());
} finally {
buildFinish();
}
}
+ private ConstraintSecurityHandler buildSecurityHandler() {
+ if ( passwordFile == null )
+ return null;
+ UserStore userStore = JettyLib.makeUserStore(passwordFile);
+ return JettyLib.makeSecurityHandler(realm, userStore, authScheme);
+ }
+
// Only valid during the build() process.
- private boolean hasAuthenication = false;
- private boolean hasAllowedUsers = false;
+ private boolean hasAuthenticationHandler = false;
+ private boolean hasAuthenticationUse = false;
private boolean hasDataAccessControl = false;
private List<DatasetGraph> datasets = null;
-
+
private void buildStart() {
// -- Server, dataset authentication
- hasAuthenication = (passwordFile != null) || (securityHandler != null) ;
+ hasAuthenticationHandler = (passwordFile != null) || (securityHandler != null) ;
+
+ if ( realm == null )
+ realm = Auth.dftRealm;
// See if there are any DatasetGraphAccessControl.
hasDataAccessControl =
@@ -669,32 +673,38 @@ public class FusekiServer {
.map(name-> dataAccessPoints.get(name).getDataService().getDataset())
.anyMatch(DataAccessCtl::isAccessControlled);
- hasAllowedUsers = ( serverAuth != null );
- if ( ! hasAllowedUsers ) {
+ // Server level.
+ hasAuthenticationUse = ( serverAuth != null );
+ // Dataset level.
+ if ( ! hasAuthenticationUse ) {
// Any datasets with allowedUsers?
- hasAllowedUsers =
- dataAccessPoints.keys().stream()
+ hasAuthenticationUse = dataAccessPoints.keys().stream()
.map(name-> dataAccessPoints.get(name).getDataService())
.anyMatch(dSvc->dSvc.authPolicy() != null);
}
+ // Endpoint level.
+ if ( ! hasAuthenticationUse ) {
+ hasAuthenticationUse = dataAccessPoints.keys().stream()
+ .map(name-> dataAccessPoints.get(name).getDataService())
+ .flatMap(dSrv->dSrv.getEndpoints().stream())
+ .anyMatch(ep->ep.getAuthPolicy()!=null);
+ }
// If only a password file given, and nothing else, set the server to allowedUsers="*" (must log in).
- if ( passwordFile != null && ! hasAllowedUsers ) {
- hasAllowedUsers = true;
- serverAuth = Auth.ANY_USER;
- }
+ if ( passwordFile != null && ! hasAuthenticationUse )
+ hasAuthenticationUse = true;
}
private void buildFinish() {
- hasAuthenication = false;
+ hasAuthenticationHandler = false;
hasDataAccessControl = false;
datasets = null;
}
/** Do some checking to make sure setup is consistent. */
private void validate() {
- if ( ! hasAuthenication ) {
- if ( hasAllowedUsers ) {
+ if ( ! hasAuthenticationHandler ) {
+ if ( hasAuthenticationUse ) {
Fuseki.configLog.warn("'allowedUsers' is set but there is no authentication setup (e.g. password file)");
}
@@ -719,7 +729,7 @@ public class FusekiServer {
DataAccessPointRegistry.set(cxt, dapRegistry);
JettyLib.setMimeTypes(handler);
servletsAndFilters(handler);
- buildAccessControl(cxt);
+ buildAccessControl(handler);
if ( hasDataAccessControl ) {
// Consider making this "always" and changing the standard operation bindings.
@@ -731,28 +741,34 @@ public class FusekiServer {
return handler;
}
- private ConstraintSecurityHandler buildSecurityHandler() {
- if ( passwordFile == null )
- return null;
- UserStore userStore = JettyLib.makeUserStore(passwordFile);
- return JettyLib.makeSecurityHandler(realm, userStore, authScheme);
- }
-
- private void buildAccessControl(ServletContext cxt) {
+ private void buildAccessControl(ServletContextHandler cxt) {
// -- Access control
- if ( securityHandler != null && securityHandler instanceof ConstraintSecurityHandler ) {
- ConstraintSecurityHandler csh = (ConstraintSecurityHandler)securityHandler;
- if ( serverAuth != null )
- JettyLib.addPathConstraint(csh, "/*");
- else {
- DataAccessPointRegistry.get(cxt).forEach((name, dap)-> {
- DatasetGraph dsg = dap.getDataService().getDataset();
- if ( dap.getDataService().authPolicy() != null ) {
- // Not need if whole server ACL'ed.
- JettyLib.addPathConstraint(csh, DataAccessPoint.canonical(name));
- JettyLib.addPathConstraint(csh, DataAccessPoint.canonical(name)+"/*");
- }
- });
+ if ( securityHandler != null ) {
+ cxt.setSecurityHandler(securityHandler);
+ if ( securityHandler instanceof ConstraintSecurityHandler ) {
+ ConstraintSecurityHandler csh = (ConstraintSecurityHandler)securityHandler;
+ if ( serverAuth != null )
+ JettyLib.addPathConstraint(csh, "/*");
+ else {
+ // Find datatsets than need filters.
+ DataAccessPointRegistry.get(cxt.getServletContext()).forEach((name, dap)-> {
+ DatasetGraph dsg = dap.getDataService().getDataset();
+ if ( dap.getDataService().authPolicy() != null ) {
+ JettyLib.addPathConstraint(csh, DataAccessPoint.canonical(name));
+ JettyLib.addPathConstraint(csh, DataAccessPoint.canonical(name)+"/*");
+ }
+ else {
+ // Endpoint level.
+ dap.getDataService().getEndpoints().forEach(ep->{
+ if ( ep.getAuthPolicy()!=null ) {
+ JettyLib.addPathConstraint(csh, DataAccessPoint.canonical(name)+"/"+ep.getName());
+ if ( Fuseki.GSP_DIRECT_NAMING )
+ JettyLib.addPathConstraint(csh, DataAccessPoint.canonical(name)+"/"+ep.getName()+"/*");
+ }
+ });
+ }
+ });
+ }
}
}
}
@@ -787,7 +803,7 @@ public class FusekiServer {
addFilter(context, "/*", authFilter);
//JettyLib.addPathConstraint(null, contextPath);
}
- // Second in chain.
+ // Second in chain?.
FusekiFilter ff = new FusekiFilter();
addFilter(context, "/*", ff);
http://git-wip-us.apache.org/repos/asf/jena/blob/070fae10/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/access/AbstractTestFusekiSecurityAssembler.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/access/AbstractTestFusekiSecurityAssembler.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/access/AbstractTestFusekiSecurityAssembler.java
index 7369c4f..2304a6e 100644
--- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/access/AbstractTestFusekiSecurityAssembler.java
+++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/access/AbstractTestFusekiSecurityAssembler.java
@@ -53,7 +53,7 @@ import org.junit.Before;
import org.junit.Test;
/**
- * Test on the assembler for data access control.
+ * Tests on the assembler for data access control.
* <ul>
* <li>assem-security.ttl - two services "/database" and "/plain" each with their own dataset.
* <li>assem-security-shared.ttl - two services "/database" and "/plain" with a shared dataset.
http://git-wip-us.apache.org/repos/asf/jena/blob/070fae10/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/access/TS_SecurityFuseki.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/access/TS_SecurityFuseki.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/access/TS_SecurityFuseki.java
index e344d60..efc29a1 100644
--- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/access/TS_SecurityFuseki.java
+++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/access/TS_SecurityFuseki.java
@@ -31,8 +31,8 @@ import org.junit.runners.Suite;
, TestFusekiSecurityAssemblerSeparate.class
, TestFusekiSecurityAssemblerShared.class
- , TestPasswordServer.class
- , TestPasswordServices.class
+ , TestSecurityConfig.class
+ , TestSecurityBuilderSetup.class
})
public class TS_SecurityFuseki {
http://git-wip-us.apache.org/repos/asf/jena/blob/070fae10/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/access/TestPasswordServer.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/access/TestPasswordServer.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/access/TestPasswordServer.java
deleted file mode 100644
index d24c701..0000000
--- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/access/TestPasswordServer.java
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * 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.fuseki.main.access;
-
-import static org.junit.Assert.assertNull;
-
-import org.apache.http.client.HttpClient;
-import org.apache.jena.atlas.web.HttpException;
-import org.apache.jena.atlas.web.TypedInputStream;
-import org.apache.jena.atlas.web.WebLib;
-import org.apache.jena.fuseki.jetty.JettyLib;
-import org.apache.jena.fuseki.main.FusekiServer;
-import org.apache.jena.rdfconnection.LibSec;
-import org.apache.jena.rdfconnection.RDFConnection;
-import org.apache.jena.rdfconnection.RDFConnectionRemote;
-import org.apache.jena.riot.web.HttpOp;
-import org.apache.jena.sparql.engine.http.QueryExceptionHTTP;
-import org.apache.jena.web.AuthSetup;
-import org.apache.jena.web.HttpSC;
-import org.eclipse.jetty.security.ConstraintSecurityHandler;
-import org.eclipse.jetty.security.UserStore;
-import org.junit.After;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-/** Tests for
- * <ul>
- * <li>password access at the server-level
- * <li>assembler file
- * </ul>
- */
-public class TestPasswordServer {
-
- // Per test.
- private FusekiServer fusekiServer = null;
-
- private static String REALM = "TripleStore";
- private AuthSetup authSetup1(FusekiServer server) { return new AuthSetup("localhost", server.getPort(), "user1", "pw1", REALM); }
- private AuthSetup authSetup2(FusekiServer server) { return new AuthSetup("localhost", server.getPort(), "user2", "pw2", REALM); }
- private AuthSetup authSetup3(FusekiServer server) { return new AuthSetup("localhost", server.getPort(), "user3", "pw3", REALM); }
- // Not in the user store.
- private AuthSetup authSetupX(FusekiServer server) { return new AuthSetup("localhost", server.getPort(), "userX", "pwX", REALM); }
-
- private static String serverURL(FusekiServer server) {
- return "http://localhost:"+server.getPort()+"/";
- }
-
- private FusekiServer fusekiServer(String configFile) {
- int port = WebLib.choosePort();
- // Read from assembler+passwd file.
- UserStore userStore = JettyLib.makeUserStore("testing/Access/passwd");
- ConstraintSecurityHandler sh = JettyLib.makeSecurityHandler(REALM, userStore);
-
- fusekiServer =
- FusekiServer.create()
- .port(port)
- .parseConfigFile(configFile)
- .securityHandler(sh)
- //.staticFileBase(".")
- .build();
- fusekiServer.start();
- return fusekiServer;
- }
-
- @BeforeClass
- public static void beforeClass() {
- // Reset before every test and after the suite.
- HttpClient hc = HttpOp.createDefaultHttpClient();
- HttpOp.setDefaultHttpClient(hc);
- }
-
- @After
- public void after() {
- if ( fusekiServer != null )
- fusekiServer.stop();
- HttpClient hc = HttpOp.createDefaultHttpClient();
- HttpOp.setDefaultHttpClient(hc);
- }
-
- private static void expectQuery403(Runnable action) {
- try{
- action.run();
- throw new HttpException("action completed");
- } catch (QueryExceptionHTTP ex) {
- // 404 is OK - no static file area.
- if ( ex.getResponseCode() != HttpSC.FORBIDDEN_403 )
- throw ex;
- }
- }
-
- // Server authentication.
-
- @Test public void access_serverAny_user1() {
- FusekiServer fusekiServer = fusekiServer("testing/Access/config-server-1.ttl");
- try {
- // Must be logged in.
- HttpClient hc = LibSec.httpClient(authSetup1(fusekiServer));
- try( TypedInputStream in = HttpOp.execHttpGet(serverURL(fusekiServer), null, hc, null) ) {
- assertNull(in);
- } catch (HttpException ex) {
- // 404 is OK - no static file area.
- if ( ex.getResponseCode() != HttpSC.NOT_FOUND_404 )
- throw ex;
- }
- } finally {
- fusekiServer.stop();
- fusekiServer = null;
- }
- }
-
- @Test public void access_serverAny_db1() {
- FusekiServer fusekiServer = fusekiServer("testing/Access/config-server-1.ttl");
- try {
- // Must be logged in.
- HttpClient hc = LibSec.httpClient(authSetup1(fusekiServer));
- try ( RDFConnection conn = RDFConnectionRemote
- .create().destination(serverURL(fusekiServer)+"/database1").httpClient(hc).build() ) {
- conn.queryAsk("ASK{}");
- }
- } finally {
- fusekiServer.stop();
- fusekiServer = null;
- }
- }
-
- @Test public void access_serverAny_db2() {
- FusekiServer fusekiServer = fusekiServer("testing/Access/config-server-1.ttl");
- try {
- // Must be logged in.
- HttpClient hc = LibSec.httpClient(authSetup1(fusekiServer));
- try ( RDFConnection conn = RDFConnectionRemote
- .create().destination(serverURL(fusekiServer)+"/database2").httpClient(hc).build() ) {
- conn.queryAsk("ASK{}");
- }
- } finally {
- fusekiServer.stop();
- fusekiServer = null;
- }
- }
-
- @Test public void access_serverAny_db1_wrongUser() {
- FusekiServer fusekiServer = fusekiServer("testing/Access/config-server-1.ttl");
- try {
- // Must be logged in.
- HttpClient hc = LibSec.httpClient(authSetup2(fusekiServer)); // 2
- try ( RDFConnection conn = RDFConnectionRemote
- .create().destination(serverURL(fusekiServer)+"/database1").httpClient(hc).build() ) {
- expectQuery403(()->conn.queryAsk("ASK{}"));
- }
- } finally {
- fusekiServer.stop();
- fusekiServer = null;
- }
- }
-
- // Specific server user.
- @Test public void access_serverUser_user1() {
- FusekiServer fusekiServer = fusekiServer("testing/Access/config-server-2.ttl");
- try {
- // Must be logged in as user1
- HttpClient hc = LibSec.httpClient(authSetup1(fusekiServer));
- try ( RDFConnection conn = RDFConnectionRemote
- .create().destination(serverURL(fusekiServer)+"/database1").httpClient(hc).build() ) {
- conn.queryAsk("ASK{}");
- }
- } finally {
- fusekiServer.stop();
- fusekiServer = null;
- }
- }
-
- // Specific server user.
- @Test public void access_serverUser_user2() {
- FusekiServer fusekiServer = fusekiServer("testing/Access/config-server-2.ttl");
- try {
- // user2 does not have service access
- HttpClient hc = LibSec.httpClient(authSetup2(fusekiServer));
- try ( RDFConnection conn = RDFConnectionRemote
- .create().destination(serverURL(fusekiServer)+"/database1").httpClient(hc).build() ) {
- expectQuery403(()->conn.queryAsk("ASK{}"));
- }
- } finally {
- fusekiServer.stop();
- fusekiServer = null;
- }
- }
-
- // Specific server user.
- @Test public void access_serverUser_user3() {
- FusekiServer fusekiServer = fusekiServer("testing/Access/config-server-2.ttl");
- try {
- // user3 does not have server access
- HttpClient hc = LibSec.httpClient(authSetup3(fusekiServer));
- try ( RDFConnection conn = RDFConnectionRemote
- .create().destination(serverURL(fusekiServer)+"/database1").httpClient(hc).build() ) {
- expectQuery403(()->conn.queryAsk("ASK{}"));
- }
- } finally {
- fusekiServer.stop();
- fusekiServer = null;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/jena/blob/070fae10/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/access/TestPasswordServices.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/access/TestPasswordServices.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/access/TestPasswordServices.java
deleted file mode 100644
index dc0ff32..0000000
--- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/access/TestPasswordServices.java
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * 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.fuseki.main.access;
-
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.fail;
-
-import org.apache.http.client.HttpClient;
-import org.apache.jena.atlas.logging.LogCtl;
-import org.apache.jena.atlas.web.HttpException;
-import org.apache.jena.atlas.web.TypedInputStream;
-import org.apache.jena.atlas.web.WebLib;
-import org.apache.jena.fuseki.auth.Auth;
-import org.apache.jena.fuseki.auth.AuthPolicy;
-import org.apache.jena.fuseki.build.FusekiBuilder;
-import org.apache.jena.fuseki.jetty.JettyLib;
-import org.apache.jena.fuseki.main.FusekiServer;
-import org.apache.jena.fuseki.server.DataService;
-import org.apache.jena.query.DatasetFactory;
-import org.apache.jena.rdfconnection.LibSec;
-import org.apache.jena.riot.web.HttpCaptureResponse;
-import org.apache.jena.riot.web.HttpOp;
-import org.apache.jena.riot.web.HttpOp.CaptureInput;
-import org.apache.jena.sparql.core.DatasetGraphFactory;
-import org.apache.jena.web.AuthSetup;
-import org.apache.jena.web.HttpSC;
-import org.eclipse.jetty.security.ConstraintSecurityHandler;
-import org.eclipse.jetty.security.UserStore;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-/**
- * Tests for password access to services when there is no server-level access control
- * and also programmatic setup.
- * <p>
- * See {@link TestPasswordServer} for tests with server-level access control
- * and also access control by assembler
- * <p>
- * See {@link TestSecurityFilterFuseki} for graph-level access control.
- *
- */
-public class TestPasswordServices {
-
- private static FusekiServer fusekiServer = null;
- private static int port = WebLib.choosePort();
- private static String serverURL = "http://localhost:"+port+"/";
- private static AuthSetup authSetup1 = new AuthSetup("localhost", port, "user1", "pw1", "TripleStore");
- private static AuthSetup authSetup2 = new AuthSetup("localhost", port, "user2", "pw2", "TripleStore");
- // Not in the user store.
- private static AuthSetup authSetupX = new AuthSetup("localhost", port, "userX", "pwX", "TripleStore");
-
- @BeforeClass
- public static void beforeClass() {
- if ( false )
- // To watch the HTTP headers
- LogCtl.enable("org.apache.http.headers");
-
- // Two authorized users.
- UserStore userStore = new UserStore();
- JettyLib.addUser(userStore, authSetup1.user, authSetup1.password);
- JettyLib.addUser(userStore, authSetup2.user, authSetup2.password);
- try { userStore.start(); }
- catch (Exception ex) { throw new RuntimeException("UserStore", ex); }
-
- ConstraintSecurityHandler sh = JettyLib.makeSecurityHandler(authSetup1.realm, userStore);
-
- // Secure these areas.
- // User needs to be logged in.
- JettyLib.addPathConstraint(sh, "/ds");
- // Allow auth control even through there isn't anything there
- JettyLib.addPathConstraint(sh, "/nowhere");
- // user1 only.
- JettyLib.addPathConstraint(sh, "/ctl");
-
- // Not controlled: "/open"
-
- DataService dSrv = new DataService(DatasetGraphFactory.createTxnMem());
- FusekiBuilder.populateStdServices(dSrv, false);
- AuthPolicy reqAuth = Auth.policyAllowSpecific("user1");
- dSrv.setAuthPolicy(reqAuth);
-
- fusekiServer =
- FusekiServer.create()
- .port(port)
- .add("/ds", DatasetFactory.createTxnMem())
- .add("/open", DatasetFactory.createTxnMem())
- .add("/ctl", dSrv)
- .securityHandler(sh)
- //.staticFileBase(".")
- .build();
- fusekiServer.start();
- }
-
- @Before
- public void before() {
- // Reset before every test and after the suite.
- HttpClient hc = HttpOp.createDefaultHttpClient();
- HttpOp.setDefaultHttpClient(hc);
- }
-
-
- @AfterClass
- public static void afterClass() {
- fusekiServer.stop();
- HttpClient hc = HttpOp.createDefaultHttpClient();
- HttpOp.setDefaultHttpClient(hc);
- }
-
- // Server authentication.
-
- @Test public void access_server() {
- try( TypedInputStream in = HttpOp.execHttpGet(serverURL) ) {
- assertNotNull(in);
- fail("Didn't expect to succeed");
- } catch (HttpException ex) {
- // 404 is OK - no static file area.
- if ( ex.getResponseCode() != HttpSC.NOT_FOUND_404 )
- throw ex;
- }
- }
-
- @Test public void access_open() {
- try( TypedInputStream in = HttpOp.execHttpGet(serverURL+"open") ) {
- assertNotNull(in);
- }
- }
-
- @Test public void access_open_user1() {
- // OK.
- LibSec.withAuth(serverURL+"open", authSetup1, (conn)->{
- conn.queryAsk("ASK{}");
- });
- }
-
- @Test public void access_open_userX() {
- // OK.
- LibSec.withAuth(serverURL+"open", authSetupX, (conn)->{
- conn.queryAsk("ASK{}");
- });
- }
-
-
- // Should fail.
- @Test public void access_deny_ds() {
- try( TypedInputStream in = HttpOp.execHttpGet(serverURL+"ds") ) {
- fail("Didn't expect to succeed");
- } catch (HttpException ex) {
- if ( ex.getResponseCode() != HttpSC.UNAUTHORIZED_401 )
- throw ex;
- }
- }
-
- // Should be 401, not be 404.
- @Test public void access_deny_nowhere() {
- try( TypedInputStream in = HttpOp.execHttpGet(serverURL+"nowhere") ) {
- fail("Didn't expect to succeed");
- } catch (HttpException ex) {
- if ( ex.getResponseCode() != HttpSC.UNAUTHORIZED_401 )
- throw ex;
- }
- }
-
- @Test public void access_allow_nowhere() {
- HttpClient hc = LibSec.httpClient(authSetup1);
- HttpCaptureResponse<TypedInputStream> handler = new CaptureInput();
- try( TypedInputStream in = HttpOp.execHttpGet(serverURL+"nowhere", null, hc, null) ) {
- // null for 404.
- assertNull(in);
- } catch (HttpException ex) {
- if ( ex.getResponseCode() != HttpSC.NOT_FOUND_404)
- throw ex;
- }
- }
-
- @Test public void access_allow_ds() {
- HttpClient hc = LibSec.httpClient(authSetup1);
- HttpCaptureResponse<TypedInputStream> handler = new CaptureInput();
- try( TypedInputStream in = HttpOp.execHttpGet(serverURL+"ds", null, hc, null) ) {
- assertNotNull(in);
- }
- }
-
- // Service level : ctl.
-
- @Test public void access_service_ctl_user1() {
- // user1 -- allowed.
- HttpClient hc = LibSec.httpClient(authSetup1);
- try( TypedInputStream in = HttpOp.execHttpGet(serverURL+"ctl", null, hc, null) ) {
- assertNotNull(in);
- }
- }
-
- @Test public void access_service_ctl_user2() {
- // user2 -- can login, not allowed.
- HttpClient hc = LibSec.httpClient(authSetup2);
- try( TypedInputStream in = HttpOp.execHttpGet(serverURL+"ctl", null, hc, null) ) {
- fail("Didn't expect to succeed");
- } catch (HttpException ex) {
- if ( ex.getResponseCode() != HttpSC.FORBIDDEN_403)
- throw ex;
- }
- }
-
- @Test public void access_service_ctl_userX() {
- // userX -- can't login, not allowed.
- HttpClient hc = LibSec.httpClient(authSetupX);
- try( TypedInputStream in = HttpOp.execHttpGet(serverURL+"ctl", null, hc, null) ) {
- fail("Didn't expect to succeed");
- } catch (HttpException ex) {
- if ( ex.getResponseCode() != HttpSC.UNAUTHORIZED_401)
- throw ex;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/jena/blob/070fae10/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/access/TestSecurityBuilderSetup.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/access/TestSecurityBuilderSetup.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/access/TestSecurityBuilderSetup.java
new file mode 100644
index 0000000..2938455
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/access/TestSecurityBuilderSetup.java
@@ -0,0 +1,229 @@
+/*
+ * 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.fuseki.main.access;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+import org.apache.http.client.HttpClient;
+import org.apache.jena.atlas.logging.LogCtl;
+import org.apache.jena.atlas.web.HttpException;
+import org.apache.jena.atlas.web.TypedInputStream;
+import org.apache.jena.atlas.web.WebLib;
+import org.apache.jena.fuseki.auth.Auth;
+import org.apache.jena.fuseki.auth.AuthPolicy;
+import org.apache.jena.fuseki.build.FusekiBuilder;
+import org.apache.jena.fuseki.jetty.JettyLib;
+import org.apache.jena.fuseki.main.FusekiServer;
+import org.apache.jena.fuseki.server.DataService;
+import org.apache.jena.query.DatasetFactory;
+import org.apache.jena.rdfconnection.LibSec;
+import org.apache.jena.riot.web.HttpCaptureResponse;
+import org.apache.jena.riot.web.HttpOp;
+import org.apache.jena.riot.web.HttpOp.CaptureInput;
+import org.apache.jena.sparql.core.DatasetGraphFactory;
+import org.apache.jena.web.AuthSetup;
+import org.apache.jena.web.HttpSC;
+import org.eclipse.jetty.security.ConstraintSecurityHandler;
+import org.eclipse.jetty.security.UserStore;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * Tests for access to services using programmatic setup.
+ * <p>
+ * See {@link TestSecurityConfig} for tests with server-level access control and also
+ * access control by assembler
+ * <p>
+ * See {@link TestSecurityFilterFuseki} for graph-level access control.
+ */
+public class TestSecurityBuilderSetup {
+
+ private static FusekiServer fusekiServer = null;
+ private static int port = WebLib.choosePort();
+ private static String serverURL = "http://localhost:"+port+"/";
+ private static AuthSetup authSetup1 = new AuthSetup("localhost", port, "user1", "pw1", "TripleStore");
+ private static AuthSetup authSetup2 = new AuthSetup("localhost", port, "user2", "pw2", "TripleStore");
+ // Not in the user store.
+ private static AuthSetup authSetupX = new AuthSetup("localhost", port, "userX", "pwX", "TripleStore");
+
+ @BeforeClass
+ public static void beforeClass() {
+ if ( false )
+ // To watch the HTTP headers
+ LogCtl.enable("org.apache.http.headers");
+
+ // Two authorized users.
+ UserStore userStore = new UserStore();
+ JettyLib.addUser(userStore, authSetup1.user, authSetup1.password);
+ JettyLib.addUser(userStore, authSetup2.user, authSetup2.password);
+ try { userStore.start(); }
+ catch (Exception ex) { throw new RuntimeException("UserStore", ex); }
+
+ ConstraintSecurityHandler sh = JettyLib.makeSecurityHandler(authSetup1.realm, userStore);
+
+ // Secure these areas.
+ // User needs to be logged in.
+ JettyLib.addPathConstraint(sh, "/ds");
+ // Allow auth control even through there isn't anything there
+ JettyLib.addPathConstraint(sh, "/nowhere");
+ // user1 only.
+ JettyLib.addPathConstraint(sh, "/ctl");
+
+ // Not controlled: "/open"
+
+ DataService dSrv = new DataService(DatasetGraphFactory.createTxnMem());
+ FusekiBuilder.populateStdServices(dSrv, false);
+ AuthPolicy reqAuth = Auth.policyAllowSpecific("user1");
+ dSrv.setAuthPolicy(reqAuth);
+
+ fusekiServer =
+ FusekiServer.create()
+ .port(port)
+ .add("/ds", DatasetFactory.createTxnMem())
+ .add("/open", DatasetFactory.createTxnMem())
+ .add("/ctl", dSrv)
+ .securityHandler(sh)
+ //.staticFileBase(".")
+ .build();
+ fusekiServer.start();
+ }
+
+ @Before
+ public void before() {
+ // Reset before every test and after the suite.
+ HttpClient hc = HttpOp.createDefaultHttpClient();
+ HttpOp.setDefaultHttpClient(hc);
+ }
+
+ @AfterClass
+ public static void afterClass() {
+ fusekiServer.stop();
+ HttpClient hc = HttpOp.createDefaultHttpClient();
+ HttpOp.setDefaultHttpClient(hc);
+ }
+
+ // Server authentication.
+
+ @Test public void access_server() {
+ try( TypedInputStream in = HttpOp.execHttpGet(serverURL) ) {
+ assertNotNull(in);
+ fail("Didn't expect to succeed");
+ } catch (HttpException ex) {
+ // 404 is OK - no static file area.
+ if ( ex.getResponseCode() != HttpSC.NOT_FOUND_404 )
+ throw ex;
+ }
+ }
+
+ @Test public void access_open() {
+ try( TypedInputStream in = HttpOp.execHttpGet(serverURL+"open") ) {
+ assertNotNull(in);
+ }
+ }
+
+ @Test public void access_open_user1() {
+ // OK.
+ LibSec.withAuth(serverURL+"open", authSetup1, (conn)->{
+ conn.queryAsk("ASK{}");
+ });
+ }
+
+ @Test public void access_open_userX() {
+ // OK.
+ LibSec.withAuth(serverURL+"open", authSetupX, (conn)->{
+ conn.queryAsk("ASK{}");
+ });
+ }
+
+
+ // Should fail.
+ @Test public void access_deny_ds() {
+ try( TypedInputStream in = HttpOp.execHttpGet(serverURL+"ds") ) {
+ fail("Didn't expect to succeed");
+ } catch (HttpException ex) {
+ if ( ex.getResponseCode() != HttpSC.UNAUTHORIZED_401 )
+ throw ex;
+ }
+ }
+
+ // Should be 401, not be 404.
+ @Test public void access_deny_nowhere() {
+ try( TypedInputStream in = HttpOp.execHttpGet(serverURL+"nowhere") ) {
+ fail("Didn't expect to succeed");
+ } catch (HttpException ex) {
+ if ( ex.getResponseCode() != HttpSC.UNAUTHORIZED_401 )
+ throw ex;
+ }
+ }
+
+ @Test public void access_allow_nowhere() {
+ HttpClient hc = LibSec.httpClient(authSetup1);
+ HttpCaptureResponse<TypedInputStream> handler = new CaptureInput();
+ try( TypedInputStream in = HttpOp.execHttpGet(serverURL+"nowhere", null, hc, null) ) {
+ // null for 404.
+ assertNull(in);
+ } catch (HttpException ex) {
+ if ( ex.getResponseCode() != HttpSC.NOT_FOUND_404)
+ throw ex;
+ }
+ }
+
+ @Test public void access_allow_ds() {
+ HttpClient hc = LibSec.httpClient(authSetup1);
+ HttpCaptureResponse<TypedInputStream> handler = new CaptureInput();
+ try( TypedInputStream in = HttpOp.execHttpGet(serverURL+"ds", null, hc, null) ) {
+ assertNotNull(in);
+ }
+ }
+
+ // Service level : ctl.
+ @Test public void access_service_ctl_user1() {
+ // user1 -- allowed.
+ HttpClient hc = LibSec.httpClient(authSetup1);
+ try( TypedInputStream in = HttpOp.execHttpGet(serverURL+"ctl", null, hc, null) ) {
+ assertNotNull(in);
+ }
+ }
+
+ @Test public void access_service_ctl_user2() {
+ // user2 -- can login, not allowed.
+ HttpClient hc = LibSec.httpClient(authSetup2);
+ try( TypedInputStream in = HttpOp.execHttpGet(serverURL+"ctl", null, hc, null) ) {
+ fail("Didn't expect to succeed");
+ } catch (HttpException ex) {
+ if ( ex.getResponseCode() != HttpSC.FORBIDDEN_403)
+ throw ex;
+ }
+ }
+
+ @Test public void access_service_ctl_userX() {
+ // userX -- can't login, not allowed.
+ HttpClient hc = LibSec.httpClient(authSetupX);
+ try( TypedInputStream in = HttpOp.execHttpGet(serverURL+"ctl", null, hc, null) ) {
+ fail("Didn't expect to succeed");
+ } catch (HttpException ex) {
+ if ( ex.getResponseCode() != HttpSC.UNAUTHORIZED_401)
+ throw ex;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/070fae10/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/access/TestSecurityConfig.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/access/TestSecurityConfig.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/access/TestSecurityConfig.java
new file mode 100644
index 0000000..370c188
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/access/TestSecurityConfig.java
@@ -0,0 +1,411 @@
+/*
+ * 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.fuseki.main.access;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.util.function.Consumer;
+
+import org.apache.http.client.HttpClient;
+import org.apache.jena.atlas.web.HttpException;
+import org.apache.jena.atlas.web.TypedInputStream;
+import org.apache.jena.atlas.web.WebLib;
+import org.apache.jena.fuseki.main.FusekiServer;
+import org.apache.jena.rdfconnection.LibSec;
+import org.apache.jena.rdfconnection.RDFConnection;
+import org.apache.jena.rdfconnection.RDFConnectionRemote;
+import org.apache.jena.riot.web.HttpOp;
+import org.apache.jena.sparql.engine.http.QueryExceptionHTTP;
+import org.apache.jena.web.AuthSetup;
+import org.apache.jena.web.HttpSC;
+import org.junit.After;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * Tests for security of the server, services and endpoints using configuration file setup.
+ */
+public class TestSecurityConfig {
+
+ private static String REALM = "TripleStore";
+ private AuthSetup authSetup1(FusekiServer server) { return new AuthSetup("localhost", server.getPort(), "user1", "pw1", REALM); }
+ private AuthSetup authSetup2(FusekiServer server) { return new AuthSetup("localhost", server.getPort(), "user2", "pw2", REALM); }
+ private AuthSetup authSetup3(FusekiServer server) { return new AuthSetup("localhost", server.getPort(), "user3", "pw3", REALM); }
+ // Not in the user store.
+ private AuthSetup authSetupX(FusekiServer server) { return new AuthSetup("localhost", server.getPort(), "userX", "pwX", REALM); }
+
+ private static String serverURL(FusekiServer server) {
+ return "http://localhost:"+server.getPort()+"/";
+ }
+
+ private static String datasetURL(FusekiServer server, String dsName) {
+ if ( dsName.startsWith("/") )
+ dsName = dsName.substring(1);
+ return "http://localhost:"+server.getPort()+"/"+dsName;
+ }
+
+ private static FusekiServer fusekiServer(String configFile) {
+ int port = WebLib.choosePort();
+ FusekiServer fusekiServer =
+ FusekiServer.create()
+ .port(port)
+ .parseConfigFile(configFile)
+ .passwordFile("testing/Access/passwd")
+ .build();
+ fusekiServer.start();
+ return fusekiServer;
+ }
+
+ @BeforeClass
+ public static void beforeClass() {
+ // Reset before every test and after the suite.
+ HttpClient hc = HttpOp.createDefaultHttpClient();
+ HttpOp.setDefaultHttpClient(hc);
+ }
+
+ @After
+ public void after() {
+ HttpClient hc = HttpOp.createDefaultHttpClient();
+ HttpOp.setDefaultHttpClient(hc);
+ }
+
+ private static void expectQuery403(Runnable action) {
+ expectQuery(action, HttpSC.FORBIDDEN_403);
+ }
+
+ private static void expectQuery401(Runnable action) {
+ expectQuery(action, HttpSC.UNAUTHORIZED_401);
+ }
+
+ private static void expectQuery(Runnable action, int expected) {
+ try {
+ action.run();
+ throw new HttpException("action completed");
+ } catch (QueryExceptionHTTP ex) {
+ if ( ex.getResponseCode() != expected )
+ throw ex;
+ }
+ }
+
+ private static void test(String configFile, Consumer<FusekiServer> action) {
+ FusekiServer fusekiServer = fusekiServer(configFile);
+ try {
+ action.accept(fusekiServer);
+ } finally {
+ fusekiServer.stop();
+ fusekiServer = null;
+ }
+ }
+
+ // config-server-0.ttl : service level ACL
+ @Test public void access_serverNone() {
+ test("testing/Access/config-server-0.ttl", fusekiServer -> {
+ // Server access.
+ try (TypedInputStream in = HttpOp.execHttpGet(serverURL(fusekiServer))) {
+ assertNotNull(in);
+ } catch (HttpException ex) {
+ // 404 is OK - no static file area.
+ if ( ex.getResponseCode() != HttpSC.NOT_FOUND_404 )
+ throw ex;
+ }
+ });
+ }
+
+ @Test public void access_serverNone_db1() {
+ test("testing/Access/config-server-0.ttl", (fusekiServer)->{
+ // db1 - secured - try no user
+ try ( RDFConnection conn = RDFConnectionRemote.create().destination(datasetURL(fusekiServer, "database1"))
+ .build() ) {
+ expectQuery401(()->conn.queryAsk("ASK{}"));
+ }
+ // db1 - secured - try wrong user
+ HttpClient hcUser2 = LibSec.httpClient(authSetup2(fusekiServer));
+ try ( RDFConnection conn = RDFConnectionRemote.create().destination(datasetURL(fusekiServer, "database1"))
+ .httpClient(hcUser2)
+ .build() ) {
+ expectQuery403(()->conn.queryAsk("ASK{}"));
+ }
+
+ // db1 - secured - with user
+ HttpClient hcUser1 = LibSec.httpClient(authSetup1(fusekiServer));
+ try ( RDFConnection conn = RDFConnectionRemote.create().destination(datasetURL(fusekiServer, "database1"))
+ .httpClient(hcUser1)
+ .build() ) {
+ conn.queryAsk("ASK{}");
+ }
+ });
+ }
+
+ @Test public void access_serverNone_db2() {
+ test("testing/Access/config-server-0.ttl", (fusekiServer)->{
+ try ( RDFConnection conn = RDFConnectionRemote.create()
+ .destination(datasetURL(fusekiServer, "database2"))
+ // No HttpClient.
+ .build() ) {
+ conn.queryAsk("ASK{}");
+ }
+ });
+ }
+
+ // config-server-1.ttl : server=*; service level ACL
+ @Test public void access_serverAny_user1() {
+ test("testing/Access/config-server-1.ttl", fusekiServer->{
+ // Must be logged in.
+ HttpClient hc = LibSec.httpClient(authSetup1(fusekiServer));
+ try( TypedInputStream in = HttpOp.execHttpGet(serverURL(fusekiServer), null, hc, null) ) {
+ assertNull(in);
+ } catch (HttpException ex) {
+ // 404 is OK - no static file area.
+ if ( ex.getResponseCode() != HttpSC.NOT_FOUND_404 )
+ throw ex;
+ }
+ });
+ }
+
+ @Test public void access_dataset_db1() {
+ test("testing/Access/config-server-1.ttl", fusekiServer->{
+ // Must be logged in.
+ HttpClient hc = LibSec.httpClient(authSetup1(fusekiServer));
+ try ( RDFConnection conn = RDFConnectionRemote
+ .create().destination(datasetURL(fusekiServer, "database1")).httpClient(hc).build() ) {
+ conn.queryAsk("ASK{}");
+ }
+ });
+ }
+
+ @Test public void access_dataset_db2() {
+ test("testing/Access/config-server-1.ttl", fusekiServer->{
+ // Must be logged in.
+ HttpClient hc = LibSec.httpClient(authSetup1(fusekiServer));
+ try ( RDFConnection conn = RDFConnectionRemote
+ .create().destination(datasetURL(fusekiServer, "database2")).httpClient(hc).build() ) {
+ conn.queryAsk("ASK{}");
+ }
+ });
+ }
+
+ @Test public void access_dataset_db1_wrongUser() {
+ test("testing/Access/config-server-1.ttl", fusekiServer->{
+ // Must be logged in.
+ HttpClient hc = LibSec.httpClient(authSetup2(fusekiServer));
+ try ( RDFConnection conn = RDFConnectionRemote
+ .create().destination(datasetURL(fusekiServer, "database1")).httpClient(hc).build() ) {
+ expectQuery403(()->conn.queryAsk("ASK{}"));
+ }
+ });
+ }
+
+ // config-server-2.ttl : server=user1,user2; service level ACL
+ @Test public void access_dataset_user1() {
+ test("testing/Access/config-server-2.ttl", fusekiServer->{
+ // Must be logged in as user1
+ HttpClient hc = LibSec.httpClient(authSetup1(fusekiServer));
+ try ( RDFConnection conn = RDFConnectionRemote
+ .create().destination(datasetURL(fusekiServer, "database1")).httpClient(hc).build() ) {
+ conn.queryAsk("ASK{}");
+ }
+ });
+ }
+
+ // Specific server user.
+ @Test public void access_dataset_user2() {
+ test("testing/Access/config-server-2.ttl", fusekiServer->{
+ // user2 does not have service access
+ HttpClient hc = LibSec.httpClient(authSetup2(fusekiServer));
+ try ( RDFConnection conn = RDFConnectionRemote
+ .create().destination(datasetURL(fusekiServer, "database1")).httpClient(hc).build() ) {
+ expectQuery403(()->conn.queryAsk("ASK{}"));
+ }
+ });
+ }
+
+ // Specific server user.
+ @Test public void access_dataset_user3() {
+ test("testing/Access/config-server-2.ttl", fusekiServer->{
+ // user3 does not have server access
+ HttpClient hc = LibSec.httpClient(authSetup3(fusekiServer));
+ try ( RDFConnection conn = RDFConnectionRemote
+ .create().destination(datasetURL(fusekiServer, "database1")).httpClient(hc).build() ) {
+ expectQuery403(()->conn.queryAsk("ASK{}"));
+ }
+ });
+ }
+
+ // config-server-3.ttl : service and endpoint
+ @Test public void serviceAndEndpoint_anon() {
+ test("testing/Access/config-server-3.ttl", fusekiServer->{
+ try ( RDFConnection conn = RDFConnectionRemote
+ .create().destination(datasetURL(fusekiServer, "db")).build() ) {
+ expectQuery401(()->conn.queryAsk("ASK{}"));
+ }
+ });
+ }
+
+ @Test public void serviceAndEndpoint_unknownUser() {
+ test("testing/Access/config-server-3.ttl", fusekiServer->{
+ HttpClient hc = LibSec.httpClient(authSetupX(fusekiServer));
+ try ( RDFConnection conn = RDFConnectionRemote
+ .create().destination(datasetURL(fusekiServer, "db")).httpClient(hc).build() ) {
+ // Fails authentication.
+ expectQuery401(()->conn.queryAsk("ASK{}"));
+ }
+ });
+ }
+
+ // Deny - not in every endpoint
+ @Test public void serviceAndEndpoint_user1() {
+ test("testing/Access/config-server-3.ttl", fusekiServer->{
+ HttpClient hc1 = LibSec.httpClient(authSetup1(fusekiServer));
+ try ( RDFConnection conn = RDFConnectionRemote
+ .create().destination(datasetURL(fusekiServer, "db"))
+ .httpClient(hc1).build() ) {
+ expectQuery403(()->conn.queryAsk("ASK{}"));
+ }
+ });
+ }
+
+ // Go to endpoint.
+ @Test public void serviceAndEndpointDirect_user1() {
+ test("testing/Access/config-server-3.ttl", fusekiServer->{
+ HttpClient hc1 = LibSec.httpClient(authSetup1(fusekiServer));
+
+ try ( RDFConnection conn = RDFConnectionRemote
+ .create().destination(datasetURL(fusekiServer, "db"))
+ .queryEndpoint(datasetURL(fusekiServer, "db")+"/query1")
+ .httpClient(hc1).build() ) {
+ conn.queryAsk("ASK{}");
+ }
+ });
+ }
+
+ @Test public void serviceAndEndpoint_user2() {
+ test("testing/Access/config-server-3.ttl", fusekiServer->{
+ HttpClient hc2 = LibSec.httpClient(authSetup2(fusekiServer));
+ // -- Dataset query. User2 is not in dataset.
+ try ( RDFConnection conn = RDFConnectionRemote
+ .create().destination(datasetURL(fusekiServer, "db")).httpClient(hc2).build() ) {
+ expectQuery403(()->conn.queryAsk("ASK{}"));
+ }
+ });
+ }
+
+ // Still "no" - dataset excludes.
+ @Test public void serviceAndEndpointDirect_user2() {
+ test("testing/Access/config-server-3.ttl", fusekiServer->{
+ HttpClient hc2 = LibSec.httpClient(authSetup2(fusekiServer));
+ // -- Dataset query. User2 is not in dataset.
+ try ( RDFConnection conn = RDFConnectionRemote
+ .create().destination(datasetURL(fusekiServer, "db"))
+ .queryEndpoint(datasetURL(fusekiServer, "db")+"/query2")
+ .httpClient(hc2).build() ) {
+ expectQuery403(()->conn.queryAsk("ASK{}"));
+ }
+ });
+ }
+
+ @Test public void serviceAndEndpoint_user3() {
+ // Not user3 - it is not in every endpoint.
+ test("testing/Access/config-server-3.ttl", fusekiServer->{
+ HttpClient hc3 = LibSec.httpClient(authSetup3(fusekiServer));
+ try ( RDFConnection conn = RDFConnectionRemote
+ .create().destination(datasetURL(fusekiServer, "db")).httpClient(hc3).build() ) {
+ expectQuery403(()->conn.queryAsk("ASK{}"));
+ }
+ });
+ }
+
+ // config-server-4.ttl : endpoint only.
+ // Deny - not in every endpoint
+ @Test public void endpoint_user1() {
+ test("testing/Access/config-server-4.ttl", fusekiServer->{
+ HttpClient hc1 = LibSec.httpClient(authSetup1(fusekiServer));
+ try ( RDFConnection conn = RDFConnectionRemote
+ .create().destination(datasetURL(fusekiServer, "db2"))
+ .httpClient(hc1).build() ) {
+ expectQuery403(()->conn.queryAsk("ASK{}"));
+ }
+ });
+ }
+
+
+ // Go to endpoint.
+ @Test public void endpointDirect_user1() {
+ test("testing/Access/config-server-4.ttl", fusekiServer->{
+ HttpClient hc1 = LibSec.httpClient(authSetup1(fusekiServer));
+
+ try ( RDFConnection conn = RDFConnectionRemote
+ .create().destination(datasetURL(fusekiServer, "db2"))
+ .queryEndpoint(datasetURL(fusekiServer, "db2")+"/query1")
+ .httpClient(hc1).build() ) {
+ conn.queryAsk("ASK{}");
+ }
+ });
+ }
+
+ @Test public void endpoint_user2() {
+ test("testing/Access/config-server-4.ttl", fusekiServer->{
+ HttpClient hc2 = LibSec.httpClient(authSetup2(fusekiServer));
+ // -- Dataset query. User2 is not in dataset.
+ try ( RDFConnection conn = RDFConnectionRemote
+ .create().destination(datasetURL(fusekiServer, "db2")).httpClient(hc2).build() ) {
+ expectQuery403(()->conn.queryAsk("ASK{}"));
+ }
+ });
+ }
+
+ // Yes by endpoint only.
+ @Test public void endpointDirect_user2() {
+ test("testing/Access/config-server-4.ttl", fusekiServer->{
+ HttpClient hc2 = LibSec.httpClient(authSetup2(fusekiServer));
+ // -- Dataset query. User2 is onthis specific endpoint.
+ try ( RDFConnection conn = RDFConnectionRemote
+ .create().destination(datasetURL(fusekiServer, "db2"))
+ .queryEndpoint(datasetURL(fusekiServer, "db2")+"/query2")
+ .httpClient(hc2).build() ) {
+ conn.queryAsk("ASK{}");
+ }
+ });
+ }
+
+ // No - not at this endpoint.
+ @Test public void endpointDirect_user2a() {
+ test("testing/Access/config-server-4.ttl", fusekiServer->{
+ HttpClient hc2 = LibSec.httpClient(authSetup2(fusekiServer));
+ // -- Dataset query. User2 is onthis specific endpoint.
+ try ( RDFConnection conn = RDFConnectionRemote
+ .create().destination(datasetURL(fusekiServer, "db2"))
+ .queryEndpoint(datasetURL(fusekiServer, "db2")+"/query3")
+ .httpClient(hc2).build() ) {
+ expectQuery403(()->conn.queryAsk("ASK{}"));
+ }
+ });
+ }
+
+ @Test public void endpoint_user3() {
+ // Not user3 - it is not in every endpoint.
+ test("testing/Access/config-server-4.ttl", fusekiServer->{
+ HttpClient hc3 = LibSec.httpClient(authSetup3(fusekiServer));
+ try ( RDFConnection conn = RDFConnectionRemote
+ .create().destination(datasetURL(fusekiServer, "db2")).httpClient(hc3).build() ) {
+ expectQuery403(()->conn.queryAsk("ASK{}"));
+ }
+ });
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/070fae10/jena-fuseki2/jena-fuseki-main/testing/Access/allowedUsers.ttl
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-main/testing/Access/allowedUsers.ttl b/jena-fuseki2/jena-fuseki-main/testing/Access/allowedUsers.ttl
index b45fecc..679d43b 100644
--- a/jena-fuseki2/jena-fuseki-main/testing/Access/allowedUsers.ttl
+++ b/jena-fuseki2/jena-fuseki-main/testing/Access/allowedUsers.ttl
@@ -1,12 +1,11 @@
# Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
+# Data for testing parsing "fuseki:allowedUsers" : TestAuthorized
+
PREFIX : <http://example/>
PREFIX fuseki: <http://jena.apache.org/fuseki#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-PREFIX tdb2: <http://jena.apache.org/2016/tdb#>
-PREFIX ja: <http://jena.hpl.hp.com/2005/11/Assembler#>
-PREFIX access: <http://jena.apache.org/access#>
:none :p 123 .
@@ -14,4 +13,3 @@ PREFIX access: <http://jena.apache.org/access#>
:r2 fuseki:allowedUsers ( "user1" "user2" ) .
:rLoggedIn fuseki:allowedUsers "*" .
-
http://git-wip-us.apache.org/repos/asf/jena/blob/070fae10/jena-fuseki2/jena-fuseki-main/testing/Access/assem-security-shared.ttl
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-main/testing/Access/assem-security-shared.ttl b/jena-fuseki2/jena-fuseki-main/testing/Access/assem-security-shared.ttl
index c16f66c..210ff9e 100644
--- a/jena-fuseki2/jena-fuseki-main/testing/Access/assem-security-shared.ttl
+++ b/jena-fuseki2/jena-fuseki-main/testing/Access/assem-security-shared.ttl
@@ -14,6 +14,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+# Use in TestFusekiSecurityAssemblerShared
+# Tests on the assembler for graph-level data access control.
+
PREFIX : <#>
PREFIX fuseki: <http://jena.apache.org/fuseki#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
http://git-wip-us.apache.org/repos/asf/jena/blob/070fae10/jena-fuseki2/jena-fuseki-main/testing/Access/assem-security.ttl
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-main/testing/Access/assem-security.ttl b/jena-fuseki2/jena-fuseki-main/testing/Access/assem-security.ttl
index 286ab2e..8c6f3d3 100644
--- a/jena-fuseki2/jena-fuseki-main/testing/Access/assem-security.ttl
+++ b/jena-fuseki2/jena-fuseki-main/testing/Access/assem-security.ttl
@@ -14,6 +14,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+# Use in TestFusekiSecurityAssemblerSeparate
+# Tests on the assembler for graph-level data access control.
+
PREFIX : <#>
PREFIX fuseki: <http://jena.apache.org/fuseki#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
http://git-wip-us.apache.org/repos/asf/jena/blob/070fae10/jena-fuseki2/jena-fuseki-main/testing/Access/config-server-0.ttl
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-main/testing/Access/config-server-0.ttl b/jena-fuseki2/jena-fuseki-main/testing/Access/config-server-0.ttl
new file mode 100644
index 0000000..1432b7d
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-main/testing/Access/config-server-0.ttl
@@ -0,0 +1,61 @@
+# 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.
+
+# Used by TestSecurityConfig
+# No server level security, only service level.
+
+PREFIX : <#>
+PREFIX fuseki: <http://jena.apache.org/fuseki#>
+PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
+PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
+PREFIX tdb2: <http://jena.apache.org/2016/tdb#>
+PREFIX ja: <http://jena.hpl.hp.com/2005/11/Assembler#>
+PREFIX access: <http://jena.apache.org/access#>
+
+[] rdf:type fuseki:Server ;
+ fuseki:services (
+ <#service_tdb2>
+ <#service_plain>
+ ) .
+
+<#service_tdb2> rdf:type fuseki:Service ;
+ rdfs:label "Access controlled dataset" ;
+ fuseki:allowedUsers "user1", "user3";
+ fuseki:name "database1" ;
+ fuseki:serviceQuery "query" ;
+ fuseki:serviceQuery "sparql" ;
+ fuseki:serviceReadGraphStore "get" ;
+ fuseki:dataset <#dataset1>;
+ .
+
+## Own database
+<#dataset1> rdf:type ja:MemoryDataset ;
+ .
+
+## Dataset 2
+## No service
+<#service_plain> rdf:type fuseki:Service ;
+ fuseki:name "database2";
+ fuseki:serviceQuery "query";
+ fuseki:serviceQuery "sparql";
+ fuseki:serviceReadGraphStore "get" ;
+ fuseki:dataset <#tdb_dataset> ;
+ .
+
+<#tdb_dataset> rdf:type tdb2:DatasetTDB2 ;
+ tdb2:location "--mem--" ;
+ .
+
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jena/blob/070fae10/jena-fuseki2/jena-fuseki-main/testing/Access/config-server-1.ttl
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-main/testing/Access/config-server-1.ttl b/jena-fuseki2/jena-fuseki-main/testing/Access/config-server-1.ttl
index e06b687..bb12dca 100644
--- a/jena-fuseki2/jena-fuseki-main/testing/Access/config-server-1.ttl
+++ b/jena-fuseki2/jena-fuseki-main/testing/Access/config-server-1.ttl
@@ -14,6 +14,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+# Used by TestSecurityConfig
+# Server is "*"
+
PREFIX : <#>
PREFIX fuseki: <http://jena.apache.org/fuseki#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
http://git-wip-us.apache.org/repos/asf/jena/blob/070fae10/jena-fuseki2/jena-fuseki-main/testing/Access/config-server-2.ttl
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-main/testing/Access/config-server-2.ttl b/jena-fuseki2/jena-fuseki-main/testing/Access/config-server-2.ttl
index d08ad90..a1df3cf 100644
--- a/jena-fuseki2/jena-fuseki-main/testing/Access/config-server-2.ttl
+++ b/jena-fuseki2/jena-fuseki-main/testing/Access/config-server-2.ttl
@@ -14,6 +14,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+# Used by TestSecurityConfig
+# Server is "user1", "user2
+
PREFIX : <#>
PREFIX fuseki: <http://jena.apache.org/fuseki#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
http://git-wip-us.apache.org/repos/asf/jena/blob/070fae10/jena-fuseki2/jena-fuseki-main/testing/Access/config-server-3.ttl
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-main/testing/Access/config-server-3.ttl b/jena-fuseki2/jena-fuseki-main/testing/Access/config-server-3.ttl
new file mode 100644
index 0000000..dc63661
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-main/testing/Access/config-server-3.ttl
@@ -0,0 +1,51 @@
+# 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.
+
+# Used by TestSecurityConfig
+# Endpoint ACLs.
+
+PREFIX : <#>
+PREFIX fuseki: <http://jena.apache.org/fuseki#>
+PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
+PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
+PREFIX tdb2: <http://jena.apache.org/2016/tdb#>
+PREFIX ja: <http://jena.hpl.hp.com/2005/11/Assembler#>
+PREFIX access: <http://jena.apache.org/access#>
+
+# Defaults to
+#[] rdf:type fuseki:Server ;
+# fuseki:allowedUsers "*";
+# .
+
+<#service> rdf:type fuseki:Service ;
+ rdfs:label "Access controlled dataset" ;
+ fuseki:allowedUsers "user1", "user3";
+ fuseki:name "db" ;
+ fuseki:serviceQuery [ fuseki:name "query1" ;
+ fuseki:allowedUsers ("user1" "user2")
+ ] ;
+ fuseki:serviceQuery [ fuseki:name "query2" ;
+ # Not accessible - service is 1&3
+ fuseki:allowedUsers ("user1" "user2")
+ ] ;
+ fuseki:serviceQuery [ fuseki:name "query3" ;
+ fuseki:allowedUsers ("user3")
+ ] ;
+ fuseki:serviceQuery [ fuseki:name "open" ;
+ fuseki:allowedUsers ("*")
+ ] ;
+ fuseki:dataset [ rdf:type ja:MemoryDataset ];
+ .
http://git-wip-us.apache.org/repos/asf/jena/blob/070fae10/jena-fuseki2/jena-fuseki-main/testing/Access/config-server-4.ttl
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-main/testing/Access/config-server-4.ttl b/jena-fuseki2/jena-fuseki-main/testing/Access/config-server-4.ttl
new file mode 100644
index 0000000..b5ef5d5
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-main/testing/Access/config-server-4.ttl
@@ -0,0 +1,45 @@
+# 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.
+
+# Used by TestSecurityConfig
+# Endpoint ACLs only.
+
+PREFIX : <#>
+PREFIX fuseki: <http://jena.apache.org/fuseki#>
+PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
+PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
+PREFIX tdb2: <http://jena.apache.org/2016/tdb#>
+PREFIX ja: <http://jena.hpl.hp.com/2005/11/Assembler#>
+PREFIX access: <http://jena.apache.org/access#>
+
+<#service> rdf:type fuseki:Service ;
+ rdfs:label "Access controlled dataset" ;
+ fuseki:name "db2" ;
+ fuseki:serviceQuery [ fuseki:name "query1" ;
+ fuseki:allowedUsers ("user1" "user2")
+ ] ;
+ fuseki:serviceQuery [ fuseki:name "query2" ;
+ # Not accessible - service is 1&3
+ fuseki:allowedUsers ("user1" "user2")
+ ] ;
+ fuseki:serviceQuery [ fuseki:name "query3" ;
+ fuseki:allowedUsers ("user3")
+ ] ;
+ fuseki:serviceQuery [ fuseki:name "open" ;
+ fuseki:allowedUsers ("*")
+ ] ;
+ fuseki:dataset [ rdf:type ja:MemoryDataset ];
+ .