Authelia 深度指南:用 authelia storage encryption 命令族管理数据库加密
2026/9/13 3:00:36 网站建设 项目流程

Authelia 深度指南:用 authelia storage encryption 命令族管理数据库加密

【免费下载链接】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 使用 AES-GCM 对 SQLite、MySQL 与 PostgreSQL 数据库中存储的 TOTP 密钥、WebAuthn 凭据、OAuth2 会话等敏感数据做应用层加密,加密密钥由storage.encryption_key配置项提供。当密钥泄露、需要验证密钥与数据库数据是否匹配、或需要轮换一次性验证码的 HMAC 密钥时,官方 CLI 提供了authelia storage encryption命令族(change-key/check/rotate三个子命令)。读完本篇,你将掌握这三个子命令的完整用法与参数、密钥在底层如何派生(HKDF)与加密(GCM + AAD),以及密钥变更前后的标准安全操作流程。

命令定位:一个只做分组、没有直接动作的父命令

authelia storage encryption本身是一个分组命令(group command),直接执行它只会打印帮助,所有实际操作都在其子命令中完成。从源码 newStorageEncryptionCmd 可以看到,该命令被声明为Args: cobra.NoArgs,并挂接了三个子命令:

子命令作用参考文档
authelia storage encryption change-key更换存储加密密钥(全库重加密)authelia_storage_encryption_change-key.md
authelia storage encryption check校验当前密钥能否解密数据库数据authelia_storage_encryption_check.md
authelia storage encryption rotate轮换存储加密相关的其他值(HMAC 密钥)authelia_storage_encryption_rotate.md

它的父命令authelia storage用于管理 Authelia 的 SQL 数据库,允许执行一系列手动操作起来非常困难的进阶任务(参见 authelia storage 文档)。encryption命令不接收位置参数,唯一的示例就是:

authelia storage encryption --help

选项只有-h, --help,其余选项全部继承自父命令(见下一节)。

继承选项:如何指定数据库与密钥

encryption命令族继承自authelia storage及其上层的持久化标志,完整列表如下(引自官方参考文档 authelia_storage_encryption.md):

-c, --config strings configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) --config.experimental.filters strings list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters' --encryption-key string the storage encryption key to use --mysql.address string the MySQL server address (default "tcp://127.0.0.1:3306") --mysql.database string the MySQL database name (default "authelia") --mysql.password string the MySQL password --mysql.username string the MySQL username (default "authelia") --postgres.address string the PostgreSQL server address (default "tcp://127.0.0.1:5432") --postgres.database string the PostgreSQL database name (default "authelia") --postgres.password string the PostgreSQL password --postgres.schema string the PostgreSQL schema name (default "public") --postgres.username string the PostgreSQL username (default "authelia") --sqlite.path string the SQLite database path

这些标志在源码 newStorageCmd 中通过cmd.PersistentFlags()注册,因此对storage下所有子命令生效:

  • -c, --config:指定配置文件或目录,默认加载configuration.yml。配置文件中已声明storage部分时,此处的数据库标志用于临时覆盖(例如在容器网络内操作另一台主机上的数据库)。
  • --encryption-key:指定要使用的存储加密密钥,避免把密钥写在命令行历史之外的配置里;执行check时尤其有用——用它验证「某个密钥是否就是该数据库实际使用的密钥」,而不必改动正在运行的配置。
  • --sqlite.path/--mysql.*/--postgres.*:三种后端数据库的连接覆盖参数,默认值与源码中的注册默认值一致(MySQLtcp://127.0.0.1:3306、PostgreSQLtcp://127.0.0.1:5432,库名/用户名均为authelia)。

change-key:更换加密密钥并全库重加密

change-key用于更换 Authelia SQL 数据库的加密密钥:用当前配置的密钥解密全部受保护数据,再用新密钥重新加密并写回。

用法与示例

authelia storage encryption change-key [flags]

官方文档给出的示例(见 change-key 参考):

# 方式一:密钥来自配置文件 authelia storage encryption change-key --config config.yml --new-encryption-key 0e95cb49-5804-4ad9-be82-bb04a9ddecd8 # 方式二:旧密钥与连接参数全部走命令行 authelia storage encryption change-key --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 \ --new-encryption-key 0e95cb49-5804-4ad9-be82-bb04a9ddecd8 \ --postgres.address tcp://postgres:5432 --postgres.password autheliapw

专属选项只有一个:

-h, --help help for change-key --new-encryption-key string the new key to encrypt the data with

执行流程与约束(源码视角)

CLI 入口在 StorageSchemaEncryptionChangeKeyRunE,其中包含几条硬性约束:

  1. 数据库 schema 版本必须至少为 1,否则直接报错schema version must be at least version 1 to change the encryption key
  2. 新密钥至少 20 个字符且不能为空len(key) < 20会失败);
  3. 省略--new-encryption-key时进入交互式模式:命令行会提示Enter New Storage Encryption Key:,从终端安全读取(不显示输入)。

