1
votes

Using Jackrabbit Oak, I've been attempting to configure security through SecurityProvider and SecurityConfigurations. 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 node
  • session.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 SecurityConfigurations, 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

1

1 Answers

0
votes

This turned out be a bug in Jackrabbit Oak - Link to issue.

This has been resolved as of version 1.12.0