生产环境 Admin 初始化与 Secret 生命周期
生产环境首次管理员初始化不再依赖读取服务日志。Halro 提供浏览器交互式 Secret 文件和离线自动化 Bootstrap Job 两条路径;两者都把 Secret 交付、业务服务与观测权限分离。
选择初始化模式
Section titled “选择初始化模式”| 模式 | 适用场景 | Secret 交付 | 主服务启动方式 |
|---|---|---|---|
本地 start | 开发机、评估环境 | 未配置文件时只在操作者控制的终端显示进程级 Token | halro start |
| 远程交互式 | 指定人员在浏览器创建管理员 | Kubernetes Secret、Vault、Secrets Manager 或 CSI 只读文件 | Init Job 后 halro serve |
| 自动化离线 | Kubernetes、GitOps、CI/CD | 密码文件只挂载给一次性 Bootstrap container | Bootstrap 与 Verification Job 后 halro serve |
Halro 不读取 Kubernetes Secret API,也不创建、更新或删除 Secret。kubelet、CSI 或受控 Injector 负责文件投影。应用工程师不需要 pods/log、pods/exec 或 namespace 级 Secret 权限。
交互式 Setup Token 文件
Section titled “交互式 Setup Token 文件”admin: setup_token_file: /run/secrets/halro/setup-token setup_token_ttl: 30msetup_token_file 必须是绝对路径。setup_token_ttl 默认 30m,必须大于 0,最大 24h;它限制生成 Token 的生命周期,也限制文件在加载时允许的最大剩余有效期。
使用与目标版本相同的 Halro 二进制离线生成文件:
halro admin setup-token generate \ --ttl 30m \ --output /secure/path/setup-token命令使用 32 字节 CSPRNG,按 0600 排他创建新文件,目标已存在时拒绝覆盖。它不会把 Token 写入 stdout、stderr、应用日志或 Audit。文件是两行信封:第一行是 49 字节 setup_ Token,第二行是生成时确定的 UTC 绝对过期时间。
setup_<32-byte-CSPRNG-as-unpadded-base64url>expires_at=<RFC3339Nano UTC>不要使用 shell literal、命令替换、环境变量、--from-literal、工单、聊天或 Git 传递 Token。让 Secret Manager 或 Kubernetes 客户端直接读取文件:
kubectl -n halro create secret generic halro-bootstrap \ --from-file=setup-token=/secure/path/setup-token加载与失效语义
Section titled “加载与失效语义”- 只有“数据库没有管理员且 Setup Token 必需”时才读取文件;已有管理员后不再读取。
- 文件在进程启动时读取一次,不支持热重载。修改或删除 Secret 不会撤销旧进程已加载的 Token。
- 绝对
expires_at不因重启或 Pod 重调度延长;过期后必须生成新文件、轮换 Secret 并启动新 Pod。 - 文件缺失、不可读、为空、格式错误或剩余 TTL 过长时 fail-closed,不回退到自动生成或日志输出。
- 配置文件路径时,即使 Admin 只监听 loopback,也显式要求提交 Token。
- Setup Status 与错误响应不暴露 Token 来源、文件路径或“错误/过期”的区别。
- 首个管理员事务提交后 Token 立即失效;即使自动登录 Session 创建失败,也应转到登录页,不能再次初始化。
前端提示为“从启动终端或部署管理员提供的安全通道获取”。初始化审批人通过组织已有的 Secret 审批通道取得 Token,不需要生产日志或 kubectl exec 权限。
自动化离线 Bootstrap
Section titled “自动化离线 Bootstrap”主 Deployment 必须尚未创建或已缩容到 0,且数据目录没有其他写者。自动化使用绝对密码文件路径,避免无人值守任务等待 stdin:
halro init --if-needed --config /etc/halro/config.yamlhalro admin bootstrap \ --config /etc/halro/config.yaml \ --username admin \ --password-file /run/secrets/halro/admin-password \ --if-needed \ --operation-id install-production-20260917--password-file 与 stdin 使用相同的 1024 字节上限、密码策略和单个末尾 LF/CRLF 处理;命令没有 --password <value> 选项,也不会在错误中回显密码或路径。
幂等与恢复边界
Section titled “幂等与恢复边界”稳定、非秘密的 operation-id 标识一次安装:
- 首个管理员、目标用户名、Bootstrap Intent 和 Completion 持久关联;管理员记录与 Audit Intent 在一个事务中提交。
- 相同 operation ID 与用户名重试会恢复或确认 Audit 交付和 checkpoint,然后返回
already_completed,不会修改密码。 - 不同 operation ID、用户名不匹配、已有管理员却没有匹配 Completion,或部分状态无法判定时 fail-closed。
- 进程在数据库提交、Audit 追加或 checkpoint 边界崩溃后,同一 operation ID 可以恢复为确定状态,不会创建第二个管理员。
自动化以退出码判断成功,再读取稳定单行结果:
Admin bootstrap result: created (operation_id=install-production-20260917)Admin bootstrap result: already_completed (operation_id=install-production-20260917)两种结果都返回退出码 0;冲突、歧义、输入和基础设施错误返回非 0。不要更换 operation ID 来绕过失败。
审计完整性验证
Section titled “审计完整性验证”admin.bootstrap 记录 source=generated|file|offline、operation ID 和目标用户名,不记录 Token、Token 摘要、密码、Secret 名称或文件路径。Completion 保存具体 Audit Event ID;重试与验收要求该事件存在于认证后的 Audit 链,并且 action、target 与 operation ID 一致。
Bootstrap Job 完成后、启动主 Deployment 前,保持 PVC 离线并运行:
halro doctor --config /etc/halro/config.yamlhalro audit verify --config /etc/halro/config.yamldoctor 检查 Bootstrap Completion、待投递 Audit Intent 和后续管理员变化;audit verify 验证 Audit HMAC 链、trusted checkpoint,以及 Completion 指向的 Audit Event。任一检查失败都不能启动 Runtime,也不能通过手工编辑数据库或改 operation ID 消除。
Kubernetes 正式交付顺序
Section titled “Kubernetes 正式交付顺序”官方自动化 Job 路径当前只承诺 storage.master_key.mode: key_slots。File Master Key 初始化需要一套生成后安全外送和持久保管协议,在完成评审前不属于官方自动化 Job 支持范围。
PVC / 完整配置 / Secret / 默认拒绝 NetworkPolicy ↓一次性 Bootstrap Job(init container: init --if-needed) ↓Verification Job(doctor → audit verify) ↓删除 Job、密码 Secret 与 install-only GitOps 声明 ↓撤销临时 KMS Lifecycle 身份 ↓启动正式 Deployment:halro serve仓库提供:
deploy/kubernetes/halro-init-job.yaml:交互式模式的新 PVC 初始化;deploy/kubernetes/halro-bootstrap-job.yaml:自动化首管理员创建;deploy/kubernetes/halro-bootstrap-verify-job.yaml:离线 Doctor 与 Audit 验证;deploy/kubernetes/halro-bootstrap-default-deny-network-policy.yaml:install-only 默认拒绝基线;deploy/kubernetes/halro-aws-kms.yaml:AWS KMS Runtime 强化示例。
自动化示例:
kubectl -n halro create secret generic halro-admin-bootstrap \ --from-file=admin-password=/secure/path/admin-passwordkubectl -n halro apply -f deploy/kubernetes/halro-bootstrap-job.yamlkubectl -n halro wait --for=condition=complete \ job/halro-bootstrap-install-id --timeout=15mkubectl -n halro delete job halro-bootstrap-install-id --wait=truekubectl -n halro apply -f deploy/kubernetes/halro-bootstrap-verify-job.yamlkubectl -n halro wait --for=condition=complete \ job/halro-bootstrap-verify-install-id --timeout=10mKubernetes 安全约束
Section titled “Kubernetes 安全约束”- Bootstrap/Verification Job 与 Runtime 禁止重叠;优先
ReadWriteOncePod,但 PVC access mode 不能替代编排顺序和 Halro 数据目录锁。 - Job 使用独立 ServiceAccount 和临时 KMS Lifecycle 权限;Runtime 只保留审核过的 Primary decrypt 权限。
- Secret 仅投影给需要它的 container;管理员密码不挂载给 init、verification 或正式 Deployment。
- 所有容器 non-root、只读根文件系统、drop capabilities、启用 seccomp,并限制 deadline/backoff。
- AWS 容器设置
AWS_EC2_METADATA_DISABLED=true,禁止工作负载身份失败后回退到 EC2 IMDS 节点角色。 - 原生 NetworkPolicy 不能按 KMS FQDN 表达规则;部署方必须为 DNS、Workload Identity 和私有 KMS endpoint 增加集群精确 allow policy,其余出站默认拒绝。
- ServiceAccount 不需要
secrets/get、pods/log或pods/exec。任意 Pod 创建、工作负载 patch、ephemeral container、PVC snapshot 或冒用外部身份等权限应按等价 Secret 访问治理。
GitOps 与 Secret 删除
Section titled “GitOps 与 Secret 删除”Bootstrap 是 install-only 状态,不是每次同步的 hook。使用显式流水线阶段或成功后从 desired state 删除的一次性 Application。不要同时设置 Job 自动 TTL 删除并让 GitOps 永久声明同名 Job,否则控制器会循环重建 Bootstrap。
首个管理员提交后按载体清理:
- 原生 Kubernetes Secret 示例使用
optional: true;从 desired state 删除 Secret 后,真正删除并重新调度 Pod,确认已有管理员实例仍可登录。 - CSI/Injector 先发布一个移除 volume、mount 和同步资源的新 Deployment,确认新 Pod Ready 和登录正常,再撤销外部 Secret。
- 自动化模式先删除 Job/Pod并等待 PVC detach,再删除密码 Secret、撤销临时 KMS 身份,最后创建 Runtime Deployment。
Halro“已有管理员后不读取文件”和 kubelet/CSI“Secret 缺失时能否构造 Pod”是两个独立依赖,必须分别验收。
Secret 泄露、轮换与恢复
Section titled “Secret 泄露、轮换与恢复”发现 Token 或首管理员密码进入日志、工单、聊天、shell history、崩溃产物、Tracing 或 CI 输出时,停止自动部署并保留证据,但不要再次复制 Secret。
- 阻断 Admin Setup 入口,并停止所有可能已加载 Token 的 Pod;只删除 Secret 不能清除旧进程内存。
- 从 GitOps desired state 和外部 Secret Manager 撤销旧值。
- 用
admin setup-token generate生成新的绝对过期信封,创建新版本 Secret。 - 启动一个新 Pod完成初始化,并验证
admin.bootstrapAudit 记录。 - 按两阶段顺序解除挂载依赖并删除 Secret。
自动化密码在 Completion 出现前泄露时,停止 Job、轮换密码来源,并使用相同 operation ID 恢复;先用离线诊断判定事务是否提交,不能用新 ID 绕过冲突。
管理员事务提交后 Setup Token 已失效,但仍需删除所有副本并审查 Setup、Ingress、WAF/APM、Job、应用和云审计记录。若首个密码可能泄露,停止 Runtime,使用新密码文件执行批准的离线 reset-password;验证旧密码和 Session 失效,再检查管理员身份、MFA 以及可疑 Session 创建的凭据。
CLI 与进程安全
Section titled “CLI 与进程安全”涉及初始化秘密的 init、admin bootstrap、admin reset-password、admin setup-token generate、doctor 和 Audit 验证会在接触密钥前启用 core-dump/dumpable 防护;保护无法建立时 fail-closed。生产环境还应禁用 core dump,并防止 crash report、heap/profile 和诊断包收集 Secret 文件内容。
上线验收至少证明:日志没有 Token/密码;相同 operation ID 可幂等恢复;不同 ID fail-closed;Doctor 与 Audit 验证通过;Bootstrap 身份已撤销;Runtime 权限未扩大;删除 Secret 并重新调度后实例仍能登录。