审计日志记录
审计日志记录是 Apache Cassandra 4.0 中的一项新功能 (CASSANDRA-12151)。此新功能适用于生产环境,并具有可配置的堆内存和磁盘空间限制,以防止出现内存不足错误。所有数据库活动都按节点记录为基于文件的记录,存储在指定的本地文件系统目录中。审计日志文件根据可配置的值定期滚动。
审计日志记录的一些功能包括
-
不需要额外的数据库容量来存储审计日志。
-
不需要查询工具来存储审计日志。
-
数据库操作的延迟不受影响,因此不会影响性能。
-
堆内存使用量受加权队列限制,可配置的最大权重位于日志记录线程之前。
-
磁盘利用率受可配置的大小限制,一旦达到限制,就会删除旧的日志段。
-
可以在启动时使用
cassandra.yaml
或在运行时使用 JMX 工具nodetool
启用或禁用。 -
可以在
cassandra.yaml
文件中或使用nodetool
配置设置。
审计日志记录包括所有 CQL 请求,包括成功和失败的请求。它还捕获所有成功和失败的身份验证和授权事件,例如登录尝试。完整查询日志记录 (FQL) 和审计日志记录之间的区别在于,FQL 仅捕获成功的 CQL 请求,允许重放或比较日志。审计日志记录对合规性和调试很有用,而 FQL 对调试、性能基准测试、测试和审计 CQL 查询很有用。
记录的审计信息
审计日志包含
-
配置的键空间中的所有事件,包括
-
配置的类别中的所有事件,包括
-
配置的用户执行的所有事件,包括
审计日志不包含
-
在
cassandra.yaml
文件中进行的配置更改 -
nodetool
命令 -
作为 DCL 语句的一部分提到的密码:密码将被混淆为 *\**\**\*\*。
-
无法解析的语句将在出现单词密码后的所有内容都混淆为 *\**\**\*\*。
-
包含拼写错误的单词“password”的语句将不进行混淆地记录。请确保在重试时使用不同的密码。
-
审计日志是一系列日志条目。审计日志条目包含
-
键空间 (String) - 执行请求的键空间
-
操作 (String) - 数据库操作,例如 CQL 命令
-
用户 (String) - 用户名
-
范围 (String) - 请求的范围,例如表/函数/聚合名称
-
类型 (AuditLogEntryType) - 请求类型
-
CQL 审计日志条目类型
-
通用审计日志条目类型
-
-
源 (InetAddressAndPort) - 请求发起的源 IP 地址
-
时间戳 (long) - 请求的时间戳
-
批次 (UUID) - 请求的批次
-
选项 (QueryOptions) - CQL 查询选项
-
状态 (QueryState) - 与给定查询相关的状态
每个条目都包含与给定事件相关的所有适用属性,并用管道 (|) 连接。
CQL 审计日志条目类型是以下 CQL 命令。每个命令都分配给特定的指定类别以进行日志记录
类别 | CQL 命令 |
---|---|
DDL |
ALTER_KEYSPACE, CREATE_KEYSPACE, DROP_KEYSPACE, ALTER_TABLE, CREATE_TABLE, DROP_TABLE, CREATE_FUNCTION, DROP_FUNCTION, CREATE_AGGREGATE, DROP_AGGREGATE, CREATE_INDEX, DROP_INDEX, ALTER_TYPE, CREATE_TYPE, DROP_TYPE, CREATE_TRIGGER, DROP_TRIGGER, ALTER_VIEW, CREATE_VIEW, DROP_VIEW, TRUNCATE |
DML |
BATCH, DELETE, UPDATE |
DCL |
GRANT, REVOKE, ALTER_ROLE, CREATE_ROLE, DROP_ROLE, LIST_ROLES, LIST_PERMISSIONS, LIST_USERS |
其他 |
USE_KEYSPACE |
查询 |
SELECT |
准备 |
PREPARE_STATEMENT |
通用审计日志条目类型是以下类型之一
类别 | CQL 命令 |
---|---|
身份验证 |
LOGIN_SUCCESS, LOGIN_ERROR, UNAUTHORIZED_ATTEMPT |
错误 |
REQUEST_FAILURE |
可用性和持久性
与数据不同,审计日志条目不会复制 |
对于给定的查询,相应的审计条目仅存储在协调节点上。例如,在复制因子为 3 的键空间中进行 INSERT
操作将在一个节点(处理请求的协调节点)上生成一个审计条目,而不会在另外两个节点上生成。出于这个原因,并且根据您必须满足的合规性要求,请确保审计日志存储在非短暂存储上。
您可以使用 archive_command 选项来满足自定义需求。
在 cassandra.yaml 中配置审计日志记录
cassandra.yaml
文件可用于配置和启用审计日志记录。根据 cassandra.yaml
文件设置,每个节点上的配置和启用方式可能相同或不同。
在启用该功能时,也可以使用 nodetool
配置审计日志记录,这将覆盖在 cassandra.yaml
文件中设置的任何值,如 使用 nodetool 启用审计日志记录 中所述。
每个启用的节点都会生成审计日志,因此每个节点上的日志都将包含该节点的查询。所有审计日志记录选项都可以在 cassandra.yaml
文件中的 audit_logging_options:
下设置。
该文件包含以下选项,可以取消注释以供使用
# Audit logging - Logs every incoming CQL command request, authentication to a node. See the docs
# on audit_logging for full details about the various configuration options.
audit_logging_options:
enabled: false
logger:
- class_name: BinAuditLogger
# audit_logs_dir:
# included_keyspaces:
# excluded_keyspaces: system, system_schema, system_virtual_schema
# included_categories:
# excluded_categories:
# included_users:
# excluded_users:
# roll_cycle: HOURLY
# block: true
# max_queue_weight: 268435456 # 256 MiB
# max_log_size: 17179869184 # 16 GiB
## archive command is "/path/to/script.sh %path" where %path is replaced with the file being rolled:
# archive_command:
# max_archive_retries: 10
enabled
控制是否启用或禁用审计日志记录(默认值)。
要启用审计日志记录,请将 enabled: true
设置为 true
。
如果启用此选项,则 Cassandra 启动时将启动审计日志记录。之后可以使用 nodetool 在运行时禁用它。
您可以使用 JMX MBean org.apache.cassandra.db:type=StorageService 的 AuditLogEnabled 属性来监控审计日志记录是否已启用。 |
logger
使用 logger
选项设置审计记录器的类型。支持的值为
-
BinAuditLogger
(默认值) -
FileAuditLogger
-
NoOpAuditLogger
BinAuditLogger
将事件记录到二进制格式的文件中。FileAuditLogger
使用标准日志记录机制 slf4j
将事件记录到 audit/audit.log
文件中。它是一个同步的基于文件的审计记录器。roll_cycle
将在 logback.xml
文件中设置。NoOpAuditLogger
是审计记录器的无操作实现,应在禁用审计日志记录时指定。
例如
logger:
- class_name: FileAuditLogger
BinAuditLogger 在后台使用开源 Chronicle Queue。如果您考虑将审计日志记录用于法规遵从目的,那么熟悉此库可能很明智。请参阅 archive_command 和 roll_cycle 以了解其影响的示例。 |
audit_logs_dir
要写入审计日志,必须在 audit_logs_dir
中设置一个现有目录。
该目录必须设置适当的权限,以允许读取、写入和执行。日志记录将根据需要递归地删除目录内容。不要在此目录中放置指向文件系统其他部分的链接。例如,audit_logs_dir: /non_ephemeral_storage/audit/logs/hourly
。
也可以使用系统属性 cassandra.logdir.audit
配置审计日志目录,该属性默认设置为 cassandra.logdir + /audit/
。
included_keyspaces 和 excluded_keyspaces
使用 included_keyspaces
选项设置要包含的键空间,使用 excluded_keyspaces
选项设置要排除的键空间。默认情况下,system
、system_schema
和 system_virtual_schema
被排除,所有其他键空间都被包含。
例如
included_keyspaces: test, demo
excluded_keyspaces: system, system_schema, system_virtual_schema
included_categories 和 excluded_categories
要包含的数据库操作类别使用 included_categories
选项指定,以逗号分隔的列表形式。要排除的数据库操作类别使用 excluded_categories
选项指定,以逗号分隔的列表形式。审计日志支持的类别为:AUTH
、DCL
、DDL
、DML
、ERROR
、OTHER
、PREPARE
和 QUERY
。默认情况下,包含所有支持的类别,不排除任何类别。
included_categories: AUTH, ERROR, DCL
excluded_categories: DDL, DML, QUERY, PREPARE
included_users 和 excluded_users
用户审计日志的设置使用included_users
和excluded_users
选项。included_users
选项指定要明确包含的用户列表,以逗号分隔。excluded_users
选项指定要明确排除的用户列表,以逗号分隔。默认情况下,所有用户都包含在内,没有用户被排除。
included_users:
excluded_users: john, mary
roll_cycle
roll_cycle
定义审计日志段的滚动频率。支持的值为
-
MINUTELY
-
FIVE_MINUTELY
-
TEN_MINUTELY
-
TWENTY_MINUTELY
-
HALF_HOURLY
-
HOURLY
(默认) -
TWO_HOURLY
-
FOUR_HOURLY
-
SIX_HOURLY
-
DAILY
例如:roll_cycle: DAILY
在生产节点上更改roll_cycle 时,请阅读以下段落。 |
使用BinLogger
实现,任何尝试在先前已启用审计日志的节点上修改滚动周期的尝试都将由于Chronicle Queue滚动周期推断机制而静默失败(即使您删除了metadata.cq4t
文件)。
以下是在Cassandra日志中可见的这种覆盖的示例
INFO [main] <DATE TIME> BinLog.java:420 - Attempting to configure bin log: Path: /path/to/audit Roll cycle: TWO_HOURLY [...] WARN [main] <DATE TIME> SingleChronicleQueueBuilder.java:477 - Overriding roll cycle from TWO_HOURLY to FIVE_MINUTE
为了更改节点上的roll_cycle
,您必须
-
停止Cassandra
-
将所有审计日志移至或卸载到其他位置(安全且持久的位置)
-
重新启动Cassandra。
-
检查Cassandra日志
-
确保
audit_logs_dir
下的审计日志文件名与新的滚动周期相对应。
block
block
选项指定如果审计日志落后,审计日志是否应该阻止写入或丢弃日志记录。支持的布尔值为true
(默认)或false
。
例如:block: false
以丢弃记录(例如,如果审计用于故障排除)
出于合规目的,最好明确设置block: true
,以防止在将来默认值更改的情况下出现任何回归。
max_queue_weight
max_queue_weight
选项设置等待写入文件之前的记录的内存队列的最大权重,然后再阻塞或丢弃。该选项必须设置为正值。默认值为268435456,即256 MiB。
例如,要更改默认值:max_queue_weight: 134217728 # 128 MiB
max_log_size
max_log_size
选项设置在删除最旧文件之前,磁盘上保留的已滚动文件的最大大小。该选项必须设置为正值。默认值为17179869184,即16 GiB。例如,要更改默认值:max_log_size: 34359738368 # 32 GiB
如果设置了archive_command 选项,则max_log_size 将被忽略。 |
archive_command
如果archive_command 选项为空或未设置(默认),Cassandra将使用内置的DeletingArchiver,如果达到max_log_size ,则删除最旧的文件。 |
archive_command
选项设置在已滚动日志文件上执行的用户定义的存档脚本。例如:archive_command: "/usr/local/bin/archiveit.sh %path"
%path
将替换为正在滚动的文件的绝对文件路径。
使用用户定义的脚本时,Cassandra不会使用DeletingArchiver,因此脚本负责进行任何必要的清理。
Cassandra将在日志文件滚动后立即调用用户定义的脚本。这意味着Chronicle Queue的QueueFileShrinkManager将无法缩小稀疏日志文件,因为它是在异步完成的。换句话说,所有日志文件将至少具有默认块大小(80 MiB)的大小,即使只有几 KB 的实际数据。因此,Cassandra system.log中会显示一些警告。
WARN [main/queue~file~shrink~daemon] <DATE TIME> QueueFileShrinkManager.java:63 - Failed to shrink file as it exists no longer, file=/path/to/xxx.cq4
由于Cassandra不使用Pretoucher,您可以配置Chronicle Queue以同步缩小文件(即在文件滚动后立即缩小) - 使用chronicle.queue.synchronousFileShrinking JVM 属性。例如,您可以在cassandra-env.sh 的末尾添加以下行:JVM_OPTS="$JVM_OPTS -Dchronicle.queue.synchronousFileShrinking=true" |
使用nodetool
启用审计日志记录
使用nodetool enableauditlog
命令在每个节点的基础上启用审计日志记录。日志记录目录必须在cassandra.yaml
文件中使用audit_logs_dir
定义,或者使用默认值cassandra.logdir.audit
。
nodetool enableauditlog
命令的语法具有与可以在cassandra.yaml
文件中设置的相同选项,除了audit_logs_dir
。此外,nodetool
具有用于设置运行命令的主机和端口的选项,以及如果命令需要身份验证,则设置用户名和密码的选项。
nodetool [(-h <host> | --host <host>)] [(-p <port> | --port <port>)]
[(-pp | --print-port)] [(-pw <password> | --password <password>)]
[(-pwf <passwordFilePath> | --password-file <passwordFilePath>)]
[(-u <username> | --username <username>)] enableauditlog
[--excluded-categories <excluded_categories>]
[--excluded-keyspaces <excluded_keyspaces>]
[--excluded-users <excluded_users>]
[--included-categories <included_categories>]
[--included-keyspaces <included_keyspaces>]
[--included-users <included_users>] [--logger <logger>]
OPTIONS
--excluded-categories <excluded_categories>
Comma separated list of Audit Log Categories to be excluded for
audit log. If not set the value from cassandra.yaml will be used
--excluded-keyspaces <excluded_keyspaces>
Comma separated list of keyspaces to be excluded for audit log. If
not set the value from cassandra.yaml will be used
--excluded-users <excluded_users>
Comma separated list of users to be excluded for audit log. If not
set the value from cassandra.yaml will be used
-h <host>, --host <host>
Node hostname or ip address
--included-categories <included_categories>
Comma separated list of Audit Log Categories to be included for
audit log. If not set the value from cassandra.yaml will be used
--included-keyspaces <included_keyspaces>
Comma separated list of keyspaces to be included for audit log. If
not set the value from cassandra.yaml will be used
--included-users <included_users>
Comma separated list of users to be included for audit log. If not
set the value from cassandra.yaml will be used
--logger <logger>
Logger name to be used for AuditLogging. Default BinAuditLogger. If
not set the value from cassandra.yaml will be used
-p <port>, --port <port>
Remote jmx agent port number
-pp, --print-port
Operate in 4.0 mode with hosts disambiguated by port number
-pw <password>, --password <password>
Remote jmx agent password
-pwf <passwordFilePath>, --password-file <passwordFilePath>
Path to the JMX password file
-u <username>, --username <username>
Remote jmx agent username
要启用审计日志记录,请在要启用日志记录的集群中的每个节点上运行以下命令
$ nodetool enableauditlog
查看审计日志
如果记录器是BinAuditLogger
,则可以使用auditlogviewer
工具查看(转储)审计日志。auditlogviewer
将二进制日志文件转换为人类可读的格式;只需要提供审计日志目录作为命令行选项。如果设置了记录器FileAuditLogger
,则日志文件已经是人类可读的格式,不需要auditlogviewer
来读取文件。
auditlogviewer
的语法为
auditlogviewer
Audit log files directory path is a required argument.
usage: auditlogviewer <path1> [<path2>...<pathN>] [options]
--
View the audit log contents in human readable format
--
Options are:
-f,--follow Upon reaching the end of the log continue indefinitely
waiting for more records
-h,--help display this help message
-r,--roll_cycle How often to roll the log file was rolled. May be
necessary for Chronicle to correctly parse file names. (MINUTELY, HOURLY,
DAILY). Default HOURLY.
示例
-
为了演示审计日志记录,首先使用以下设置配置
cassandra.yaml
文件
audit_logging_options:
enabled: true
logger: BinAuditLogger
audit_logs_dir: "/cassandra/audit/logs/hourly"
# included_keyspaces:
# excluded_keyspaces: system, system_schema, system_virtual_schema
# included_categories:
# excluded_categories:
# included_users:
# excluded_users:
roll_cycle: HOURLY
# block: true
# max_queue_weight: 268435456 # 256 MiB
# max_log_size: 17179869184 # 16 GiB
## archive command is "/path/to/script.sh %path" where %path is replaced with the file being rolled:
# archive_command:
# max_archive_retries: 10
-
创建审计日志目录
/cassandra/audit/logs/hourly
并将目录权限设置为所有人的读、写和执行权限。
-
现在使用
cqlsh
创建一个演示键空间和表并插入一些数据
cqlsh> CREATE KEYSPACE auditlogkeyspace
... WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 1};
cqlsh> USE auditlogkeyspace;
cqlsh:auditlogkeyspace> CREATE TABLE t (
...id int,
...k int,
...v text,
...PRIMARY KEY (id)
... );
cqlsh:auditlogkeyspace> INSERT INTO t (id, k, v) VALUES (0, 0, 'val0');
cqlsh:auditlogkeyspace> INSERT INTO t (id, k, v) VALUES (0, 1, 'val1');
所有支持的CQL命令都将记录到审计日志目录。
-
更改到审计日志目录。
$ cd /cassandra/audit/logs/hourly
-
列出审计日志文件和目录。
$ ls -l
您应该看到类似于以下的结果
total 28
-rw-rw-r--. 1 ec2-user ec2-user 65536 Aug 2 03:01 directory-listing.cq4t
-rw-rw-r--. 1 ec2-user ec2-user 83886080 Aug 2 03:01 20190802-02.cq4
-rw-rw-r--. 1 ec2-user ec2-user 83886080 Aug 2 03:01 20190802-03.cq4
所有审计日志文件都将列出,文件类型为.cq4
。审计目录的类型为.cq4t
。
-
运行
auditlogviewer
工具以查看审计日志。
$ auditlogviewer /cassandra/audit/logs/hourly
此命令将返回日志的可读版本。以下是此演示中命令的日志的示例部分
WARN 03:12:11,124 Using Pauser.sleepy() as not enough processors, have 2, needs 8+
Type: AuditLog
LogMessage:
user:anonymous|host:10.0.2.238:7000|source:/127.0.0.1|port:46264|timestamp:1564711427328|type :USE_KEYSPACE|category:OTHER|ks:auditlogkeyspace|operation:USE AuditLogKeyspace;
Type: AuditLog
LogMessage:
user:anonymous|host:10.0.2.238:7000|source:/127.0.0.1|port:46264|timestamp:1564711427329|type :USE_KEYSPACE|category:OTHER|ks:auditlogkeyspace|operation:USE "auditlogkeyspace"
Type: AuditLog
LogMessage:
user:anonymous|host:10.0.2.238:7000|source:/127.0.0.1|port:46264|timestamp:1564711446279|type :SELECT|category:QUERY|ks:auditlogkeyspace|scope:t|operation:SELECT * FROM t;
Type: AuditLog
LogMessage:
user:anonymous|host:10.0.2.238:7000|source:/127.0.0.1|port:46264|timestamp:1564713878834|type :DROP_TABLE|category:DDL|ks:auditlogkeyspace|scope:t|operation:DROP TABLE IF EXISTS
AuditLogKeyspace.t;
Type: AuditLog
LogMessage:
user:anonymous|host:10.0.2.238:7000|source:/3.91.56.164|port:42382|timestamp:1564714618360|ty
pe:REQUEST_FAILURE|category:ERROR|operation:CREATE KEYSPACE AuditLogKeyspace
WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 1};; Cannot add
existing keyspace "auditlogkeyspace"
Type: AuditLog
LogMessage:
user:anonymous|host:10.0.2.238:7000|source:/127.0.0.1|port:46264|timestamp:1564714690968|type :DROP_KEYSPACE|category:DDL|ks:auditlogkeyspace|operation:DROP KEYSPACE AuditLogKeyspace;
Type: AuditLog
LogMessage:
user:anonymous|host:10.0.2.238:7000|source:/3.91.56.164|port:42406|timestamp:1564714708329|ty pe:CREATE_KEYSPACE|category:DDL|ks:auditlogkeyspace|operation:CREATE KEYSPACE
AuditLogKeyspace
WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 1};
Type: AuditLog
LogMessage:
user:anonymous|host:10.0.2.238:7000|source:/127.0.0.1|port:46264|timestamp:1564714870678|type :USE_KEYSPACE|category:OTHER|ks:auditlogkeyspace|operation:USE auditlogkeyspace;
Password obfuscation examples:
LogMessage: user:cassandra|host:localhost/127.0.0.1:7000|source:/127.0.0.1|port:65282|timestamp:1622630496708|type:CREATE_ROLE|category:DCL|operation:CREATE ROLE role1 WITH PASSWORD = '*******';
Type: audit
LogMessage: user:cassandra|host:localhost/127.0.0.1:7000|source:/127.0.0.1|port:65282|timestamp:1622630634552|type:ALTER_ROLE|category:DCL|operation:ATLER ROLE role1 WITH PASSWORD = '*******';
Type: audit
LogMessage: user:cassandra|host:localhost/127.0.0.1:7000|source:/127.0.0.1|port:65282|timestamp:1622630698686|type:CREATE_ROLE|category:DCL|operation:CREATE USER user1 WITH PASSWORD '*******';
Type: audit
LogMessage: user:cassandra|host:localhost/127.0.0.1:7000|source:/127.0.0.1|port:65282|timestamp:1622630747344|type:ALTER_ROLE|category:DCL|operation:ALTER USER user1 WITH PASSWORD '*******';