160 lines
7.0 KiB
Markdown
160 lines
7.0 KiB
Markdown
|
|
# 更新客户端架构
|
|||
|
|
|
|||
|
|
## 目的
|
|||
|
|
|
|||
|
|
更新客户端强制执行一条受控的产品入口路径,并执行事务性更新,而不会将可编辑的安装文件作为信任边界的一部分。父项目 SimCAE 拥有集成和交付的控制权。
|
|||
|
|
|
|||
|
|
本文档描述了运行时合约。服务器发布、管理员界面、数据库模式和对象存储实现均在此仓库之外。
|
|||
|
|
|
|||
|
|
## 产品入口规则
|
|||
|
|
|
|||
|
|
在每个支持的操作系统上,必须通过 `Launcher` 进入发布版本。如果某个平台尚未提供可用的启动器和更新运行时,其发布配置或打包必须失败。直接启动应用程序不是可接受的备用方案。
|
|||
|
|
|
|||
|
|
调试版本可以禁用启动门以供开发者迭代使用。但带有此例外的构建版本不得分发。
|
|||
|
|
|
|||
|
|
## 组件
|
|||
|
|
|
|||
|
|
### 启动器
|
|||
|
|
|
|||
|
|
`启动器` 是面向用户的入口。它:
|
|||
|
|
|
|||
|
|
1. 加载嵌入式产品配置和机器范围的可变状态。
|
|||
|
|
2. 建立或验证设备凭证。
|
|||
|
|
3. 加载并验证已签名的版本策略。
|
|||
|
|
4. 检查防回滚、系统时钟倒退和离线有效性条件。
|
|||
|
|
5. 将已安装的版本与已签名的清单进行比对验证。
|
|||
|
|
6. 在有网络连接时检查服务器是否允许更新。
|
|||
|
|
7. 当需要更新时启动 `Updater`。
|
|||
|
|
8. 否则创建一个短期有效的一次性票据并启动 SimCAE。
|
|||
|
|
|
|||
|
|
在需要提升权限才能进行机器范围状态或安装更新的平台上,发布启动器必须通过平台原生机制请求所需权限。
|
|||
|
|
|
|||
|
|
### 主程序
|
|||
|
|
|
|||
|
|
交付的 SimCAE 可执行文件实现了合同中的主应用程序部分。此仓库中的 `MainApp` 是一个集成示例,不是第二个产品可执行文件。
|
|||
|
|
|
|||
|
|
该应用程序必须:
|
|||
|
|
|
|||
|
|
* 在正常启动前消耗并验证 `--ticket-file=<path>`;
|
|||
|
|
* 拒绝在受控发布构建中缺失、过期、重复或不匹配的票证;
|
|||
|
|
* 仅在启动达到更新器预期的健康点后,将 `ok\n` 写入 `--health-file=<path>`。
|
|||
|
|
|
|||
|
|
在当前集成中,启动器拥有已签名策略和已安装文件完整性检查。应用程序独立验证短期票证;将策略或清单验证移至 SimCAE 需要单独的共享运行时协议,且不得由本文件暗示。
|
|||
|
|
|
|||
|
|
启动票证阻止了对 `Launcher` 的随意绕过。它不是已签名策略、清单验证或服务器授权的替代品。
|
|||
|
|
|
|||
|
|
### 更新器
|
|||
|
|
|
|||
|
|
`Updater` 拥有更新事务。它:
|
|||
|
|
|
|||
|
|
* 获取已签名的目标清单和授权下载位置;
|
|||
|
|
* 在进行任何文件操作前验证路径;
|
|||
|
|
* 比较本地文件与完整清单;
|
|||
|
|
* 仅下载缺失或不匹配的文件;
|
|||
|
|
* 在安装前验证签名、大小和哈希值;
|
|||
|
|
* 备份被替换或删除的文件;
|
|||
|
|
* 安装阶段内容;
|
|||
|
|
* 在必要时将锁定文件的替换委托给 `Bootstrap`;
|
|||
|
|
* 使用启动票和健康文件请求启动更新后的应用程序;
|
|||
|
|
* 仅在健康确认后提交;
|
|||
|
|
* 在失败时恢复上一版本。
|
|||
|
|
|
|||
|
|
下载可以是增量的,但完整性验证始终针对完整的签名清单。
|
|||
|
|
|
|||
|
|
### 引导启动
|
|||
|
|
|
|||
|
|
`Bootstrap` 有意设计得非常小。它会等待更新程序进程释放被锁定的文件,执行已批准的替换方案,并重新启动更新程序以继续验证。它必须拒绝不安全的相对路径,且不得擅自制定更新策略。
|
|||
|
|
|
|||
|
|
### 通用运行时
|
|||
|
|
|
|||
|
|
共享库提供配置访问、原生状态、设备标识、HTTP 请求、签名策略处理、本地防回滚状态、清单完整性验证以及启动票操作。共享辅助工具不会削弱组件特定的检查。
|
|||
|
|
|
|||
|
|
## 启动序列
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
用户
|
|||
|
|
-> 启动器
|
|||
|
|
-> 嵌入式产品配置
|
|||
|
|
-> 机器状态和设备凭证
|
|||
|
|
-> 签名策略和清单验证
|
|||
|
|
-> 是否需要更新? -> 更新器 -> 需要时启动引导程序
|
|||
|
|
-> 创建一次性票据
|
|||
|
|
-> SimCAE
|
|||
|
|
-> 消耗票据
|
|||
|
|
-> 重新验证策略和完整性
|
|||
|
|
-> 按请求报告启动健康状态
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
设备激活是机器识别,而不是终端用户登录。普通客户端启动不会创建管理员会话,也不应接收服务器的发布权限。
|
|||
|
|
|
|||
|
|
## 更新事务
|
|||
|
|
|
|||
|
|
一个持久的事务必须至少区分这些阶段:
|
|||
|
|
|
|||
|
|
1. 初始化事务标识符和暂存区。
|
|||
|
|
2. 验证目标清单和所有暂存的负载。
|
|||
|
|
3. 记录已更改和过时的路径。
|
|||
|
|
4. 备份当前文件。
|
|||
|
|
5. 安装未被锁定的文件。
|
|||
|
|
6. 当需要时,将锁定文件的工作交给 `Bootstrap`。
|
|||
|
|
7. 启动候选版本并等待其健康标记。
|
|||
|
|
8. 提交并删除临时数据仅在成功验证后进行。
|
|||
|
|
9. 在任何失败后回滚并验证恢复的版本。
|
|||
|
|
|
|||
|
|
在进程启动时,必须在开始新事务之前恢复中断的事务。在持久化状态仍需要恢复时,不得删除暂存和备份数据。
|
|||
|
|
|
|||
|
|
## 信任边界
|
|||
|
|
|
|||
|
|
| 数据或机制 | 权限 | 说明 |
|
|||
|
|
| --- | --- | --- |
|
|||
|
|
| 服务器私有签名密钥 | 仅限服务器 | 从未运送到客户。 |
|
|||
|
|
| 已签署的版本策略 | 服务器 | 控制运行、更新、降级和离线决策。 |
|
|||
|
|
| 签名的清单 | 服务器 | 定义了完整的受保护文件集合和预期的哈希值。 |
|
|||
|
|
| 签名的设备凭证 | 服务器 | 绑定应用程序、频道、安装、设备和许可证身份。它不是用户会话。 |
|
|||
|
|
| 嵌入式产品配置 | 构建流水线 | 防止随意覆盖安装文件;可由管理员检查和修改。 |
|
|||
|
|
| 原生可变状态 | 本地机器 | 保持注册和安装状态;它不涉及授权。 |
|
|||
|
|
| 一次性启动票 | 本地启动器 | 证明预期的启动器启动了此进程。它不授予服务器权限。 |
|
|||
|
|
| 健康标识 | 候选流程 | 信号提交或回滚的启动完成;它不能证明包的真实性。 |
|
|||
|
|
|
|||
|
|
带签名的 JSON 合约必须使用确定性序列化,从已签名的负载中省略签名字段,标识算法和密钥 ID,并支持受控的公钥轮换窗口。验证失败将导致系统关闭。
|
|||
|
|
|
|||
|
|
## 运行时布局
|
|||
|
|
|
|||
|
|
父安装程序拥有最终的布局。预期的可执行文件关系为:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
<install-root>/
|
|||
|
|
bin/
|
|||
|
|
Launcher<platform-suffix>
|
|||
|
|
Updater<platform-suffix>
|
|||
|
|
Bootstrap<platform-suffix>
|
|||
|
|
SimCAE<platform-suffix>
|
|||
|
|
config/
|
|||
|
|
<仅在需要时缓存已签名的运行时>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
安装目录中不应包含可编辑的产品策略 JSON 文件。更新缓存、备份、已签名策略缓存和机器状态必须使用集成运行时选择的位置,并且必须遵守平台的写入权限规则。
|
|||
|
|
|
|||
|
|
## 失败策略
|
|||
|
|
|
|||
|
|
* 无效签名、不安全路径、身份不匹配、策略回滚以及受保护文件损坏将导致系统关闭。
|
|||
|
|
* 一个临时的网络故障可能会使用仍然有效的已签名离线策略;它不能静默地创建新的允许项。
|
|||
|
|
* 过期的离线策略或被禁止的版本会阻止启动。
|
|||
|
|
* 失败的候选健康触发器会导致回滚。
|
|||
|
|
* 回滚失败会留下可恢复的状态和诊断错误;它不能报告更新成功。
|
|||
|
|
|
|||
|
|
## 接受场景
|
|||
|
|
|
|||
|
|
发布接受必须涵盖:
|
|||
|
|
|
|||
|
|
* 通过 `Launcher` 正常启动;
|
|||
|
|
* 直接 SimCAE 启动拒绝;
|
|||
|
|
* 首次设备注册及后续离线启动;
|
|||
|
|
* 更新到较新的已发布版本;
|
|||
|
|
* 篡改的受保护文件被拒绝;
|
|||
|
|
* 篡改的策略或清单被拒绝;
|
|||
|
|
* 强制更新和禁用版本行为;
|
|||
|
|
* 频道选择和禁止降级行为;
|
|||
|
|
* 中断更新恢复;
|
|||
|
|
* 候选失败和成功回滚;
|
|||
|
|
* 从实际安装位置启动并更新,通过正常的最终用户交互并需要提升权限。
|