[ 
https://issues.apache.org/jira/browse/CASSANDRA-20423?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17933647#comment-17933647
 ] 

Dmitry Konstantinov commented on CASSANDRA-20423:
-------------------------------------------------

Root cause analysis:
 * The issue is not reproduced locally, so I have analysed the related source 
code to find a cause.
 * There is only one place in source code which throws an exception with "You 
do not have access to this datacenter" text. It is 
org.apache.cassandra.service.ClientState#validateLogin
 * It throws the exception when the following check returns false:
{code:java}
networkPermissionsCache.get(this.getPrimaryRole()).canAccess(Datacenters.thisDatacenter())
{code}
networkPermissionsCache values are populated by INetworkAuthorizer 
implementation

 * According to the test code we use 
org.apache.cassandra.auth.AuthTestUtils.LocalCassandraNetworkAuthorizer
 * org.apache.cassandra.auth.DCPermissions#canAccess is implemented by 3 
implementations:
 ** org.apache.cassandra.auth.DCPermissions#ALL - always return true, so we 
cannot get false result here
 ** org.apache.cassandra.auth.DCPermissions.SubsetPermissions - we do not 
configure any explicit permissions, so 
org.apache.cassandra.auth.DCPermissions.Builder#build should return all(), so 
we cannot get false result here
 ** org.apache.cassandra.auth.DCPermissions#NONE - it is used in 
org.apache.cassandra.auth.CassandraNetworkAuthorizer#authorize:
{code:java}
    public DCPermissions authorize(RoleResource role)
    {
        if (!Roles.canLogin(role))
        {
            return DCPermissions.none();
        }
{code}
so, it looks like our case - if a role does not have a login flag set we can 
return such error.

 * The failing test sets the flag but we retrieve the flag from a cache 
(networkPermissionsCache)
 * The test methods shares a common Cassandra instance and they use the same 
user across them, f we check other test methods we can find that 
org.apache.cassandra.auth.GrantAndRevokeTest#testSpecificGrantsOnSystemKeyspaces
{code:java}
executeNet("CREATE ROLE '" + user + "'");
{code}
without LOGIN = true flag.

 * So, we may have a case when a role is updated by 
testSpecificGrantsOnSystemKeyspaces, then dropped by tearDown() method
{code:java}
executeNet("DROP ROLE " + user);
{code}
but roles cache is not updated yet, so when another test method is executing - 
it can uses an old version of the role without LOGIN = true flag and get the 
error.

 * let's check the hypothesis:
 ** increase roles validity from default 2 sec to 10 seconds
 ** run junit tests in a specific order to establish a CQL connection first 
with a valid user, then fill the role cache with such user name but without 
login grants and finally execute our failing test:
{code:java}
org.apache.cassandra.auth.GrantAndRevokeTest,testGrantedAllTables
org.apache.cassandra.auth.GrantAndRevokeTest,testSpecificGrantsOnSystemKeyspaces
org.apache.cassandra.auth.GrantAndRevokeTest,testGrantOnAllKeyspaces
{code}
and evict caches in testSpecificGrantsOnSystemKeyspaces to force the required 
invalid content loading:
{code:java}
    @Test
    public void testSpecificGrantsOnSystemKeyspaces() throws Throwable
    {
        Roles.cache.invalidate();
        AuthenticatedUser.networkPermissionsCache.invalidate();
{code}
* by applying all these tricks I was able get the failed test on my laptop 
quite frequently:
{code}
java.lang.AssertionError: Expected error message to contain 'User user has no 
MODIFY permission on <table user_keyspace.t1> or any of its parents', but got 
'You do not have access to this datacenter (datacenter1)'

        at org.junit.Assert.fail(Assert.java:88)
        at org.junit.Assert.assertTrue(Assert.java:41)
        at 
org.apache.cassandra.cql3.CQLTester.assertMessageContains(CQLTester.java:2472)
        at 
org.apache.cassandra.cql3.CQLTester.assertInvalidThrowMessage(CQLTester.java:2411)
        at 
org.apache.cassandra.cql3.CQLTester.assertUnauthorizedQuery(CQLTester.java:2484)
        at 
org.apache.cassandra.auth.GrantAndRevokeTest.testGrantOnAllKeyspaces(GrantAndRevokeTest.java:543)
{code}

-----
There are several options to fix the issue:
# invalidate all security caches between runs using 
AuthCacheService.instance.invalidateCaches();
# use unique user names for each test method
# do a polling check to wait for a cache refresh as we had added in 
CASSANDRA-17173 (note: as of now we do not have it in testGrantOnAllKeyspaces 
method added recently in CASSANDRA-20090)

> Test failure: org.apache.cassandra.auth.GrantAndRevokeTest
> ----------------------------------------------------------
>
>                 Key: CASSANDRA-20423
>                 URL: https://issues.apache.org/jira/browse/CASSANDRA-20423
>             Project: Apache Cassandra
>          Issue Type: Bug
>          Components: Test/unit
>            Reporter: Dmitry Konstantinov
>            Assignee: Dmitry Konstantinov
>            Priority: Normal
>             Fix For: 5.x
>
>         Attachments: Cassandra-trunk_2058_GrantAndRevokeTest.log
>
>
> Sometimes GrantAndRevokeTest fails with:
> {code:java}
> junit.framework.AssertionFailedError: Expected error message to contain 'User 
> user has no MODIFY permission on <table user_keyspace.t1> or any of its 
> parents', but got 'You do not have access to this datacenter (datacenter1)'
>       at 
> org.apache.cassandra.cql3.CQLTester.assertMessageContains(CQLTester.java:2472)
>       at 
> org.apache.cassandra.cql3.CQLTester.assertInvalidThrowMessage(CQLTester.java:2411)
>       at 
> org.apache.cassandra.cql3.CQLTester.assertUnauthorizedQuery(CQLTester.java:2484)
>       at 
> org.apache.cassandra.auth.GrantAndRevokeTest.testGrantOnAllKeyspaces(GrantAndRevokeTest.java:537)
>       at 
> java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>       at 
> java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
>       at 
> java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>  {code}
> log:  [^Cassandra-trunk_2058_GrantAndRevokeTest.log] 
> A recent example for 4.1: 
> https://ci-cassandra.apache.org/view/Cassandra%204.1/job/Cassandra-4.1/556/testReport/junit/org.apache.cassandra.auth/GrantAndRevokeTest/testGrantOnAllKeyspaces/



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org
For additional commands, e-mail: commits-h...@cassandra.apache.org

Reply via email to