Commit be572f27 authored by Sam Tunnicliffe's avatar Sam Tunnicliffe

Merge branch 'cassandra-3.11' into trunk

parents 259c63f1 408f969f
......@@ -56,6 +56,7 @@ Merged from 3.0:
* cqlsh return non-zero status when STDIN CQL fails (CASSANDRA-15623)
* Don't skip sstables in slice queries based only on local min/max/deletion timestamp (CASSANDRA-15690)
Merged from 2.2:
* Fix nomenclature of allow and deny lists (CASSANDRA-15862)
* Remove generated files from source artifact (CASSANDRA-15849)
* Remove duplicated tools binaries from tarballs (CASSANDRA-15768)
* Duplicate results with DISTINCT queries in mixed mode (CASSANDRA-15501)
......
......@@ -252,6 +252,14 @@ Upgrading
break existing scripts that rely on the current behavior. See CASSANDRA-15623 for more details.
Deprecation
-----------
- The JMX MBean org.apache.cassandra.db:type=BlacklistedDirectories has been
deprecated in favor of org.apache.cassandra.db:type=DisallowedDirectories
and will be removed in a subsequent major version.
Materialized Views
-------------------
- Following a discussion regarding concerns about the design and safety of Materialized Views, the C* development
......
......@@ -69,7 +69,7 @@ import org.apache.cassandra.service.StorageService;
* MBeanServer::getDomains is primarily a function of the MBeanServer itself. This class makes
* such a distinction in order to identify which JMXResource the subject requires permissions on.
*
* Certain operations are never allowed for users and these are recorded in a blacklist so that we
* Certain operations are never allowed for users and these are recorded in a deny list so that we
* can short circuit authorization process if one is attempted by a remote subject.
*
*/
......@@ -78,30 +78,30 @@ public class AuthorizationProxy implements InvocationHandler
private static final Logger logger = LoggerFactory.getLogger(AuthorizationProxy.class);
/*
A whitelist of permitted methods on the MBeanServer interface which *do not* take an ObjectName
A list of permitted methods on the MBeanServer interface which *do not* take an ObjectName
as their first argument. These methods can be thought of as relating to the MBeanServer itself,
rather than to the MBeans it manages. All of the whitelisted methods are essentially descriptive,
rather than to the MBeans it manages. All of the allowed methods are essentially descriptive,
hence they require the Subject to have the DESCRIBE permission on the root JMX resource.
*/
private static final Set<String> MBEAN_SERVER_METHOD_WHITELIST = ImmutableSet.of("getDefaultDomain",
"getDomains",
"getMBeanCount",
"hashCode",
"queryMBeans",
"queryNames",
"toString");
private static final Set<String> MBEAN_SERVER_ALLOWED_METHODS = ImmutableSet.of("getDefaultDomain",
"getDomains",
"getMBeanCount",
"hashCode",
"queryMBeans",
"queryNames",
"toString");
/*
A blacklist of method names which are never permitted to be executed by a remote user,
A list of method names which are never permitted to be executed by a remote user,
regardless of privileges they may be granted.
*/
private static final Set<String> METHOD_BLACKLIST = ImmutableSet.of("createMBean",
"deserialize",
"getClassLoader",
"getClassLoaderFor",
"instantiate",
"registerMBean",
"unregisterMBean");
private static final Set<String> DENIED_METHODS = ImmutableSet.of("createMBean",
"deserialize",
"getClassLoader",
"getClassLoaderFor",
"instantiate",
"registerMBean",
"unregisterMBean");
private static final JMXPermissionsCache permissionsCache = new JMXPermissionsCache();
private MBeanServer mbs;
......@@ -203,9 +203,9 @@ public class AuthorizationProxy implements InvocationHandler
return true;
// Restrict access to certain methods by any remote user
if (METHOD_BLACKLIST.contains(methodName))
if (DENIED_METHODS.contains(methodName))
{
logger.trace("Access denied to blacklisted method {}", methodName);
logger.trace("Access denied to restricted method {}", methodName);
return false;
}
......@@ -233,7 +233,7 @@ public class AuthorizationProxy implements InvocationHandler
/**
* Authorize execution of a method on the MBeanServer which does not take an MBean ObjectName
* as its first argument. The whitelisted methods that match this criteria are generally
* as its first argument. The allowed methods that match this criteria are generally
* descriptive methods concerned with the MBeanServer itself, rather than with any particular
* set of MBeans managed by the server and so we check the DESCRIBE permission on the root
* JMXResource (representing the MBeanServer)
......@@ -247,8 +247,8 @@ public class AuthorizationProxy implements InvocationHandler
private boolean authorizeMBeanServerMethod(RoleResource subject, String methodName)
{
logger.trace("JMX invocation of {} on MBeanServer requires permission {}", methodName, Permission.DESCRIBE);
return (MBEAN_SERVER_METHOD_WHITELIST.contains(methodName) &&
hasPermission(subject, Permission.DESCRIBE, JMXResource.root()));
return (MBEAN_SERVER_ALLOWED_METHODS.contains(methodName) &&
hasPermission(subject, Permission.DESCRIBE, JMXResource.root()));
}
/**
......
......@@ -84,19 +84,19 @@ public abstract class UDFunction extends AbstractFunction implements ScalarFunct
protected final UDFContext udfContext;
//
// Access to classes is controlled via a whitelist and a blacklist.
// Access to classes is controlled via allow and disallow lists.
//
// When a class is requested (both during compilation and runtime),
// the whitelistedPatterns array is searched first, whether the
// the allowedPatterns array is searched first, whether the
// requested name matches one of the patterns. If not, nothing is
// returned from the class-loader - meaning ClassNotFoundException
// during runtime and "type could not resolved" during compilation.
//
// If a whitelisted pattern has been found, the blacklistedPatterns
// If an allowed pattern has been found, the disallowedPatterns
// array is searched for a match. If a match is found, class-loader
// rejects access. Otherwise the class/resource can be loaded.
//
private static final String[] whitelistedPatterns =
private static final String[] allowedPatterns =
{
"com/google/common/reflect/TypeToken",
"java/io/IOException.class",
......@@ -120,8 +120,8 @@ public abstract class UDFunction extends AbstractFunction implements ScalarFunct
"org/apache/cassandra/exceptions/",
"org/apache/cassandra/transport/ProtocolVersion.class"
};
// Only need to blacklist a pattern, if it would otherwise be allowed via whitelistedPatterns
private static final String[] blacklistedPatterns =
// Only need to disallow a pattern, if it would otherwise be allowed via allowedPatterns
private static final String[] disallowedPatterns =
{
"com/datastax/driver/core/Cluster.class",
"com/datastax/driver/core/Metrics.class",
......@@ -164,13 +164,13 @@ public abstract class UDFunction extends AbstractFunction implements ScalarFunct
while (resource.startsWith("/"))
resource = resource.substring(1);
for (String white : whitelistedPatterns)
if (resource.startsWith(white))
for (String allowed : allowedPatterns)
if (resource.startsWith(allowed))
{
// resource is in whitelistedPatterns, let's see if it is not explicityl blacklisted
for (String black : blacklistedPatterns)
if (resource.startsWith(black))
// resource is in allowedPatterns, let's see if it is not explicitly disallowed
for (String disallowed : disallowedPatterns)
if (resource.startsWith(disallowed))
{
logger.trace("access denied: resource {}", resource);
return false;
......
......@@ -324,10 +324,10 @@ public class Directories
/**
* Basically the same as calling {@link #getWriteableLocationAsFile(long)} with an unknown size ({@code -1L}),
* which may return any non-blacklisted directory - even a data directory that has no usable space.
* which may return any allowed directory - even a data directory that has no usable space.
* Do not use this method in production code.
*
* @throws FSWriteError if all directories are blacklisted.
* @throws FSWriteError if all directories are disallowed.
*/
public File getDirectoryForNewSSTables()
{
......@@ -335,9 +335,9 @@ public class Directories
}
/**
* Returns a non-blacklisted data directory that _currently_ has {@code writeSize} bytes as usable space.
* Returns an allowed directory that _currently_ has {@code writeSize} bytes as usable space.
*
* @throws FSWriteError if all directories are blacklisted.
* @throws FSWriteError if all directories are disallowed.
*/
public File getWriteableLocationAsFile(long writeSize)
{
......@@ -352,9 +352,9 @@ public class Directories
* data directory then use that one as data directory otherwise use {@link #getWriteableLocationAsFile(long)} to
* find suitable data directory.
*
* Also makes sure returned directory is non-blacklisted.
* Also makes sure returned directory is not disallowed.
*
* @throws FSWriteError if all directories are blacklisted
* @throws FSWriteError if all directories are disallowed.
*/
public File getWriteableLocationToLoadFile(final File sourceFile)
{
......@@ -363,7 +363,7 @@ public class Directories
final FileStore srcFileStore = Files.getFileStore(sourceFile.toPath());
for (final File dataPath : dataPaths)
{
if (BlacklistedDirectories.isUnwritable(dataPath))
if (DisallowedDirectories.isUnwritable(dataPath))
{
continue;
}
......@@ -383,11 +383,11 @@ public class Directories
}
/**
* Returns a temporary subdirectory on non-blacklisted data directory
* Returns a temporary subdirectory on allowed data directory
* that _currently_ has {@code writeSize} bytes as usable space.
* This method does not create the temporary directory.
*
* @throws IOError if all directories are blacklisted.
* @throws IOError if all directories are disallowed.
*/
public File getTemporaryWriteableDirectoryAsFile(long writeSize)
{
......@@ -411,10 +411,9 @@ public class Directories
}
/**
* Returns a non-blacklisted data directory that _currently_ has {@code writeSize} bytes as usable space, null if
* there is not enough space left in all directories.
* Returns an allowed data directory that _currently_ has {@code writeSize} bytes as usable space.
*
* @throws FSWriteError if all directories are blacklisted.
* @throws FSWriteError if all directories are disallowed.
*/
public DataDirectory getWriteableLocation(long writeSize)
{
......@@ -422,13 +421,13 @@ public class Directories
long totalAvailable = 0L;
// pick directories with enough space and so that resulting sstable dirs aren't blacklisted for writes.
// pick directories with enough space and so that resulting sstable dirs aren't disallowed for writes.
boolean tooBig = false;
for (DataDirectory dataDir : paths)
{
if (BlacklistedDirectories.isUnwritable(getLocationForDisk(dataDir)))
if (DisallowedDirectories.isUnwritable(getLocationForDisk(dataDir)))
{
logger.trace("removing blacklisted candidate {}", dataDir.location);
logger.trace("removing disallowed candidate {}", dataDir.location);
continue;
}
DataDirectoryCandidate candidate = new DataDirectoryCandidate(dataDir);
......@@ -447,7 +446,7 @@ public class Directories
if (tooBig)
throw new FSDiskFullWriteError(new IOException("Insufficient disk space to write " + writeSize + " bytes"), "");
else
throw new FSWriteError(new IOException("All configured data directories have been blacklisted as unwritable for erroring out"), "");
throw new FSWriteError(new IOException("All configured data directories have been disallowed as unwritable for erroring out"), "");
// shortcut for single data directory systems
if (candidates.size() == 1)
......@@ -492,8 +491,8 @@ public class Directories
for (DataDirectory dataDir : paths)
{
if (BlacklistedDirectories.isUnwritable(getLocationForDisk(dataDir)))
continue;
if (DisallowedDirectories.isUnwritable(getLocationForDisk(dataDir)))
continue;
DataDirectoryCandidate candidate = new DataDirectoryCandidate(dataDir);
// exclude directory if its total writeSize does not fit to data directory
if (candidate.availableSpace < writeSize)
......@@ -505,14 +504,14 @@ public class Directories
public DataDirectory[] getWriteableLocations()
{
List<DataDirectory> nonBlacklistedDirs = new ArrayList<>();
List<DataDirectory> allowedDirs = new ArrayList<>();
for (DataDirectory dir : paths)
{
if (!BlacklistedDirectories.isUnwritable(dir.location))
nonBlacklistedDirs.add(dir);
if (!DisallowedDirectories.isUnwritable(dir.location))
allowedDirs.add(dir);
}
Collections.sort(nonBlacklistedDirs, new Comparator<DataDirectory>()
Collections.sort(allowedDirs, new Comparator<DataDirectory>()
{
@Override
public int compare(DataDirectory o1, DataDirectory o2)
......@@ -520,7 +519,7 @@ public class Directories
return o1.location.compareTo(o2.location);
}
});
return nonBlacklistedDirs.toArray(new DataDirectory[nonBlacklistedDirs.size()]);
return allowedDirs.toArray(new DataDirectory[allowedDirs.size()]);
}
public static File getSnapshotDirectory(Descriptor desc, String snapshotName)
......@@ -780,7 +779,7 @@ public class Directories
for (File location : dataPaths)
{
if (BlacklistedDirectories.isUnreadable(location))
if (DisallowedDirectories.isUnreadable(location))
continue;
if (snapshotName != null)
......
......@@ -28,23 +28,24 @@ import java.util.concurrent.atomic.AtomicInteger;
import com.google.common.annotations.VisibleForTesting;
import org.apache.cassandra.utils.JVMStabilityInspector;
import org.apache.cassandra.utils.MBeanWrapper;
public class BlacklistedDirectories implements BlacklistedDirectoriesMBean
public class DisallowedDirectories implements DisallowedDirectoriesMBean
{
public static final String MBEAN_NAME = "org.apache.cassandra.db:type=BlacklistedDirectories";
private static final Logger logger = LoggerFactory.getLogger(BlacklistedDirectories.class);
private static final BlacklistedDirectories instance = new BlacklistedDirectories();
public static final String DEPRECATED_MBEAN_NAME = "org.apache.cassandra.db:type=BlacklistedDirectories";
public static final String MBEAN_NAME = "org.apache.cassandra.db:type=DisallowedDirectories";
private static final Logger logger = LoggerFactory.getLogger(DisallowedDirectories.class);
private static final DisallowedDirectories instance = new DisallowedDirectories();
private final Set<File> unreadableDirectories = new CopyOnWriteArraySet<File>();
private final Set<File> unwritableDirectories = new CopyOnWriteArraySet<File>();
private static final AtomicInteger directoriesVersion = new AtomicInteger();
private BlacklistedDirectories()
private DisallowedDirectories()
{
// Register this instance with JMX
MBeanWrapper.instance.registerMBean(this, DEPRECATED_MBEAN_NAME, MBeanWrapper.OnException.LOG);
MBeanWrapper.instance.registerMBean(this, MBEAN_NAME, MBeanWrapper.OnException.LOG);
}
......@@ -72,7 +73,7 @@ public class BlacklistedDirectories implements BlacklistedDirectoriesMBean
* Adds parent directory of the file (or the file itself, if it is a directory)
* to the set of unreadable directories.
*
* @return the blacklisted directory or null if nothing has been added to the list.
* @return the disallowed directory or null if nothing has been added to the list.
*/
public static File maybeMarkUnreadable(File path)
{
......@@ -80,7 +81,7 @@ public class BlacklistedDirectories implements BlacklistedDirectoriesMBean
if (instance.unreadableDirectories.add(directory))
{
directoriesVersion.incrementAndGet();
logger.warn("Blacklisting {} for reads", directory);
logger.warn("Disallowing {} for reads", directory);
return directory;
}
return null;
......@@ -90,7 +91,7 @@ public class BlacklistedDirectories implements BlacklistedDirectoriesMBean
* Adds parent directory of the file (or the file itself, if it is a directory)
* to the set of unwritable directories.
*
* @return the blacklisted directory or null if nothing has been added to the list.
* @return the disallowed directory or null if nothing has been added to the list.
*/
public static File maybeMarkUnwritable(File path)
{
......@@ -98,7 +99,7 @@ public class BlacklistedDirectories implements BlacklistedDirectoriesMBean
if (instance.unwritableDirectories.add(directory))
{
directoriesVersion.incrementAndGet();
logger.warn("Blacklisting {} for writes", directory);
logger.warn("Disallowing {} for writes", directory);
return directory;
}
return null;
......@@ -121,8 +122,8 @@ public class BlacklistedDirectories implements BlacklistedDirectoriesMBean
/**
* Tells whether or not the directory is blacklisted for reads.
* @return whether or not the directory is blacklisted for reads.
* Tells whether or not the directory is disallowed for reads.
* @return whether or not the directory is disallowed for reads.
*/
public static boolean isUnreadable(File directory)
{
......@@ -130,8 +131,8 @@ public class BlacklistedDirectories implements BlacklistedDirectoriesMBean
}
/**
* Tells whether or not the directory is blacklisted for writes.
* @return whether or not the directory is blacklisted for reads.
* Tells whether or not the directory is disallowed for writes.
* @return whether or not the directory is disallowed for reads.
*/
public static boolean isUnwritable(File directory)
{
......
......@@ -20,7 +20,7 @@ package org.apache.cassandra.db;
import java.io.File;
import java.util.Set;
public interface BlacklistedDirectoriesMBean
public interface DisallowedDirectoriesMBean
{
public Set<File> getUnreadableDirectories();
......
......@@ -91,7 +91,7 @@ public class DiskBoundaries
{
if (isInvalid)
return true;
int currentDiskVersion = BlacklistedDirectories.getDirectoriesVersion();
int currentDiskVersion = DisallowedDirectories.getDirectoriesVersion();
long currentRingVersion = StorageService.instance.getTokenMetadata().getRingVersion();
return currentDiskVersion != directoriesVersion || (ringVersion != -1 && currentRingVersion != ringVersion);
}
......
......@@ -46,7 +46,7 @@ public class DiskBoundaryManager
public DiskBoundaries getDiskBoundaries(ColumnFamilyStore cfs)
{
if (!cfs.getPartitioner().splitter().isPresent())
return new DiskBoundaries(cfs, cfs.getDirectories().getWriteableLocations(), BlacklistedDirectories.getDirectoriesVersion());
return new DiskBoundaries(cfs, cfs.getDirectories().getWriteableLocations(), DisallowedDirectories.getDirectoriesVersion());
if (diskBoundaries == null || diskBoundaries.isOutOfDate())
{
synchronized (this)
......@@ -101,10 +101,10 @@ public class DiskBoundaryManager
Directories.DataDirectory[] dirs;
do
{
directoriesVersion = BlacklistedDirectories.getDirectoriesVersion();
directoriesVersion = DisallowedDirectories.getDirectoriesVersion();
dirs = cfs.getDirectories().getWriteableLocations();
}
while (directoriesVersion != BlacklistedDirectories.getDirectoriesVersion()); // if directoriesVersion has changed we need to recalculate
while (directoriesVersion != DisallowedDirectories.getDirectoriesVersion()); // if directoriesVersion has changed we need to recalculate
if (localRanges == null || localRanges.isEmpty())
return new DiskBoundaries(cfs, dirs, null, ringVersion, directoriesVersion);
......
......@@ -209,10 +209,10 @@ public abstract class AbstractCompactionStrategy
public abstract long getMaxSSTableBytes();
/**
* Filters SSTables that are to be blacklisted from the given collection
* Filters SSTables that are to be excluded from the given collection
*
* @param originalCandidates The collection to check for blacklisted SSTables
* @return list of the SSTables with blacklisted ones filtered out
* @param originalCandidates The collection to check for excluded SSTables
* @return list of the SSTables with excluded ones filtered out
*/
public static List<SSTableReader> filterSuspectSSTables(Iterable<SSTableReader> originalCandidates)
{
......
......@@ -638,7 +638,7 @@ public class LeveledManifest
/**
* @return highest-priority sstables to compact for the given level.
* If no compactions are possible (because of concurrent compactions or because some sstables are blacklisted
* If no compactions are possible (because of concurrent compactions or because some sstables are excluded
* for prior failure), will return an empty list. Never returns null.
*/
private Collection<SSTableReader> getCandidatesFor(int level)
......
......@@ -216,24 +216,24 @@ public class RangeStreamer
/**
* Source filter which only includes endpoints contained within a provided set.
*/
public static class WhitelistedSourcesFilter implements SourceFilter
public static class AllowedSourcesFilter implements SourceFilter
{
private final Set<InetAddressAndPort> whitelistedSources;
private final Set<InetAddressAndPort> allowedSources;
public WhitelistedSourcesFilter(Set<InetAddressAndPort> whitelistedSources)
public AllowedSourcesFilter(Set<InetAddressAndPort> allowedSources)
{
this.whitelistedSources = whitelistedSources;
this.allowedSources = allowedSources;
}
public boolean apply(Replica replica)
{
return whitelistedSources.contains(replica.endpoint());
return allowedSources.contains(replica.endpoint());
}
@Override
public String message(Replica replica)
{
return "Filtered " + replica + " out because it was not whitelisted, whitelisted sources: " + whitelistedSources;
return "Filtered " + replica + " out because it was not in the allowed set: " + allowedSources;
}
}
......
......@@ -242,7 +242,7 @@ final class HintsDispatchExecutor
{
logger.error(String.format("Failed to dispatch hints file %s: file is corrupted", descriptor.fileName()), e);
store.cleanUp(descriptor);
store.blacklist(descriptor);
store.markCorrupted(descriptor);
throw e;
}
}
......
......@@ -52,7 +52,7 @@ final class HintsStore
private final Map<HintsDescriptor, InputPosition> dispatchPositions;
private final Deque<HintsDescriptor> dispatchDequeue;
private final Queue<HintsDescriptor> blacklistedFiles;
private final Queue<HintsDescriptor> corruptedFiles;
// last timestamp used in a descriptor; make sure to not reuse the same timestamp for new descriptors.
private volatile long lastUsedTimestamp;
......@@ -66,7 +66,7 @@ final class HintsStore
dispatchPositions = new ConcurrentHashMap<>();
dispatchDequeue = new ConcurrentLinkedDeque<>(descriptors);
blacklistedFiles = new ConcurrentLinkedQueue<>();
corruptedFiles = new ConcurrentLinkedQueue<>();
//noinspection resource
lastUsedTimestamp = descriptors.stream().mapToLong(d -> d.timestamp).max().orElse(0L);
......@@ -119,7 +119,7 @@ final class HintsStore
delete(descriptor);
}
while ((descriptor = blacklistedFiles.poll()) != null)
while ((descriptor = corruptedFiles.poll()) != null)
{
cleanUp(descriptor);
delete(descriptor);
......@@ -158,9 +158,9 @@ final class HintsStore
dispatchPositions.remove(descriptor);
}
void blacklist(HintsDescriptor descriptor)
void markCorrupted(HintsDescriptor descriptor)
{
blacklistedFiles.add(descriptor);
corruptedFiles.add(descriptor);
}
/*
......
......@@ -1742,7 +1742,7 @@ public abstract class SSTableReader extends SSTable implements SelfRefCounted<SS
public void markSuspect()
{
if (logger.isTraceEnabled())
logger.trace("Marking {} as a suspect for blacklisting.", getFilename());
logger.trace("Marking {} as a suspect to be excluded from reads.", getFilename());
isSuspect.getAndSet(true);
}
......
......@@ -24,7 +24,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.db.BlacklistedDirectories;
import org.apache.cassandra.db.DisallowedDirectories;
import org.apache.cassandra.db.Keyspace;
import org.apache.cassandra.io.FSError;
import org.apache.cassandra.io.FSErrorHandler;
......@@ -66,10 +66,10 @@ public class DefaultFSErrorHandler implements FSErrorHandler
break;
case best_effort:
// for both read and write errors mark the path as unwritable.
BlacklistedDirectories.maybeMarkUnwritable(e.path);
DisallowedDirectories.maybeMarkUnwritable(e.path);
if (e instanceof FSReadError)
{
File directory = BlacklistedDirectories.maybeMarkUnreadable(e.path);
File directory = DisallowedDirectories.maybeMarkUnreadable(e.path);
if (directory != null)
Keyspace.removeUnreadableSSTables(directory);
}
......
......@@ -1256,7 +1256,7 @@ public class StorageService extends NotificationBroadcasterSupport implements IE
throw new IllegalArgumentException("Unknown host specified " + stringHost, ex);
}
}
streamer.addSourceFilter(new RangeStreamer.WhitelistedSourcesFilter(sources));
streamer.addSourceFilter(new RangeStreamer.AllowedSourcesFilter(sources));
}
streamer.addRanges(keyspace, streamRanges.build());
......
......@@ -706,14 +706,14 @@ public class Util
for ( ; ; )
{
DataDirectory dir = cfs.getDirectories().getWriteableLocation(1);
BlacklistedDirectories.maybeMarkUnwritable(cfs.getDirectories().getLocationForDisk(dir));
DisallowedDirectories.maybeMarkUnwritable(cfs.getDirectories().getLocationForDisk(dir));