跳转到内容
v0.8.4正式版

生产环境 Admin 初始化与 Secret 生命周期

生产环境首次管理员初始化不再依赖读取服务日志。Halro 提供浏览器交互式 Secret 文件和离线自动化 Bootstrap Job 两条路径;两者都把 Secret 交付、业务服务与观测权限分离。

选择初始化模式
模式适用场景Secret 交付主服务启动方式
本地 start开发机、评估环境未配置文件时只在操作者控制的终端显示进程级 Tokenhalro start
远程交互式指定人员在浏览器创建管理员Kubernetes Secret、Vault、Secrets Manager 或 CSI 只读文件Init Job 后 halro serve
自动化离线Kubernetes、GitOps、CI/CD密码文件只挂载给一次性 Bootstrap containerBootstrap 与 Verification Job 后 halro serve

Halro 不读取 Kubernetes Secret API,也不创建、更新或删除 Secret。kubelet、CSI 或受控 Injector 负责文件投影。应用工程师不需要 pods/logpods/exec 或 namespace 级 Secret 权限。

admin:
setup_token_file: /run/secrets/halro/setup-token
setup_token_ttl: 30m

setup_token_file 必须是绝对路径。setup_token_ttl 默认 30m,必须大于 0,最大 24h;它限制生成 Token 的生命周期,也限制文件在加载时允许的最大剩余有效期。

使用与目标版本相同的 Halro 二进制离线生成文件:

Terminal window
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 客户端直接读取文件:

Terminal window
kubectl -n halro create secret generic halro-bootstrap \
--from-file=setup-token=/secure/path/setup-token
  • 只有“数据库没有管理员且 Setup Token 必需”时才读取文件;已有管理员后不再读取。
  • 文件在进程启动时读取一次,不支持热重载。修改或删除 Secret 不会撤销旧进程已加载的 Token。
  • 绝对 expires_at 不因重启或 Pod 重调度延长;过期后必须生成新文件、轮换 Secret 并启动新 Pod。
  • 文件缺失、不可读、为空、格式错误或剩余 TTL 过长时 fail-closed,不回退到自动生成或日志输出。
  • 配置文件路径时,即使 Admin 只监听 loopback,也显式要求提交 Token。
  • Setup Status 与错误响应不暴露 Token 来源、文件路径或“错误/过期”的区别。
  • 首个管理员事务提交后 Token 立即失效;即使自动登录 Session 创建失败,也应转到登录页,不能再次初始化。

前端提示为“从启动终端或部署管理员提供的安全通道获取”。初始化审批人通过组织已有的 Secret 审批通道取得 Token,不需要生产日志或 kubectl exec 权限。

主 Deployment 必须尚未创建或已缩容到 0,且数据目录没有其他写者。自动化使用绝对密码文件路径,避免无人值守任务等待 stdin:

Terminal window
halro init --if-needed --config /etc/halro/config.yaml
halro 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> 选项,也不会在错误中回显密码或路径。

稳定、非秘密的 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 来绕过失败。

admin.bootstrap 记录 source=generated|file|offline、operation ID 和目标用户名,不记录 Token、Token 摘要、密码、Secret 名称或文件路径。Completion 保存具体 Audit Event ID;重试与验收要求该事件存在于认证后的 Audit 链,并且 action、target 与 operation ID 一致。

Bootstrap Job 完成后、启动主 Deployment 前,保持 PVC 离线并运行:

Terminal window
halro doctor --config /etc/halro/config.yaml
halro audit verify --config /etc/halro/config.yaml

doctor 检查 Bootstrap Completion、待投递 Audit Intent 和后续管理员变化;audit verify 验证 Audit HMAC 链、trusted checkpoint,以及 Completion 指向的 Audit Event。任一检查失败都不能启动 Runtime,也不能通过手工编辑数据库或改 operation ID 消除。

官方自动化 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 强化示例。

自动化示例:

Terminal window
kubectl -n halro create secret generic halro-admin-bootstrap \
--from-file=admin-password=/secure/path/admin-password
kubectl -n halro apply -f deploy/kubernetes/halro-bootstrap-job.yaml
kubectl -n halro wait --for=condition=complete \
job/halro-bootstrap-install-id --timeout=15m
kubectl -n halro delete job halro-bootstrap-install-id --wait=true
kubectl -n halro apply -f deploy/kubernetes/halro-bootstrap-verify-job.yaml
kubectl -n halro wait --for=condition=complete \
job/halro-bootstrap-verify-install-id --timeout=10m
  • 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/getpods/logpods/exec。任意 Pod 创建、工作负载 patch、ephemeral container、PVC snapshot 或冒用外部身份等权限应按等价 Secret 访问治理。

Bootstrap 是 install-only 状态,不是每次同步的 hook。使用显式流水线阶段或成功后从 desired state 删除的一次性 Application。不要同时设置 Job 自动 TTL 删除并让 GitOps 永久声明同名 Job,否则控制器会循环重建 Bootstrap。

首个管理员提交后按载体清理:

  1. 原生 Kubernetes Secret 示例使用 optional: true;从 desired state 删除 Secret 后,真正删除并重新调度 Pod,确认已有管理员实例仍可登录。
  2. CSI/Injector 先发布一个移除 volume、mount 和同步资源的新 Deployment,确认新 Pod Ready 和登录正常,再撤销外部 Secret。
  3. 自动化模式先删除 Job/Pod并等待 PVC detach,再删除密码 Secret、撤销临时 KMS 身份,最后创建 Runtime Deployment。

Halro“已有管理员后不读取文件”和 kubelet/CSI“Secret 缺失时能否构造 Pod”是两个独立依赖,必须分别验收。

发现 Token 或首管理员密码进入日志、工单、聊天、shell history、崩溃产物、Tracing 或 CI 输出时,停止自动部署并保留证据,但不要再次复制 Secret。

  1. 阻断 Admin Setup 入口,并停止所有可能已加载 Token 的 Pod;只删除 Secret 不能清除旧进程内存。
  2. 从 GitOps desired state 和外部 Secret Manager 撤销旧值。
  3. admin setup-token generate 生成新的绝对过期信封,创建新版本 Secret。
  4. 启动一个新 Pod完成初始化,并验证 admin.bootstrap Audit 记录。
  5. 按两阶段顺序解除挂载依赖并删除 Secret。

自动化密码在 Completion 出现前泄露时,停止 Job、轮换密码来源,并使用相同 operation ID 恢复;先用离线诊断判定事务是否提交,不能用新 ID 绕过冲突。

管理员事务提交后 Setup Token 已失效,但仍需删除所有副本并审查 Setup、Ingress、WAF/APM、Job、应用和云审计记录。若首个密码可能泄露,停止 Runtime,使用新密码文件执行批准的离线 reset-password;验证旧密码和 Session 失效,再检查管理员身份、MFA 以及可疑 Session 创建的凭据。

涉及初始化秘密的 initadmin bootstrapadmin reset-passwordadmin setup-token generatedoctor 和 Audit 验证会在接触密钥前启用 core-dump/dumpable 防护;保护无法建立时 fail-closed。生产环境还应禁用 core dump,并防止 crash report、heap/profile 和诊断包收集 Secret 文件内容。

上线验收至少证明:日志没有 Token/密码;相同 operation ID 可幂等恢复;不同 ID fail-closed;Doctor 与 Audit 验证通过;Bootstrap 身份已撤销;Runtime 权限未扩大;删除 Secret 并重新调度后实例仍能登录。