完全指南:监控 CQL 与 Alternator 操作的安全实践)
ScyllaDB 审计Auditing完全指南监控 CQL 与 Alternator 操作的安全实践【免费下载链接】scylladbNoSQL data store using the Seastar framework, compatible with Apache Cassandra and Amazon DynamoDB项目地址: https://gitcode.com/GitHub_Trending/sc/scylladbScyllaDB 审计Auditing功能允许管理员监控集群中的活动包括 CQL 查询、数据变更以及 Alternator兼容 Amazon DynamoDB 的 API请求审计信息可写入 Syslog 或 ScyllaDB 表。本指南基于官方文档与仓库源码系统讲解审计的启用、配置、类别体系、Alternator 审计细节、审计规则audit_rules与存储后端选型帮助你构建可落地的集群安全监控方案。读完本文你将掌握audit、audit_categories、audit_tables、audit_keyspaces、audit_rules等全部配置项的语义与典型用法并能读懂审计日志输出。前置条件先启用认证与授权审计记录的是谁在什么时候做了什么因此它依赖身份信息。启用审计前必须先在 ScyllaDB 中启用认证Authentication与授权Authorization认证参见 认证指南授权参见 授权指南只有先让集群具备用户与角色体系审计日志中的username字段才有实际意义audit_rules中的角色匹配roles也才能发挥作用。启用审计默认情况下ScyllaDB 的审计功能是开启的且使用table后端。审计的开关由scylla.yaml配置文件中的audit:参数控制可选值如下取值含义none关闭审计table开启审计消息写入 ScyllaDB 表默认值syslog开启审计消息发送到 Syslogsyslog,table开启审计消息同时写入 ScyllaDB 表和 Syslog配置为其他任何值都会导致 ScyllaDB 启动时报错。这一校验逻辑可以在源码 audit/audit.cc 的parse_audit_sinks()中看到函数按逗号切分配置值并逐项识别识别到none直接返回空集合禁用识别到table/syslog则设置对应的 sink 位遇到未知值则抛出audit_exception(Bad configuration: invalid audit: ...)。仓库自带的 conf/scylla.yaml 中默认配置为# audit settings # Table audit is enabled by default. # audit config option controls if and where to output audited events: # - none: auditing is disabled # - table: save audited events in audit.audit_log column family (default) # - syslog: send audited events via syslog (depends on OS, but usually to /dev/log) audit: table配置审计三个基础过滤参数审计行为可通过以下命令行 flag 或scylla.yaml条目进行调优Flag默认值描述audit_categoriesDCL,AUTH,ADMIN需要审计的语句类别列表逗号分隔audit_tables需要审计的表名列表格式为keyspace_name.table_nameAlternator 表使用alternator.table_name格式见下文 Alternator 审计一节audit_keyspaces需要审计的 keyspace 列表逗号分隔。必须至少指定一个 keyspace留空则没有任何 keyspace 会被审计三条关键使用规则要审计某个 keyspace 下的所有表在audit_keyspaces中指定该 keyspace并保持audit_tables为空。DCL、AUTH、ADMIN类别不需要指定任何 keyspace 或 table 即可审计——它们属于与表无关的类别见下文源码佐证。需要注意默认值audit_categories默认审计DCL,AUTH,ADMIN这意味着即使你不做任何额外配置登录事件、授权变更和服务级别操作也会被记录。从源码看这三个参数的解析分别由 audit/audit.cc 中的parse_audit_categories()、parse_audit_tables()、parse_audit_keyspaces()完成全部按逗号切分并去空白非法类别值同样抛出audit_exception。特别地parse_audit_tables()要求每个条目恰好由.分隔为两段keyspace 与 table否则报错。audit_categories 参数详解audit_categories支持的类别及其含义如下参数日志内容适用范围AUTH记录登录事件CQLDML记录 insert、update、delete 等数据操纵语言DML事件CQL、AlternatorDDL记录对象与角色的 create、alter、drop 等数据定义语言DDL事件CQL、AlternatorDCL记录 grant、revoke、create role、drop role、list roles 事件CQLQUERY记录所有查询CQL、AlternatorADMIN记录服务级别service level操作create、alter、drop、attach、detach、list用于服务级别审计CQL类别集合在 audit/audit_rule.hh 中以statement_category枚举形式定义QUERY, DML, DDL, DCL, AUTH, ADMIN并使用enum_set位图高效存储。性能提示启用审计可能对性能产生负面影响审计写入表还会消耗额外存储尤其是在审计DML和QUERY类别时——这两类会生成大量审计消息规划容量时务必考虑。审计 Alternator 请求启用审计后AlternatorDynamoDB 兼容 API请求使用与 CQL 操作相同的后端和过滤配置进行审计没有单独的 Alternator 审计设置。过滤配置包括audit_categories、audit_keyspaces、audit_tables以及对有表上下文的操作生效的audit_rules。成功和失败的 Alternator 请求都会被审计。在源码中Alternator 的审计信息通过专门的audit_info_alternator类见 audit/audit.hh承载与 CQL 不同CQL 的一致性级别来自 query_options由audit::log()单独传入Alternator 没有 query_options因此把一致性级别CL存进 audit_info 对象只有数据读写操作GetItem、PutItem、Query、Scan 等才有有意义的 CLschema 操作与元数据查询传入std::nullopt。Alternator 操作类别映射每个 Alternator API 操作都被归入一个标准审计类别类别Alternator 操作DDLCreateTable、DeleteTable、UpdateTable、TagResource、UntagResource、UpdateTimeToLiveDMLPutItem、UpdateItem、DeleteItem、BatchWriteItemQUERYGetItem、BatchGetItem、Query、Scan、DescribeTable、ListTables、DescribeEndpoints、ListTagsOfResource、DescribeTimeToLive、DescribeContinuousBackups、ListStreams、DescribeStream、GetShardIterator、GetRecords注意AUTH、DCL、ADMIN类别不适用于 Alternator 操作它们是 CQL 认证、授权和服务级别管理特有的。operation 字段格式对于 CQL 操作审计日志的operation字段包含原始 CQL 查询字符串对于 Alternator 操作格式为OperationName|JSON request body示例PutItem|{TableName:my_table,Item:{p:{S:pk_val},c:{S:ck_val},v:{S:data}}}该格式的拼装逻辑可以在 audit/audit.hh 的audit_info::set_query_string()中看到当传入非空的operation参数时内部以operation | query_string的方式组合成最终的_query。注意完整的 JSON 请求体会包含在operation字段中。对于批量操作如 BatchWriteItem这可能非常大最大可达 16 MB。Alternator 的 Keyspace 与 Table 过滤Alternator 表T的真实 keyspace 名是alternator_T。audit_tables配置使用简写格式alternator.T引用此类表——解析器会自动将其展开为真实 keyspace 名而对于audit_keyspaces则需要直接使用真实 keyspace 名。例如要审计名为my_table_name的 Alternator 表两种写法均可# Using audit_tables - use alternator as the keyspace name: audit_tables: alternator.my_table_name # Using audit_keyspaces - use the real keyspace name: audit_keyspaces: alternator_my_table_name这个展开逻辑在 audit/audit.cc 的parse_audit_tables()中实现解析到 keyspace 部分为alternator时直接改写为alternator_ 表名。全局与批量操作的特殊处理ListTables和DescribeEndpoints不关联任何 keyspace 或 table。只要其类别匹配audit_categories就会被记录不受audit_keyspaces、audit_tables过滤影响其keyspace_name字段为空。源码 audit/audit.cc 的will_log()对此有明确注释keyspace 为空如 ListTables 或跨多表的批量操作时操作无法按 keyspace/table 过滤因此只要类别匹配就记录。BatchWriteItem和BatchGetItem可能跨多张表因此其审计条目的keyspace_name字段为空。这些操作仍会针对批次中的每一张表逐一匹配audit_keyspaces、audit_tables以及表限定的audit_rules过滤器。table_name字段只包含被审计的表多个表以竖线|分隔operation字段中的 JSON 请求体会被剥离属于未被审计表的数据避免未审计表的数据泄露到审计记录中。若批次中没有任何表匹配审计过滤条件则不产生任何审计条目当批次中不同表匹配不同的审计 sink 时每个 sink 最多收到一条审计条目仅包含与该 sink 匹配的表。例如给定audit_tables: alternator.my_table或一条qualified_table_names只匹配alternator_my_table.*的 audit_rules 条目一个同时作用于my_table和other_table的BatchWriteItem其审计条目的table_name字段只会列出my_table——other_table被过滤掉other_table的 JSON 请求体内容也不会出现在审计条目中如果同一个BatchWriteItem只作用于other_table则根本不会产生审计条目。批量过滤的实现位于 audit/audit.ccprint_alternator_table_names()负责把匹配表拼成竖线分隔的字符串print_filtered_alternator_batch_query()用 RapidJSON 解析请求体后删除不属于匹配表的RequestItems成员再重新序列化从而保证非审计表的数据不外泄。DynamoDB Streams 操作对于流相关操作DescribeStream、GetShardIterator、GetRecordstable_name字段包含基础表名和 CDC 日志表名两者以竖线分隔例如my_table|my_table_scylla_cdc_log。Alternator 审计日志示例Syslog 输出示例PutItemMar 18 10:15:03 ip-10-143-2-108 scylla-audit[28387]: node10.143.2.108, categoryDML, clLOCAL_QUORUM, errorfalse, keyspacealternator_my_table, queryPutItem|{\TableName\:\my_table\,\Item\:{\p\:{\S\:\pk_val\}}}, client_ip127.0.0.1, tablemy_table, usernameanonymous表输出示例PutItemSELECT * FROM audit.audit_log ;返回date | node | event_time | category | consistency | error | keyspace_name | operation | source | table_name | username | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 2026-03-18 00:00:000000 | 10.143.2.108 | 3429b1a5-2a94-11e8-8f4e-000000000001 | DML | LOCAL_QUORUM | False | alternator_my_table | PutItem|{TableName:my_table,Item:{p:{S:pk_val}}} | 127.0.0.1 | my_table | anonymous | (1 row)Syslog 消息的完整格式可在 audit/audit_syslog_storage_helper.cc 的write()中看到scylla-audit:前缀、node/category/cl/error/keyspace/query/client_ip/table/username十个键值对其中 query 内容经过 JSON 转义json_escape()。审计规则Audit Rules细粒度、角色感知的审计audit_rules提供细粒度、角色感知的审计能力可以与audit_categories、audit_tables、audit_keyspaces一起使用以更细的规则扩展已有审计配置。这些设置不会互相覆盖对每个事件ScyllaDB 独立评估两种机制只要其中一种匹配事件就会被审计。对于新配置优先使用audit_rules因为它提供更精确的匹配选项包括表模式和角色模式。每条规则包含以下字段sinks—— 匹配事件的目标 sink如table、syslog。必须是全局audit设置的子集规则引用了全局未启用的 sink 会记录错误且该 sink 对应的事件不会被写入。categories—— 要审计的操作类型DML、DDL、QUERY、AUTH、ADMIN、DCL。空列表不匹配任何事件。qualified_table_names—— 要匹配的keyspace.table模式。对于与表无关的类别AUTH、ADMIN、DCL此字段被忽略对于表相关类别DML、DDL、QUERY空列表阻止匹配。roles—— 要匹配的角色模式。空列表不匹配任何事件。qualified_table_names和roles字段支持带扩展语法FNM_EXTMATCH的 fnmatch glob 模式包括取反!(…)、多选一(a|b)以及量词(…)、*(…)、?(…)。例如表模式prod_ks.*或!(system).*角色模式admin_*。规则的四字段结构与匹配语义在 audit/audit_rule.hh 中定义is_table_scoped_category()表相关类别为 DML/DDL/QUERY与matches_category()、matches_table()、matches_role()等函数实现具体匹配逻辑。规则会在审计实例构造时预处理preprocessed_audit_rules并监听 schema 变更——表/视图的创建与删除会动态更新已知表集合见 audit/audit.cc 的audit_schema_listener。audit_rules是**可热更新live-updatable**的参数。要在运行时应用变更编辑scylla.yaml后向 ScyllaDB 进程发送SIGHUP即可。关于热更新与配置优先级的更多细节参见 配置参数参考。scylla.yaml配置示例audit_rules: - sinks: [table] categories: [DML, DDL] qualified_table_names: [prod_ks.*] roles: [admin_*] - sinks: [syslog] categories: [AUTH] qualified_table_names: [] roles: [*]规则热更新与 sink 不匹配告警的实现可在 audit/audit.cc 的rebuild_rules()与warn_on_sink_mismatch()中找到当审计被设置为none却配置了规则时启动日志会给出明确警告。配置审计存储审计消息可以发送到 Syslog、存入 ScyllaDB 表或两者同时。将审计消息存储到 Syslog操作步骤在scylla.yaml中将audit参数设置为syslog例如# audit setting # audit config option controls if and where to output audited events: audit: syslog # # List of statement categories that should be audited. audit_categories: DCL,DDL,AUTH # # List of tables that should be audited. audit_tables: mykespace.mytable # # List of keyspaces that should be fully audited. # All tables in those keyspaces will be audited audit_keyspaces: mykespace重启 ScyllaDB 节点。默认情况下审计消息写入与 ScyllaDB 日志相同的目标进程名为scylla-audit。Syslog 后端通过 Unix 域套接字默认/dev/log可用audit_unix_socket_path覆盖直接与 syslog 通信——这是因为 ScyllaDB 日志器已占用全局 ident无法再用openlog/syslog源码 audit/audit_syslog_storage_helper.cc 对此有明确说明。日志输出示例CQL drop tableMar 18 09:53:52 ip-10-143-2-108 scylla-audit[28387]: node10.143.2.108, categoryDDL, clONE, errorfalse, keyspacenba, queryDROP TABLE nba.team_roster ;, client_ip127.0.0.1, tableteam_roster, usernameanonymous要将 Syslog 输出重定向到文件仅适用于 CentOS安装 rsyslogsudo dnf install rsyslog编辑/etc/rsyslog.conf并在文件末尾追加if $programname contains scylla-audit then /var/log/scylla-audit.log启动 rsyslogsystemctl start rsyslog启用 rsyslog 开机自启systemctl enable rsyslog将审计消息存储到表审计消息存储在一张名为audit.audit_log的 ScyllaDB 表中。其建表语句如下CREATE TABLE IF NOT EXISTS audit.audit_log ( date timestamp, node inet, event_time timeuuid, category text, consistency text, table_name text, keyspace_name text, operation text, source inet, username text, error boolean, PRIMARY KEY ((date, node), event_time));该表结构在源码中由 audit/audit_cf_storage_helper.cc 的CREATE TABLE IF NOT EXISTS语句定义写入通过 table_helper 完成写入一致性级别固定为CLONE见make_data()中的db::consistency_level::ONE。注意audit.audit_log的 schema 在 2024.2 版本中从SimpleStrategy RF1迁移为NetworkTopologyStrategy RF3默认情况下每个 DC 将有 3 份审计副本。如果新增一个 DC为了让该 DC 也包含审计副本需要手动修改 audit 的 schema。写入的 CL 仍然是1这意味着以 CLQuorum 读取审计行可能失败在节点数少于 3 的集群中尤其明显。操作步骤在scylla.yaml中将audit参数设置为table例如# audit setting # audit config option controls if and where to output audited events: audit: table # # List of statement categories that should be audited. audit_categories: DCL,DDL,AUTH # # List of tables that should be audited. audit_tables: mykespace.mytable # # List of keyspaces that should be fully audited. # All tables in those keyspaces will be audited audit_keyspaces: mykespace重启 ScyllaDB 节点。表输出示例CQL drop tableSELECT * FROM audit.audit_log ;返回date | node | event_time | category | consistency | error | keyspace_name | operation | source | table_name | username | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 2018-03-18 00:00:000000 | 10.143.2.108 | 3429b1a5-2a94-11e8-8f4e-000000000001 | DDL | ONE | False | nba | DROP TABLE nba.team_roster ; | 127.0.0.1 | team_roster | Scylla | (1 row)同时将审计消息存储到表和 Syslog同时执行以上两个流程并将scylla.yaml中的audit参数同时设置为syslog和table只需重启一次 ScyllaDBaudit: syslog,table从源码 audit/audit.cc 的create_storage_helper()可以看到同时启用两个后端时会创建一个audit_composite_storage_helper内部组合audit_cf_storage_helper表与audit_syslog_storage_helpersyslog两个子 helper实现消息分发到多个目标。处理审计失败某些情况下审计可能无法完成例如使用表作为审计后端时保存审计行的分区不可用——持有这些分区的节点宕机或因网络问题不可达。使用 Syslog 作为审计后端时Syslog sink一个常规的 Unix socket无响应或不可用。如果审计失败、消息未存入配置的后端你仍然可以在常规的 ScyllaDB 日志中查看审计日志。以下示例展示了 Syslog 后端损坏例如 socket 被关闭时尝试使用错误凭据连接节点的审计信息如何出现在常规 ScyllaDB 日志中ERROR 2024-01-15 14:09:41,516 [shard 0:sl:d] audit - Unexpected exception when writing login log with: node_ip IP:port client_ip IP:port username username error true exception audit::audit_exception (Starting syslog audit backend failed (sending a message to socket_path resulted in sendto: No such file or directory).)源码中这一兜底行为体现在 audit/audit.cc 的log_with_sinks()写入存储的 future 挂接.handle_exception()捕获gate_closed_exception存储关闭竞态或其他异常统一通过logger.error输出到 ScyllaDB 常规日志Syslog 后端的 socket 发送失败同样会被包装为audit_exception并记录错误见 audit/audit_syslog_storage_helper.cc。此外存储未就绪时_storage_started为假审计日志会以on_internal_error_noexcept方式输出告警保证事件信息不静默丢失。附加资源授权Authorization认证Authentication相关实现参考audit/audit.cc审计核心实现包括配置解析、sink 路由、批量操作过滤与失败处理audit/audit.hh审计信息模型audit_info、audit_info_alternator与audit类接口audit/audit_rule.hh审计规则结构与类别/表/角色匹配语义audit/audit_cf_storage_helper.cc表后端的建表与写入实现audit/audit_syslog_storage_helper.ccSyslog 后端的消息格式与发送实现conf/scylla.yaml默认审计配置与完整注释示例【免费下载链接】scylladbNoSQL data store using the Seastar framework, compatible with Apache Cassandra and Amazon DynamoDB项目地址: https://gitcode.com/GitHub_Trending/sc/scylladb创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考