Authelia storage encryption check:用 CLI 校验存储加密密钥与数据库密文完整性的完整指南 Authelia storage encryption check用 CLI 校验存储加密密钥与数据库密文完整性的完整指南【免费下载链接】autheliaThe Single Sign-On Multi-Factor portal for web apps. OpenID Certified™ and Post-Quantum Cryptography Ready.项目地址: https://gitcode.com/GitHub_Trending/au/authelia本文围绕 Authelia 提供的authelia storage encryption check命令展开讲清楚它的用法、参数、输出结果的含义并深入到internal/storage包中的源码实现说明它如何基于加密校验值check value与 AES-GCM 的附加认证数据AAD来验证存储加密密钥与数据库中密文的匹配关系。读完本文你能够熟练地在生产环境或备份恢复场景中验证storage.encryption_key配置是否正确并能从源码层面理解校验失败FAILURE/UNKNOWN的各类原因。命令概览authelia storage encryption check的作用是对照数据库中的数据来检查当前配置的存储加密密钥是否有效。官方参考文档中的原始描述是Checks the encryption key against the database data. This is useful for validating all data that can be encrypted is intact.也就是说该命令用于验证数据库中所有可加密的数据TOTP 密钥、WebAuthn 凭据、OIDC 会话等在当前密钥下仍然是完整的、可解密的。这在以下场景尤其重要更换或调整配置后确认storage.encryption_key与数据库中已有密文匹配跨机器迁移、备份恢复 SQLite/MySQL/PostgreSQL 数据库文件后做完整性校验排查“部分用户无法二次认证”这类疑似密文损坏问题的定位手段。命令的基本形式为authelia storage encryption check [flags]官方文档给出的标准示例如下authelia storage encryption check authelia storage encryption check --verbose authelia storage encryption check --verbose --config config.yml authelia storage encryption check --verbose --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.address tcp://postgres:5432 --postgres.password autheliapw最后一条示例展示了典型的运维用法不改动配置文件直接通过命令行标志覆盖加密密钥与 PostgreSQL 连接参数来完成校验这对在只读副本或恢复后的数据库上验证密钥尤其方便。参数参考check子命令自身只有一个开关定义见 storage.go 中的 newStorageEncryptionCheckCmd参数说明-h, --help显示 check 子命令的帮助信息--verbose启用详细模式逐行校验每一张加密表的每一行数据并输出每张表的校验统计从父命令authelia storage继承的持久化标志同样定义在 storage.go默认值与文档一致参数默认值说明-c, --configconfiguration.yml要加载的配置文件或目录strings可多个--config.experimental.filters无应用于所有配置文件的过滤器列表--encryption-key无要使用的存储加密密钥对应配置项storage.encryption_key--mysql.addresstcp://127.0.0.1:3306MySQL 服务器地址--mysql.databaseautheliaMySQL 数据库名--mysql.usernameautheliaMySQL 用户名--mysql.password无MySQL 密码--postgres.addresstcp://127.0.0.1:5432PostgreSQL 服务器地址--postgres.databaseautheliaPostgreSQL 数据库名--postgres.password无PostgreSQL 密码--postgres.schemapublicPostgreSQL schema 名--postgres.usernameautheliaPostgreSQL 用户名--sqlite.path无SQLite 数据库路径对应storage.local.path这些命令行标志并不是简单透传而是在 storage_run.go 的 ConfigStorageCommandLineConfigRunE 中被显式映射到配置键上如--encryption-key-storage.encryption_key、--postgres.address-storage.postgres.address也就是说命令行标志的优先级会覆盖配置文件中的同名项这是它能“不改配置直接验证某个密钥”的根本原因。storage.encryption_key在配置模板中的定义与约束见 config.template.yml该密钥是用于加密数据库中敏感信息的字符串最小长度为 20模板注释同时提醒如果之前配置过密钥、现在想更换必须通过 CLI 修改数据库中的密文而不能只改配置。命令的执行流程从 PreRunE 到 RunE结合 storage.go 的源码结构authelia storage的所有子命令包括encryption check都会按顺序执行一条PersistentPreRunE链ConfigStorageCommandLineConfigRunE把命令行标志映射进配置对象HelperConfigLoadRunE加载并合并-c/--config指定的配置文件或目录ConfigValidateStorageRunE校验存储与 TOTP 相关配置项的合法性见 storage_run.go 的 ConfigValidateStorageRunELoadProvidersStorageRunE加载受信任证书并按配置构造真正的存储 ProviderSQLite/MySQL/PostgreSQL见 storage_run.go 的 LoadProvidersStorageRunE。之后才进入check自己的RunE: StorageSchemaEncryptionCheckRunE。其逻辑非常直接先调用ctx.CheckSchemaVersion()确认数据库 schema 处于可用状态失败则包一层错误返回读取--verbose标志调用runStorageSchemaEncryptionCheckKey并输出结果。runStorageSchemaEncryptionCheckKeystorage_run.go的输出只有四种形态Storage Encryption Key Validation: SUCCESS Storage Encryption Key Validation: FAILURE Cause: The schema version doesnt support encryption. Storage Encryption Key Validation: FAILURE Cause: the configured encryption key does not appear to be valid for this database... Storage Encryption Key Validation: UNKNOWN Cause: 底层错误信息.对应到源码底层方法返回storage.ErrSchemaEncryptionVersionUnsupported时打印“FAILURE Cause: The schema version doesnt support encryption”返回其他错误时打印“UNKNOWN 错误原因”返回结果对象result.Success()为真打印SUCCESS否则打印FAILURE并附带storage.ErrSchemaEncryptionInvalidKey的错误文案该错误定义见 errors.go其完整文案明确提示这种情况通常发生在“只在配置里改了密钥、却没有用 CLI 在数据库中改密钥”。值得注意的是即便校验失败该函数也返回nil命令以正常退出码结束只把原因写进输出。这意味着把它放进脚本时应该解析SUCCESS/FAILURE/UNKNOWN文本而非退出码。校验原理check value、AAD 与逐行校验核心实现在 sql_provider_encryption.go 的 SchemaEncryptionCheckKey整个过程分两层。第一层加密校验值encryption check value无论是否--verbose都会先执行checkEncryptionCheckValuesql_provider_encryption.go读取encryption表中名为 check 值encryptionNameCheck的记录用当前配置的加密密钥 与该数据库 schema 版本匹配的 AAD 尝试解密解密成功 密钥与数据库匹配失败 在结果中标记InvalidCheckValue true。这个 check 值是如何产生的从 setNewEncryptionCheckValue 可以看到它就是一个用当前密钥加密的随机 UUID 明文在 schema 初始化/升级过程中写入数据库。它相当于数据库内嵌的“密钥指纹探针”——密钥没变时永远能解开密钥错或密文被改坏时立刻失败。源码注释还解释了一个历史细节早期schema 25 之前的库使用“legacy SHA256 派生密钥 无 AAD”的方式加密该值因此checkEncryptionCheckValue在version schemaVersionEncryptionKeyDerivation时会改用utils.DeriveLegacyCryptographicKey派生旧式密钥来验证避免在升级迁移运行前误报失败。第二层--verbose 下的逐表逐行校验--verbose时命令会对所有含密文的表逐行解密。从 SchemaEncryptionCheckKey 的函数列表可以看到覆盖范围schemaEncryptionCheckKeyOneTimeCodeone_time_code表的code列一次性代码按行signature绑定 AADschemaEncryptionCheckKeyTOTPtotp_configurations表的secret列TOTP 共享密钥按username绑定 AADschemaEncryptionCheckKeyWebAuthnwebauthn_credentials表的public_key与attestation两列按KIDRPID作为 issuer 绑定 AADschemaEncryptionCheckKeyCachedDatacached_data表的value列缓存数据如 MDS3 元数据按name绑定 AADschemaEncryptionCheckKeyOpenIDConnect所有 OIDC/OAuth2 会话类型对应的表的session_data列源码通过遍历OAuth2SessionType动态覆盖所有会话表schemaEncryptionCheckKeyEncryptionencryption表本身HMAC 密钥等加密存储的密钥值。每张表的结果汇入EncryptionValidationTableResult{Error, Total, Invalid}整体结果汇入EncryptionValidationResult定义见 types.go。Success()的判定规则是InvalidCheckValue为真或任意表存在Invalid ! 0或查询错误Error ! nil即整体失败。--verbose时的输出格式见 storage_run.go会对表名排序后逐张打印Tables: Table (cached_data): SUCCESS Invalid Rows: 0 Total Rows: 3 ...其中Invalid Rows/Total Rows分别对应table.Invalid与table.Total某张表总行数为 0 时描述显示为N/AResultDescriptor逻辑有无效行或查询错误则显示FAILURE。AAD密钥之外的第二道绑定Authelia 使用 AES-GCM 加密数据库密文GCM 的 Additional Authenticated DataAAD决定了密文与“表:列:行”上下文的绑定关系。encryption_aad.go 定义了三种 AAD 方案并由aadForSchemaVersion按 schema 版本选择方案适用 schema 版本AAD 内容源码aadNone 25schemaVersionEncryptionKeyDerivation之前无 AADEncryptionAADNoneaadColumn恰好 25authelia:storage:表:列OIDC 会话类为表:issuer:列把值绑定到表列EncryptionAADColumnaadRow 26schemaVersionEncryptionAADRowScoped及以后authelia:storage:表:列:行OIDC 会话类再追加 issuer把值绑定到具体行EncryptionAADRow版本常量定义在 const.goschemaVersionEncryptionKeyDerivation 25、schemaVersionEncryptionAADRowScoped 26。AAD 的意义在于即使攻击者拿到了数据库文件和密钥也无法把某行的密文原样复制到另一行/另一列或另一张表去“换行复用”因为解密时的 AAD 上下文不匹配会直接失败。encryption check --verbose的逐行校验正是对这种绑定的完整性验证——任何密文被篡改、错放、或部分恢复不完整都会以该表Invalid Rows 0的形式暴露出来。输出解读与配套命令结合上文可以给出完整的输出解读输出含义典型原因SUCCESS配置的密钥能解开 check valueverbose 下所有行均可解密配置与数据库一致FAILURE schema version doesnt support encryptionschema 版本 1空库或尚未完成迁移FAILURE the configured encryption key does not appear to be valid...check value 解不开只改了配置里的encryption_key却没用 CLI 改库内密文恢复的库与密钥不匹配UNKNOWN 具体错误校验过程本身出错连不上数据库、表缺失、权限不足等校验逻辑并非只有这条 CLI 在使用服务启动时sql_provider.go 在构造 Provider 时同样调用SchemaEncryptionCheckKey密钥与数据库不匹配时服务端会给出相同性质的报错authelia storage schema-inforunStorageSchemaInfo 会把校验结果摘要为Schema Encryption Key: valid/invalid/unsupported (schema version)一行authelia storage encryption change-key真正“换钥匙”的入口。它先执行一次 check 确认当前密钥有效sql_provider_encryption.go再在新旧密钥之间对全部表执行解密-重加密的原子事务新密钥同样有“至少 20 字符”的约束见 storage_run.go 的 runStorageSchemaEncryptionChangeKey。因此推荐的运维习惯是任何一次密钥变更或数据库迁移前后都跑一遍authelia storage encryption check --verbose——变更前确认基线为 SUCCESS变更后再次确认形成闭环。相关源码与文档索引内容路径check 命令定义与标志internal/commands/storage.goRunE 与结果输出internal/commands/storage_run.go命令行标志到配置键的映射internal/commands/storage_run.goSchemaEncryptionCheckKey 核心实现internal/storage/sql_provider_encryption.gocheck value 校验internal/storage/sql_provider_encryption.goAAD 三方案与版本选择internal/storage/encryption_aad.go结果类型与 Success 判定internal/storage/types.go错误常量定义internal/storage/errors.goencryption_key配置模板config.template.yml单元测试覆盖internal/storage/sql_provider_encryption_test.go父命令参考文档docs/content/reference/cli/authelia/authelia_storage_encryption.mdsql_provider_encryption_test.go中的TestSchemaEncryptionCheckKeyWithData、TestSchemaEncryptionCheckKeyWithInvalidData等测试用例分别在“有数据”“数据被破坏”“表查询报错”等分支上验证了本文描述的判定行为可作为实现行为的直接佐证。【免费下载链接】autheliaThe Single Sign-On Multi-Factor portal for web apps. OpenID Certified™ and Post-Quantum Cryptography Ready.项目地址: https://gitcode.com/GitHub_Trending/au/authelia创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考