mirror of https://github.com/apache/cassandra
Implement Virtual Tables for Auth Caches
Patch by Aleksei Zotov; reviewed by Sam Tunnicliffe, and Benjamin Lerer for CASSANDRA-16914
This commit is contained in:
parent
eae7b9c3ad
commit
63292292b8
|
|
@ -1,4 +1,5 @@
|
|||
4.1
|
||||
* Implement Virtual Tables for Auth Caches (CASSANDRA-16914)
|
||||
* Actively update auth cache in the background (CASSANDRA-16957)
|
||||
* Add unix time conversion functions (CASSANDRA-17029)
|
||||
* JVMStabilityInspector.forceHeapSpaceOomMaybe should handle all non-heap OOMs rather than only supporting direct only (CASSANDRA-17128)
|
||||
|
|
|
|||
5
NEWS.txt
5
NEWS.txt
|
|
@ -69,6 +69,9 @@ New features
|
|||
- Added a new feature to allow denylisting (i.e. blocking read, write, or range read configurable) access to partition
|
||||
keys in configured keyspaces and tables. See doc/operating/denylisting_partitions.rst for details on using this new
|
||||
feature. Also see CASSANDRA-12106.
|
||||
- Information about pending hints is now available through `nodetool listpendinghints` and `pending_hints` virtual
|
||||
table.
|
||||
- Added ability to invalidate auth caches through corresponding `nodetool` commands and virtual tables.
|
||||
|
||||
Upgrading
|
||||
---------
|
||||
|
|
@ -76,8 +79,6 @@ Upgrading
|
|||
confirm it is set to value lower than 31 otherwise Cassandra will fail to start. See CASSANDRA-9384
|
||||
for further details. You also need to regenerate passwords for users for who the password
|
||||
was created while the above property was set to be more than 30 otherwise they will not be able to log in.
|
||||
- Information about pending hints is now available through `nodetool listpendinghints` and `pending_hints` virtual
|
||||
table.
|
||||
|
||||
Deprecation
|
||||
-----------
|
||||
|
|
|
|||
|
|
@ -17,8 +17,7 @@
|
|||
Virtual Tables
|
||||
--------------
|
||||
|
||||
Apache Cassandra 4.0 implements virtual tables (`CASSANDRA-7622
|
||||
<https://issues.apache.org/jira/browse/CASSANDRA-7622>`_).
|
||||
Virtual tables are supported starting from version 4.0.
|
||||
|
||||
Definition
|
||||
^^^^^^^^^^
|
||||
|
|
@ -92,52 +91,69 @@ Virtual tables in a virtual keyspace may be listed with ``DESC TABLES``. The ``
|
|||
|
||||
cqlsh> USE system_views;
|
||||
cqlsh:system_views> DESC TABLES;
|
||||
coordinator_scans clients tombstones_scanned internode_inbound
|
||||
disk_usage sstable_tasks live_scanned caches
|
||||
local_writes max_partition_size local_reads
|
||||
coordinator_writes internode_outbound thread_pools
|
||||
local_scans coordinator_reads settings
|
||||
caches internode_outbound roles_cache_keys
|
||||
clients jmx_permissions_cache_keys rows_per_read
|
||||
coordinator_read_latency local_read_latency settings
|
||||
coordinator_scan_latency local_scan_latency sstable_tasks
|
||||
coordinator_write_latency local_write_latency system_properties
|
||||
credentials_cache_keys max_partition_size thread_pools
|
||||
disk_usage network_permissions_cache_keys tombstones_per_read
|
||||
internode_inbound permissions_cache_keys
|
||||
|
||||
Some of the salient virtual tables in ``system_views`` virtual keyspace are described in Table 1.
|
||||
|
||||
Table 1 : Virtual Tables in system_views
|
||||
|
||||
+------------------+---------------------------------------------------+
|
||||
|Virtual Table | Description |
|
||||
+------------------+---------------------------------------------------+
|
||||
| clients |Lists information about all connected clients. |
|
||||
+------------------+---------------------------------------------------+
|
||||
| disk_usage |Disk usage including disk_space, keyspace_name, |
|
||||
| |and table_name by system keyspaces. |
|
||||
+------------------+---------------------------------------------------+
|
||||
| local_writes |A table metric for local writes |
|
||||
| |including count, keyspace_name, |
|
||||
| |max, median, per_second, and |
|
||||
| |table_name. |
|
||||
+------------------+---------------------------------------------------+
|
||||
| caches |Displays the general cache information including |
|
||||
| |cache name, capacity_bytes, entry_count, hit_count,|
|
||||
| |hit_ratio double, recent_hit_rate_per_second, |
|
||||
| |recent_request_rate_per_second, request_count, and |
|
||||
| |size_bytes. |
|
||||
+------------------+---------------------------------------------------+
|
||||
| local_reads |A table metric for local reads information. |
|
||||
+------------------+---------------------------------------------------+
|
||||
| sstable_tasks |Lists currently running tasks such as compactions |
|
||||
| |and upgrades on SSTables. |
|
||||
+------------------+---------------------------------------------------+
|
||||
|internode_inbound |Lists information about the inbound |
|
||||
| |internode messaging. |
|
||||
+------------------+---------------------------------------------------+
|
||||
| thread_pools |Lists metrics for each thread pool. |
|
||||
+------------------+---------------------------------------------------+
|
||||
| settings |Displays configuration settings in cassandra.yaml. |
|
||||
+------------------+---------------------------------------------------+
|
||||
|max_partition_size|A table metric for maximum partition size. |
|
||||
+------------------+---------------------------------------------------+
|
||||
|internode_outbound|Information about the outbound internode messaging.|
|
||||
| | |
|
||||
+------------------+---------------------------------------------------+
|
||||
+------------------------------+---------------------------------------------------+
|
||||
|Virtual Table | Description |
|
||||
+------------------------------+---------------------------------------------------+
|
||||
| clients |Lists information about all connected clients. |
|
||||
+------------------------------+---------------------------------------------------+
|
||||
| disk_usage |Disk usage including disk_space, keyspace_name, |
|
||||
| |and table_name by system keyspaces. |
|
||||
+------------------------------+---------------------------------------------------+
|
||||
| local_writes |A table metric for local writes |
|
||||
| |including count, keyspace_name, |
|
||||
| |max, median, per_second, and |
|
||||
| |table_name. |
|
||||
+------------------------------+---------------------------------------------------+
|
||||
| caches |Displays the general cache information including |
|
||||
| |cache name, capacity_bytes, entry_count, hit_count,|
|
||||
| |hit_ratio double, recent_hit_rate_per_second, |
|
||||
| |recent_request_rate_per_second, request_count, and |
|
||||
| |size_bytes. |
|
||||
+------------------------------+---------------------------------------------------+
|
||||
| local_reads |A table metric for local reads information. |
|
||||
+------------------------------+---------------------------------------------------+
|
||||
| sstable_tasks |Lists currently running tasks such as compactions |
|
||||
| |and upgrades on SSTables. |
|
||||
+------------------------------+---------------------------------------------------+
|
||||
| internode_inbound |Lists information about the inbound internode |
|
||||
| |messaging. |
|
||||
+------------------------------+---------------------------------------------------+
|
||||
| thread_pools |Lists metrics for each thread pool. |
|
||||
+------------------------------+---------------------------------------------------+
|
||||
| settings |Displays configuration settings in cassandra.yaml. |
|
||||
+------------------------------+---------------------------------------------------+
|
||||
| max_partition_size |A table metric for maximum partition size. |
|
||||
+------------------------------+---------------------------------------------------+
|
||||
| internode_outbound |Information about the outbound internode messaging.|
|
||||
+------------------------------+---------------------------------------------------+
|
||||
| credentials_cache_keys |Displays credentials cache keys. Supports DELETE |
|
||||
| |and TRUNCATE operations. |
|
||||
+------------------------------+---------------------------------------------------+
|
||||
| jmx_permissions_cache_keys |Displays JMX permissions cache keys. Supports |
|
||||
| |DELETE and TRUNCATE operations. |
|
||||
+------------------------------+---------------------------------------------------+
|
||||
|network_permissions_cache_keys|Displays netwrok permissions cache keys. Supports |
|
||||
| |DELETE and TRUNCATE operations. |
|
||||
+------------------------------+---------------------------------------------------+
|
||||
| permissions_cache_keys |Displays permissions cache keys. Supports DELETE |
|
||||
| |and TRUNCATE operations. |
|
||||
+------------------------------+---------------------------------------------------+
|
||||
| roles_cache_keys |Displays roles cache keys. Supports DELETE and |
|
||||
| |TRUNCATE operations. |
|
||||
+------------------------------+---------------------------------------------------+
|
||||
|
||||
We shall discuss some of the virtual tables in more detail next.
|
||||
|
||||
|
|
@ -187,7 +203,7 @@ The virtual tables may be described with ``DESCRIBE`` statement. The DDL listed
|
|||
|
||||
Caches Virtual Table
|
||||
********************
|
||||
The ``caches`` virtual table lists information about the caches. The four caches presently created are chunks, counters, keys and rows. A query on the ``caches`` virtual table returns the following details:
|
||||
The ``caches`` virtual table lists information about the caches. The four caches presently created are chunks, counters, keys and rows. A query on the ``caches`` virtual table returns the following details:
|
||||
|
||||
::
|
||||
|
||||
|
|
@ -307,6 +323,57 @@ As another example, to find how much time is remaining for SSTable tasks, use th
|
|||
SELECT total - progress AS remaining
|
||||
FROM system_views.sstable_tasks;
|
||||
|
||||
Auth Caches Keys Virtual Tables
|
||||
****************************
|
||||
|
||||
Every authentication cache has a separate virtual table associated. The virtual tables show the keys stored in caches
|
||||
and additionally support DELETE and TRUNCATE operations. In fact these operations just invalidate data in caches, no
|
||||
data is actually deleted from real tables.
|
||||
|
||||
The tables show the following information:
|
||||
|
||||
::
|
||||
|
||||
cqlsh:system_views> select * from credentials_cache_keys;
|
||||
role
|
||||
------
|
||||
bob
|
||||
(1 rows)
|
||||
|
||||
::
|
||||
|
||||
cqlsh:system_views> select * from jmx_permissions_cache_keys;
|
||||
role
|
||||
------
|
||||
bob
|
||||
(1 rows)
|
||||
|
||||
::
|
||||
|
||||
cqlsh:system_views> select * from network_permissions_cache_keys;
|
||||
role
|
||||
------
|
||||
bob
|
||||
(1 rows)
|
||||
|
||||
::
|
||||
|
||||
cqlsh:system_views> select * from permissions_cache_keys;
|
||||
role | resource
|
||||
------+-------------
|
||||
bob | roles/alice
|
||||
bob | data/ks1
|
||||
(2 rows)
|
||||
|
||||
::
|
||||
|
||||
cqlsh:system_views> select * from roles_cache_keys;
|
||||
role
|
||||
------
|
||||
bob
|
||||
(1 rows)
|
||||
|
||||
|
||||
Other Virtual Tables
|
||||
********************
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,9 @@
|
|||
|
||||
package org.apache.cassandra.auth;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
|
@ -188,6 +190,17 @@ public class AuthCache<K, V> implements AuthCacheMBean, Shutdownable
|
|||
return MBEAN_NAME_BASE + name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrive all cached entries. Will call {@link LoadingCache#asMap()} which does not trigger "load".
|
||||
* @return a map of cached key-value pairs
|
||||
*/
|
||||
public Map<K, V> getAll()
|
||||
{
|
||||
if (cache == null)
|
||||
return Collections.emptyMap();
|
||||
|
||||
return Collections.unmodifiableMap(cache.asMap());
|
||||
}
|
||||
/**
|
||||
* Retrieve a value from the cache. Will call {@link LoadingCache#get(Object)} which will
|
||||
* "load" the value if it's not present, thus populating the key.
|
||||
|
|
@ -213,7 +226,7 @@ public class AuthCache<K, V> implements AuthCacheMBean, Shutdownable
|
|||
}
|
||||
|
||||
/**
|
||||
* Invalidate a key
|
||||
* Invalidate a key.
|
||||
* @param k key to invalidate
|
||||
*/
|
||||
public void invalidate(K k)
|
||||
|
|
|
|||
|
|
@ -38,8 +38,8 @@ public class AuthenticatedUser
|
|||
public static final AuthenticatedUser ANONYMOUS_USER = new AuthenticatedUser(ANONYMOUS_USERNAME);
|
||||
|
||||
// User-level permissions cache.
|
||||
private static final PermissionsCache permissionsCache = new PermissionsCache(DatabaseDescriptor.getAuthorizer());
|
||||
private static final NetworkPermissionsCache networkPermissionsCache = new NetworkPermissionsCache(DatabaseDescriptor.getNetworkAuthorizer());
|
||||
public static final PermissionsCache permissionsCache = new PermissionsCache(DatabaseDescriptor.getAuthorizer());
|
||||
public static final NetworkPermissionsCache networkPermissionsCache = new NetworkPermissionsCache(DatabaseDescriptor.getNetworkAuthorizer());
|
||||
|
||||
private final String name;
|
||||
// primary Role of the logged in user
|
||||
|
|
|
|||
|
|
@ -81,6 +81,11 @@ public class PasswordAuthenticator implements IAuthenticator
|
|||
return true;
|
||||
}
|
||||
|
||||
public CredentialsCache getCredentialsCache()
|
||||
{
|
||||
return cache;
|
||||
}
|
||||
|
||||
protected static boolean checkpw(String password, String hash)
|
||||
{
|
||||
try
|
||||
|
|
@ -271,7 +276,7 @@ public class PasswordAuthenticator implements IAuthenticator
|
|||
}
|
||||
}
|
||||
|
||||
private static class CredentialsCache extends AuthCache<String, String> implements CredentialsCacheMBean
|
||||
public static class CredentialsCache extends AuthCache<String, String> implements CredentialsCacheMBean
|
||||
{
|
||||
private CredentialsCache(PasswordAuthenticator authenticator)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -45,8 +45,8 @@ public class PermissionsCache extends AuthCache<Pair<AuthenticatedUser, IResourc
|
|||
return get(Pair.create(user, resource));
|
||||
}
|
||||
|
||||
public void invalidatePermissions(String userName, String resourceName)
|
||||
public void invalidatePermissions(String roleName, String resourceName)
|
||||
{
|
||||
invalidate(Pair.create(new AuthenticatedUser(userName), Resources.fromName(resourceName)));
|
||||
invalidate(Pair.create(new AuthenticatedUser(roleName), Resources.fromName(resourceName)));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,5 +22,5 @@ public interface PermissionsCacheMBean extends AuthCacheMBean
|
|||
{
|
||||
public static final String CACHE_NAME = "PermissionsCache";
|
||||
|
||||
public void invalidatePermissions(String userName, String resourceName);
|
||||
public void invalidatePermissions(String roleName, String resourceName);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ public class Role
|
|||
* for IRoleManager implementations (in particular, CassandraRoleManager)
|
||||
*/
|
||||
|
||||
public final RoleResource resource ;
|
||||
public final RoleResource resource;
|
||||
public final boolean isSuper;
|
||||
public final boolean canLogin;
|
||||
public final Set<String> memberOf;
|
||||
|
|
|
|||
|
|
@ -20,11 +20,8 @@ package org.apache.cassandra.auth;
|
|||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
|
@ -38,26 +35,8 @@ public class Roles
|
|||
|
||||
private static final Role NO_ROLE = new Role("", false, false, Collections.emptyMap(), Collections.emptySet());
|
||||
|
||||
private static RolesCache cache;
|
||||
static
|
||||
{
|
||||
initRolesCache(DatabaseDescriptor.getRoleManager(),
|
||||
() -> DatabaseDescriptor.getAuthenticator().requireAuthentication());
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public static void initRolesCache(IRoleManager roleManager, BooleanSupplier enableCache)
|
||||
{
|
||||
if (cache != null)
|
||||
cache.unregisterMBean();
|
||||
cache = new RolesCache(roleManager, enableCache);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public static void clearCache()
|
||||
{
|
||||
cache.invalidate();
|
||||
}
|
||||
public static final RolesCache cache = new RolesCache(DatabaseDescriptor.getRoleManager(),
|
||||
() -> DatabaseDescriptor.getAuthenticator().requireAuthentication());
|
||||
|
||||
/**
|
||||
* Identify all roles granted to the supplied Role, including both directly granted
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ public class AuthorizationProxy implements InvocationHandler
|
|||
"registerMBean",
|
||||
"unregisterMBean");
|
||||
|
||||
private static final JmxPermissionsCache permissionsCache = new JmxPermissionsCache();
|
||||
public static final JmxPermissionsCache jmxPermissionsCache = new JmxPermissionsCache();
|
||||
private MBeanServer mbs;
|
||||
|
||||
/*
|
||||
|
|
@ -118,7 +118,7 @@ public class AuthorizationProxy implements InvocationHandler
|
|||
the permissions from the local cache, which in turn loads them from the configured IAuthorizer
|
||||
but can be overridden for testing.
|
||||
*/
|
||||
protected Function<RoleResource, Set<PermissionDetails>> getPermissions = permissionsCache::get;
|
||||
protected Function<RoleResource, Set<PermissionDetails>> getPermissions = jmxPermissionsCache::get;
|
||||
|
||||
/*
|
||||
Used to decide whether authorization is enabled or not, usually this depends on the configured
|
||||
|
|
@ -477,7 +477,7 @@ public class AuthorizationProxy implements InvocationHandler
|
|||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private static final class JmxPermissionsCache extends AuthCache<RoleResource, Set<PermissionDetails>>
|
||||
public static final class JmxPermissionsCache extends AuthCache<RoleResource, Set<PermissionDetails>>
|
||||
implements JmxPermissionsCacheMBean
|
||||
{
|
||||
protected JmxPermissionsCache()
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import com.google.common.collect.BoundType;
|
|||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Range;
|
||||
|
||||
import org.apache.commons.lang.ArrayUtils;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
import org.apache.cassandra.db.Clustering;
|
||||
import org.apache.cassandra.db.ClusteringBound;
|
||||
|
|
@ -145,7 +145,7 @@ public abstract class AbstractMutableVirtualTable extends AbstractVirtualTable
|
|||
throw invalidRequest("Range deletion is not supported by table %s", metadata);
|
||||
}
|
||||
|
||||
protected void applyRowDeletion(ColumnValues partitionKey, ColumnValues clusteringColumnValues)
|
||||
protected void applyRowDeletion(ColumnValues partitionKey, ColumnValues clusteringColumns)
|
||||
{
|
||||
throw invalidRequest("Row deletion is not supported by table %s", metadata);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* 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.cassandra.db.virtual;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.cassandra.auth.IAuthenticator;
|
||||
import org.apache.cassandra.auth.PasswordAuthenticator;
|
||||
import org.apache.cassandra.config.DatabaseDescriptor;
|
||||
import org.apache.cassandra.db.marshal.UTF8Type;
|
||||
import org.apache.cassandra.dht.LocalPartitioner;
|
||||
import org.apache.cassandra.schema.TableMetadata;
|
||||
|
||||
final class CredentialsCacheKeysTable extends AbstractMutableVirtualTable
|
||||
{
|
||||
private static final String ROLE = "role";
|
||||
|
||||
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
||||
private final Optional<PasswordAuthenticator> passwordAuthenticatorOptional;
|
||||
|
||||
CredentialsCacheKeysTable(String keyspace)
|
||||
{
|
||||
super(TableMetadata.builder(keyspace, "credentials_cache_keys")
|
||||
.comment("keys in the credentials cache")
|
||||
.kind(TableMetadata.Kind.VIRTUAL)
|
||||
.partitioner(new LocalPartitioner(UTF8Type.instance))
|
||||
.addPartitionKeyColumn(ROLE, UTF8Type.instance)
|
||||
.build());
|
||||
|
||||
IAuthenticator authenticator = DatabaseDescriptor.getAuthenticator();
|
||||
if (authenticator instanceof PasswordAuthenticator)
|
||||
this.passwordAuthenticatorOptional = Optional.of((PasswordAuthenticator) authenticator);
|
||||
else
|
||||
this.passwordAuthenticatorOptional = Optional.empty();
|
||||
}
|
||||
|
||||
public DataSet data()
|
||||
{
|
||||
SimpleDataSet result = new SimpleDataSet(metadata());
|
||||
|
||||
passwordAuthenticatorOptional
|
||||
.ifPresent(passwordAuthenticator -> passwordAuthenticator.getCredentialsCache().getAll()
|
||||
.forEach((roleName, ignored) -> result.row(roleName)));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyPartitionDeletion(ColumnValues partitionKey)
|
||||
{
|
||||
String roleName = partitionKey.value(0);
|
||||
|
||||
passwordAuthenticatorOptional
|
||||
.ifPresent(passwordAuthenticator -> passwordAuthenticator.getCredentialsCache().invalidate(roleName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void truncate()
|
||||
{
|
||||
passwordAuthenticatorOptional
|
||||
.ifPresent(passwordAuthenticator -> passwordAuthenticator.getCredentialsCache().invalidate());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* 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.cassandra.db.virtual;
|
||||
|
||||
import org.apache.cassandra.auth.RoleResource;
|
||||
import org.apache.cassandra.auth.jmx.AuthorizationProxy;
|
||||
import org.apache.cassandra.db.marshal.UTF8Type;
|
||||
import org.apache.cassandra.dht.LocalPartitioner;
|
||||
import org.apache.cassandra.schema.TableMetadata;
|
||||
|
||||
final class JmxPermissionsCacheKeysTable extends AbstractMutableVirtualTable
|
||||
{
|
||||
private static final String ROLE = "role";
|
||||
|
||||
JmxPermissionsCacheKeysTable(String keyspace)
|
||||
{
|
||||
super(TableMetadata.builder(keyspace, "jmx_permissions_cache_keys")
|
||||
.comment("keys in the JMX permissions cache")
|
||||
.kind(TableMetadata.Kind.VIRTUAL)
|
||||
.partitioner(new LocalPartitioner(UTF8Type.instance))
|
||||
.addPartitionKeyColumn(ROLE, UTF8Type.instance)
|
||||
.build());
|
||||
}
|
||||
|
||||
public DataSet data()
|
||||
{
|
||||
SimpleDataSet result = new SimpleDataSet(metadata());
|
||||
|
||||
AuthorizationProxy.jmxPermissionsCache.getAll()
|
||||
.forEach((roleResource, ignored) -> result.row(roleResource.getRoleName()));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyPartitionDeletion(ColumnValues partitionKey)
|
||||
{
|
||||
RoleResource roleResource = RoleResource.role(partitionKey.value(0));
|
||||
|
||||
AuthorizationProxy.jmxPermissionsCache.invalidate(roleResource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void truncate()
|
||||
{
|
||||
AuthorizationProxy.jmxPermissionsCache.invalidate();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* 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.cassandra.db.virtual;
|
||||
|
||||
import org.apache.cassandra.auth.AuthenticatedUser;
|
||||
import org.apache.cassandra.auth.RoleResource;
|
||||
import org.apache.cassandra.db.marshal.UTF8Type;
|
||||
import org.apache.cassandra.dht.LocalPartitioner;
|
||||
import org.apache.cassandra.schema.TableMetadata;
|
||||
|
||||
final class NetworkPermissionsCacheKeysTable extends AbstractMutableVirtualTable
|
||||
{
|
||||
private static final String ROLE = "role";
|
||||
|
||||
NetworkPermissionsCacheKeysTable(String keyspace)
|
||||
{
|
||||
super(TableMetadata.builder(keyspace, "network_permissions_cache_keys")
|
||||
.comment("keys in the network permissions cache")
|
||||
.kind(TableMetadata.Kind.VIRTUAL)
|
||||
.partitioner(new LocalPartitioner(UTF8Type.instance))
|
||||
.addPartitionKeyColumn(ROLE, UTF8Type.instance)
|
||||
.build());
|
||||
}
|
||||
|
||||
public DataSet data()
|
||||
{
|
||||
SimpleDataSet result = new SimpleDataSet(metadata());
|
||||
|
||||
AuthenticatedUser.networkPermissionsCache.getAll()
|
||||
.forEach((roleResource, ignored) -> result.row(roleResource.getRoleName()));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyPartitionDeletion(ColumnValues partitionKey)
|
||||
{
|
||||
RoleResource roleResource = RoleResource.role(partitionKey.value(0));
|
||||
|
||||
AuthenticatedUser.networkPermissionsCache.invalidate(roleResource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void truncate()
|
||||
{
|
||||
AuthenticatedUser.networkPermissionsCache.invalidate();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* 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.cassandra.db.virtual;
|
||||
|
||||
import org.apache.cassandra.auth.AuthenticatedUser;
|
||||
import org.apache.cassandra.auth.IResource;
|
||||
import org.apache.cassandra.auth.Resources;
|
||||
import org.apache.cassandra.db.marshal.UTF8Type;
|
||||
import org.apache.cassandra.dht.LocalPartitioner;
|
||||
import org.apache.cassandra.schema.TableMetadata;
|
||||
import org.apache.cassandra.utils.Pair;
|
||||
|
||||
final class PermissionsCacheKeysTable extends AbstractMutableVirtualTable
|
||||
{
|
||||
private static final String ROLE = "role";
|
||||
private static final String RESOURCE = "resource";
|
||||
|
||||
PermissionsCacheKeysTable(String keyspace)
|
||||
{
|
||||
super(TableMetadata.builder(keyspace, "permissions_cache_keys")
|
||||
.comment("keys in the permissions cache")
|
||||
.kind(TableMetadata.Kind.VIRTUAL)
|
||||
.partitioner(new LocalPartitioner(UTF8Type.instance))
|
||||
.addPartitionKeyColumn(ROLE, UTF8Type.instance)
|
||||
.addPartitionKeyColumn(RESOURCE, UTF8Type.instance)
|
||||
.build());
|
||||
}
|
||||
|
||||
public DataSet data()
|
||||
{
|
||||
SimpleDataSet result = new SimpleDataSet(metadata());
|
||||
|
||||
AuthenticatedUser.permissionsCache.getAll()
|
||||
.forEach((userResoursePair, ignored) ->
|
||||
result.row(userResoursePair.left.getName(), userResoursePair.right.getName()));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyPartitionDeletion(ColumnValues partitionKey)
|
||||
{
|
||||
AuthenticatedUser user = new AuthenticatedUser(partitionKey.value(0));
|
||||
IResource resource = resourceFromNameIfExists(partitionKey.value(1));
|
||||
// no need to delete invalid resource
|
||||
if (resource == null)
|
||||
return;
|
||||
|
||||
AuthenticatedUser.permissionsCache.invalidate(Pair.create(user, resource));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void truncate()
|
||||
{
|
||||
AuthenticatedUser.permissionsCache.invalidate();
|
||||
}
|
||||
|
||||
private IResource resourceFromNameIfExists(String name)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Resources.fromName(name);
|
||||
}
|
||||
catch (IllegalArgumentException e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* 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.cassandra.db.virtual;
|
||||
|
||||
import org.apache.cassandra.auth.RoleResource;
|
||||
import org.apache.cassandra.auth.Roles;
|
||||
import org.apache.cassandra.db.marshal.UTF8Type;
|
||||
import org.apache.cassandra.dht.LocalPartitioner;
|
||||
import org.apache.cassandra.schema.TableMetadata;
|
||||
|
||||
final class RolesCacheKeysTable extends AbstractMutableVirtualTable
|
||||
{
|
||||
private static final String ROLE = "role";
|
||||
|
||||
RolesCacheKeysTable(String keyspace)
|
||||
{
|
||||
super(TableMetadata.builder(keyspace, "roles_cache_keys")
|
||||
.comment("keys in the roles cache")
|
||||
.kind(TableMetadata.Kind.VIRTUAL)
|
||||
.partitioner(new LocalPartitioner(UTF8Type.instance))
|
||||
.addPartitionKeyColumn(ROLE, UTF8Type.instance)
|
||||
.build());
|
||||
}
|
||||
|
||||
public DataSet data()
|
||||
{
|
||||
SimpleDataSet result = new SimpleDataSet(metadata());
|
||||
|
||||
Roles.cache.getAll()
|
||||
.forEach((roleResource, ignored) -> result.row(roleResource.getRoleName()));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyPartitionDeletion(ColumnValues partitionKey)
|
||||
{
|
||||
RoleResource roleResource = RoleResource.role(partitionKey.value(0));
|
||||
|
||||
Roles.cache.invalidate(roleResource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void truncate()
|
||||
{
|
||||
Roles.cache.invalidate();
|
||||
}
|
||||
}
|
||||
|
|
@ -38,6 +38,11 @@ public final class SystemViewsKeyspace extends VirtualKeyspace
|
|||
.add(new InternodeInboundTable(VIRTUAL_VIEWS))
|
||||
.add(new PendingHintsTable(VIRTUAL_VIEWS))
|
||||
.addAll(TableMetricTables.getAll(VIRTUAL_VIEWS))
|
||||
.add(new CredentialsCacheKeysTable(VIRTUAL_VIEWS))
|
||||
.add(new JmxPermissionsCacheKeysTable(VIRTUAL_VIEWS))
|
||||
.add(new NetworkPermissionsCacheKeysTable(VIRTUAL_VIEWS))
|
||||
.add(new PermissionsCacheKeysTable(VIRTUAL_VIEWS))
|
||||
.add(new RolesCacheKeysTable(VIRTUAL_VIEWS))
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -544,9 +544,9 @@ public class NodeProbe implements AutoCloseable
|
|||
pcProxy.invalidate();
|
||||
}
|
||||
|
||||
public void invalidatePermissionsCache(String userName, String resourceName)
|
||||
public void invalidatePermissionsCache(String roleName, String resourceName)
|
||||
{
|
||||
pcProxy.invalidatePermissions(userName, resourceName);
|
||||
pcProxy.invalidatePermissions(roleName, resourceName);
|
||||
}
|
||||
|
||||
public void invalidateRolesCache()
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ import static com.google.common.base.Preconditions.checkArgument;
|
|||
@Command(name = "invalidatepermissionscache", description = "Invalidate the permissions cache")
|
||||
public class InvalidatePermissionsCache extends NodeToolCmd
|
||||
{
|
||||
@Arguments(usage = "[<user>]", description = "A specific user for whom permissions need to be invalidated")
|
||||
@Arguments(usage = "[<role>]", description = "A role for which permissions to specified resources need to be invalidated")
|
||||
private List<String> args = new ArrayList<>();
|
||||
|
||||
// Data Resources
|
||||
|
|
@ -52,6 +52,11 @@ public class InvalidatePermissionsCache extends NodeToolCmd
|
|||
description = "Keyspace to invalidate permissions for")
|
||||
private String keyspace;
|
||||
|
||||
@Option(title = "all-tables",
|
||||
name = {"--all-tables"},
|
||||
description = "Invalidate permissions for 'ALL TABLES'")
|
||||
private boolean allTables;
|
||||
|
||||
@Option(title = "table",
|
||||
name = {"--table"},
|
||||
description = "Table to invalidate permissions for (you must specify --keyspace for using this option)")
|
||||
|
|
@ -105,28 +110,34 @@ public class InvalidatePermissionsCache extends NodeToolCmd
|
|||
&& !allRoles && StringUtils.isEmpty(role)
|
||||
&& !allFunctions && StringUtils.isEmpty(functionsInKeyspace) && StringUtils.isEmpty(function)
|
||||
&& !allMBeans && StringUtils.isEmpty(mBean),
|
||||
"No options allowed without a <user> being specified");
|
||||
"No resource options allowed without a <role> being specified");
|
||||
|
||||
probe.invalidatePermissionsCache();
|
||||
}
|
||||
else
|
||||
{
|
||||
checkArgument(args.size() == 1,
|
||||
"A single <user> is only supported / you have a typo in the options spelling");
|
||||
"A single <role> is only supported / you have a typo in the resource options spelling");
|
||||
List<String> resourceNames = new ArrayList<>();
|
||||
|
||||
// Data Resources
|
||||
if (allKeyspaces)
|
||||
resourceNames.add(DataResource.root().getName());
|
||||
|
||||
if (allTables)
|
||||
if (StringUtils.isNotEmpty(keyspace))
|
||||
resourceNames.add(DataResource.allTables(keyspace).getName());
|
||||
else
|
||||
throw new IllegalArgumentException("--all-tables option should be passed along with --keyspace option");
|
||||
|
||||
if (StringUtils.isNotEmpty(table))
|
||||
if (StringUtils.isNotEmpty(keyspace))
|
||||
resourceNames.add(DataResource.table(keyspace, table).getName());
|
||||
else
|
||||
throw new IllegalArgumentException("--table option should be passed along with --keyspace option");
|
||||
else
|
||||
if (StringUtils.isNotEmpty(keyspace))
|
||||
resourceNames.add(DataResource.keyspace(keyspace).getName());
|
||||
|
||||
if (StringUtils.isNotEmpty(keyspace) && !allTables && StringUtils.isEmpty(table))
|
||||
resourceNames.add(DataResource.keyspace(keyspace).getName());
|
||||
|
||||
// Roles Resources
|
||||
if (allRoles)
|
||||
|
|
@ -155,10 +166,13 @@ public class InvalidatePermissionsCache extends NodeToolCmd
|
|||
if (StringUtils.isNotEmpty(mBean))
|
||||
resourceNames.add(JMXResource.mbean(mBean).getName());
|
||||
|
||||
String userName = args.get(0);
|
||||
String roleName = args.get(0);
|
||||
|
||||
if (resourceNames.isEmpty())
|
||||
throw new IllegalArgumentException("No resource options specified");
|
||||
|
||||
for (String resourceName : resourceNames)
|
||||
probe.invalidatePermissionsCache(userName, resourceName);
|
||||
probe.invalidatePermissionsCache(roleName, resourceName);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
*/
|
||||
package org.apache.cassandra.auth;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.IntConsumer;
|
||||
|
|
@ -27,6 +28,7 @@ import org.junit.Test;
|
|||
import org.apache.cassandra.db.ConsistencyLevel;
|
||||
import org.apache.cassandra.exceptions.UnavailableException;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
|
@ -224,6 +226,43 @@ public class AuthCacheTest
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCacheLoaderIsNotCalledOnGetAllWhenCacheIsDisabled()
|
||||
{
|
||||
isCacheEnabled = false;
|
||||
TestCache<String, Integer> authCache = new TestCache<>(this::countingLoader, this::setValidity, () -> validity, () -> isCacheEnabled);
|
||||
authCache.get("10");
|
||||
Map<String, Integer> result = authCache.getAll();
|
||||
|
||||
// even though the cache is disabled and nothing is cache we still use loadFunction on get operation, so
|
||||
// its counter has been incremented
|
||||
assertThat(result).isEmpty();
|
||||
assertEquals(1, loadCounter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCacheLoaderIsNotCalledOnGetAllWhenCacheIsEmpty()
|
||||
{
|
||||
TestCache<String, Integer> authCache = new TestCache<>(this::countingLoader, this::setValidity, () -> validity, () -> isCacheEnabled);
|
||||
|
||||
Map<String, Integer> result = authCache.getAll();
|
||||
|
||||
assertThat(result).isEmpty();
|
||||
assertEquals(0, loadCounter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCacheLoaderIsNotCalledOnGetAllWhenCacheIsNotEmpty()
|
||||
{
|
||||
TestCache<String, Integer> authCache = new TestCache<>(this::countingLoader, this::setValidity, () -> validity, () -> isCacheEnabled);
|
||||
authCache.get("10");
|
||||
Map<String, Integer> result = authCache.getAll();
|
||||
|
||||
assertThat(result).hasSize(1);
|
||||
assertThat(result).containsEntry("10", 10);
|
||||
assertEquals(1, loadCounter);
|
||||
}
|
||||
|
||||
private void setValidity(int validity)
|
||||
{
|
||||
this.validity = validity;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ package org.apache.cassandra.auth;
|
|||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.apache.cassandra.auth.jmx.AuthorizationProxy;
|
||||
import org.apache.cassandra.cql3.QueryOptions;
|
||||
import org.apache.cassandra.cql3.QueryProcessor;
|
||||
import org.apache.cassandra.cql3.UntypedResultSet;
|
||||
|
|
@ -121,6 +122,15 @@ public class AuthTestUtils
|
|||
}
|
||||
}
|
||||
|
||||
public static class NoAuthSetupAuthorizationProxy extends AuthorizationProxy
|
||||
{
|
||||
public NoAuthSetupAuthorizationProxy()
|
||||
{
|
||||
super();
|
||||
this.isAuthSetupComplete = () -> true;
|
||||
}
|
||||
}
|
||||
|
||||
public static void grantRolesTo(IRoleManager roleManager, RoleResource grantee, RoleResource...granted)
|
||||
{
|
||||
for(RoleResource toGrant : granted)
|
||||
|
|
|
|||
|
|
@ -43,13 +43,12 @@ import org.apache.cassandra.exceptions.ConfigurationException;
|
|||
import org.apache.cassandra.service.ClientState;
|
||||
|
||||
import static org.apache.cassandra.auth.AuthKeyspace.NETWORK_PERMISSIONS;
|
||||
import static org.apache.cassandra.auth.AuthTestUtils.LocalCassandraRoleManager;
|
||||
import static org.apache.cassandra.auth.AuthTestUtils.getRolesReadCount;
|
||||
import static org.apache.cassandra.schema.SchemaConstants.AUTH_KEYSPACE_NAME;
|
||||
|
||||
public class CassandraNetworkAuthorizerTest
|
||||
{
|
||||
public static void setupSuperUser()
|
||||
private static void setupSuperUser()
|
||||
{
|
||||
QueryProcessor.executeInternal(String.format("INSERT INTO %s.%s (role, is_superuser, can_login, salted_hash) "
|
||||
+ "VALUES ('%s', true, true, '%s')",
|
||||
|
|
@ -63,13 +62,12 @@ public class CassandraNetworkAuthorizerTest
|
|||
public static void defineSchema() throws ConfigurationException
|
||||
{
|
||||
SchemaLoader.prepareServer();
|
||||
SchemaLoader.setupAuth(new LocalCassandraRoleManager(),
|
||||
new PasswordAuthenticator(),
|
||||
SchemaLoader.setupAuth(new AuthTestUtils.LocalCassandraRoleManager(),
|
||||
new AuthTestUtils.LocalPasswordAuthenticator(),
|
||||
new AuthTestUtils.LocalCassandraAuthorizer(),
|
||||
new AuthTestUtils.LocalCassandraNetworkAuthorizer());
|
||||
|
||||
setupSuperUser();
|
||||
// not strictly necessary to init the cache here, but better to be explicit
|
||||
Roles.initRolesCache(DatabaseDescriptor.getRoleManager(), () -> true);
|
||||
}
|
||||
|
||||
@Before
|
||||
|
|
@ -122,7 +120,7 @@ public class CassandraNetworkAuthorizerTest
|
|||
AuthenticationStatement authStmt = (AuthenticationStatement) statement;
|
||||
|
||||
// invalidate roles cache so that any changes to the underlying roles are picked up
|
||||
Roles.clearCache();
|
||||
Roles.cache.invalidate();
|
||||
authStmt.execute(getClientState());
|
||||
}
|
||||
|
||||
|
|
@ -193,7 +191,7 @@ public class CassandraNetworkAuthorizerTest
|
|||
assertDcPermRow(username, "dc1");
|
||||
|
||||
// clear the roles cache to lose the (non-)superuser status for the user
|
||||
Roles.clearCache();
|
||||
Roles.cache.invalidate();
|
||||
auth("ALTER ROLE %s WITH superuser = true", username);
|
||||
Assert.assertEquals(DCPermissions.all(), dcPerms(username));
|
||||
}
|
||||
|
|
@ -207,7 +205,7 @@ public class CassandraNetworkAuthorizerTest
|
|||
}
|
||||
|
||||
@Test
|
||||
public void getLoginPrivilegeFromRolesCache() throws Exception
|
||||
public void getLoginPrivilegeFromRolesCache()
|
||||
{
|
||||
String username = createName();
|
||||
auth("CREATE ROLE %s", username);
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ public class CassandraRoleManagerTest
|
|||
// collects all of the necessary info with a single query for each granted role.
|
||||
// This just tests that that is the case, i.e. we perform 1 read per role in the
|
||||
// transitive set of granted roles
|
||||
IRoleManager roleManager = new LocalCassandraRoleManager();
|
||||
IRoleManager roleManager = new AuthTestUtils.LocalCassandraRoleManager();
|
||||
roleManager.setup();
|
||||
for (RoleResource r : ALL_ROLES)
|
||||
roleManager.createRole(AuthenticatedUser.ANONYMOUS_USER, r, new RoleOptions());
|
||||
|
|
|
|||
|
|
@ -50,6 +50,9 @@ public class ResourcesTest
|
|||
assertEquals(DataResource.keyspace("ks1"), Resources.fromName("data/ks1"));
|
||||
assertEquals("data/ks1", DataResource.keyspace("ks1").getName());
|
||||
|
||||
assertEquals(DataResource.allTables("ks1"), Resources.fromName("data/ks1/*"));
|
||||
assertEquals("data/ks1/*", DataResource.allTables("ks1").getName());
|
||||
|
||||
assertEquals(DataResource.table("ks1", "t1"), Resources.fromName("data/ks1/t1"));
|
||||
assertEquals("data/ks1/t1", DataResource.table("ks1", "t1").getName());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,11 +28,13 @@ import org.junit.Test;
|
|||
import org.apache.cassandra.SchemaLoader;
|
||||
import org.apache.cassandra.config.DatabaseDescriptor;
|
||||
import org.apache.cassandra.db.ConsistencyLevel;
|
||||
import org.apache.cassandra.schema.KeyspaceParams;
|
||||
import org.apache.cassandra.schema.SchemaConstants;
|
||||
import org.apache.cassandra.schema.TableMetadata;
|
||||
|
||||
import static org.apache.cassandra.auth.AuthTestUtils.*;
|
||||
import static org.apache.cassandra.auth.AuthTestUtils.ALL_ROLES;
|
||||
import static org.apache.cassandra.auth.AuthTestUtils.ROLE_A;
|
||||
import static org.apache.cassandra.auth.AuthTestUtils.ROLE_B;
|
||||
import static org.apache.cassandra.auth.AuthTestUtils.ROLE_C;
|
||||
import static org.apache.cassandra.auth.AuthTestUtils.getRolesReadCount;
|
||||
import static org.apache.cassandra.auth.AuthTestUtils.grantRolesTo;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
|
|
@ -43,14 +45,12 @@ public class RolesTest
|
|||
public static void setupClass()
|
||||
{
|
||||
SchemaLoader.prepareServer();
|
||||
// create the system_auth keyspace so the IRoleManager can function as normal
|
||||
SchemaLoader.createKeyspace(SchemaConstants.AUTH_KEYSPACE_NAME,
|
||||
KeyspaceParams.simple(1),
|
||||
Iterables.toArray(AuthKeyspace.metadata().tables, TableMetadata.class));
|
||||
IRoleManager roleManager = new AuthTestUtils.LocalCassandraRoleManager();
|
||||
SchemaLoader.setupAuth(roleManager,
|
||||
new AuthTestUtils.LocalPasswordAuthenticator(),
|
||||
new AuthTestUtils.LocalCassandraAuthorizer(),
|
||||
new AuthTestUtils.LocalCassandraNetworkAuthorizer());
|
||||
|
||||
IRoleManager roleManager = new LocalCassandraRoleManager();
|
||||
roleManager.setup();
|
||||
Roles.initRolesCache(roleManager, () -> true);
|
||||
for (RoleResource role : ALL_ROLES)
|
||||
roleManager.createRole(AuthenticatedUser.ANONYMOUS_USER, role, new RoleOptions());
|
||||
grantRolesTo(roleManager, ROLE_A, ROLE_B, ROLE_C);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* 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.cassandra.db.virtual;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.datastax.driver.core.EndPoint;
|
||||
import com.datastax.driver.core.PlainTextAuthProvider;
|
||||
import org.apache.cassandra.auth.AuthTestUtils;
|
||||
import org.apache.cassandra.auth.AuthenticatedUser;
|
||||
import org.apache.cassandra.auth.IAuthenticator;
|
||||
import org.apache.cassandra.auth.IRoleManager;
|
||||
import org.apache.cassandra.auth.RoleResource;
|
||||
import org.apache.cassandra.config.DatabaseDescriptor;
|
||||
import org.apache.cassandra.cql3.CQLTester;
|
||||
|
||||
import static org.apache.cassandra.auth.AuthTestUtils.ROLE_A;
|
||||
import static org.apache.cassandra.auth.AuthTestUtils.ROLE_B;
|
||||
|
||||
public class CredentialsCacheKeysTableTest extends CQLTester
|
||||
{
|
||||
private static final String KS_NAME = "vts";
|
||||
private static AuthTestUtils.LocalPasswordAuthenticator passwordAuthenticator;
|
||||
|
||||
@SuppressWarnings("FieldCanBeLocal")
|
||||
private CredentialsCacheKeysTable table;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass()
|
||||
{
|
||||
// high value is used for convenient debugging
|
||||
DatabaseDescriptor.setCredentialsValidity(20_000);
|
||||
|
||||
CQLTester.setUpClass();
|
||||
CQLTester.requireAuthentication();
|
||||
passwordAuthenticator = (AuthTestUtils.LocalPasswordAuthenticator) DatabaseDescriptor.getAuthenticator();
|
||||
|
||||
IRoleManager roleManager = DatabaseDescriptor.getRoleManager();
|
||||
roleManager.createRole(AuthenticatedUser.SYSTEM_USER, ROLE_A, AuthTestUtils.getLoginRoleOptions());
|
||||
roleManager.createRole(AuthenticatedUser.SYSTEM_USER, ROLE_B, AuthTestUtils.getLoginRoleOptions());
|
||||
}
|
||||
|
||||
@Before
|
||||
public void config()
|
||||
{
|
||||
table = new CredentialsCacheKeysTable(KS_NAME);
|
||||
VirtualKeyspaceRegistry.instance.register(new VirtualKeyspace(KS_NAME, ImmutableList.of(table)));
|
||||
|
||||
// ensure nothing keeps cached between tests
|
||||
passwordAuthenticator.getCredentialsCache().invalidate();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass()
|
||||
{
|
||||
DatabaseDescriptor.setCredentialsValidity(DatabaseDescriptor.getRawConfig().credentials_validity_in_ms);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectAllWhenPermissionsAreNotCached() throws Throwable
|
||||
{
|
||||
assertEmpty(execute("SELECT * FROM vts.credentials_cache_keys"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectAllWhenPermissionsAreCached() throws Throwable
|
||||
{
|
||||
cachePermissions(ROLE_A);
|
||||
cachePermissions(ROLE_B);
|
||||
|
||||
assertRows(execute("SELECT * FROM vts.credentials_cache_keys"),
|
||||
row("role_a"),
|
||||
row("role_b"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectPartitionWhenPermissionsAreNotCached() throws Throwable
|
||||
{
|
||||
assertEmpty(execute("SELECT * FROM vts.credentials_cache_keys WHERE role='role_a'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectPartitionWhenPermissionsAreCached() throws Throwable
|
||||
{
|
||||
cachePermissions(ROLE_A);
|
||||
cachePermissions(ROLE_B);
|
||||
|
||||
assertRows(execute("SELECT * FROM vts.credentials_cache_keys WHERE role='role_a'"),
|
||||
row("role_a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeletePartition() throws Throwable
|
||||
{
|
||||
cachePermissions(ROLE_A);
|
||||
cachePermissions(ROLE_B);
|
||||
|
||||
execute("DELETE FROM vts.credentials_cache_keys WHERE role='role_a'");
|
||||
|
||||
assertRows(execute("SELECT * FROM vts.credentials_cache_keys"),
|
||||
row("role_b"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeletePartitionWithInvalidValues() throws Throwable
|
||||
{
|
||||
cachePermissions(ROLE_A);
|
||||
|
||||
execute("DELETE FROM vts.credentials_cache_keys WHERE role='invalid_role'");
|
||||
|
||||
assertRows(execute("SELECT * FROM vts.credentials_cache_keys WHERE role='role_a'"),
|
||||
row("role_a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTruncateTable() throws Throwable
|
||||
{
|
||||
cachePermissions(ROLE_A);
|
||||
cachePermissions(ROLE_B);
|
||||
|
||||
execute("TRUNCATE vts.credentials_cache_keys");
|
||||
|
||||
assertEmpty(execute("SELECT * FROM vts.credentials_cache_keys"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnsupportedOperations() throws Throwable
|
||||
{
|
||||
// range tombstone is not supported, however, this table has no clustering columns, so it is not covered by tests
|
||||
|
||||
// column deletion is not supported, however, this table has no regular columns, so it is not covered by tests
|
||||
|
||||
// insert is not supported
|
||||
assertInvalidMessage("Column modification is not supported by table vts.credentials_cache_keys",
|
||||
"INSERT INTO vts.credentials_cache_keys (role) VALUES ('role_e')");
|
||||
|
||||
// update is not supported, however, this table has no regular columns, so it is not covered by tests
|
||||
}
|
||||
|
||||
private void cachePermissions(RoleResource roleResource)
|
||||
{
|
||||
IAuthenticator.SaslNegotiator saslNegotiator = passwordAuthenticator.newSaslNegotiator(null);
|
||||
saslNegotiator.evaluateResponse(new PlainTextAuthProvider(roleResource.getRoleName(), "ignored")
|
||||
.newAuthenticator((EndPoint) null, null)
|
||||
.initialResponse());
|
||||
saslNegotiator.getAuthenticatedUser();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
* 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.cassandra.db.virtual;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.security.auth.Subject;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.apache.cassandra.auth.AuthTestUtils;
|
||||
import org.apache.cassandra.auth.AuthenticatedUser;
|
||||
import org.apache.cassandra.auth.CassandraPrincipal;
|
||||
import org.apache.cassandra.auth.IAuthorizer;
|
||||
import org.apache.cassandra.auth.IResource;
|
||||
import org.apache.cassandra.auth.IRoleManager;
|
||||
import org.apache.cassandra.auth.JMXResource;
|
||||
import org.apache.cassandra.auth.Permission;
|
||||
import org.apache.cassandra.auth.RoleResource;
|
||||
import org.apache.cassandra.auth.jmx.AuthorizationProxy;
|
||||
import org.apache.cassandra.config.DatabaseDescriptor;
|
||||
import org.apache.cassandra.cql3.CQLTester;
|
||||
|
||||
import static org.apache.cassandra.auth.AuthTestUtils.ROLE_A;
|
||||
import static org.apache.cassandra.auth.AuthTestUtils.ROLE_B;
|
||||
|
||||
public class JmxPermissionsCacheKeysTableTest extends CQLTester
|
||||
{
|
||||
private static final String KS_NAME = "vts";
|
||||
private static final AuthorizationProxy authorizationProxy = new AuthTestUtils.NoAuthSetupAuthorizationProxy();
|
||||
|
||||
@SuppressWarnings("FieldCanBeLocal")
|
||||
private JmxPermissionsCacheKeysTable table;
|
||||
|
||||
// this method is intentionally not called "setUpClass" to let it throw exception brought by startJMXServer method
|
||||
@BeforeClass
|
||||
public static void setup() throws Exception {
|
||||
// high value is used for convenient debugging
|
||||
DatabaseDescriptor.setPermissionsValidity(20_000);
|
||||
|
||||
CQLTester.setUpClass();
|
||||
CQLTester.requireAuthentication();
|
||||
|
||||
IRoleManager roleManager = DatabaseDescriptor.getRoleManager();
|
||||
roleManager.createRole(AuthenticatedUser.SYSTEM_USER, ROLE_A, AuthTestUtils.getLoginRoleOptions());
|
||||
roleManager.createRole(AuthenticatedUser.SYSTEM_USER, ROLE_B, AuthTestUtils.getLoginRoleOptions());
|
||||
|
||||
List<IResource> resources = Arrays.asList(
|
||||
JMXResource.root(),
|
||||
JMXResource.mbean("org.apache.cassandra.db:type=Tables,*"));
|
||||
|
||||
IAuthorizer authorizer = DatabaseDescriptor.getAuthorizer();
|
||||
for (IResource resource : resources)
|
||||
{
|
||||
Set<Permission> permissions = resource.applicablePermissions();
|
||||
authorizer.grant(AuthenticatedUser.SYSTEM_USER, permissions, resource, ROLE_A);
|
||||
authorizer.grant(AuthenticatedUser.SYSTEM_USER, permissions, resource, ROLE_B);
|
||||
}
|
||||
|
||||
startJMXServer();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void config()
|
||||
{
|
||||
table = new JmxPermissionsCacheKeysTable(KS_NAME);
|
||||
VirtualKeyspaceRegistry.instance.register(new VirtualKeyspace(KS_NAME, ImmutableList.of(table)));
|
||||
|
||||
// ensure nothing keeps cached between tests
|
||||
AuthorizationProxy.jmxPermissionsCache.invalidate();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass()
|
||||
{
|
||||
DatabaseDescriptor.setPermissionsValidity(DatabaseDescriptor.getRawConfig().permissions_validity_in_ms);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectAllWhenPermissionsAreNotCached() throws Throwable
|
||||
{
|
||||
assertEmpty(execute("SELECT * FROM vts.jmx_permissions_cache_keys"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectAllWhenPermissionsAreCached() throws Throwable
|
||||
{
|
||||
cachePermissions(ROLE_A);
|
||||
cachePermissions(ROLE_B);
|
||||
|
||||
assertRows(execute("SELECT * FROM vts.jmx_permissions_cache_keys"),
|
||||
row("role_a"),
|
||||
row("role_b"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectPartitionWhenPermissionsAreNotCached() throws Throwable
|
||||
{
|
||||
assertEmpty(execute("SELECT * FROM vts.jmx_permissions_cache_keys WHERE role='role_a'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectPartitionWhenPermissionsAreCached() throws Throwable
|
||||
{
|
||||
cachePermissions(ROLE_A);
|
||||
cachePermissions(ROLE_B);
|
||||
|
||||
assertRows(execute("SELECT * FROM vts.jmx_permissions_cache_keys WHERE role='role_a'"),
|
||||
row("role_a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeletePartition() throws Throwable
|
||||
{
|
||||
cachePermissions(ROLE_A);
|
||||
cachePermissions(ROLE_B);
|
||||
|
||||
execute("DELETE FROM vts.jmx_permissions_cache_keys WHERE role='role_a'");
|
||||
|
||||
assertRows(execute("SELECT * FROM vts.jmx_permissions_cache_keys"),
|
||||
row("role_b"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeletePartitionWithInvalidValues() throws Throwable
|
||||
{
|
||||
cachePermissions(ROLE_A);
|
||||
|
||||
execute("DELETE FROM vts.jmx_permissions_cache_keys WHERE role='invalid_role'");
|
||||
|
||||
assertRows(execute("SELECT * FROM vts.jmx_permissions_cache_keys WHERE role='role_a'"),
|
||||
row("role_a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTruncateTable() throws Throwable
|
||||
{
|
||||
cachePermissions(ROLE_A);
|
||||
cachePermissions(ROLE_B);
|
||||
|
||||
execute("TRUNCATE vts.jmx_permissions_cache_keys");
|
||||
|
||||
assertEmpty(execute("SELECT * FROM vts.jmx_permissions_cache_keys"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnsupportedOperations() throws Throwable
|
||||
{
|
||||
// range tombstone is not supported, however, this table has no clustering columns, so it is not covered by tests
|
||||
|
||||
// column deletion is not supported, however, this table has no regular columns, so it is not covered by tests
|
||||
|
||||
// insert is not supported
|
||||
assertInvalidMessage("Column modification is not supported by table vts.jmx_permissions_cache_keys",
|
||||
"INSERT INTO vts.jmx_permissions_cache_keys (role) VALUES ('role_e')");
|
||||
|
||||
// update is not supported, however, this table has no regular columns, so it is not covered by tests
|
||||
}
|
||||
|
||||
private void cachePermissions(RoleResource roleResource)
|
||||
{
|
||||
Subject userSubject = new Subject();
|
||||
userSubject.getPrincipals().add(new CassandraPrincipal(roleResource.getRoleName()));
|
||||
|
||||
authorizationProxy.authorize(userSubject, "queryNames", null);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* 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.cassandra.db.virtual;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.apache.cassandra.auth.AuthTestUtils;
|
||||
import org.apache.cassandra.auth.AuthenticatedUser;
|
||||
import org.apache.cassandra.auth.DCPermissions;
|
||||
import org.apache.cassandra.auth.INetworkAuthorizer;
|
||||
import org.apache.cassandra.auth.IRoleManager;
|
||||
import org.apache.cassandra.auth.RoleResource;
|
||||
import org.apache.cassandra.config.DatabaseDescriptor;
|
||||
import org.apache.cassandra.cql3.CQLTester;
|
||||
|
||||
import static org.apache.cassandra.auth.AuthTestUtils.ROLE_A;
|
||||
import static org.apache.cassandra.auth.AuthTestUtils.ROLE_B;
|
||||
|
||||
public class NetworkPermissionsCacheKeysTableTest extends CQLTester
|
||||
{
|
||||
private static final String KS_NAME = "vts";
|
||||
|
||||
@SuppressWarnings("FieldCanBeLocal")
|
||||
private NetworkPermissionsCacheKeysTable table;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass()
|
||||
{
|
||||
// high value is used for convenient debugging
|
||||
DatabaseDescriptor.setPermissionsValidity(20_000);
|
||||
|
||||
CQLTester.setUpClass();
|
||||
CQLTester.requireAuthentication();
|
||||
|
||||
IRoleManager roleManager = DatabaseDescriptor.getRoleManager();
|
||||
roleManager.createRole(AuthenticatedUser.SYSTEM_USER, ROLE_A, AuthTestUtils.getLoginRoleOptions());
|
||||
roleManager.createRole(AuthenticatedUser.SYSTEM_USER, ROLE_B, AuthTestUtils.getLoginRoleOptions());
|
||||
|
||||
INetworkAuthorizer networkAuthorizer = DatabaseDescriptor.getNetworkAuthorizer();
|
||||
networkAuthorizer.setRoleDatacenters(ROLE_A, DCPermissions.all());
|
||||
networkAuthorizer.setRoleDatacenters(ROLE_B, DCPermissions.subset(DATA_CENTER, DATA_CENTER_REMOTE));
|
||||
}
|
||||
|
||||
@Before
|
||||
public void config()
|
||||
{
|
||||
table = new NetworkPermissionsCacheKeysTable(KS_NAME);
|
||||
VirtualKeyspaceRegistry.instance.register(new VirtualKeyspace(KS_NAME, ImmutableList.of(table)));
|
||||
|
||||
// ensure nothing keeps cached between tests
|
||||
AuthenticatedUser.networkPermissionsCache.invalidate();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass()
|
||||
{
|
||||
DatabaseDescriptor.setPermissionsValidity(DatabaseDescriptor.getRawConfig().permissions_validity_in_ms);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectAllWhenPermissionsAreNotCached() throws Throwable
|
||||
{
|
||||
assertEmpty(execute("SELECT * FROM vts.network_permissions_cache_keys"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectAllWhenPermissionsAreCached() throws Throwable
|
||||
{
|
||||
cachePermissions(ROLE_A);
|
||||
cachePermissions(ROLE_B);
|
||||
|
||||
assertRows(execute("SELECT * FROM vts.network_permissions_cache_keys"),
|
||||
row("role_a"),
|
||||
row("role_b"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectPartitionWhenPermissionsAreNotCached() throws Throwable
|
||||
{
|
||||
assertEmpty(execute("SELECT * FROM vts.network_permissions_cache_keys WHERE role='role_a'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectPartitionWhenPermissionsAreCached() throws Throwable
|
||||
{
|
||||
cachePermissions(ROLE_A);
|
||||
cachePermissions(ROLE_B);
|
||||
|
||||
assertRows(execute("SELECT * FROM vts.network_permissions_cache_keys WHERE role='role_a'"),
|
||||
row("role_a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeletePartition() throws Throwable
|
||||
{
|
||||
cachePermissions(ROLE_A);
|
||||
cachePermissions(ROLE_B);
|
||||
|
||||
execute("DELETE FROM vts.network_permissions_cache_keys WHERE role='role_a'");
|
||||
|
||||
assertRows(execute("SELECT * FROM vts.network_permissions_cache_keys"),
|
||||
row("role_b"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeletePartitionWithInvalidValues() throws Throwable
|
||||
{
|
||||
cachePermissions(ROLE_A);
|
||||
|
||||
execute("DELETE FROM vts.network_permissions_cache_keys WHERE role='invalid_role'");
|
||||
|
||||
assertRows(execute("SELECT * FROM vts.network_permissions_cache_keys WHERE role='role_a'"),
|
||||
row("role_a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTruncateTable() throws Throwable
|
||||
{
|
||||
cachePermissions(ROLE_A);
|
||||
cachePermissions(ROLE_B);
|
||||
|
||||
execute("TRUNCATE vts.network_permissions_cache_keys");
|
||||
|
||||
assertEmpty(execute("SELECT * FROM vts.network_permissions_cache_keys"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnsupportedOperations() throws Throwable
|
||||
{
|
||||
// range tombstone is not supported, however, this table has no clustering columns, so it is not covered by tests
|
||||
|
||||
// column deletion is not supported, however, this table has no regular columns, so it is not covered by tests
|
||||
|
||||
// insert is not supported
|
||||
assertInvalidMessage("Column modification is not supported by table vts.network_permissions_cache_keys",
|
||||
"INSERT INTO vts.network_permissions_cache_keys (role) VALUES ('role_e')");
|
||||
|
||||
// update is not supported, however, this table has no regular columns, so it is not covered by tests
|
||||
}
|
||||
|
||||
private void cachePermissions(RoleResource roleResource)
|
||||
{
|
||||
AuthenticatedUser.networkPermissionsCache.get(roleResource);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
* 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.cassandra.db.virtual;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.apache.cassandra.auth.AuthTestUtils;
|
||||
import org.apache.cassandra.auth.AuthenticatedUser;
|
||||
import org.apache.cassandra.auth.DataResource;
|
||||
import org.apache.cassandra.auth.IAuthorizer;
|
||||
import org.apache.cassandra.auth.IResource;
|
||||
import org.apache.cassandra.auth.IRoleManager;
|
||||
import org.apache.cassandra.auth.Permission;
|
||||
import org.apache.cassandra.auth.RoleResource;
|
||||
import org.apache.cassandra.config.DatabaseDescriptor;
|
||||
import org.apache.cassandra.cql3.CQLTester;
|
||||
|
||||
import static org.apache.cassandra.auth.AuthTestUtils.ROLE_A;
|
||||
import static org.apache.cassandra.auth.AuthTestUtils.ROLE_B;
|
||||
|
||||
public class PermissionsCacheKeysTableTest extends CQLTester
|
||||
{
|
||||
private static final String KS_NAME = "vts";
|
||||
|
||||
@SuppressWarnings("FieldCanBeLocal")
|
||||
private PermissionsCacheKeysTable table;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass()
|
||||
{
|
||||
// high value is used for convenient debugging
|
||||
DatabaseDescriptor.setPermissionsValidity(20_000);
|
||||
|
||||
CQLTester.setUpClass();
|
||||
CQLTester.requireAuthentication();
|
||||
|
||||
IRoleManager roleManager = DatabaseDescriptor.getRoleManager();
|
||||
roleManager.createRole(AuthenticatedUser.SYSTEM_USER, ROLE_A, AuthTestUtils.getLoginRoleOptions());
|
||||
roleManager.createRole(AuthenticatedUser.SYSTEM_USER, ROLE_B, AuthTestUtils.getLoginRoleOptions());
|
||||
|
||||
List<IResource> resources = Arrays.asList(
|
||||
DataResource.root(),
|
||||
DataResource.keyspace(KEYSPACE),
|
||||
DataResource.table(KEYSPACE, "t1"));
|
||||
|
||||
IAuthorizer authorizer = DatabaseDescriptor.getAuthorizer();
|
||||
for (IResource resource : resources)
|
||||
{
|
||||
Set<Permission> permissions = resource.applicablePermissions();
|
||||
authorizer.grant(AuthenticatedUser.SYSTEM_USER, permissions, resource, ROLE_A);
|
||||
authorizer.grant(AuthenticatedUser.SYSTEM_USER, permissions, resource, ROLE_B);
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
public void config()
|
||||
{
|
||||
table = new PermissionsCacheKeysTable(KS_NAME);
|
||||
VirtualKeyspaceRegistry.instance.register(new VirtualKeyspace(KS_NAME, ImmutableList.of(table)));
|
||||
|
||||
// ensure nothing keeps cached between tests
|
||||
AuthenticatedUser.permissionsCache.invalidate();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass()
|
||||
{
|
||||
DatabaseDescriptor.setPermissionsValidity(DatabaseDescriptor.getRawConfig().permissions_validity_in_ms);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectAllWhenPermissionsAreNotCached() throws Throwable
|
||||
{
|
||||
assertEmpty(execute("SELECT * FROM vts.permissions_cache_keys"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectAllWhenPermissionsAreCached() throws Throwable
|
||||
{
|
||||
cachePermissionsForResource(ROLE_A, DataResource.root());
|
||||
cachePermissionsForResource(ROLE_A, DataResource.keyspace(KEYSPACE));
|
||||
cachePermissionsForResource(ROLE_B, DataResource.table(KEYSPACE, "t1"));
|
||||
|
||||
assertRows(execute("SELECT * FROM vts.permissions_cache_keys"),
|
||||
row("role_a", "data"),
|
||||
row("role_a", "data/cql_test_keyspace"),
|
||||
row("role_b", "data/cql_test_keyspace/t1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectPartitionWhenPermissionsAreNotCached() throws Throwable
|
||||
{
|
||||
assertEmpty(execute("SELECT * FROM vts.permissions_cache_keys WHERE role='role_a' AND resource='data'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectPartitionWhenPermissionsAreCached() throws Throwable
|
||||
{
|
||||
cachePermissionsForResource(ROLE_A, DataResource.root());
|
||||
cachePermissionsForResource(ROLE_A, DataResource.keyspace(KEYSPACE));
|
||||
cachePermissionsForResource(ROLE_B, DataResource.table(KEYSPACE, "t1"));
|
||||
|
||||
assertRows(execute("SELECT * FROM vts.permissions_cache_keys WHERE role='role_a' AND resource='data'"),
|
||||
row("role_a", "data"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeletePartition() throws Throwable
|
||||
{
|
||||
cachePermissionsForResource(ROLE_A, DataResource.root());
|
||||
cachePermissionsForResource(ROLE_A, DataResource.keyspace(KEYSPACE));
|
||||
|
||||
execute("DELETE FROM vts.permissions_cache_keys WHERE role='role_a' AND resource='data'");
|
||||
|
||||
assertRows(execute("SELECT * FROM vts.permissions_cache_keys"),
|
||||
row("role_a", "data/cql_test_keyspace"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeletePartitionWithInvalidValues() throws Throwable
|
||||
{
|
||||
cachePermissionsForResource(ROLE_A, DataResource.root());
|
||||
|
||||
execute("DELETE FROM vts.permissions_cache_keys WHERE role='invalid_role' AND resource='data'");
|
||||
execute("DELETE FROM vts.permissions_cache_keys WHERE role='role_a' AND resource='invalid_resource'");
|
||||
|
||||
assertRows(execute("SELECT * FROM vts.permissions_cache_keys WHERE role='role_a' AND resource='data'"),
|
||||
row("role_a", "data"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTruncateTable() throws Throwable
|
||||
{
|
||||
cachePermissionsForResource(ROLE_A, DataResource.root());
|
||||
cachePermissionsForResource(ROLE_B, DataResource.table(KEYSPACE, "t1"));
|
||||
|
||||
execute("TRUNCATE vts.permissions_cache_keys");
|
||||
|
||||
assertEmpty(execute("SELECT * FROM vts.permissions_cache_keys"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnsupportedOperations() throws Throwable
|
||||
{
|
||||
// range tombstone is not supported, however, this table has no clustering columns, so it is not covered by tests
|
||||
|
||||
// column deletion is not supported, however, this table has no regular columns, so it is not covered by tests
|
||||
|
||||
// insert is not supported
|
||||
assertInvalidMessage("Column modification is not supported by table vts.permissions_cache_keys",
|
||||
"INSERT INTO vts.permissions_cache_keys (role, resource) VALUES ('role_e', 'data')");
|
||||
|
||||
// update is not supported, however, this table has no regular columns, so it is not covered by tests
|
||||
}
|
||||
|
||||
private void cachePermissionsForResource(RoleResource roleResource, IResource resource)
|
||||
{
|
||||
AuthenticatedUser role = new AuthenticatedUser(roleResource.getRoleName());
|
||||
role.getPermissions(resource);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* 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.cassandra.db.virtual;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.apache.cassandra.auth.AuthTestUtils;
|
||||
import org.apache.cassandra.auth.AuthenticatedUser;
|
||||
import org.apache.cassandra.auth.IRoleManager;
|
||||
import org.apache.cassandra.auth.RoleResource;
|
||||
import org.apache.cassandra.auth.Roles;
|
||||
import org.apache.cassandra.config.DatabaseDescriptor;
|
||||
import org.apache.cassandra.cql3.CQLTester;
|
||||
|
||||
import static org.apache.cassandra.auth.AuthTestUtils.ROLE_A;
|
||||
import static org.apache.cassandra.auth.AuthTestUtils.ROLE_B;
|
||||
import static org.apache.cassandra.auth.AuthTestUtils.ROLE_C;
|
||||
|
||||
public class RolesCacheKeysTableTest extends CQLTester
|
||||
{
|
||||
private static final String KS_NAME = "vts";
|
||||
|
||||
@SuppressWarnings("FieldCanBeLocal")
|
||||
private RolesCacheKeysTable table;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass()
|
||||
{
|
||||
// high value is used for convenient debugging
|
||||
DatabaseDescriptor.setRolesValidity(20_000);
|
||||
|
||||
CQLTester.setUpClass();
|
||||
CQLTester.requireAuthentication();
|
||||
|
||||
IRoleManager roleManager = DatabaseDescriptor.getRoleManager();
|
||||
roleManager.createRole(AuthenticatedUser.SYSTEM_USER, ROLE_A, AuthTestUtils.getLoginRoleOptions());
|
||||
roleManager.createRole(AuthenticatedUser.SYSTEM_USER, ROLE_B, AuthTestUtils.getLoginRoleOptions());
|
||||
roleManager.createRole(AuthenticatedUser.SYSTEM_USER, ROLE_C, AuthTestUtils.getLoginRoleOptions());
|
||||
|
||||
AuthTestUtils.grantRolesTo(roleManager, ROLE_A, ROLE_C);
|
||||
AuthTestUtils.grantRolesTo(roleManager, ROLE_B, ROLE_C);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void config()
|
||||
{
|
||||
table = new RolesCacheKeysTable(KS_NAME);
|
||||
VirtualKeyspaceRegistry.instance.register(new VirtualKeyspace(KS_NAME, ImmutableList.of(table)));
|
||||
|
||||
// ensure nothing keeps cached between tests
|
||||
Roles.cache.invalidate();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass()
|
||||
{
|
||||
DatabaseDescriptor.setRolesValidity(DatabaseDescriptor.getRawConfig().roles_validity_in_ms);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectAllWhenPermissionsAreNotCached() throws Throwable
|
||||
{
|
||||
assertEmpty(execute("SELECT * FROM vts.roles_cache_keys"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectAllWhenPermissionsAreCached() throws Throwable
|
||||
{
|
||||
cachePermissions(ROLE_A);
|
||||
cachePermissions(ROLE_B);
|
||||
|
||||
assertRows(execute("SELECT * FROM vts.roles_cache_keys"),
|
||||
row("role_a"),
|
||||
row("role_b"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectPartitionWhenPermissionsAreNotCached() throws Throwable
|
||||
{
|
||||
assertEmpty(execute("SELECT * FROM vts.roles_cache_keys WHERE role='role_a'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectPartitionWhenPermissionsAreCached() throws Throwable
|
||||
{
|
||||
cachePermissions(ROLE_A);
|
||||
cachePermissions(ROLE_B);
|
||||
|
||||
assertRows(execute("SELECT * FROM vts.roles_cache_keys WHERE role='role_a'"),
|
||||
row("role_a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeletePartition() throws Throwable
|
||||
{
|
||||
cachePermissions(ROLE_A);
|
||||
cachePermissions(ROLE_B);
|
||||
|
||||
execute("DELETE FROM vts.roles_cache_keys WHERE role='role_a'");
|
||||
|
||||
assertRows(execute("SELECT * FROM vts.roles_cache_keys"),
|
||||
row("role_b"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeletePartitionWithInvalidValues() throws Throwable
|
||||
{
|
||||
cachePermissions(ROLE_A);
|
||||
|
||||
execute("DELETE FROM vts.roles_cache_keys WHERE role='invalid_role'");
|
||||
|
||||
assertRows(execute("SELECT * FROM vts.roles_cache_keys WHERE role='role_a'"),
|
||||
row("role_a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTruncateTable() throws Throwable
|
||||
{
|
||||
cachePermissions(ROLE_A);
|
||||
cachePermissions(ROLE_B);
|
||||
|
||||
execute("TRUNCATE vts.roles_cache_keys");
|
||||
|
||||
assertEmpty(execute("SELECT * FROM vts.roles_cache_keys"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnsupportedOperations() throws Throwable
|
||||
{
|
||||
// range tombstone is not supported, however, this table has no clustering columns, so it is not covered by tests
|
||||
|
||||
// column deletion is not supported, however, this table has no regular columns, so it is not covered by tests
|
||||
|
||||
// insert is not supported
|
||||
assertInvalidMessage("Column modification is not supported by table vts.roles_cache_keys",
|
||||
"INSERT INTO vts.roles_cache_keys (role) VALUES ('role_e')");
|
||||
|
||||
// update is not supported, however, this table has no regular columns, so it is not covered by tests
|
||||
}
|
||||
|
||||
private void cachePermissions(RoleResource roleResource)
|
||||
{
|
||||
Roles.getRoleDetails(roleResource);
|
||||
}
|
||||
}
|
||||
|
|
@ -30,10 +30,8 @@ import org.apache.cassandra.SchemaLoader;
|
|||
import org.apache.cassandra.auth.AuthKeyspace;
|
||||
import org.apache.cassandra.auth.AuthTestUtils;
|
||||
import org.apache.cassandra.auth.AuthenticatedUser;
|
||||
import org.apache.cassandra.auth.CassandraAuthorizer;
|
||||
import org.apache.cassandra.auth.DataResource;
|
||||
import org.apache.cassandra.auth.IResource;
|
||||
import org.apache.cassandra.auth.IRoleManager;
|
||||
import org.apache.cassandra.auth.Permission;
|
||||
import org.apache.cassandra.auth.Roles;
|
||||
import org.apache.cassandra.config.DatabaseDescriptor;
|
||||
|
|
@ -64,7 +62,8 @@ public class ClientStateTest
|
|||
}
|
||||
|
||||
@Test
|
||||
public void permissionsCheckStartsAtHeadOfResourceChain() throws Exception {
|
||||
public void permissionsCheckStartsAtHeadOfResourceChain()
|
||||
{
|
||||
// verify that when performing a permissions check, we start from the
|
||||
// root IResource in the applicable hierarchy and proceed to the more
|
||||
// granular resources until we find the required permission (or until
|
||||
|
|
@ -94,12 +93,10 @@ public class ClientStateTest
|
|||
public boolean canLogin() { return true; }
|
||||
};
|
||||
|
||||
IRoleManager roleManager = new AuthTestUtils.LocalCassandraRoleManager();
|
||||
roleManager.setup();
|
||||
Roles.initRolesCache(roleManager, () -> true);
|
||||
Roles.cache.invalidate();
|
||||
|
||||
// finally, need to configure CassandraAuthorizer so we don't shortcircuit out of the authz process
|
||||
DatabaseDescriptor.setAuthorizer(new CassandraAuthorizer());
|
||||
DatabaseDescriptor.setAuthorizer(new AuthTestUtils.LocalCassandraAuthorizer());
|
||||
|
||||
// check permissions on the table, which should check for the root resource first
|
||||
// & return successfully without needing to proceed further
|
||||
|
|
|
|||
|
|
@ -46,20 +46,20 @@ public class InvalidateCredentialsCacheTest extends CQLTester
|
|||
{
|
||||
SchemaLoader.prepareServer();
|
||||
AuthTestUtils.LocalCassandraRoleManager roleManager = new AuthTestUtils.LocalCassandraRoleManager();
|
||||
PasswordAuthenticator authenticator = new AuthTestUtils.LocalPasswordAuthenticator();
|
||||
PasswordAuthenticator passwordAuthenticator = new AuthTestUtils.LocalPasswordAuthenticator();
|
||||
SchemaLoader.setupAuth(roleManager,
|
||||
authenticator,
|
||||
new AuthTestUtils.LocalCassandraAuthorizer(),
|
||||
new AuthTestUtils.LocalCassandraNetworkAuthorizer());
|
||||
passwordAuthenticator,
|
||||
new AuthTestUtils.LocalCassandraAuthorizer(),
|
||||
new AuthTestUtils.LocalCassandraNetworkAuthorizer());
|
||||
|
||||
roleManager.createRole(AuthenticatedUser.SYSTEM_USER, ROLE_A, AuthTestUtils.getLoginRoleOptions());
|
||||
roleManager.createRole(AuthenticatedUser.SYSTEM_USER, ROLE_B, AuthTestUtils.getLoginRoleOptions());
|
||||
|
||||
roleANegotiator = authenticator.newSaslNegotiator(null);
|
||||
roleANegotiator = passwordAuthenticator.newSaslNegotiator(null);
|
||||
roleANegotiator.evaluateResponse(new PlainTextAuthProvider(ROLE_A.getRoleName(), "ignored")
|
||||
.newAuthenticator((EndPoint) null, null)
|
||||
.initialResponse());
|
||||
roleBNegotiator = authenticator.newSaslNegotiator(null);
|
||||
roleBNegotiator = passwordAuthenticator.newSaslNegotiator(null);
|
||||
roleBNegotiator.evaluateResponse(new PlainTextAuthProvider(ROLE_B.getRoleName(), "ignored")
|
||||
.newAuthenticator((EndPoint) null, null)
|
||||
.initialResponse());
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
|
||||
public class InvalidateJmxPermissionsCacheTest extends CQLTester
|
||||
{
|
||||
private static final AuthorizationProxy authorizationProxy = new NoAuthSetupAuthorizationProxy();
|
||||
private static final AuthorizationProxy authorizationProxy = new AuthTestUtils.NoAuthSetupAuthorizationProxy();
|
||||
|
||||
@BeforeClass
|
||||
public static void setup() throws Exception
|
||||
|
|
@ -50,9 +50,9 @@ public class InvalidateJmxPermissionsCacheTest extends CQLTester
|
|||
AuthTestUtils.LocalCassandraRoleManager roleManager = new AuthTestUtils.LocalCassandraRoleManager();
|
||||
AuthTestUtils.LocalCassandraAuthorizer authorizer = new AuthTestUtils.LocalCassandraAuthorizer();
|
||||
SchemaLoader.setupAuth(roleManager,
|
||||
new AuthTestUtils.LocalPasswordAuthenticator(),
|
||||
authorizer,
|
||||
new AuthTestUtils.LocalCassandraNetworkAuthorizer());
|
||||
new AuthTestUtils.LocalPasswordAuthenticator(),
|
||||
authorizer,
|
||||
new AuthTestUtils.LocalCassandraNetworkAuthorizer());
|
||||
|
||||
JMXResource rootJmxResource = JMXResource.root();
|
||||
Set<Permission> jmxPermissions = rootJmxResource.applicablePermissions();
|
||||
|
|
@ -178,12 +178,4 @@ public class InvalidateJmxPermissionsCacheTest extends CQLTester
|
|||
return subject;
|
||||
}
|
||||
|
||||
private static class NoAuthSetupAuthorizationProxy extends AuthorizationProxy
|
||||
{
|
||||
public NoAuthSetupAuthorizationProxy()
|
||||
{
|
||||
super();
|
||||
this.isAuthSetupComplete = () -> true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,9 +40,9 @@ public class InvalidateNetworkPermissionsCacheTest extends CQLTester
|
|||
SchemaLoader.prepareServer();
|
||||
AuthTestUtils.LocalCassandraRoleManager roleManager = new AuthTestUtils.LocalCassandraRoleManager();
|
||||
SchemaLoader.setupAuth(roleManager,
|
||||
new AuthTestUtils.LocalPasswordAuthenticator(),
|
||||
new AuthTestUtils.LocalCassandraAuthorizer(),
|
||||
new AuthTestUtils.LocalCassandraNetworkAuthorizer());
|
||||
new AuthTestUtils.LocalPasswordAuthenticator(),
|
||||
new AuthTestUtils.LocalCassandraAuthorizer(),
|
||||
new AuthTestUtils.LocalCassandraNetworkAuthorizer());
|
||||
|
||||
roleManager.createRole(AuthenticatedUser.SYSTEM_USER, ROLE_A, AuthTestUtils.getLoginRoleOptions());
|
||||
roleManager.createRole(AuthenticatedUser.SYSTEM_USER, ROLE_B, AuthTestUtils.getLoginRoleOptions());
|
||||
|
|
|
|||
|
|
@ -56,9 +56,9 @@ public class InvalidatePermissionsCacheTest extends CQLTester
|
|||
AuthTestUtils.LocalCassandraRoleManager roleManager = new AuthTestUtils.LocalCassandraRoleManager();
|
||||
AuthTestUtils.LocalCassandraAuthorizer authorizer = new AuthTestUtils.LocalCassandraAuthorizer();
|
||||
SchemaLoader.setupAuth(roleManager,
|
||||
new AuthTestUtils.LocalPasswordAuthenticator(),
|
||||
authorizer,
|
||||
new AuthTestUtils.LocalCassandraNetworkAuthorizer());
|
||||
new AuthTestUtils.LocalPasswordAuthenticator(),
|
||||
authorizer,
|
||||
new AuthTestUtils.LocalCassandraNetworkAuthorizer());
|
||||
|
||||
roleManager.createRole(AuthenticatedUser.SYSTEM_USER, ROLE_A, AuthTestUtils.getLoginRoleOptions());
|
||||
roleManager.createRole(AuthenticatedUser.SYSTEM_USER, ROLE_B, AuthTestUtils.getLoginRoleOptions());
|
||||
|
|
@ -66,6 +66,7 @@ public class InvalidatePermissionsCacheTest extends CQLTester
|
|||
List<IResource> resources = Arrays.asList(
|
||||
DataResource.root(),
|
||||
DataResource.keyspace(KEYSPACE),
|
||||
DataResource.allTables(KEYSPACE),
|
||||
DataResource.table(KEYSPACE, "t1"),
|
||||
RoleResource.root(),
|
||||
RoleResource.role("role_x"),
|
||||
|
|
@ -104,10 +105,10 @@ public class InvalidatePermissionsCacheTest extends CQLTester
|
|||
" [(-pwf <passwordFilePath> | --password-file <passwordFilePath>)]\n" +
|
||||
" [(-u <username> | --username <username>)] invalidatepermissionscache\n" +
|
||||
" [--all-functions] [--all-keyspaces] [--all-mbeans] [--all-roles]\n" +
|
||||
" [--function <function>]\n" +
|
||||
" [--all-tables] [--function <function>]\n" +
|
||||
" [--functions-in-keyspace <functions-in-keyspace>]\n" +
|
||||
" [--keyspace <keyspace>] [--mbean <mbean>] [--role <role>]\n" +
|
||||
" [--table <table>] [--] [<user>]\n" +
|
||||
" [--table <table>] [--] [<role>]\n" +
|
||||
"\n" +
|
||||
"OPTIONS\n" +
|
||||
" --all-functions\n" +
|
||||
|
|
@ -122,6 +123,9 @@ public class InvalidatePermissionsCacheTest extends CQLTester
|
|||
" --all-roles\n" +
|
||||
" Invalidate permissions for 'ALL ROLES'\n" +
|
||||
"\n" +
|
||||
" --all-tables\n" +
|
||||
" Invalidate permissions for 'ALL TABLES'\n" +
|
||||
"\n" +
|
||||
" --function <function>\n" +
|
||||
" Function to invalidate permissions for (you must specify\n" +
|
||||
" --functions-in-keyspace for using this option; function format:\n" +
|
||||
|
|
@ -166,8 +170,9 @@ public class InvalidatePermissionsCacheTest extends CQLTester
|
|||
" list of argument, (useful when arguments might be mistaken for\n" +
|
||||
" command-line options\n" +
|
||||
"\n" +
|
||||
" [<user>]\n" +
|
||||
" A specific user for whom permissions need to be invalidated\n" +
|
||||
" [<role>]\n" +
|
||||
" A role for which permissions to specified resources need to be\n" +
|
||||
" invalidated\n" +
|
||||
"\n" +
|
||||
"\n";
|
||||
assertThat(tool.getStdout()).isEqualTo(help);
|
||||
|
|
@ -179,28 +184,40 @@ public class InvalidatePermissionsCacheTest extends CQLTester
|
|||
ToolRunner.ToolResult tool = ToolRunner.invokeNodetool("invalidatepermissionscache", "--all-keyspaces");
|
||||
assertThat(tool.getExitCode()).isEqualTo(1);
|
||||
assertThat(tool.getStdout())
|
||||
.isEqualTo(wrapByDefaultNodetoolMessage("No options allowed without a <user> being specified"));
|
||||
.isEqualTo(wrapByDefaultNodetoolMessage("No resource options allowed without a <role> being specified"));
|
||||
assertThat(tool.getStderr()).isEmpty();
|
||||
|
||||
tool = ToolRunner.invokeNodetool("invalidatepermissionscache", "user1", "--invalid-option");
|
||||
tool = ToolRunner.invokeNodetool("invalidatepermissionscache", "role1");
|
||||
assertThat(tool.getExitCode()).isEqualTo(1);
|
||||
assertThat(tool.getStdout())
|
||||
.isEqualTo(wrapByDefaultNodetoolMessage("A single <user> is only supported / you have a typo in the options spelling"));
|
||||
.isEqualTo(wrapByDefaultNodetoolMessage("No resource options specified"));
|
||||
assertThat(tool.getStderr()).isEmpty();
|
||||
|
||||
tool = ToolRunner.invokeNodetool("invalidatepermissionscache", "user1", "--table", "t1");
|
||||
tool = ToolRunner.invokeNodetool("invalidatepermissionscache", "role1", "--invalid-option");
|
||||
assertThat(tool.getExitCode()).isEqualTo(1);
|
||||
assertThat(tool.getStdout())
|
||||
.isEqualTo(wrapByDefaultNodetoolMessage("A single <role> is only supported / you have a typo in the resource options spelling"));
|
||||
assertThat(tool.getStderr()).isEmpty();
|
||||
|
||||
tool = ToolRunner.invokeNodetool("invalidatepermissionscache", "role1", "--all-tables");
|
||||
assertThat(tool.getExitCode()).isEqualTo(1);
|
||||
assertThat(tool.getStdout())
|
||||
.isEqualTo(wrapByDefaultNodetoolMessage("--all-tables option should be passed along with --keyspace option"));
|
||||
assertThat(tool.getStderr()).isEmpty();
|
||||
|
||||
tool = ToolRunner.invokeNodetool("invalidatepermissionscache", "role1", "--table", "t1");
|
||||
assertThat(tool.getExitCode()).isEqualTo(1);
|
||||
assertThat(tool.getStdout())
|
||||
.isEqualTo(wrapByDefaultNodetoolMessage("--table option should be passed along with --keyspace option"));
|
||||
assertThat(tool.getStderr()).isEmpty();
|
||||
|
||||
tool = ToolRunner.invokeNodetool("invalidatepermissionscache", "user1", "--function", "f[Int32Type]");
|
||||
tool = ToolRunner.invokeNodetool("invalidatepermissionscache", "role1", "--function", "f[Int32Type]");
|
||||
assertThat(tool.getExitCode()).isEqualTo(1);
|
||||
assertThat(tool.getStdout())
|
||||
.isEqualTo(wrapByDefaultNodetoolMessage("--function option should be passed along with --functions-in-keyspace option"));
|
||||
assertThat(tool.getStderr()).isEmpty();
|
||||
|
||||
tool = ToolRunner.invokeNodetool("invalidatepermissionscache", "user1", "--functions-in-keyspace",
|
||||
tool = ToolRunner.invokeNodetool("invalidatepermissionscache", "role1", "--functions-in-keyspace",
|
||||
KEYSPACE, "--function", "f[x]");
|
||||
assertThat(tool.getExitCode()).isEqualTo(1);
|
||||
assertThat(tool.getStdout())
|
||||
|
|
@ -213,6 +230,7 @@ public class InvalidatePermissionsCacheTest extends CQLTester
|
|||
{
|
||||
assertInvalidation(DataResource.root(), Collections.singletonList("--all-keyspaces"));
|
||||
assertInvalidation(DataResource.keyspace(KEYSPACE), Arrays.asList("--keyspace", KEYSPACE));
|
||||
assertInvalidation(DataResource.allTables(KEYSPACE), Arrays.asList("--keyspace", KEYSPACE, "--all-tables"));
|
||||
assertInvalidation(DataResource.table(KEYSPACE, "t1"),
|
||||
Arrays.asList("--keyspace", KEYSPACE, "--table", "t1"));
|
||||
assertInvalidation(RoleResource.root(), Collections.singletonList("--all-roles"));
|
||||
|
|
@ -273,7 +291,7 @@ public class InvalidatePermissionsCacheTest extends CQLTester
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidatePermissionsForAllUsers()
|
||||
public void testInvalidatePermissionsForAllRoles()
|
||||
{
|
||||
DataResource rootDataResource = DataResource.root();
|
||||
Set<Permission> dataPermissions = rootDataResource.applicablePermissions();
|
||||
|
|
|
|||
|
|
@ -40,9 +40,9 @@ public class InvalidateRolesCacheTest extends CQLTester
|
|||
SchemaLoader.prepareServer();
|
||||
AuthTestUtils.LocalCassandraRoleManager roleManager = new AuthTestUtils.LocalCassandraRoleManager();
|
||||
SchemaLoader.setupAuth(roleManager,
|
||||
new AuthTestUtils.LocalPasswordAuthenticator(),
|
||||
new AuthTestUtils.LocalCassandraAuthorizer(),
|
||||
new AuthTestUtils.LocalCassandraNetworkAuthorizer());
|
||||
new AuthTestUtils.LocalPasswordAuthenticator(),
|
||||
new AuthTestUtils.LocalCassandraAuthorizer(),
|
||||
new AuthTestUtils.LocalCassandraNetworkAuthorizer());
|
||||
|
||||
roleManager.createRole(AuthenticatedUser.SYSTEM_USER, ROLE_A, AuthTestUtils.getLoginRoleOptions());
|
||||
roleManager.createRole(AuthenticatedUser.SYSTEM_USER, ROLE_B, AuthTestUtils.getLoginRoleOptions());
|
||||
|
|
|
|||
Loading…
Reference in New Issue