ScyllaDB 从 Users 到 Roles 的访问控制迁移机制解析
ScyllaDB 从 Users 到 Roles 的访问控制迁移机制解析【免费下载链接】scylladbNoSQL data store using the Seastar framework, compatible with Apache Cassandra and Amazon DynamoDB项目地址: https://gitcode.com/GitHub_Trending/sc/scylladb在 ScyllaDB 中访问控制系统auth 子系统位于auth/目录最初基于用户users模型用户登录系统并被授予对特定 keyspace、表等资源的权限。引入角色roles模型后授权规则变得更加灵活——角色可以被授予另一个角色权限随之继承。本文基于仓库文档 从用户迁移到角色 展开完整讲解这次元数据模式迁移的背景、逐节点升级策略、各模块的迁移判定规则、ROLES特性标志的强制校验机制以及升级后的验证与故障恢复步骤并结合当前源码gms/feature_service.cc、db/system_keyspace.cc、auth/service.cc 等说明迁移在代码中的落点。一、背景Users 模型与 Roles 模型的区别早期 Scylla 的访问控制基于用户一个用户能够登录系统执行查询用户可以被授予对数据库中资源特定 keyspace 和表执行特定操作的权限。角色模型引入后规则更灵活角色是一个拥有一组被授予权限的实体角色可以授予角色如果角色a被授予给角色b那么a的所有权限都会被b继承所有用户都是角色但并非所有角色都是用户——区分用户与角色的依据是该角色能否登录系统执行查询。这一模型变化要求 Scylla 内部维护元数据的表结构发生变更维度旧模型Users新模型Roles身份存储system_auth.userssystem_auth.roles密码存储system_auth.credentials角色表中的salted_hash属性权限存储system_auth.permissionssystem_auth.role_permissions角色从属关系无system_auth.role_members虽然元数据表结构变了但 auth 系统内部包含自动在后台执行迁移的代码。当前代码库中角色相关表已作为系统 keyspace 的正式成员定义在 db/system_keyspace.cc 中roles、role_members、role_attributes、role_permissions的 schema 定义而表名常量集中声明在 db/system_keyspace.hh。值得注意的是当前版本的 gms/feature_service.cc 中ROLES已出现在弃用特性Deprecated features列表中——即通过 gossip 广播给其他节点但在代码中始终被假定为 true。这说明该迁移在历史上已经完成本文描述的正是当年集群升级时经历的完整过程。二、迁移策略与前置条件Scylla 一般支持逐节点升级、零停机的集群升级。针对 users→roles 的迁移文档明确了两条硬性前提system_authkeyspace 的副本因子必须等于集群规模。这是所有 Scylla 版本启用访问控制的先决条件db/config.cc 中对PasswordAuthenticator/CassandraAuthorizer的配置说明也反复提示如果system_auth只存在单副本持有该副本的节点宕机后可能无法登录集群升级期间禁止对访问控制做任何变更——不得修改用户、角色或权限。单节点升级流程在一个由n个运行旧版本 Scylla 的节点组成的集群中停止单个节点升级其scylla-server可执行文件重启该节点。节点重启后涵盖访问控制的三个模块——角色管理role-management、认证authentication、授权authorization——各自执行自己的迁移。每个模块的统一迁移判定逻辑对每个模块迁移遵循相同流程新表中已存在任何非默认元数据什么都不做不发生迁移。若此时旧表仍然存在向日志打印一条警告旧表存在将旧表中的每一条记录转换后写入新表新表中已存在的条目会被覆盖原因见下。迁移开始和结束时分别打印日志消息迁移数据出错错误写入日志并允许异常继续向上传播。为什么迁移时要覆盖新表中已有条目文档给出了明确的容错考量如果两个节点被同时重启虽然官方不支持这种操作并且两个节点都观察到新表中无非默认元数据从而各自开始迁移覆盖写仍然能保证所有数据都被完整拷贝过去——即迁移是幂等的。三、混合版本集群中的行为老节点 vs 新节点单节点升级完成后客户端可能连接到旧节点也可能连接到新节点两条路径的行为截然不同连接到旧节点任何访问控制变更都会成功因为旧代码访问的仍是依然存在的旧表但这些变更不受支持——它们不一定会反映到新表中升级完成后可能造成新旧数据不一致连接到新节点所有访问控制 CQL 语句都会访问新表。此时一个名为ROLES的新 gossip 特性标志发挥作用用于强制执行升级期间禁止修改访问控制这一限制除非集群中所有节点都通告自己支持ROLES任何修改访问控制的 CQL 语句都会记录错误并拒绝执行。源码视角gossip 特性标志的实现从源码结构看ROLES标志基于 Scylla 的 gossip 特性服务实现。gms/feature.hh 中定义的feature类跟踪当前节点所知晓的所有节点是否都支持某个特性并通过when_enabled回调机制在特性变为全局可用时触发后续逻辑gms/feature_service.cc 中的supported_feature_set()维护本节点通告的特性集合。在当前代码库中ROLESsv已列入弃用特性列表与COUNTERS、SCHEMA_TABLES_V3等同列表示该特性对所有新节点恒为真——这正是迁移收尾后的最终形态。角色元数据表本身则定义在 db/system_keyspace.ccroles表以roleutf8为分区键承载认证与 RBAC 所需属性role_members表连接用户与其被授予的角色role_permissions表存储 RBAC 权限。四、升级完成后的验证与清理当所有节点都升级完毕后文档要求执行以下收尾步骤以超级用户身份核对新表内容检查system_auth.{roles, role_permissions, role_members}并与旧的用户表system_auth.{users, credentials, permissions}逐一对比或者通过常规 CQL 语句探查迁移后的访问控制数据例如LIST ROLESLIST USERSLIST PERMISSIONS这些 CQL 语句在解析层由 cql3/Cql.g 文法支持listRolesStatement规则支持LIST ROLES [OF rolename] [NORECURSIVE]等形式roleResource规则支持ON ALL ROLES/ON ROLE name资源语法确认所有元数据迁移成功且系统行为符合预期后删除遗留表drop the legacy tables。五、故障恢复Recovery如果某个节点在迁移元数据时失败它会记录一条错误日志。文档给出的恢复手段是删除新表中的相关条目drop any entries in the new tables重启该节点。由于迁移逻辑是幂等的旧表条目会被逐条转换重写新表已有条目会被覆盖清空后重启可以干净地重跑整个迁移过程而不会受到半迁移状态的影响。六、当前代码库中的迁移痕迹从源码结构看本次迁移在仓库中留下了多处可考据的痕迹方便读者追溯过渡性认证组件auth/transitional.hh 定义了transitional_authenticator未提供凭据或认证失败时允许匿名访问和transitional_authorizer向所有用户授予一组固定权限注释明确标注 Used for migration scenarios.服务于迁移场景下新旧集群的平滑过渡认证器/角色管理器工厂auth/service.cc 中make_authenticator_factory、make_role_manager_factory等工厂函数统一接收migration_manager与raft_group0_client各认证器password_authenticator、certificate_authenticator、saslauthd_authenticator等的构造函数签名中也普遍携带::service::migration_manager参数从源码结构看这是当年旧表存在则迁移逻辑在模块初始化链路中的统一入口旧 keyspace 的兼容创建auth/service.cc 中保留了create_legacy_keyspace_if_missing方法用于在需要兼容旧版本时确保system_authkeyspace 存在版本标识db/auth_version.hh 定义了auth_version_t枚举v1、v2从命名推断用于区分认证元数据的模式版本特性标志的最终状态如前所述ROLES已位于 gms/feature_service.cc 的弃用特性列表中代码中恒假定为真——对今天的 ScyllaDB 用户而言这意味着 users→roles 迁移是历史性的新部署直接使用 roles 模型而只有从旧版本升级上来的集群才需要执行本文描述的策略、验证与清理步骤。小结迁移是逐节点、零停机的停一个节点、升级、重启三个访问控制模块各自后台迁移自己的元数据迁移判定是幂等且可重入的新表已有非默认数据则跳过旧表存在则逐条转换覆盖写入出错则记日志并传播异常ROLESgossip 特性标志是升级窗口的闸门全集群未通告ROLES之前任何访问控制变更在新节点上都会被拒绝收尾必须做两件事以超级用户核对新旧表或执行LIST ROLES/LIST USERS/LIST PERMISSIONS确认无误后删除遗留表迁移失败时清空新表相关条目并重启节点即可重跑迁移。【免费下载链接】scylladbNoSQL data store using the Seastar framework, compatible with Apache Cassandra and Amazon DynamoDB项目地址: https://gitcode.com/GitHub_Trending/sc/scylladb创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考