mirror of https://github.com/apache/cassandra
Make capacity/validity/updateinterval/activeupdate for Auth Caches configurable via nodetool
patch by Aleksei Zotov; reviewed by Josh McKenzie for CASSANDRA-17063
This commit is contained in:
parent
7bd2764962
commit
bc20bddceb
|
|
@ -1,4 +1,5 @@
|
|||
4.1
|
||||
* Make capacity/validity/updateinterval/activeupdate for Auth Caches configurable via nodetool (CASSANDRA-17063)
|
||||
* Added startup check for read_ahead_kb setting (CASSANDRA-16436)
|
||||
* Avoid unecessary array allocations and initializations when performing query checks (CASSANDRA-17209)
|
||||
* Add guardrail for list operations that require read before write (CASSANDRA-17154)
|
||||
|
|
|
|||
1
NEWS.txt
1
NEWS.txt
|
|
@ -38,6 +38,7 @@ using the provided 'sstableupgrade' tool.
|
|||
|
||||
New features
|
||||
------------
|
||||
- Added ability to configure auth caches through corresponding `nodetool` commands.
|
||||
- CDC data flushing now can be configured to be non-blocking with the configuration cdc_block_writes. Setting to true,
|
||||
any writes to the CDC-enabled tables will be blocked when reaching to the limit for CDC data on disk, which is the
|
||||
existing and the default behavior. Setting to false, the writes to the CDC-enabled tables will be accepted and
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ import org.apache.cassandra.audit.AuditLogOptions;
|
|||
import org.apache.cassandra.audit.AuditLogOptionsCompositeData;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import org.apache.cassandra.auth.AuthCache;
|
||||
import org.apache.cassandra.auth.AuthCacheMBean;
|
||||
import org.apache.cassandra.auth.NetworkPermissionsCache;
|
||||
import org.apache.cassandra.auth.NetworkPermissionsCacheMBean;
|
||||
import org.apache.cassandra.auth.PasswordAuthenticator;
|
||||
|
|
@ -569,6 +570,25 @@ public class NodeProbe implements AutoCloseable
|
|||
cacheService.invalidateRowCache();
|
||||
}
|
||||
|
||||
public AuthCacheMBean getAuthCacheMBean(String cacheName)
|
||||
{
|
||||
switch (cacheName)
|
||||
{
|
||||
case PasswordAuthenticator.CredentialsCacheMBean.CACHE_NAME:
|
||||
return ccProxy;
|
||||
case AuthorizationProxy.JmxPermissionsCacheMBean.CACHE_NAME:
|
||||
return jpcProxy;
|
||||
case NetworkPermissionsCacheMBean.CACHE_NAME:
|
||||
return npcProxy;
|
||||
case PermissionsCacheMBean.CACHE_NAME:
|
||||
return pcProxy;
|
||||
case RolesCacheMBean.CACHE_NAME:
|
||||
return rcProxy;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown cache name: " + cacheName);
|
||||
}
|
||||
}
|
||||
|
||||
public void drain() throws IOException, InterruptedException, ExecutionException
|
||||
{
|
||||
ssProxy.drain();
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ public class NodeTool
|
|||
GarbageCollect.class,
|
||||
GcStats.class,
|
||||
GetAuditLog.class,
|
||||
GetAuthCacheConfig.class,
|
||||
GetBatchlogReplayTrottle.class,
|
||||
GetColumnIndexSize.class,
|
||||
GetCompactionThreshold.class,
|
||||
|
|
@ -187,6 +188,7 @@ public class NodeTool
|
|||
ResumeHandoff.class,
|
||||
Ring.class,
|
||||
Scrub.class,
|
||||
SetAuthCacheConfig.class,
|
||||
SetBatchlogReplayThrottle.class,
|
||||
SetCacheCapacity.class,
|
||||
SetCacheKeysToSave.class,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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.tools.nodetool;
|
||||
|
||||
import io.airlift.airline.Command;
|
||||
import io.airlift.airline.Option;
|
||||
import org.apache.cassandra.auth.AuthCacheMBean;
|
||||
import org.apache.cassandra.tools.NodeProbe;
|
||||
import org.apache.cassandra.tools.NodeTool;
|
||||
|
||||
@Command(name = "getauthcacheconfig", description = "Get configuration of Auth cache")
|
||||
public class GetAuthCacheConfig extends NodeTool.NodeToolCmd
|
||||
{
|
||||
@SuppressWarnings("unused")
|
||||
@Option(title = "cache-name",
|
||||
name = {"--cache-name"},
|
||||
description = "Name of Auth cache (required)",
|
||||
required = true)
|
||||
private String cacheName;
|
||||
|
||||
@Override
|
||||
public void execute(NodeProbe probe)
|
||||
{
|
||||
AuthCacheMBean authCacheMBean = probe.getAuthCacheMBean(cacheName);
|
||||
|
||||
probe.output().out.println("Validity Period: " + authCacheMBean.getValidity());
|
||||
probe.output().out.println("Update Interval: " + authCacheMBean.getUpdateInterval());
|
||||
probe.output().out.println("Max Entries: " + authCacheMBean.getMaxEntries());
|
||||
probe.output().out.println("Active Update: " + authCacheMBean.getActiveUpdate());
|
||||
}
|
||||
}
|
||||
|
|
@ -182,7 +182,7 @@ public class InvalidatePermissionsCache extends NodeToolCmd
|
|||
return FunctionResource.fromName("functions/" + functionsInKeyspace + '/' + function).getName();
|
||||
} catch (ConfigurationException e)
|
||||
{
|
||||
throw new IllegalArgumentException("An error was encountered when looking up function definition; " + e.getMessage());
|
||||
throw new IllegalArgumentException("An error was encountered when looking up function definition: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* 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.tools.nodetool;
|
||||
|
||||
import io.airlift.airline.Command;
|
||||
import io.airlift.airline.Option;
|
||||
import org.apache.cassandra.auth.AuthCacheMBean;
|
||||
import org.apache.cassandra.tools.NodeProbe;
|
||||
import org.apache.cassandra.tools.NodeTool.NodeToolCmd;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
|
||||
@Command(name = "setauthcacheconfig", description = "Set configuration for Auth cache")
|
||||
public class SetAuthCacheConfig extends NodeToolCmd
|
||||
{
|
||||
@SuppressWarnings("unused")
|
||||
@Option(title = "cache-name",
|
||||
name = {"--cache-name"},
|
||||
description = "Name of Auth cache (required)",
|
||||
required = true)
|
||||
private String cacheName;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Option(title = "validity-period",
|
||||
name = {"--validity-period"},
|
||||
description = "Validity period in milliseconds")
|
||||
private Integer validityPeriod;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Option(title = "update-interval",
|
||||
name = {"--update-interval"},
|
||||
description = "Update interval in milliseconds")
|
||||
private Integer updateInterval;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Option(title = "max-entries",
|
||||
name = {"--max-entries"},
|
||||
description = "Max entries")
|
||||
private Integer maxEntries;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Option(title = "enable-active-update",
|
||||
name = {"--enable-active-update"},
|
||||
description = "Enable active update")
|
||||
private Boolean enableActiveUpdate;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Option(title = "disable-active-update",
|
||||
name = {"--disable-active-update"},
|
||||
description = "Disable active update")
|
||||
private Boolean disableActiveUpdate;
|
||||
|
||||
@Override
|
||||
public void execute(NodeProbe probe)
|
||||
{
|
||||
Boolean activeUpdate = getActiveUpdate(enableActiveUpdate, disableActiveUpdate);
|
||||
|
||||
checkArgument(validityPeriod != null || updateInterval != null
|
||||
|| maxEntries != null || activeUpdate != null,
|
||||
"At least one optional parameter need to be passed");
|
||||
|
||||
AuthCacheMBean authCacheMBean = probe.getAuthCacheMBean(cacheName);
|
||||
|
||||
if (validityPeriod != null)
|
||||
{
|
||||
authCacheMBean.setValidity(validityPeriod);
|
||||
probe.output().out.println("Changed Validity Period to " + validityPeriod);
|
||||
}
|
||||
|
||||
if (updateInterval != null)
|
||||
{
|
||||
authCacheMBean.setUpdateInterval(updateInterval);
|
||||
probe.output().out.println("Changed Update Interval to " + updateInterval);
|
||||
}
|
||||
|
||||
if (maxEntries != null)
|
||||
{
|
||||
authCacheMBean.setMaxEntries(maxEntries);
|
||||
probe.output().out.println("Changed Max Entries to " + maxEntries);
|
||||
}
|
||||
|
||||
if (activeUpdate != null)
|
||||
{
|
||||
authCacheMBean.setActiveUpdate(activeUpdate);
|
||||
probe.output().out.println("Changed Active Update to " + activeUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
private Boolean getActiveUpdate(Boolean enableActiveUpdate, Boolean disableActiveUpdate)
|
||||
{
|
||||
if (enableActiveUpdate == null && disableActiveUpdate == null)
|
||||
return null;
|
||||
|
||||
if (enableActiveUpdate != null && disableActiveUpdate != null)
|
||||
throw new IllegalArgumentException("enable-active-update and disable-active-update cannot be used together");
|
||||
|
||||
return Boolean.TRUE.equals(enableActiveUpdate) ? Boolean.TRUE : Boolean.FALSE;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* 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.tools.nodetool;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.apache.cassandra.auth.AuthCache;
|
||||
import org.apache.cassandra.auth.AuthenticatedUser;
|
||||
import org.apache.cassandra.auth.NetworkPermissionsCacheMBean;
|
||||
import org.apache.cassandra.auth.PasswordAuthenticator;
|
||||
import org.apache.cassandra.auth.PermissionsCacheMBean;
|
||||
import org.apache.cassandra.auth.Roles;
|
||||
import org.apache.cassandra.auth.RolesCacheMBean;
|
||||
import org.apache.cassandra.auth.jmx.AuthorizationProxy;
|
||||
import org.apache.cassandra.config.DatabaseDescriptor;
|
||||
import org.apache.cassandra.cql3.CQLTester;
|
||||
import org.apache.cassandra.tools.ToolRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class GetAuthCacheConfigTest extends CQLTester
|
||||
{
|
||||
@BeforeClass
|
||||
public static void setup() throws Exception
|
||||
{
|
||||
CQLTester.setUpClass();
|
||||
CQLTester.requireAuthentication();
|
||||
startJMXServer();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("SingleCharacterStringConcatenation")
|
||||
public void testMaybeChangeDocs()
|
||||
{
|
||||
// If you added, modified options or help, please update docs if necessary
|
||||
ToolRunner.ToolResult tool = ToolRunner.invokeNodetool("help", "getauthcacheconfig");
|
||||
tool.assertOnCleanExit();
|
||||
|
||||
String help = "NAME\n" +
|
||||
" nodetool getauthcacheconfig - Get configuration of Auth cache\n" +
|
||||
"\n" +
|
||||
"SYNOPSIS\n" +
|
||||
" nodetool [(-h <host> | --host <host>)] [(-p <port> | --port <port>)]\n" +
|
||||
" [(-pp | --print-port)] [(-pw <password> | --password <password>)]\n" +
|
||||
" [(-pwf <passwordFilePath> | --password-file <passwordFilePath>)]\n" +
|
||||
" [(-u <username> | --username <username>)] getauthcacheconfig\n" +
|
||||
" --cache-name <cache-name>\n" +
|
||||
"\n" +
|
||||
"OPTIONS\n" +
|
||||
" --cache-name <cache-name>\n" +
|
||||
" Name of Auth cache (required)\n" +
|
||||
"\n" +
|
||||
" -h <host>, --host <host>\n" +
|
||||
" Node hostname or ip address\n" +
|
||||
"\n" +
|
||||
" -p <port>, --port <port>\n" +
|
||||
" Remote jmx agent port number\n" +
|
||||
"\n" +
|
||||
" -pp, --print-port\n" +
|
||||
" Operate in 4.0 mode with hosts disambiguated by port number\n" +
|
||||
"\n" +
|
||||
" -pw <password>, --password <password>\n" +
|
||||
" Remote jmx agent password\n" +
|
||||
"\n" +
|
||||
" -pwf <passwordFilePath>, --password-file <passwordFilePath>\n" +
|
||||
" Path to the JMX password file\n" +
|
||||
"\n" +
|
||||
" -u <username>, --username <username>\n" +
|
||||
" Remote jmx agent username\n" +
|
||||
"\n" +
|
||||
"\n";
|
||||
assertThat(tool.getStdout()).isEqualTo(help);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidCacheName()
|
||||
{
|
||||
ToolRunner.ToolResult tool = ToolRunner.invokeNodetool("getauthcacheconfig");
|
||||
assertThat(tool.getExitCode()).isEqualTo(1);
|
||||
assertThat(tool.getStdout()).isEqualTo(wrapByDefaultNodetoolMessage("Required option '--cache-name' is missing"));
|
||||
assertThat(tool.getStderr()).isEmpty();
|
||||
|
||||
tool = ToolRunner.invokeNodetool("getauthcacheconfig", "--cache-name");
|
||||
assertThat(tool.getExitCode()).isEqualTo(1);
|
||||
assertThat(tool.getStdout()).isEqualTo(wrapByDefaultNodetoolMessage("Required values for option 'cache-name' not provided"));
|
||||
assertThat(tool.getStderr()).isEmpty();
|
||||
|
||||
tool = ToolRunner.invokeNodetool("getauthcacheconfig", "--cache-name", "wrong");
|
||||
assertThat(tool.getExitCode()).isEqualTo(1);
|
||||
assertThat(tool.getStdout()).isEqualTo(wrapByDefaultNodetoolMessage("Unknown cache name: wrong"));
|
||||
assertThat(tool.getStderr()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetConfig()
|
||||
{
|
||||
assertGetConfig(AuthenticatedUser.permissionsCache, PermissionsCacheMBean.CACHE_NAME);
|
||||
|
||||
PasswordAuthenticator passwordAuthenticator = (PasswordAuthenticator) DatabaseDescriptor.getAuthenticator();
|
||||
assertGetConfig(passwordAuthenticator.getCredentialsCache(), PasswordAuthenticator.CredentialsCacheMBean.CACHE_NAME);
|
||||
|
||||
assertGetConfig(AuthorizationProxy.jmxPermissionsCache, AuthorizationProxy.JmxPermissionsCacheMBean.CACHE_NAME);
|
||||
|
||||
assertGetConfig(AuthenticatedUser.networkPermissionsCache, NetworkPermissionsCacheMBean.CACHE_NAME);
|
||||
|
||||
assertGetConfig(Roles.cache, RolesCacheMBean.CACHE_NAME);
|
||||
}
|
||||
|
||||
@SuppressWarnings("SingleCharacterStringConcatenation")
|
||||
private void assertGetConfig(AuthCache<?, ?> authCache, String cacheName)
|
||||
{
|
||||
ToolRunner.ToolResult tool = ToolRunner.invokeNodetool("getauthcacheconfig", "--cache-name", cacheName);
|
||||
tool.assertOnCleanExit();
|
||||
assertThat(tool.getStdout()).isEqualTo("Validity Period: " + authCache.getValidity() + "\n" +
|
||||
"Update Interval: " + authCache.getUpdateInterval() + "\n" +
|
||||
"Max Entries: " + authCache.getMaxEntries() + "\n" +
|
||||
"Active Update: " + authCache.getActiveUpdate() + "\n");
|
||||
}
|
||||
|
||||
private String wrapByDefaultNodetoolMessage(String s)
|
||||
{
|
||||
return "nodetool: " + s + "\nSee 'nodetool help' or 'nodetool help <command>'.\n";
|
||||
}
|
||||
}
|
||||
|
|
@ -23,11 +23,12 @@ import org.junit.Test;
|
|||
|
||||
import com.datastax.driver.core.EndPoint;
|
||||
import com.datastax.driver.core.PlainTextAuthProvider;
|
||||
import org.apache.cassandra.SchemaLoader;
|
||||
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.PasswordAuthenticator;
|
||||
import org.apache.cassandra.config.DatabaseDescriptor;
|
||||
import org.apache.cassandra.cql3.CQLTester;
|
||||
import org.apache.cassandra.tools.ToolRunner;
|
||||
|
||||
|
|
@ -44,17 +45,14 @@ public class InvalidateCredentialsCacheTest extends CQLTester
|
|||
@BeforeClass
|
||||
public static void setup() throws Exception
|
||||
{
|
||||
SchemaLoader.prepareServer();
|
||||
AuthTestUtils.LocalCassandraRoleManager roleManager = new AuthTestUtils.LocalCassandraRoleManager();
|
||||
PasswordAuthenticator passwordAuthenticator = new AuthTestUtils.LocalPasswordAuthenticator();
|
||||
SchemaLoader.setupAuth(roleManager,
|
||||
passwordAuthenticator,
|
||||
new AuthTestUtils.LocalCassandraAuthorizer(),
|
||||
new AuthTestUtils.LocalCassandraNetworkAuthorizer());
|
||||
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());
|
||||
|
||||
PasswordAuthenticator passwordAuthenticator = (PasswordAuthenticator) DatabaseDescriptor.getAuthenticator();
|
||||
roleANegotiator = passwordAuthenticator.newSaslNegotiator(null);
|
||||
roleANegotiator.evaluateResponse(new PlainTextAuthProvider(ROLE_A.getRoleName(), "ignored")
|
||||
.newAuthenticator((EndPoint) null, null)
|
||||
|
|
|
|||
|
|
@ -24,13 +24,15 @@ import javax.security.auth.Subject;
|
|||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.apache.cassandra.SchemaLoader;
|
||||
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.IRoleManager;
|
||||
import org.apache.cassandra.auth.JMXResource;
|
||||
import org.apache.cassandra.auth.Permission;
|
||||
import org.apache.cassandra.auth.jmx.AuthorizationProxy;
|
||||
import org.apache.cassandra.config.DatabaseDescriptor;
|
||||
import org.apache.cassandra.cql3.CQLTester;
|
||||
import org.apache.cassandra.tools.ToolRunner;
|
||||
|
||||
|
|
@ -46,21 +48,18 @@ public class InvalidateJmxPermissionsCacheTest extends CQLTester
|
|||
@BeforeClass
|
||||
public static void setup() throws Exception
|
||||
{
|
||||
SchemaLoader.prepareServer();
|
||||
AuthTestUtils.LocalCassandraRoleManager roleManager = new AuthTestUtils.LocalCassandraRoleManager();
|
||||
AuthTestUtils.LocalCassandraAuthorizer authorizer = new AuthTestUtils.LocalCassandraAuthorizer();
|
||||
SchemaLoader.setupAuth(roleManager,
|
||||
new AuthTestUtils.LocalPasswordAuthenticator(),
|
||||
authorizer,
|
||||
new AuthTestUtils.LocalCassandraNetworkAuthorizer());
|
||||
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());
|
||||
|
||||
JMXResource rootJmxResource = JMXResource.root();
|
||||
Set<Permission> jmxPermissions = rootJmxResource.applicablePermissions();
|
||||
|
||||
roleManager.createRole(AuthenticatedUser.SYSTEM_USER, ROLE_A, AuthTestUtils.getLoginRoleOptions());
|
||||
IAuthorizer authorizer = DatabaseDescriptor.getAuthorizer();
|
||||
authorizer.grant(AuthenticatedUser.SYSTEM_USER, jmxPermissions, rootJmxResource, ROLE_A);
|
||||
|
||||
roleManager.createRole(AuthenticatedUser.SYSTEM_USER, ROLE_B, AuthTestUtils.getLoginRoleOptions());
|
||||
authorizer.grant(AuthenticatedUser.SYSTEM_USER, jmxPermissions, rootJmxResource, ROLE_B);
|
||||
|
||||
startJMXServer();
|
||||
|
|
|
|||
|
|
@ -21,9 +21,10 @@ package org.apache.cassandra.tools.nodetool;
|
|||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.apache.cassandra.SchemaLoader;
|
||||
import org.apache.cassandra.auth.AuthTestUtils;
|
||||
import org.apache.cassandra.auth.AuthenticatedUser;
|
||||
import org.apache.cassandra.auth.IRoleManager;
|
||||
import org.apache.cassandra.config.DatabaseDescriptor;
|
||||
import org.apache.cassandra.cql3.CQLTester;
|
||||
import org.apache.cassandra.tools.ToolRunner;
|
||||
|
||||
|
|
@ -37,13 +38,10 @@ public class InvalidateNetworkPermissionsCacheTest extends CQLTester
|
|||
@BeforeClass
|
||||
public static void setup() throws Exception
|
||||
{
|
||||
SchemaLoader.prepareServer();
|
||||
AuthTestUtils.LocalCassandraRoleManager roleManager = new AuthTestUtils.LocalCassandraRoleManager();
|
||||
SchemaLoader.setupAuth(roleManager,
|
||||
new AuthTestUtils.LocalPasswordAuthenticator(),
|
||||
new AuthTestUtils.LocalCassandraAuthorizer(),
|
||||
new AuthTestUtils.LocalCassandraNetworkAuthorizer());
|
||||
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());
|
||||
|
||||
|
|
|
|||
|
|
@ -28,12 +28,13 @@ import org.apache.commons.lang3.StringUtils;
|
|||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.apache.cassandra.SchemaLoader;
|
||||
import org.apache.cassandra.auth.AuthTestUtils;
|
||||
import org.apache.cassandra.auth.AuthenticatedUser;
|
||||
import org.apache.cassandra.auth.DataResource;
|
||||
import org.apache.cassandra.auth.FunctionResource;
|
||||
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;
|
||||
|
|
@ -52,14 +53,10 @@ public class InvalidatePermissionsCacheTest extends CQLTester
|
|||
@BeforeClass
|
||||
public static void setup() throws Exception
|
||||
{
|
||||
SchemaLoader.prepareServer();
|
||||
AuthTestUtils.LocalCassandraRoleManager roleManager = new AuthTestUtils.LocalCassandraRoleManager();
|
||||
AuthTestUtils.LocalCassandraAuthorizer authorizer = new AuthTestUtils.LocalCassandraAuthorizer();
|
||||
SchemaLoader.setupAuth(roleManager,
|
||||
new AuthTestUtils.LocalPasswordAuthenticator(),
|
||||
authorizer,
|
||||
new AuthTestUtils.LocalCassandraNetworkAuthorizer());
|
||||
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());
|
||||
|
||||
|
|
@ -78,6 +75,7 @@ public class InvalidatePermissionsCacheTest extends CQLTester
|
|||
JMXResource.root(),
|
||||
JMXResource.mbean("org.apache.cassandra.auth:type=*"));
|
||||
|
||||
IAuthorizer authorizer = DatabaseDescriptor.getAuthorizer();
|
||||
for (IResource resource : resources)
|
||||
{
|
||||
Set<Permission> permissions = resource.applicablePermissions();
|
||||
|
|
@ -221,7 +219,7 @@ public class InvalidatePermissionsCacheTest extends CQLTester
|
|||
KEYSPACE, "--function", "f[x]");
|
||||
assertThat(tool.getExitCode()).isEqualTo(1);
|
||||
assertThat(tool.getStdout())
|
||||
.isEqualTo(wrapByDefaultNodetoolMessage("An error was encountered when looking up function definition; Unable to find abstract-type class 'org.apache.cassandra.db.marshal.x'"));
|
||||
.isEqualTo(wrapByDefaultNodetoolMessage("An error was encountered when looking up function definition: Unable to find abstract-type class 'org.apache.cassandra.db.marshal.x'"));
|
||||
assertThat(tool.getStderr()).isEmpty();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,9 +21,10 @@ package org.apache.cassandra.tools.nodetool;
|
|||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.apache.cassandra.SchemaLoader;
|
||||
import org.apache.cassandra.auth.AuthTestUtils;
|
||||
import org.apache.cassandra.auth.AuthenticatedUser;
|
||||
import org.apache.cassandra.auth.IRoleManager;
|
||||
import org.apache.cassandra.config.DatabaseDescriptor;
|
||||
import org.apache.cassandra.cql3.CQLTester;
|
||||
import org.apache.cassandra.tools.ToolRunner;
|
||||
|
||||
|
|
@ -37,13 +38,10 @@ public class InvalidateRolesCacheTest extends CQLTester
|
|||
@BeforeClass
|
||||
public static void setup() throws Exception
|
||||
{
|
||||
SchemaLoader.prepareServer();
|
||||
AuthTestUtils.LocalCassandraRoleManager roleManager = new AuthTestUtils.LocalCassandraRoleManager();
|
||||
SchemaLoader.setupAuth(roleManager,
|
||||
new AuthTestUtils.LocalPasswordAuthenticator(),
|
||||
new AuthTestUtils.LocalCassandraAuthorizer(),
|
||||
new AuthTestUtils.LocalCassandraNetworkAuthorizer());
|
||||
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());
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
* 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.tools.nodetool;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.apache.cassandra.auth.AuthCache;
|
||||
import org.apache.cassandra.auth.AuthenticatedUser;
|
||||
import org.apache.cassandra.auth.NetworkPermissionsCacheMBean;
|
||||
import org.apache.cassandra.auth.PasswordAuthenticator;
|
||||
import org.apache.cassandra.auth.PermissionsCacheMBean;
|
||||
import org.apache.cassandra.auth.Roles;
|
||||
import org.apache.cassandra.auth.RolesCacheMBean;
|
||||
import org.apache.cassandra.auth.jmx.AuthorizationProxy;
|
||||
import org.apache.cassandra.config.DatabaseDescriptor;
|
||||
import org.apache.cassandra.cql3.CQLTester;
|
||||
import org.apache.cassandra.tools.ToolRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class SetAuthCacheConfigTest extends CQLTester
|
||||
{
|
||||
@BeforeClass
|
||||
public static void setup() throws Exception
|
||||
{
|
||||
CQLTester.setUpClass();
|
||||
CQLTester.requireAuthentication();
|
||||
startJMXServer();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("SingleCharacterStringConcatenation")
|
||||
public void testMaybeChangeDocs()
|
||||
{
|
||||
// If you added, modified options or help, please update docs if necessary
|
||||
ToolRunner.ToolResult tool = ToolRunner.invokeNodetool("help", "setauthcacheconfig");
|
||||
tool.assertOnCleanExit();
|
||||
|
||||
String help = "NAME\n" +
|
||||
" nodetool setauthcacheconfig - Set configuration for Auth cache\n" +
|
||||
"\n" +
|
||||
"SYNOPSIS\n" +
|
||||
" nodetool [(-h <host> | --host <host>)] [(-p <port> | --port <port>)]\n" +
|
||||
" [(-pp | --print-port)] [(-pw <password> | --password <password>)]\n" +
|
||||
" [(-pwf <passwordFilePath> | --password-file <passwordFilePath>)]\n" +
|
||||
" [(-u <username> | --username <username>)] setauthcacheconfig\n" +
|
||||
" --cache-name <cache-name> [--disable-active-update]\n" +
|
||||
" [--enable-active-update] [--max-entries <max-entries>]\n" +
|
||||
" [--update-interval <update-interval>]\n" +
|
||||
" [--validity-period <validity-period>]\n" +
|
||||
"\n" +
|
||||
"OPTIONS\n" +
|
||||
" --cache-name <cache-name>\n" +
|
||||
" Name of Auth cache (required)\n" +
|
||||
"\n" +
|
||||
" --disable-active-update\n" +
|
||||
" Disable active update\n" +
|
||||
"\n" +
|
||||
" --enable-active-update\n" +
|
||||
" Enable active update\n" +
|
||||
"\n" +
|
||||
" -h <host>, --host <host>\n" +
|
||||
" Node hostname or ip address\n" +
|
||||
"\n" +
|
||||
" --max-entries <max-entries>\n" +
|
||||
" Max entries\n" +
|
||||
"\n" +
|
||||
" -p <port>, --port <port>\n" +
|
||||
" Remote jmx agent port number\n" +
|
||||
"\n" +
|
||||
" -pp, --print-port\n" +
|
||||
" Operate in 4.0 mode with hosts disambiguated by port number\n" +
|
||||
"\n" +
|
||||
" -pw <password>, --password <password>\n" +
|
||||
" Remote jmx agent password\n" +
|
||||
"\n" +
|
||||
" -pwf <passwordFilePath>, --password-file <passwordFilePath>\n" +
|
||||
" Path to the JMX password file\n" +
|
||||
"\n" +
|
||||
" -u <username>, --username <username>\n" +
|
||||
" Remote jmx agent username\n" +
|
||||
"\n" +
|
||||
" --update-interval <update-interval>\n" +
|
||||
" Update interval in milliseconds\n" +
|
||||
"\n" +
|
||||
" --validity-period <validity-period>\n" +
|
||||
" Validity period in milliseconds\n" +
|
||||
"\n" +
|
||||
"\n";
|
||||
assertThat(tool.getStdout()).isEqualTo(help);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidCacheName()
|
||||
{
|
||||
ToolRunner.ToolResult tool = ToolRunner.invokeNodetool("setauthcacheconfig");
|
||||
assertThat(tool.getExitCode()).isEqualTo(1);
|
||||
assertThat(tool.getStdout()).isEqualTo(wrapByDefaultNodetoolMessage("Required option '--cache-name' is missing"));
|
||||
assertThat(tool.getStderr()).isEmpty();
|
||||
|
||||
tool = ToolRunner.invokeNodetool("setauthcacheconfig", "--cache-name");
|
||||
assertThat(tool.getExitCode()).isEqualTo(1);
|
||||
assertThat(tool.getStdout()).isEqualTo(wrapByDefaultNodetoolMessage("Required values for option 'cache-name' not provided"));
|
||||
assertThat(tool.getStderr()).isEmpty();
|
||||
|
||||
tool = ToolRunner.invokeNodetool("setauthcacheconfig", "--cache-name", "wrong", "--validity-period", "1");
|
||||
assertThat(tool.getExitCode()).isEqualTo(1);
|
||||
assertThat(tool.getStdout()).isEqualTo(wrapByDefaultNodetoolMessage("Unknown cache name: wrong"));
|
||||
assertThat(tool.getStderr()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoOptionalParameters()
|
||||
{
|
||||
ToolRunner.ToolResult tool = ToolRunner.invokeNodetool("setauthcacheconfig", "--cache-name", "PermissionCache");
|
||||
assertThat(tool.getExitCode()).isEqualTo(1);
|
||||
assertThat(tool.getStdout()).isEqualTo(wrapByDefaultNodetoolMessage("At least one optional parameter need to be passed"));
|
||||
assertThat(tool.getStderr()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBothEnableAndDisableActiveUpdate()
|
||||
{
|
||||
ToolRunner.ToolResult tool = ToolRunner.invokeNodetool("setauthcacheconfig",
|
||||
"--cache-name", "PermissionCache",
|
||||
"--enable-active-update",
|
||||
"--disable-active-update");
|
||||
assertThat(tool.getExitCode()).isEqualTo(1);
|
||||
assertThat(tool.getStdout()).isEqualTo(wrapByDefaultNodetoolMessage("enable-active-update and disable-active-update cannot be used together"));
|
||||
assertThat(tool.getStderr()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetConfig()
|
||||
{
|
||||
assertSetConfig(AuthenticatedUser.permissionsCache, PermissionsCacheMBean.CACHE_NAME);
|
||||
|
||||
PasswordAuthenticator passwordAuthenticator = (PasswordAuthenticator) DatabaseDescriptor.getAuthenticator();
|
||||
assertSetConfig(passwordAuthenticator.getCredentialsCache(), PasswordAuthenticator.CredentialsCacheMBean.CACHE_NAME);
|
||||
|
||||
assertSetConfig(AuthorizationProxy.jmxPermissionsCache, AuthorizationProxy.JmxPermissionsCacheMBean.CACHE_NAME);
|
||||
|
||||
assertSetConfig(AuthenticatedUser.networkPermissionsCache, NetworkPermissionsCacheMBean.CACHE_NAME);
|
||||
|
||||
assertSetConfig(Roles.cache, RolesCacheMBean.CACHE_NAME);
|
||||
}
|
||||
|
||||
private void assertSetConfig(AuthCache<?, ?> authCache, String cacheName)
|
||||
{
|
||||
ToolRunner.ToolResult tool = ToolRunner.invokeNodetool("setauthcacheconfig",
|
||||
"--cache-name", cacheName,
|
||||
"--validity-period", "1",
|
||||
"--update-interval", "2",
|
||||
"--max-entries", "3",
|
||||
"--disable-active-update");
|
||||
tool.assertOnCleanExit();
|
||||
assertThat(tool.getStdout()).isEqualTo("Changed Validity Period to 1\n" +
|
||||
"Changed Update Interval to 2\n" +
|
||||
"Changed Max Entries to 3\n" +
|
||||
"Changed Active Update to false\n");
|
||||
|
||||
assertThat(authCache.getValidity()).isEqualTo(1);
|
||||
assertThat(authCache.getUpdateInterval()).isEqualTo(2);
|
||||
assertThat(authCache.getMaxEntries()).isEqualTo(3);
|
||||
assertThat(authCache.getActiveUpdate()).isFalse();
|
||||
}
|
||||
|
||||
private String wrapByDefaultNodetoolMessage(String s)
|
||||
{
|
||||
return "nodetool: " + s + "\nSee 'nodetool help' or 'nodetool help <command>'.\n";
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue