Cassandra 文档

版本

您正在查看预发布版本的文档。

安全

Cassandra 提供的安全功能主要包含三个部分

  • 用于客户端和节点间通信的 TLS/SSL 加密

  • 客户端身份验证

  • 授权

默认情况下,这些功能处于禁用状态,因为 Cassandra 被配置为易于查找和被集群中的其他成员找到。换句话说,开箱即用的 Cassandra 安装为恶意攻击者提供了很大的攻击面。使用二进制协议为客户端启用身份验证不足以保护集群。能够访问节点间通信和 JMX 端口的恶意用户仍然可以

  • 制作节点间消息以将用户插入身份验证模式

  • 制作节点间消息以截断或删除模式

  • 使用 sstableloader 等工具覆盖 system_auth

  • 直接连接到集群以捕获写入流量

所有三个安全组件的正确配置应抵消这些向量。因此,了解 Cassandra 的安全功能对于配置集群以满足您的安全需求至关重要。

TLS/SSL 加密

Cassandra 在客户端机器与数据库集群之间以及集群内的节点之间提供安全通信。启用加密可确保传输中的数据不会被泄露,并以安全的方式传输。客户端到节点和节点到节点加密的选项是分开管理的,可以独立配置。

在这两种情况下,启用加密时,将使用支持的协议和密码套件的 JVM 默认值。这些值可以使用 cassandra.yaml 中的设置覆盖,但不建议这样做,除非存在规定某些设置的策略,或者需要在无法更新 JVM 的情况下禁用易受攻击的密码或协议。

可以在 JVM 级别配置符合 FIPS 的设置,并且不应涉及更改 cassandra.yaml 中的加密设置。有关更多详细信息,请参阅 有关 FIPS 的 Java 文档

Cassandra 提供了使用基于 Java 的密钥材料或完全自定义 SSL 上下文的灵活性。您可以选择 Java 支持的任何密钥库格式(JKS、PKCS12 等)以及其他标准,如 PEM。您甚至可以自定义 SSL 上下文创建以使用 Kubernetes Secrets 等云原生技术来存储密钥材料,或与您的内部密钥管理系统集成。

有关使用 SSL 通信中使用的 Java 支持的密钥库生成密钥库和信任库文件的信息,请参阅 有关创建密钥库的 Java 文档

要自定义 SSL 上下文创建,您可以实现 ISslContextCreationFactory 接口或扩展其公共子类之一。然后,您可以将 ssl_context_factory 设置用于 server_encryption_optionsclient_encryption_options 部分。有关详细信息,请参阅 ssl-factory 示例。请参考下面的类图以了解类层次结构。

image

使用基于 PEM 的密钥材料

您可以使用内置类 PEMBasedSSLContextFactory 作为基于 PEM 的密钥材料的 ssl_context_factory 设置。

您可以使用内联 PEM 数据或使用包含所需 PEM 数据的文件来配置此工厂,如下所示:

  • 配置:内联定义的 PEM 密钥/证书(注意 YAML 中的空格!)

   client/server_encryption_options:
     ssl_context_factory:
        class_name: org.apache.cassandra.security.PEMBasedSslContextFactory
        parameters:
            private_key: |
             -----BEGIN ENCRYPTED PRIVATE KEY----- OR -----BEGIN PRIVATE KEY-----
             <your base64 encoded private key>
             -----END ENCRYPTED PRIVATE KEY----- OR -----END PRIVATE KEY-----
             -----BEGIN CERTIFICATE-----
             <your base64 encoded certificate chain>
             -----END CERTIFICATE-----

            private_key_password: "<your password if the private key is encrypted with a password>"

            trusted_certificates: |
              -----BEGIN CERTIFICATE-----
              <your base64 encoded certificate>
              -----END CERTIFICATE-----
  • 配置:文件中定义的 PEM 密钥/证书

    client/server_encryption_options:
     ssl_context_factory:
        class_name: org.apache.cassandra.security.PEMBasedSslContextFactory
     keystore: <file path to the keystore file in the PEM format with the private key and the certificate chain>
     keystore_password: "<your password if the private key is encrypted with a password>"
     truststore: <file path to the truststore file in the PEM format>

SSL 证书热重载

从 Cassandra 4 开始,Cassandra 支持 SSL 证书的热重载。如果在 Cassandra 中启用了 SSL/TLS 支持,并且您使用的是默认的基于文件的密钥材料,则节点会定期(每 10 分钟)轮询 cassandra.yaml 中指定的信任库和密钥库。当文件更新时,Cassandra 将重新加载它们并将其用于后续连接。请注意,信任库和密钥库密码是 yaml 的一部分,因此更新后的文件也应使用相同的密码。

如果您通过 ssl_context_factory 设置自定义 SSL 配置,Cassandra 会定期(以上述相同的周期)轮询您的实现以检查是否需要重新加载 SSL 证书。有关更多详细信息,请参阅 ISslContextFactory 文档。如果您使用的是 Cassandra 的内置 SSL 上下文工厂类之一(例如:PEMBasedSslContextFactory)并使用基于文件的密钥材料,则它支持如上所述的 SSL 证书的热重载。

也可以使用 nodetool reloadssl 命令触发证书热重载。如果您希望 Cassandra 立即注意到更改的证书,请使用此命令。

节点间加密

管理节点间加密的设置位于 cassandra.yamlserver_encryption_options 部分。要启用节点间加密,请将 internode_encryption 设置从其默认值 none 更改为以下值之一:rackdcall

客户端到节点加密

管理客户端到节点加密的设置位于 cassandra.yamlclient_encryption_options 部分。这里有两个主要开关用于启用加密,enabledoptional

  • 如果两者均未设置为 true,则客户端连接完全未加密。

  • 如果 enabled 设置为 trueoptional 设置为 false,则所有客户端连接都必须是安全的。

  • 如果两个选项都设置为 true,则使用相同的端口支持加密和未加密的连接。使用此配置进行加密的客户端连接将被服务器自动检测和处理。

作为 optional 设置的替代方案,还可以为安全连接和不安全连接配置单独的端口,以满足操作需求。为此,请将 optional 设置为 false,并使用 cassandra.yaml 中的 native_transport_port_ssl 设置指定用于安全客户端通信的端口。

角色

Cassandra 在身份验证和权限管理中都使用数据库角色,这些角色可以代表单个用户或一组用户。角色管理是 Cassandra 中的一个扩展点,可以使用 cassandra.yaml 中的 role_manager 设置进行配置。默认设置使用 CassandraRoleManager,这是一种将角色信息存储在 system_auth 密钥空间的表中的实现。

另请参阅 有关角色的 CQL 文档

身份验证

身份验证在 Cassandra 中是可插拔的,并使用 cassandra.yaml 中的 authenticator 设置进行配置。Cassandra 附带了默认发行版中包含的两个选项。

默认情况下,Cassandra 配置了 AllowAllAuthenticator,它不执行任何身份验证检查,因此不需要任何凭据。它用于完全禁用身份验证。请注意,身份验证是 Cassandra 权限子系统的必要条件,因此如果禁用身份验证,则权限也会被禁用。

默认发行版还包含PasswordAuthenticator,它将加密的凭据存储在系统表中。这可用于启用简单的用户名/密码身份验证。

启用密码身份验证

在集群上启用客户端身份验证之前,应使用其预期凭据预先配置客户端应用程序。当连接启动时,服务器只会在启用身份验证后才请求凭据,因此提前设置客户端配置是安全的。相反,一旦服务器启用了身份验证,任何没有正确凭据的连接尝试都将被拒绝,这可能会导致客户端应用程序的可用性问题。一旦客户端设置完毕并准备启用身份验证,请按照以下步骤在集群上启用身份验证。

选择集群中的一个节点来执行初始配置。理想情况下,在设置过程中,没有客户端应该连接到此节点,因此您可能希望将其从客户端配置中删除,在网络级别阻止它,或者可能为此目的向集群添加一个新的临时节点。在该节点上,执行以下步骤

  1. 打开一个cqlsh会话并更改system_auth键空间的复制因子。默认情况下,此键空间使用SimpleReplicationStrategyreplication_factor为 1。建议为任何非平凡部署更改此设置,以确保即使节点不可用,登录仍然可能。最佳做法是为每个数据中心配置 3 到 5 的复制因子。

ALTER KEYSPACE system_auth WITH replication = {'class': 'NetworkTopologyStrategy', 'DC1': 3, 'DC2': 3};
  1. 编辑cassandra.yaml以更改authenticator选项,如下所示

authenticator: PasswordAuthenticator
  1. 重新启动节点。

  2. 使用默认超级用户的凭据打开一个新的cqlsh会话

$ cqlsh -u cassandra -p cassandra
  1. 在登录期间,默认超级用户的凭据以QUORUM的一致性级别读取,而所有其他用户的凭据(包括超级用户)以LOCAL_ONE读取。出于性能、可用性和安全性的考虑,操作员应创建另一个超级用户并禁用默认超级用户。此步骤是可选的,但强烈建议。在以默认超级用户身份登录时,创建另一个超级用户角色,该角色可用于引导进一步的配置。

# create a new superuser
CREATE ROLE dba WITH SUPERUSER = true AND LOGIN = true AND PASSWORD = 'super';
  1. 启动一个新的 cqlsh 会话,这次以 new_superuser 身份登录并禁用默认超级用户。

ALTER ROLE cassandra WITH SUPERUSER = false AND LOGIN = false;
  1. 最后,使用CREATE ROLE语句为您的应用程序用户设置角色和凭据。

完成这些步骤后,一个节点将配置为使用密码身份验证。要将此配置推广到整个集群,请在集群中的每个节点上重复步骤 2 和 3。一旦所有节点都已重新启动,身份验证将在整个集群中完全启用。

请注意,使用PasswordAuthenticator还需要使用CassandraRoleManager.

另请参见:setting-credentials-for-internal-authenticationCREATE ROLEALTER ROLEALTER KEYSPACEGRANT PERMISSION.

授权

授权在 Cassandra 中是可插拔的,并使用cassandra.yaml中的authorizer设置进行配置。Cassandra 附带了默认发行版中包含的两个选项。

默认情况下,Cassandra 配置为使用AllowAllAuthorizer,它不执行任何检查,因此实际上将所有权限授予所有角色。如果AllowAllAuthenticator是配置的验证器,则必须使用此设置。

默认发行版还包含CassandraAuthorizer,它确实实现了完整的权限管理功能,并将数据存储在 Cassandra 系统表中。

启用内部授权

权限被建模为白名单,默认情况下假设给定角色没有访问任何数据库资源的权限。这意味着一旦在节点上启用了授权,所有请求都将被拒绝,直到授予所需的权限。因此,强烈建议在不处理客户端请求的节点上执行初始设置。

以下假设身份验证已通过password-authentication中概述的过程启用。执行以下步骤以在整个集群中启用内部授权

  1. 在选定的节点上,编辑cassandra.yaml以更改authorizer选项,如下所示

authorizer: CassandraAuthorizer
  1. 重新启动节点。

  2. 使用具有超级用户凭据的角色的凭据打开一个新的cqlsh会话

$ cqlsh -u dba -p super
  1. 使用GRANT PERMISSION语句为您的客户端配置适当的访问权限。在其他节点上,在配置更新并重新启动节点之前,这将不起作用,因此避免了对客户端的干扰。

GRANT SELECT ON ks.t1 TO db_user;
  1. 一旦授予了所有必要的权限,请依次对每个节点重复步骤 1 和 2。随着每个节点重新启动和客户端重新连接,授予的权限的强制执行将开始。

缓存

启用身份验证和授权会通过频繁读取system_auth表来增加集群的负载。此外,这些读取位于许多客户端操作的关键路径中,因此有可能严重影响服务质量。为了缓解这种情况,身份验证数据(如凭据、权限和角色详细信息)将被缓存一段时间。缓存可以从cassandra.yaml或使用 JMX 客户端进行配置(甚至禁用)。JMX 接口还支持使各种缓存失效,但通过 JMX 做出的任何更改都不持久,并在节点重新启动时从cassandra.yaml重新读取。

每个缓存都有 3 个可以设置的选项

有效期

控制缓存条目的过期。在此期限后,条目将失效并从缓存中删除。

刷新率

控制执行后台读取以获取基础数据的任何更改的速率。在执行这些异步刷新时,缓存将继续提供(可能)过时的數據。通常,这将设置为比有效期更短的时间。

最大条目

控制缓存大小的上限。

cassandra.yaml中,这些选项的命名遵循以下约定

  • <type>_validity_in_ms

  • <type>_update_interval_in_ms

  • <type>_cache_max_entries

其中<type>credentialspermissionsroles之一。

如上所述,这些选项也通过org.apache.cassandra.auth域下的 mbean 在 JMX 中公开。

JMX 访问

JMX 客户端的访问控制与 CQL 的访问控制分开配置。对于身份验证和授权,都提供两个提供程序;第一个基于标准 JMX 安全性,第二个与 Cassandra 自己的身份验证子系统更紧密地集成。

Cassandra 的默认设置使 JMX 只能从 localhost 访问。要启用远程 JMX 连接,请编辑cassandra-env.sh以将LOCAL_JMX设置更改为no。在标准配置下,当启用远程 JMX 连接时,standard JMX authentication <standard-jmx-auth>也会打开。

请注意,默认情况下,仅本地连接不受身份验证,但可以启用此功能。

