Using Jackrabbit Oak, I've been attempting to configure security through SecurityProvider
and SecurityConfiguration
s. In particular, I've been using the restrictions which generally works as expected. However, when dealing with JCR-SQL2
queries, more gets filtered out than expected.
Details
It can be reproduced with the repository below.
/
node [nt:unstructured]
subnode [nt:unstructured]
On node
, I add an access control entry with privilege JCR_ALL
for user
together with a restriction for rep:glob
-> ""
, such that user
do not have access to any children of node
.
It works as expected when using session.getNode
:
session.getNode("/node")
returns the nodesession.getNode("/node/subnode")
throws PathNotFoundException
as expected due to the restriction.However, when I execute the following JCR-SQL2
query:
SELECT * FROM [nt:unstructured]
I get no results back. Here I would have expected to get /node
, as it is otherwise available when using session.getNode
.
Code
public static void main(String[] args) throws Exception {
Repository repository = new Jcr().with(new MySecurityProvider()).createRepository();
Session session = repository.login(new UserIdCredentials("")); // principal is "SystemPrincipal.INSTANCE"
// Create nodes
Node node = session.getRootNode().addNode("node", "nt:unstructured");
node.addNode("subnode", "nt:unstructured");
// Add access control entry + restriction
AccessControlManager acm = session.getAccessControlManager();
JackrabbitAccessControlList acl = (JackrabbitAccessControlList) acm
.getApplicablePolicies("/node").nextAccessControlPolicy();
Privilege[] privileges = new Privilege[]{acm.privilegeFromName(Privilege.JCR_ALL)};
Map<String, Value> restrictions = new HashMap<String, Value>() {{put("rep:glob", new StringValue(""));}};
acl.addEntry(new PrincipalImpl("user"), privileges, true, restrictions);
acm.setPolicy("/node", acl);
session.save();
// executes query
RowIterator rows = repository.login(new UserIdCredentials("user")).getWorkspace().getQueryManager()
.createQuery("SELECT * FROM [nt:unstructured]", Query.JCR_SQL2).execute().getRows();
System.out.println("Number of rows: " + rows.getSize()); //Prints 0
}
If one were to remove restrictions
from the code above, both node
and subnode
appears in the query results as expected.
MySecurityProvider
uses ConfigurationParameters.EMPTY
and the default implementations of all SecurityConfiguration
s, except for AuthenticationConfiguration
which I've implemented myself:
class MyAuthenticationConfiguration extends AuthenticationConfigurationImpl {
public MyAuthenticationConfiguration(SecurityProvider securityProvider) {
super(securityProvider);
}
@NotNull
@Override
public LoginContextProvider getLoginContextProvider(ContentRepository contentRepository) {
return new LoginContextProvider() {
@NotNull
public LoginContext getLoginContext(Credentials credentials, String workspaceName) {
String userId = ((UserIdCredentials) credentials).getUserId();
Set<Principal> principalSets = new HashSet<>();
if (userId.isEmpty()) {
principalSets.add(SystemPrincipal.INSTANCE);
} else {
principalSets.add(new PrincipalImpl(userId));
}
Map<String, ? extends Principal> publicPrivileges = new HashMap<>();
AuthInfoImpl authInfoImpl = new AuthInfoImpl(userId, publicPrivileges, principalSets);
Subject subject = new Subject(true, principalSets, Collections.singleton(authInfoImpl), new HashSet<Principal>());
return new PreAuthContext(subject);
}
};
}
}
I am using Jackrabbit Oak version 1.10.0
This turned out be a bug in Jackrabbit Oak - Link to issue.
This has been resolved as of version 1.12.0