核心概念
以下是支撑 enodia 设计的关键决策。理解它们,就能解释许多否则看起来很随意的行为。
两个阶段,有意设计为可分离
Section titled “两个阶段,有意设计为可分离”收集阶段与您的服务通信。评估阶段与互联网通信(厂商的生命周期日历)。在许多真实的基础设施中,没有任何一台机器能同时访问这两者。
collect → inventory.jsonl → evaluate → assessment → render# 在封闭网络内部——无需互联网enodia collect --config config.yaml -o inventory.jsonl
# 在其他任何地方——无需访问您的服务enodia check --from inventory.jsonl不带 --from 的 enodia check 就是在一个进程中组合起来的这两个阶段,而不是第二条代码路径——
过程中生成的清单是一个真实的一等产物(拥有自己的 schema 和版本),而不仅仅是内存中的中间值。
三个正交维度,而不是一个状态
Section titled “三个正交维度,而不是一个状态”一个分支可能完全健康,同时却已经存在更新的主版本——Confluence 10 LTS 在其分支内是最新的、正在获得积极支持,并且已经发布了更新的主版本,这三者同时成立。把这些压缩成单一状态,会丢掉您真正想要的信息。
| 维度 | 取值 |
|---|---|
| 补丁 | current · behind · ahead · unknown |
| 生命周期 | active · security · eol · unknown |
| 更新的分支 | latest · newer · newer_lts · unknown |
ahead 并不罕见——候选发布版本,以及厂商发布公告与其下载页面之间的日历滞后,都会经常产生这种情况。
已知 CVE(在已配置时)是与三个维度并列的一项独立事实,而不是第四个维度:它们按评估结果列出,但从不影响严重级别、退出码或 --fail-on。
事实与判断相互分离
Section titled “事实与判断相互分离”Observation 保存实际观察到的内容:版本字符串、目标是否可达、发生了什么错误(如果有的话)。
Assessment 保存 enodia 的策略对这些事实的看法——严重级别,它是在事实之上根据您所控制的策略计算出来的。
使用 --format json 导出时输出的是事实。有不同优先级的使用方可以在其上应用自己的策略,而不是 enodia 的策略。如果把严重级别直接写进观测结果本身,这就不可能实现了。
时间是一个参数
Section titled “时间是一个参数”评估接受一个显式的 asOf 时间戳——评估路径中没有任何地方直接调用系统时钟。check --from
从清单自身的头部(collectedAt)获取 asOf,因此一份一个月前的清单会按照其收集时进行评估,而不会被悄悄地按今天重新评判。之后重新运行同样的评估会得到同样的结果。
探针是编译进来的,而不是 YAML DSL
Section titled “探针是编译进来的,而不是 YAML DSL”各厂商的 API 差异之大,使得声明式的探针语言只在遇到其设计范围之外的第一个厂商之前看起来是通用的。每个探针是一个 Go 文件,并在注册表中有一个明确的条目——用代码来编码厂商知识,意味着 if
就只是一个 if,可读且可调试,而不是用 YAML 重新表达的条件判断。
这意味着添加一个新产品需要发布新版本,而不仅仅是修改您自己的配置。应急出口是:product: generic
直接从您的配置中接受一个解析器规格(json / xml / header / plaintext / regex),用于那些永远不会有专用探针的内部系统——请参阅配置。通用探针的表达能力被有意冻结:没有条件判断、没有循环、没有链式请求。需要其中任何一项的目标,都需要一个用 Go 编写的真正探针。
HTTPS 优先,默认绝不以明文发送凭据
Section titled “HTTPS 优先,默认绝不以明文发送凭据”对于地址中没有显式 https:///http:// 的目标,协议解析方式为:先尝试 https,再回退到 http,两种情况下都会发出警告。enodia 从不先尝试 http——第一个请求就已经以明文携带了凭据,之后再重定向到 https 也无法撤回已发送的内容。附带凭据的 http:// 目标会被视为硬错误,除非在该特定服务上设置了 allow_insecure_transport: true。
没有按请求轮询的内置 Web 服务器
Section titled “没有按请求轮询的内置 Web 服务器”enodia serve 和 export --format html 都显示最近一次已完成的快照——两者都不会因为收到请求而触发新的收集。每次点击都会轮询整个服务器群的刷新按钮,等于对您自己的生产环境发起了一场自找的拒绝服务攻击。收集按计划运行(serve --interval,或由 cron/systemd 定时器重新生成 HTML 导出);
HTTP 只会读取上一次成功周期所生成的内容。