如果启用远程连接,建议也使用SSL连接。

最后,在启用身份验证和/或 SSL 后,请确保使用 JMX 的工具(如nodetool)已正确配置并按预期工作。

标准 JMX 身份验证

允许连接到 JMX 服务器的用户在简单的文本文件中指定。此文件的路径由cassandra-env.sh中的以下行设置

JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.password.file=/etc/cassandra/jmxremote.password"

编辑密码文件以添加用户名/密码对

jmx_user jmx_password

保护凭据文件,以便只有运行 Cassandra 进程的用户可以读取它

$ chown cassandra:cassandra /etc/cassandra/jmxremote.password
$ chmod 400 /etc/cassandra/jmxremote.password

可选地,启用访问控制以限制定义的用户可以通过 JMX 执行的操作范围。请注意,在这种情况下,这是一个相当粗略的工具,因为 Cassandra 中的大多数操作工具都需要完全读写访问权限。要配置一个简单的访问文件,请在cassandra-env.sh中取消注释此行

#JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.access.file=/etc/cassandra/jmxremote.access"

然后编辑访问文件以授予您的 JMX 用户读写权限

jmx_user readwrite

Cassandra 必须重新启动才能获取新设置。

Cassandra 集成身份验证

除了开箱即用的 JMX 身份验证之外,还可以使用 Cassandra 自己的身份验证和/或授权提供程序来为 JMX 客户端提供服务。这可能更灵活且更安全,但它有一个主要警告。即它在节点加入环之后才可用,因为身份验证子系统直到那时才完全配置。但是,在引导期间,尤其是在引导期间,出于监控目的,拥有 JMX 访问权限通常至关重要。因此,建议在可能的情况下,在引导期间使用仅本地 JMX 身份验证,然后,如果需要远程连接,则在节点加入环并完成初始设置后切换到集成身份验证。

使用此选项,用于 CQL 身份验证的相同数据库角色可用于控制对 JMX 的访问,因此可以使用cqlsh集中管理更新。此外,可以通过GRANT PERMISSION对哪些操作在特定 MBean 上被允许进行细粒度控制。

要启用集成身份验证,请编辑cassandra-env.sh以取消注释以下行

#JVM_OPTS="$JVM_OPTS -Dcassandra.jmx.remote.login.config=CassandraLogin"
#JVM_OPTS="$JVM_OPTS -Djava.security.auth.login.config=$CASSANDRA_HOME/conf/cassandra-jaas.config"

并通过注释以下行来禁用 JMX 标准身份验证

JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.password.file=/etc/cassandra/jmxremote.password"

要启用集成授权,请取消注释以下行

#JVM_OPTS="$JVM_OPTS -Dcassandra.jmx.authorizer=org.apache.cassandra.auth.jmx.AuthorizationProxy"

通过确保以下行被注释掉来检查标准访问控制是否已关闭

#JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.access.file=/etc/cassandra/jmxremote.access"

启用集成身份验证和授权后,操作员可以定义特定角色并授予它们对所需特定 JMX 资源的访问权限。例如,一个具有使用 jconsole 或 jmc 等工具以只读模式所需的权限的角色将被定义为

CREATE ROLE jmx WITH LOGIN = false;
GRANT SELECT ON ALL MBEANS TO jmx;
GRANT DESCRIBE ON ALL MBEANS TO jmx;
GRANT EXECUTE ON MBEAN 'java.lang:type=Threading' TO jmx;
GRANT EXECUTE ON MBEAN 'com.sun.management:type=HotSpotDiagnostic' TO jmx;

# Grant the role with necessary permissions to use nodetool commands (including nodetool status) in read-only mode
GRANT EXECUTE ON MBEAN 'org.apache.cassandra.db:type=EndpointSnitchInfo' TO jmx;
GRANT EXECUTE ON MBEAN 'org.apache.cassandra.db:type=StorageService' TO jmx;

# Grant the jmx role to one with login permissions so that it can access the JMX tooling
CREATE ROLE ks_user WITH PASSWORD = 'password' AND LOGIN = true AND SUPERUSER = false;
GRANT jmx TO ks_user;

对单个 MBean 的细粒度访问控制也受支持

GRANT EXECUTE ON MBEAN 'org.apache.cassandra.db:type=Tables,keyspace=test_keyspace,table=t1' TO ks_user;
GRANT EXECUTE ON MBEAN 'org.apache.cassandra.db:type=Tables,keyspace=test_keyspace,table=*' TO ks_owner;

