[ 
https://issues.apache.org/jira/browse/OAK-7997?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Julian Reschke updated OAK-7997:
--------------------------------
    Description: 
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.
{code:java}
/ 
  node      [nt:unstructured]
    subnode [nt:unstructured] {code}
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 - in this case, only 
subnode}}.

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:
{code:java}
SELECT * FROM [nt:unstructured]{code}
I get *no results back*. Here I would have expected to get {{/node}}, as it is 
otherwise available when using {{session.getNode}}. Removing the restriction 
yields the expected result of both _/node_ and _/node/subnode_.

As discussed with [~anchela] on the _users_ mailing list, this may either be an 
actual bug, or it is a conscious decision - in which case it would be nice to 
have it documented for the security.

*Code for reproducing:*

The code for reproducing the error is shown below. The "_restrictions"_ map 
below seems to be the problem, as this is what results in both _/node_ and 
_/node/subnode_ being filtered out.

 
{code:java}
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
}
{code}
*Code for security configuration:*

The above code makes use of "MySecurityProvider". I do not suspect this to be 
the root cause, but please let me know if it can be helpful to have. The 
security provider has the configuration set to "ConfigurationParameters.EMPTY", 
and it uses all the default implementations present within the Jackrabbit Oak 
project. The only exception is the _AuthenticationConfiguration_ which uses a 
custom implementation using pre-authentication:

 
{code:java}
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);
            }
        };
    }
}
{code}
 

  was:
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.
{code:java}
/ 
  node      [nt:unstructured]
    subnode [nt:unstructured] {code}
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 - in this case, only 
subnode}}.

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:
{code:java}
SELECT * FROM [nt:unstructured]{code}
I get *no results back*. Here I would have expected to get {{/node}}, as it is 
otherwise available when using {{session.getNode}}. Removing the restriction 
yields the expected result of both _/node_ and _/node/subnode_.

As discussed with [~anchela] on the _users_ mailing list, this may either be an 
actual bug, or it is a conscious decision - in which case it would be nice to 
have it documented for the security.

*Code for reproducing:*

The code for reproducing the error is shown below. The "_restrictions"_ map 
below seems to be the problem, as this is what results in both _/node_ and 
_/node/subnode_ being filtered out.

 
{code:java}
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
}
{code}
*Code for security configuration:*

The above code makes use of "MySecurityProvider". I do not suspect this to be 
the root cause, but please let me know if it can be helpful to have. The 
security provider has the configuration set to "ConfigurationParameters.EMPTY", 
and it uses all the default implementations present within the Jackrabbit Oak 
project. The only exception is the _AuthenticationConfiguration_ which uses a 
custom implementation using pre-authentication:

 
{code:java}
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);
            }
        };
    }
}
{code}
 


> Adding restrictions to ACLs yields empty results for queries in Jackrabbit Oak
> ------------------------------------------------------------------------------
>
>                 Key: OAK-7997
>                 URL: https://issues.apache.org/jira/browse/OAK-7997
>             Project: Jackrabbit Oak
>          Issue Type: Bug
>          Components: query, security
>    Affects Versions: 1.10.0, 1.8.10
>            Reporter: Søren Jensen
>            Assignee: Angela Schreiber
>            Priority: Major
>             Fix For: 1.12.0
>
>         Attachments: OAK-7997-selectorimpl.patch, OAK-7997.patch, 
> OAK-7997_2.patch, OAK-7997_3.patch
>
>
> 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.
> {code:java}
> / 
>   node      [nt:unstructured]
>     subnode [nt:unstructured] {code}
> 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 - in this case, only 
> subnode}}.
> 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:
> {code:java}
> SELECT * FROM [nt:unstructured]{code}
> I get *no results back*. Here I would have expected to get {{/node}}, as it 
> is otherwise available when using {{session.getNode}}. Removing the 
> restriction yields the expected result of both _/node_ and _/node/subnode_.
> As discussed with [~anchela] on the _users_ mailing list, this may either be 
> an actual bug, or it is a conscious decision - in which case it would be nice 
> to have it documented for the security.
> *Code for reproducing:*
> The code for reproducing the error is shown below. The "_restrictions"_ map 
> below seems to be the problem, as this is what results in both _/node_ and 
> _/node/subnode_ being filtered out.
>  
> {code:java}
> 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
> }
> {code}
> *Code for security configuration:*
> The above code makes use of "MySecurityProvider". I do not suspect this to be 
> the root cause, but please let me know if it can be helpful to have. The 
> security provider has the configuration set to 
> "ConfigurationParameters.EMPTY", and it uses all the default implementations 
> present within the Jackrabbit Oak project. The only exception is the 
> _AuthenticationConfiguration_ which uses a custom implementation using 
> pre-authentication:
>  
> {code:java}
> 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);
>             }
>         };
>     }
> }
> {code}
>  



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to