真正的重加密逻辑在 SchemaEncryptionChangeKey:

  • 新密钥先经过HKDF-SHA256 派生(info 为authelia:kdf:storage:encryption_key:v1,见 DeriveCryptographicKey 与 const.go),派生结果若与当前密钥相同则报「the old key and the new key are the same」;
  • 调用SchemaEncryptionCheckKey先用旧密钥验证数据完整性,旧密钥不对则中止,避免把数据加密成不可恢复的状态;
  • 随后在单个数据库事务内执行 SchemaEncryptionChangeKeyAdvanced,按顺序对以下表逐行「解密→用新密钥重加密→写回」,任何一步失败则整体回滚:
    • one_time_code(OTC 一次性代码)
    • totp_configurations(TOTP 密钥)
    • webauthn_credentials(WebAuthn 公钥与 attestation)
    • cached_data(缓存数据)
    • 各 OAuth2/OIDC 会话表(oauth2_session等,遍历所有已知的OAuth2SessionType
    • encryption(存储自身的管理值,含 check 值与 HMAC 密钥)

成功后 CLI 输出:Completed the encryption key change. Please adjust your configuration to use the new key.—— 也就是说数据库侧完成后,还必须把新密钥写入运行配置storage.encryption_key或对应 secret),再重启服务。

check:校验密钥与数据库数据是否匹配

check用于验证当前配置的加密密钥对该数据库有效,官方描述是“useful for validating all data that can be encrypted is intact”,在密钥变更前后、数据库迁移或备份恢复之后执行它是最稳妥的习惯。

用法与示例

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

专属选项:

-h, --help help for check --verbose enables verbose checking of every row of encrypted data

校验逻辑与输出

  • 默认(非 verbose):只解密encryption表中的哨兵值(check value)即可判断密钥对错,代价小。核心在 checkEncryptionCheckValue,它会按当前 schema 版本选择对应的密钥派生方式与 AAD(旧库使用遗留的 SHA256 派生,新库使用 HKDF 派生),保证对未升级的旧库不会误报失败。
  • --verbose:SchemaEncryptionCheckKey 会对上面change-key提到的每一张加密表逐行执行解密,统计每张表的Total RowsInvalid Rows

CLI 输出由 runStorageSchemaEncryptionCheckKey 决定,共四种结果:

Storage Encryption Key Validation: SUCCESS
Storage Encryption Key Validation: FAILURE Cause: The schema version doesn't support encryption.
Storage Encryption Key Validation: UNKNOWN Cause: <具体错误>.

verbose 模式下还会打印各表明细:

Tables: Table (one_time_code): ... Invalid Rows: 0 Total Rows: 12

rotate:轮换 HMAC 密钥(破坏性操作)

rotate子命令族用于轮换存储中用于签名一次性验证码的 HMAC 密钥,它不改变encryption_key本身,而是重新生成 HMAC 密钥并清空其保护的表

authelia storage encryption rotate hmac otc # 轮换 OTC HMAC 密钥,清空 one_time_code 表 authelia storage encryption rotate hmac otp # 轮换 OTP HMAC 密钥,清空 totp_history 表

对应参考文档:rotate hmac、rotate hmac otc、rotate hmac otp。

从源码可以确认其破坏性与防护机制:

  • 实现 SchemaEncryptionRotateHMACKey 在一个事务里完成两件事:用crypto/rand生成新 HMAC 密钥(OTC 用 SHA-512 块大小的 key,OTP 用 SHA-256 块大小的 key)写入encryption表,然后truncate对应表——otc对应one_time_code表,otp对应totp_history表;
  • 两个子命令各带一个-f, --force标志(“force the rotation without confirmation”)。不带-f时,runStorageSchemaEncryptionRotateKey 会要求交互式确认:
This will rotate the HMAC key and truncate the 'one_time_code' table, this is not reversible, type 'ROTATE' and press return to continue:

必须输入ROTATE回车才继续,否则取消。HMAC 密钥本身是加密后存放在encryption表中的(名称形如hmac:<name>,见 setCrypographyKey),所以轮换 HMAC 密钥不影响storage.encryption_key的有效性。

底层原理:密钥派生、GCM 加密与 AAD