这允许ks_user角色调用表示test_keyspace中单个表的 MBean 上的方法,同时向ks_owner角色授予对该键空间中所有表级 MBean 的相同权限。

添加/删除角色以及授予/撤销权限在完成初始设置后会动态处理,因此如果权限发生更改,则无需进一步重新启动。

另请参见:Permissions.

使用 SSL 的 JMX

JMX SSL 配置由多个系统属性控制,其中一些是可选的。要启用 SSL,请编辑 cassandra-env.sh 中的相关行,取消注释并根据需要设置这些属性的值

com.sun.management.jmxremote.ssl

设置为 true 以启用 SSL

com.sun.management.jmxremote.ssl.need.client.auth

设置为 true 以启用客户端证书验证

com.sun.management.jmxremote.registry.ssl

为 RMI 注册表启用 SSL 套接字,客户端从中获取 JMX 连接器存根

com.sun.management.jmxremote.ssl.enabled.protocols

默认情况下,将使用 JVM 支持的协议,用逗号分隔的列表覆盖。请注意,这通常是不必要的,使用默认值是首选选项。

com.sun.management.jmxremote.ssl.enabled.cipher.suites

默认情况下,将使用 JVM 支持的密码套件,用逗号分隔的列表覆盖。请注意,这通常是不必要的,使用默认值是首选选项。

javax.net.ssl.keyStore

设置本地文件系统上包含服务器私钥和公钥证书的密钥库的路径

javax.net.ssl.keyStorePassword

设置密钥库文件的密码

javax.net.ssl.trustStore

如果需要验证客户端证书,请使用此属性指定包含受信任客户端公钥证书的信任库的路径

javax.net.ssl.trustStorePassword

设置信任库文件的密码

加密提供程序

指定自定义 Java 加密提供程序的功能是在 CASSANDRA-18624 中完成的

cassandra.yamlcrypto_provider 的默认配置如下所示

# Configures Java crypto provider. By default, it will use
# DefaultCryptoProvider which will install Amazon Correto
# Crypto Provider.
#
# Amazon Correto Crypto Provider works currently for
# x86_64 and aarch_64 platforms. If this provider fails it will
# fall back to the default crypto provider in the JRE.
#
# To force failure when the provider was not installed properly,
# set the property "fail_on_missing_provider" to "true".
#
# To bypass the installation of a crypto provider use
# class 'org.apache.cassandra.security.JREProvider'
#
crypto_provider:
  - class_name: org.apache.cassandra.security.DefaultCryptoProvider
    parameters:
      - fail_on_missing_provider: "false"

对于旧节点,当它们升级到 Cassandra 5.0 时,使用相同的 cassandra.yaml,其中 crypto_provider 部分尚未设置,它们将默认为 JREProvider,该提供程序不会安装任何提供程序,它将使用 Cassandra 运行的 JRE 中的提供程序。

如上所示,DefaultCryptoProvider 正在安装 Amazon Corretto 加密提供程序,该提供程序已被证明比 JRE 安装中的默认加密提供程序性能更高。

如果您想使用其他加密提供程序,您有两个选择。

第一个是配置您的 JRE,特别是 java.security 文件,以指示 JRE 使用哪个加密提供程序。您还需要将该加密提供程序的相应实现放入 JRE 的类路径中。

第二个选项是通过扩展 org.apache.cassandra.security.AbstractCryptoProvider 并实现四个方法来实现您自己的加密提供程序

getProviderName

返回您的提供程序的名称

getProviderClassAsString

返回实际加密提供程序的 FQCN,该提供程序扩展了 java.security.Provider

installator

返回 Runnable,它在运行时安装您的 java.security.Provider

isHealthyInstallation

如果安装是正常的,则返回 true,否则返回 false。这是一种检查您的提供程序的安装是否成功的方法。

安装加密提供程序后,AbstractCryptoProvider 会检查您要安装的提供程序是否已安装。如果已安装并且其安装位置为 1(因为提供程序按顺序安装),则会记录有关此事实的消息。如果您直接通过 java.security 配置了您的 JRE,并且您也尝试通过 Cassandra 本身安装相同的提供程序,则可能会发生这种情况。

如果它已经安装但不在第一个位置,如果 fail_on_missing_provider 设置为 true,则会抛出异常,节点将无法启动。如果提供程序的安装不成功,也会发生同样的情况。

cassandra.in.sh 脚本会自动将特定于平台的库添加到 Cassandra 的类路径中。目前,有 lib/aarch64lib/x86_64 目录,每个目录都包含针对每个相应架构的 JAR 文件。平台由 uname -m 命令的输出确定。