Return-Path: X-Original-To: apmail-cassandra-commits-archive@www.apache.org Delivered-To: apmail-cassandra-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id D6E6F17AA7 for ; Wed, 14 Jan 2015 19:51:07 +0000 (UTC) Received: (qmail 37786 invoked by uid 500); 14 Jan 2015 19:51:09 -0000 Delivered-To: apmail-cassandra-commits-archive@cassandra.apache.org Received: (qmail 37741 invoked by uid 500); 14 Jan 2015 19:51:09 -0000 Mailing-List: contact commits-help@cassandra.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cassandra.apache.org Delivered-To: mailing list commits@cassandra.apache.org Received: (qmail 37701 invoked by uid 99); 14 Jan 2015 19:51:09 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 14 Jan 2015 19:51:09 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 21034A42999; Wed, 14 Jan 2015 19:51:09 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: aleksey@apache.org To: commits@cassandra.apache.org Date: Wed, 14 Jan 2015 19:51:09 -0000 Message-Id: <55300fea081d4eda8a0e657facd66408@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [1/4] cassandra git commit: Introduce role based access control Repository: cassandra Updated Branches: refs/heads/trunk c65a9f5c6 -> 879b694d3 http://git-wip-us.apache.org/repos/asf/cassandra/blob/879b694d/src/java/org/apache/cassandra/service/ClientState.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/service/ClientState.java b/src/java/org/apache/cassandra/service/ClientState.java index 36f8326..21d10f9 100644 --- a/src/java/org/apache/cassandra/service/ClientState.java +++ b/src/java/org/apache/cassandra/service/ClientState.java @@ -18,11 +18,12 @@ package org.apache.cassandra.service; import java.net.SocketAddress; -import java.util.*; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; import java.util.concurrent.atomic.AtomicLong; import com.google.common.collect.Iterables; -import com.google.common.collect.Sets; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -31,13 +32,13 @@ import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.config.Schema; import org.apache.cassandra.cql3.QueryHandler; import org.apache.cassandra.cql3.QueryProcessor; -import org.apache.cassandra.schema.LegacySchemaTables; import org.apache.cassandra.db.SystemKeyspace; import org.apache.cassandra.exceptions.AuthenticationException; import org.apache.cassandra.exceptions.InvalidRequestException; import org.apache.cassandra.exceptions.UnauthorizedException; -import org.apache.cassandra.tracing.TraceKeyspace; +import org.apache.cassandra.schema.LegacySchemaTables; import org.apache.cassandra.thrift.ThriftValidation; +import org.apache.cassandra.tracing.TraceKeyspace; import org.apache.cassandra.utils.FBUtilities; import org.apache.cassandra.utils.JVMStabilityInspector; import org.apache.cassandra.utils.SemanticVersion; @@ -52,16 +53,27 @@ public class ClientState private static final Set READABLE_SYSTEM_RESOURCES = new HashSet<>(); private static final Set PROTECTED_AUTH_RESOURCES = new HashSet<>(); - + private static final Set ALTERABLE_SYSTEM_KEYSPACES = new HashSet<>(); + private static final Set DROPPABLE_SYSTEM_TABLES = new HashSet<>(); static { // We want these system cfs to be always readable to authenticated users since many tools rely on them // (nodetool, cqlsh, bulkloader, etc.) for (String cf : Iterables.concat(Arrays.asList(SystemKeyspace.LOCAL, SystemKeyspace.PEERS), LegacySchemaTables.ALL)) - READABLE_SYSTEM_RESOURCES.add(DataResource.columnFamily(SystemKeyspace.NAME, cf)); + READABLE_SYSTEM_RESOURCES.add(DataResource.table(SystemKeyspace.NAME, cf)); PROTECTED_AUTH_RESOURCES.addAll(DatabaseDescriptor.getAuthenticator().protectedResources()); PROTECTED_AUTH_RESOURCES.addAll(DatabaseDescriptor.getAuthorizer().protectedResources()); + PROTECTED_AUTH_RESOURCES.addAll(DatabaseDescriptor.getRoleManager().protectedResources()); + + // allow users with sufficient privileges to alter KS level options on AUTH_KS and + // TRACING_KS, and also to drop legacy tables (users, credentials, permissions) from + // AUTH_KS + ALTERABLE_SYSTEM_KEYSPACES.add(AuthKeyspace.NAME); + ALTERABLE_SYSTEM_KEYSPACES.add(TraceKeyspace.NAME); + DROPPABLE_SYSTEM_TABLES.add(DataResource.table(AuthKeyspace.NAME, PasswordAuthenticator.LEGACY_CREDENTIALS_TABLE)); + DROPPABLE_SYSTEM_TABLES.add(DataResource.table(AuthKeyspace.NAME, CassandraRoleManager.LEGACY_USERS_TABLE)); + DROPPABLE_SYSTEM_TABLES.add(DataResource.table(AuthKeyspace.NAME, CassandraAuthorizer.USER_PERMISSIONS)); } // Current user for the session @@ -200,10 +212,13 @@ public class ClientState */ public void login(AuthenticatedUser user) throws AuthenticationException { - if (!user.isAnonymous() && !Auth.isExistingUser(user.getName())) - throw new AuthenticationException(String.format("User %s doesn't exist - create it with CREATE USER query first", - user.getName())); - this.user = user; + // Login privilege is not inherited via granted roles, so just + // verify that the role with the credentials that were actually + // supplied has it + if (user.isAnonymous() || DatabaseDescriptor.getRoleManager().canLogin(user.getName())) + this.user = user; + else + throw new AuthenticationException(String.format("%s is not permitted to log in", user.getName())); } public void hasAllKeyspacesAccess(Permission perm) throws UnauthorizedException @@ -223,7 +238,7 @@ public class ClientState throws UnauthorizedException, InvalidRequestException { ThriftValidation.validateColumnFamily(keyspace, columnFamily); - hasAccess(keyspace, perm, DataResource.columnFamily(keyspace, columnFamily)); + hasAccess(keyspace, perm, DataResource.table(keyspace, columnFamily)); } private void hasAccess(String keyspace, Permission perm, DataResource resource) @@ -264,10 +279,15 @@ public class ClientState if (SystemKeyspace.NAME.equalsIgnoreCase(keyspace)) throw new UnauthorizedException(keyspace + " keyspace is not user-modifiable."); - // we want to allow altering AUTH_KS and TRACING_KS. - Set allowAlter = Sets.newHashSet(Auth.AUTH_KS, TraceKeyspace.NAME); - if (allowAlter.contains(keyspace.toLowerCase()) && !(resource.isKeyspaceLevel() && (perm == Permission.ALTER))) + // allow users with sufficient privileges to alter KS level options on AUTH_KS and + // TRACING_KS, and also to drop legacy tables (users, credentials, permissions) from + // AUTH_KS + if (ALTERABLE_SYSTEM_KEYSPACES.contains(resource.getKeyspace().toLowerCase()) + && ((perm == Permission.ALTER && !resource.isKeyspaceLevel()) + || (perm == Permission.DROP && !DROPPABLE_SYSTEM_TABLES.contains(resource)))) + { throw new UnauthorizedException(String.format("Cannot %s %s", perm, resource)); + } } public void validateLogin() throws UnauthorizedException @@ -307,6 +327,6 @@ public class ClientState private Set authorize(IResource resource) { - return Auth.getPermissions(user, resource); + return AuthenticatedUser.getPermissions(user, resource); } } http://git-wip-us.apache.org/repos/asf/cassandra/blob/879b694d/src/java/org/apache/cassandra/service/StorageService.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/service/StorageService.java b/src/java/org/apache/cassandra/service/StorageService.java index 4740cd3..bb3e882 100644 --- a/src/java/org/apache/cassandra/service/StorageService.java +++ b/src/java/org/apache/cassandra/service/StorageService.java @@ -17,10 +17,7 @@ */ package org.apache.cassandra.service; -import java.io.ByteArrayInputStream; -import java.io.DataInputStream; -import java.io.File; -import java.io.IOException; +import java.io.*; import java.lang.management.ManagementFactory; import java.net.InetAddress; import java.net.UnknownHostException; @@ -29,20 +26,10 @@ import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; - -import javax.management.JMX; -import javax.management.MBeanServer; -import javax.management.Notification; -import javax.management.NotificationBroadcasterSupport; -import javax.management.ObjectName; +import javax.management.*; import javax.management.openmbean.TabularData; import javax.management.openmbean.TabularDataSupport; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.jmx.JMXConfiguratorMBean; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.Appender; - import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Predicate; import com.google.common.collect.*; @@ -52,12 +39,17 @@ import org.apache.commons.lang3.time.DurationFormatUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.apache.cassandra.auth.Auth; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.jmx.JMXConfiguratorMBean; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.Appender; +import org.apache.cassandra.auth.AuthKeyspace; +import org.apache.cassandra.auth.AuthMigrationListener; import org.apache.cassandra.concurrent.*; import org.apache.cassandra.config.*; -import org.apache.cassandra.cql3.UntypedResultSet; import org.apache.cassandra.cql3.QueryOptions; import org.apache.cassandra.cql3.QueryProcessor; +import org.apache.cassandra.cql3.UntypedResultSet; import org.apache.cassandra.cql3.statements.SelectStatement; import org.apache.cassandra.db.*; import org.apache.cassandra.db.commitlog.CommitLog; @@ -74,15 +66,9 @@ import org.apache.cassandra.io.sstable.SSTableLoader; import org.apache.cassandra.io.util.FileUtils; import org.apache.cassandra.locator.*; import org.apache.cassandra.metrics.StorageMetrics; -import org.apache.cassandra.net.AsyncOneResponse; -import org.apache.cassandra.net.MessageOut; -import org.apache.cassandra.net.MessagingService; -import org.apache.cassandra.net.ResponseVerbHandler; -import org.apache.cassandra.repair.RepairMessageVerbHandler; -import org.apache.cassandra.repair.RepairSessionResult; +import org.apache.cassandra.net.*; +import org.apache.cassandra.repair.*; import org.apache.cassandra.repair.messages.RepairOption; -import org.apache.cassandra.repair.RepairSession; -import org.apache.cassandra.repair.RepairParallelism; import org.apache.cassandra.service.paxos.CommitVerbHandler; import org.apache.cassandra.service.paxos.PrepareVerbHandler; import org.apache.cassandra.service.paxos.ProposeVerbHandler; @@ -843,7 +829,7 @@ public class StorageService extends NotificationBroadcasterSupport implements IE Gossiper.instance.replacedEndpoint(existing); assert tokenMetadata.sortedTokens().size() > 0; - Auth.setup(); + doAuthSetup(); } else { @@ -882,10 +868,41 @@ public class StorageService extends NotificationBroadcasterSupport implements IE logger.info("Leaving write survey mode and joining ring at operator request"); assert tokenMetadata.sortedTokens().size() > 0; - Auth.setup(); + doAuthSetup(); } } + private void doAuthSetup() + { + try + { + // if we don't have system_auth keyspace at this point, then create it manually + // otherwise, create any necessary tables as we may be upgrading in which case + // the ks exists with the only the legacy tables defined + if (Schema.instance.getKSMetaData(AuthKeyspace.NAME) == null) + { + MigrationManager.announceNewKeyspace(AuthKeyspace.definition(), 0, false); + } + else + { + for (Map.Entry table : AuthKeyspace.definition().cfMetaData().entrySet()) + { + if (Schema.instance.getCFMetaData(AuthKeyspace.NAME, table.getKey()) == null) + MigrationManager.announceNewColumnFamily(table.getValue()); + } + } + } + catch (Exception e) + { + throw new AssertionError(e); // shouldn't ever happen. + } + + DatabaseDescriptor.getRoleManager().setup(); + DatabaseDescriptor.getAuthenticator().setup(); + DatabaseDescriptor.getAuthorizer().setup(); + MigrationManager.instance.register(new AuthMigrationListener()); + } + public boolean isJoined() { return joined; http://git-wip-us.apache.org/repos/asf/cassandra/blob/879b694d/src/java/org/apache/cassandra/thrift/CassandraServer.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/thrift/CassandraServer.java b/src/java/org/apache/cassandra/thrift/CassandraServer.java index 7d89049..c0de59f 100644 --- a/src/java/org/apache/cassandra/thrift/CassandraServer.java +++ b/src/java/org/apache/cassandra/thrift/CassandraServer.java @@ -29,43 +29,30 @@ import java.util.zip.Inflater; import com.google.common.base.Function; import com.google.common.base.Joiner; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSortedSet; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; +import com.google.common.collect.*; import com.google.common.primitives.Longs; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.apache.cassandra.auth.AuthenticatedUser; import org.apache.cassandra.auth.Permission; -import org.apache.cassandra.config.CFMetaData; -import org.apache.cassandra.config.DatabaseDescriptor; -import org.apache.cassandra.config.KSMetaData; -import org.apache.cassandra.config.Schema; +import org.apache.cassandra.config.*; import org.apache.cassandra.cql3.QueryOptions; import org.apache.cassandra.cql3.statements.ParsedStatement; import org.apache.cassandra.db.*; import org.apache.cassandra.db.composites.*; import org.apache.cassandra.db.context.CounterContext; import org.apache.cassandra.db.filter.ColumnSlice; -import org.apache.cassandra.db.filter.IDiskAtomFilter; -import org.apache.cassandra.db.filter.NamesQueryFilter; -import org.apache.cassandra.db.filter.SliceQueryFilter; +import org.apache.cassandra.db.filter.*; import org.apache.cassandra.db.marshal.TimeUUIDType; import org.apache.cassandra.dht.*; +import org.apache.cassandra.dht.Range; import org.apache.cassandra.exceptions.*; import org.apache.cassandra.io.util.DataOutputBuffer; import org.apache.cassandra.locator.DynamicEndpointSnitch; import org.apache.cassandra.metrics.ClientMetrics; import org.apache.cassandra.scheduler.IRequestScheduler; import org.apache.cassandra.serializers.MarshalException; -import org.apache.cassandra.service.CASRequest; -import org.apache.cassandra.service.ClientState; -import org.apache.cassandra.service.MigrationManager; -import org.apache.cassandra.service.StorageProxy; -import org.apache.cassandra.service.StorageService; +import org.apache.cassandra.service.*; import org.apache.cassandra.service.pager.QueryPagers; import org.apache.cassandra.tracing.Tracing; import org.apache.cassandra.utils.ByteBufferUtil; @@ -1472,12 +1459,11 @@ public class CassandraServer implements Cassandra.Iface } } - public void login(AuthenticationRequest auth_request) throws AuthenticationException, AuthorizationException, TException + public void login(AuthenticationRequest auth_request) throws TException { try { - AuthenticatedUser user = DatabaseDescriptor.getAuthenticator().authenticate(auth_request.getCredentials()); - state().login(user); + state().login(DatabaseDescriptor.getAuthenticator().legacyAuthenticate(auth_request.getCredentials())); } catch (org.apache.cassandra.exceptions.AuthenticationException e) { http://git-wip-us.apache.org/repos/asf/cassandra/blob/879b694d/src/java/org/apache/cassandra/tools/BulkLoader.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/tools/BulkLoader.java b/src/java/org/apache/cassandra/tools/BulkLoader.java index a720e12..f89acfb 100644 --- a/src/java/org/apache/cassandra/tools/BulkLoader.java +++ b/src/java/org/apache/cassandra/tools/BulkLoader.java @@ -18,33 +18,33 @@ package org.apache.cassandra.tools; import java.io.File; -import java.net.*; +import java.net.InetAddress; +import java.net.MalformedURLException; +import java.net.UnknownHostException; import java.util.*; import com.google.common.base.Joiner; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; - import org.apache.commons.cli.*; -import org.apache.thrift.protocol.TBinaryProtocol; -import org.apache.thrift.protocol.TProtocol; -import org.apache.thrift.transport.TTransport; - -import org.apache.cassandra.auth.IAuthenticator; +import org.apache.cassandra.auth.PasswordAuthenticator; import org.apache.cassandra.config.*; -import org.apache.cassandra.schema.LegacySchemaTables; import org.apache.cassandra.db.SystemKeyspace; import org.apache.cassandra.db.marshal.UTF8Type; import org.apache.cassandra.dht.Range; import org.apache.cassandra.dht.Token; import org.apache.cassandra.exceptions.ConfigurationException; import org.apache.cassandra.io.sstable.SSTableLoader; +import org.apache.cassandra.schema.LegacySchemaTables; import org.apache.cassandra.streaming.*; import org.apache.cassandra.thrift.*; import org.apache.cassandra.utils.ByteBufferUtil; import org.apache.cassandra.utils.JVMStabilityInspector; import org.apache.cassandra.utils.OutputHandler; +import org.apache.thrift.protocol.TBinaryProtocol; +import org.apache.thrift.protocol.TProtocol; +import org.apache.thrift.transport.TTransport; public class BulkLoader { @@ -359,8 +359,8 @@ public class BulkLoader if (user != null && passwd != null) { Map credentials = new HashMap<>(); - credentials.put(IAuthenticator.USERNAME_KEY, user); - credentials.put(IAuthenticator.PASSWORD_KEY, passwd); + credentials.put(PasswordAuthenticator.USERNAME_KEY, user); + credentials.put(PasswordAuthenticator.PASSWORD_KEY, passwd); AuthenticationRequest authenticationRequest = new AuthenticationRequest(credentials); client.login(authenticationRequest); } http://git-wip-us.apache.org/repos/asf/cassandra/blob/879b694d/src/java/org/apache/cassandra/transport/Client.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/transport/Client.java b/src/java/org/apache/cassandra/transport/Client.java index c7c3103..571a7ce 100644 --- a/src/java/org/apache/cassandra/transport/Client.java +++ b/src/java/org/apache/cassandra/transport/Client.java @@ -22,16 +22,11 @@ import java.io.IOException; import java.io.InputStreamReader; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; +import java.util.*; import com.google.common.base.Splitter; -import org.apache.cassandra.auth.IAuthenticator; +import org.apache.cassandra.auth.PasswordAuthenticator; import org.apache.cassandra.cql3.QueryOptions; import org.apache.cassandra.db.ConsistencyLevel; import org.apache.cassandra.db.marshal.Int32Type; @@ -179,7 +174,7 @@ public class Client extends SimpleClient else if (msgType.equals("AUTHENTICATE")) { Map credentials = readCredentials(iter); - if(!credentials.containsKey(IAuthenticator.USERNAME_KEY) || !credentials.containsKey(IAuthenticator.PASSWORD_KEY)) + if(!credentials.containsKey(PasswordAuthenticator.USERNAME_KEY) || !credentials.containsKey(PasswordAuthenticator.PASSWORD_KEY)) { System.err.println("[ERROR] Authentication requires both 'username' and 'password'"); return null; @@ -221,8 +216,8 @@ public class Client extends SimpleClient private byte[] encodeCredentialsForSasl(Map credentials) { - byte[] username = credentials.get(IAuthenticator.USERNAME_KEY).getBytes(StandardCharsets.UTF_8); - byte[] password = credentials.get(IAuthenticator.PASSWORD_KEY).getBytes(StandardCharsets.UTF_8); + byte[] username = credentials.get(PasswordAuthenticator.USERNAME_KEY).getBytes(StandardCharsets.UTF_8); + byte[] password = credentials.get(PasswordAuthenticator.PASSWORD_KEY).getBytes(StandardCharsets.UTF_8); byte[] initialResponse = new byte[username.length + password.length + 2]; initialResponse[0] = 0; System.arraycopy(username, 0, initialResponse, 1, username.length); http://git-wip-us.apache.org/repos/asf/cassandra/blob/879b694d/src/java/org/apache/cassandra/transport/Server.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/transport/Server.java b/src/java/org/apache/cassandra/transport/Server.java index 99601a6..8830479 100644 --- a/src/java/org/apache/cassandra/transport/Server.java +++ b/src/java/org/apache/cassandra/transport/Server.java @@ -28,21 +28,24 @@ import java.util.concurrent.atomic.AtomicBoolean; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; -import io.netty.channel.epoll.Epoll; -import io.netty.channel.epoll.EpollEventLoopGroup; -import io.netty.channel.epoll.EpollServerSocketChannel; -import io.netty.util.Version; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.*; +import io.netty.channel.epoll.Epoll; +import io.netty.channel.epoll.EpollEventLoopGroup; +import io.netty.channel.epoll.EpollServerSocketChannel; +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.ssl.SslHandler; +import io.netty.util.Version; import io.netty.util.concurrent.EventExecutor; import io.netty.util.concurrent.GlobalEventExecutor; import io.netty.util.internal.logging.InternalLoggerFactory; import io.netty.util.internal.logging.Slf4JLoggerFactory; -import org.apache.cassandra.auth.IAuthenticator; -import org.apache.cassandra.auth.ISaslAwareAuthenticator; import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.config.EncryptionOptions; import org.apache.cassandra.db.marshal.AbstractType; @@ -50,11 +53,6 @@ import org.apache.cassandra.metrics.ClientMetrics; import org.apache.cassandra.security.SSLFactory; import org.apache.cassandra.service.*; import org.apache.cassandra.transport.messages.EventMessage; -import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.*; -import io.netty.channel.group.ChannelGroup; -import io.netty.channel.group.DefaultChannelGroup; -import io.netty.handler.ssl.SslHandler; public class Server implements CassandraDaemon.Server { @@ -132,16 +130,6 @@ public class Server implements CassandraDaemon.Server private void run() { - // Check that a SaslAuthenticator can be provided by the configured - // IAuthenticator. If not, don't start the server. - IAuthenticator authenticator = DatabaseDescriptor.getAuthenticator(); - if (authenticator.requireAuthentication() && !(authenticator instanceof ISaslAwareAuthenticator)) - { - logger.error("Not starting native transport as the configured IAuthenticator is not capable of SASL authentication"); - isRunning.compareAndSet(true, false); - return; - } - // Configure the server. eventExecutorGroup = new RequestThreadPoolExecutor(); http://git-wip-us.apache.org/repos/asf/cassandra/blob/879b694d/src/java/org/apache/cassandra/transport/ServerConnection.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/transport/ServerConnection.java b/src/java/org/apache/cassandra/transport/ServerConnection.java index b28866f..24eb643 100644 --- a/src/java/org/apache/cassandra/transport/ServerConnection.java +++ b/src/java/org/apache/cassandra/transport/ServerConnection.java @@ -20,21 +20,17 @@ package org.apache.cassandra.transport; import java.util.concurrent.ConcurrentMap; import io.netty.channel.Channel; - import org.apache.cassandra.auth.IAuthenticator; -import org.apache.cassandra.auth.ISaslAwareAuthenticator; -import org.apache.cassandra.auth.ISaslAwareAuthenticator.SaslAuthenticator; import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.service.ClientState; import org.apache.cassandra.service.QueryState; - import org.cliffc.high_scale_lib.NonBlockingHashMap; public class ServerConnection extends Connection { private enum State { UNINITIALIZED, AUTHENTICATION, READY } - private volatile SaslAuthenticator saslAuthenticator; + private volatile IAuthenticator.SaslNegotiator saslNegotiator; private final ClientState clientState; private volatile State state; @@ -104,7 +100,7 @@ public class ServerConnection extends Connection { state = State.READY; // we won't use the authenticator again, null it so that it can be GC'd - saslAuthenticator = null; + saslNegotiator = null; } break; case READY: @@ -114,14 +110,10 @@ public class ServerConnection extends Connection } } - public SaslAuthenticator getAuthenticator() + public IAuthenticator.SaslNegotiator getSaslNegotiator() { - if (saslAuthenticator == null) - { - IAuthenticator authenticator = DatabaseDescriptor.getAuthenticator(); - assert authenticator instanceof ISaslAwareAuthenticator : "Configured IAuthenticator does not support SASL authentication"; - saslAuthenticator = ((ISaslAwareAuthenticator)authenticator).newAuthenticator(); - } - return saslAuthenticator; + if (saslNegotiator == null) + saslNegotiator = DatabaseDescriptor.getAuthenticator().newSaslNegotiator(); + return saslNegotiator; } } http://git-wip-us.apache.org/repos/asf/cassandra/blob/879b694d/src/java/org/apache/cassandra/transport/messages/AuthResponse.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/transport/messages/AuthResponse.java b/src/java/org/apache/cassandra/transport/messages/AuthResponse.java index 3f3f774..cb67476 100644 --- a/src/java/org/apache/cassandra/transport/messages/AuthResponse.java +++ b/src/java/org/apache/cassandra/transport/messages/AuthResponse.java @@ -17,18 +17,14 @@ */ package org.apache.cassandra.transport.messages; +import java.nio.ByteBuffer; + +import io.netty.buffer.ByteBuf; import org.apache.cassandra.auth.AuthenticatedUser; -import org.apache.cassandra.auth.ISaslAwareAuthenticator.SaslAuthenticator; +import org.apache.cassandra.auth.IAuthenticator; import org.apache.cassandra.exceptions.AuthenticationException; import org.apache.cassandra.service.QueryState; -import org.apache.cassandra.transport.CBUtil; -import org.apache.cassandra.transport.Message; -import org.apache.cassandra.transport.ProtocolException; -import org.apache.cassandra.transport.ServerConnection; - -import io.netty.buffer.ByteBuf; - -import java.nio.ByteBuffer; +import org.apache.cassandra.transport.*; /** * A SASL token message sent from client to server. Some SASL @@ -61,11 +57,12 @@ public class AuthResponse extends Message.Request } }; - private byte[] token; + private final byte[] token; public AuthResponse(byte[] token) { super(Message.Type.AUTH_RESPONSE); + assert token != null; this.token = token; } @@ -74,11 +71,11 @@ public class AuthResponse extends Message.Request { try { - SaslAuthenticator authenticator = ((ServerConnection) connection).getAuthenticator(); - byte[] challenge = authenticator.evaluateResponse(token == null ? new byte[0] : token); - if (authenticator.isComplete()) + IAuthenticator.SaslNegotiator negotiator = ((ServerConnection) connection).getSaslNegotiator(); + byte[] challenge = negotiator.evaluateResponse(token); + if (negotiator.isComplete()) { - AuthenticatedUser user = authenticator.getAuthenticatedUser(); + AuthenticatedUser user = negotiator.getAuthenticatedUser(); queryState.getClientState().login(user); // authentication is complete, send a ready message to the client return new AuthSuccess(challenge); http://git-wip-us.apache.org/repos/asf/cassandra/blob/879b694d/src/java/org/apache/cassandra/transport/messages/CredentialsMessage.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/transport/messages/CredentialsMessage.java b/src/java/org/apache/cassandra/transport/messages/CredentialsMessage.java index eb39e30..aad4232 100644 --- a/src/java/org/apache/cassandra/transport/messages/CredentialsMessage.java +++ b/src/java/org/apache/cassandra/transport/messages/CredentialsMessage.java @@ -20,15 +20,14 @@ package org.apache.cassandra.transport.messages; import java.util.HashMap; import java.util.Map; +import io.netty.buffer.ByteBuf; import org.apache.cassandra.auth.AuthenticatedUser; import org.apache.cassandra.config.DatabaseDescriptor; -import org.apache.cassandra.transport.ProtocolException; -import io.netty.buffer.ByteBuf; - import org.apache.cassandra.exceptions.AuthenticationException; import org.apache.cassandra.service.QueryState; import org.apache.cassandra.transport.CBUtil; import org.apache.cassandra.transport.Message; +import org.apache.cassandra.transport.ProtocolException; /** * Message to indicate that the server is ready to receive requests. @@ -75,14 +74,15 @@ public class CredentialsMessage extends Message.Request { try { - AuthenticatedUser user = DatabaseDescriptor.getAuthenticator().authenticate(credentials); + AuthenticatedUser user = DatabaseDescriptor.getAuthenticator().legacyAuthenticate(credentials); state.getClientState().login(user); - return new ReadyMessage(); } catch (AuthenticationException e) { return ErrorMessage.fromException(e); } + + return new ReadyMessage(); } @Override http://git-wip-us.apache.org/repos/asf/cassandra/blob/879b694d/src/java/org/apache/cassandra/utils/FBUtilities.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/utils/FBUtilities.java b/src/java/org/apache/cassandra/utils/FBUtilities.java index 8077df8..0462e5e 100644 --- a/src/java/org/apache/cassandra/utils/FBUtilities.java +++ b/src/java/org/apache/cassandra/utils/FBUtilities.java @@ -20,19 +20,12 @@ package org.apache.cassandra.utils; import java.io.*; import java.lang.reflect.Field; import java.math.BigInteger; -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.net.SocketException; -import java.net.URL; -import java.net.UnknownHostException; +import java.net.*; import java.nio.ByteBuffer; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.*; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; +import java.util.concurrent.*; import java.util.zip.Checksum; import com.google.common.base.Joiner; @@ -43,6 +36,7 @@ import org.slf4j.LoggerFactory; import org.apache.cassandra.auth.IAuthenticator; import org.apache.cassandra.auth.IAuthorizer; +import org.apache.cassandra.auth.IRoleManager; import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.db.DecoratedKey; import org.apache.cassandra.dht.IPartitioner; @@ -54,10 +48,7 @@ import org.apache.cassandra.io.util.DataOutputBuffer; import org.apache.cassandra.io.util.FileUtils; import org.apache.cassandra.io.util.IAllocator; import org.apache.cassandra.net.AsyncOneResponse; -import org.apache.thrift.TBase; -import org.apache.thrift.TDeserializer; -import org.apache.thrift.TException; -import org.apache.thrift.TSerializer; +import org.apache.thrift.*; import org.codehaus.jackson.JsonFactory; import org.codehaus.jackson.map.ObjectMapper; @@ -439,6 +430,13 @@ public class FBUtilities return FBUtilities.construct(className, "authenticator"); } + public static IRoleManager newRoleManager(String className) throws ConfigurationException + { + if (!className.contains(".")) + className = "org.apache.cassandra.auth." + className; + return FBUtilities.construct(className, "role manager"); + } + /** * @return The Class for the given name. * @param classname Fully qualified classname.