理解这一命令族的前提是了解 Authelia 存储加密的三层结构:

1. 密钥派生:用户密钥 ≠ 实际密钥

配置中的storage.encryption_key不会直接用于加解密。新版实现通过 HKDF-SHA256 派生出 32 字节密钥(internal/utils/crypto.go):

reader := hkdf.New(hash, raw, nil, []byte(info)) // info = "authelia:kdf:storage:encryption_key:v1"

早期版本使用DeriveLegacyCryptographicKey(直接sha256.Sum256(raw))派生。这个差异决定了旧库升级路径:schema 24 及以下的库按遗留方式校验,升级迁移完成后自动切换到 HKDF 派生。

2. AES-GCM + 附加认证数据(AAD)

所有密文都用 GCM 模式打开/关闭(见 utils 加解密实现),并且每个值的 AAD(Additional Authenticated Data)把密文绑定到它所在的表、列和行,防止跨表/跨行搬移密文。三种 AAD 方案随 schema 版本演进,选择逻辑见 aadForSchemaVersion:

schema 版本AAD 方案绑定粒度
< 25aadNone无 AAD
25(未发布)aadColumn表 + 列(authelia:storage:<table>:<column>
>= 26aadRow表 + 列 + 行(如 TOTP 按 username、WebAuthn 按 KID+RPID 细化)

版本常量定义在 internal/storage/const.go(schemaVersionEncryptionKeyDerivation = 25schemaVersionEncryptionAADRowScoped = 26)。change-key在执行重加密前会先SchemaVersion查询并据此同时选定解密与加密所用的 AAD 方案。

3. 受保护的表清单

check --verbosechange-key遍历的加密列与源码一一对应:

加密列AAD 行标识
one_time_codecodesignature
totp_configurationssecretusername
webauthn_credentialspublic_keyattestationKID + RPID(issuer 化 AAD)
cached_datavaluename
oauth2_session等 OIDC 会话表session_datasignature
encryptionvaluename(HMAC 密钥、check 值等)

配置与密钥保管

加密密钥的常规配置位置在configuration.ymlstorage.encryption_key(示例见 config.template.yml 与存储介绍文档):

storage: encryption_key: 'a_very_important_secret' sqlite: path: /config/db.sqlite3

官方推荐的保管方式是secrets 配置方法:当配置键以keysecretpasswordtokencertificate_chain结尾时,可以用带_FILE后缀的环境变量指向一个 Authelia 进程可读的文件,例如AUTHELIA_STORAGE_ENCRYPTION_KEY_FILE,文件尾部的换行会被自动去除(详见 Secrets 配置方法)。注意该方法是配置分层模型中独占的一层——同一个 secret 不能同时用其他方法配置,否则 Authelia 拒绝启动。

对 CLI 场景,--encryption-key标志提供了不依赖配置文件的路径;但由于命令行参数会进入 shell 历史,生产环境更建议用--config指向包含密钥的配置,或交互式提示模式(change-key省略--new-encryption-key时即进入该模式)。

实操建议:密钥生命周期操作清单

综合上述源码行为,一次完整的密钥管理流程可以归纳为:

  1. 变更前authelia storage encryption check --verbose --config config.yml,确认当前密钥下全部Invalid Rows: 0,并备份数据库(change-key虽在事务内执行,备份仍是恢复的唯一兜底);
  2. 生成新密钥:长度不低于 20 字符(CLI 硬校验),建议用密码学安全随机源生成;
  3. 执行换钥authelia storage encryption change-key --config config.yml --new-encryption-key <new-key>;该命令内部会先跑一次完整校验,旧密钥不对会直接中止,不会留下半重加密状态;
  4. 更新运行配置:把storage.encryption_key(或AUTHELIA_STORAGE_ENCRYPTION_KEY_FILE指向的文件)改为新密钥,并重启 Authelia;
  5. 变更后验证authelia storage encryption check --verbose,全部Invalid Rows: 0且输出SUCCESS即完成;
  6. 如怀疑 OTC/OTP 签名密钥暴露:用rotate hmac otc/rotate hmac otp轮换,接受其清空对应表(一次性验证码)的代价,非交互环境加-f

需要强调的是适用前提:以上操作要求数据库 schema 版本至少为 1(check对更低版本会报告The schema version doesn't support encryption),且change-key成功后必须同步更新运行配置,否则服务重启后将以新配置密钥去解密仍用旧密钥加密的数据,登录相关功能将全部失败——这正是变更前先check --verbose、变更后再次check --verbose的价值所在。

【免费下载链接】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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询