baseline-rb 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +29 -0
- data/README-zh.md +50 -4
- data/README.md +59 -4
- data/docs/architecture-zh.md +8 -8
- data/lib/baseline/acl.rb +6 -6
- data/lib/baseline/audit.rb +34 -5
- data/lib/baseline/cisco/parser.rb +163 -89
- data/lib/baseline/comware/parser.rb +101 -57
- data/lib/baseline/evaluator.rb +31 -13
- data/lib/baseline/{configuration.rb → evidence.rb} +6 -6
- data/lib/baseline/{facts.rb → fact_builder.rb} +78 -53
- data/lib/baseline/h3c/parser.rb +7 -5
- data/lib/baseline/hillstone/document.rb +2 -2
- data/lib/baseline/hillstone/parser.rb +126 -73
- data/lib/baseline/huawei/parser.rb +15 -13
- data/lib/baseline/{quoted_document.rb → multiline_document.rb} +1 -1
- data/lib/baseline/palo_alto/command_index.rb +48 -0
- data/lib/baseline/palo_alto/document.rb +3 -3
- data/lib/baseline/palo_alto/parser.rb +116 -102
- data/lib/baseline/parser.rb +139 -34
- data/lib/baseline/policy.rb +2 -2
- data/lib/baseline/report.rb +2 -1
- data/lib/baseline/rule.rb +1 -1
- data/lib/baseline/version.rb +1 -1
- metadata +9 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6a69b4397f4b697acf294fb60e48af3ab3971ab7f17802d1bbaff4b87c6bc265
|
|
4
|
+
data.tar.gz: 965cffbfdf50b85f3c5ad210d7c21f58dedae938c156bc6e673ea468a15085f7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3c1492e3a89e7ae5fe118439a46002f3fa2750973f95c11368844bf044efd91bebfc24fd6c81e67441f4a12abbeaf6e0e22721e366090499e36e0ed75bea4042
|
|
7
|
+
data.tar.gz: f362962731008df44b80e3116fb8a0e55019d2aa775f2a2560f0255345775848dbabe737bf8c46d50903fc7afa9ac09e5a008a5f722eb5e700ea02c40caf9ba4
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,35 @@
|
|
|
2
2
|
|
|
3
3
|
Changes to the public contract are recorded here. Versions follow Semantic Versioning.
|
|
4
4
|
|
|
5
|
+
## 0.3.0 (2026-10-18)
|
|
6
|
+
|
|
7
|
+
- Breaking: rename mutable fact assembly to `FactBuilder`, immutable parsed snapshots to `Evidence`, multiline quoted-value documents to `MultilineDocument`, and the PAN-OS prefix lookup to `CommandIndex#matching_prefix`.
|
|
8
|
+
- Name parser pipeline actions `parse_*`, fact/diagnostic mutations `record_*`, regular-expression providers `*_pattern`, and policy branch selection `resolve_with_path`; rename IPv4 range/CIDR conversions to describe their results. Update require paths and callers without compatibility aliases.
|
|
9
|
+
|
|
10
|
+
- Reject malformed ACL `host` operands rather than interpreting them as unrestricted addresses in ordered deny rules.
|
|
11
|
+
- Require explicit fact capability declarations so new policy rules do not automatically advertise vendor support.
|
|
12
|
+
- Resolve the final PAN-OS management-profile binding per interface scope while retaining other interfaces independently.
|
|
13
|
+
|
|
14
|
+
- Standardize vendor NTP, Syslog, and SNMP hooks under a shared pipeline; keep syntax extraction in the vendor adapters and permission reduction in `FactBuilder`.
|
|
15
|
+
- Add Hillstone SNMPv3 group permissions, user authentication/privacy, safe credential metadata, and IPv4 polling-source evaluation.
|
|
16
|
+
- Expose immutable per-rule vendor implementation coverage via `Audit.capabilities(platform:)`, shared platform normalization, and explicit unknown diagnostics for unmodeled capabilities.
|
|
17
|
+
|
|
18
|
+
- Declare the `ctx_parser` runtime dependency without a version constraint; application lockfiles control reproducible installation versions.
|
|
19
|
+
|
|
20
|
+
- Validate Cisco/Comware server addresses before counting NTP, Syslog, or TACACS endpoints; malformed endpoint declarations remain unknown and supported endpoint cancellations remove prior entries.
|
|
21
|
+
- Preserve VRF identity while reducing supported NTP declarations and validate their full option lists; keep unsupported or malformed options unknown. Reduce IOS logging aliases in source order and discard removed TACACS host keys.
|
|
22
|
+
- Evaluate modeled management, source-interface, and AAA declarations in configuration order, preserving cancellations and malformed replacements instead of falling back to older values. Reject malformed final hostname declarations across all platforms.
|
|
23
|
+
- Diagnose multi-line PAN-OS interface bindings and handle malformed externally supplied credential facts without raising internal exceptions.
|
|
24
|
+
- Let `CtxParser::Result` own snapshot freezing and copying, avoiding a duplicate traversal of facts and diagnostic trees.
|
|
25
|
+
|
|
26
|
+
- Keep incomplete and unsupported SNMP group declarations unknown instead of proving absent write permission; reject malformed Cisco version tokens without raising an internal exception.
|
|
27
|
+
- Build each `FactBuilder#build` snapshot independently; replaced management/SNMP evidence, resolved group references, and source-free values no longer retain stale derived facts, diagnostics, or source lines.
|
|
28
|
+
- Index PAN-OS statements by decoded token prefixes with bounded depth, and reuse network deviations during evaluation, avoiding repeated full-export scans, excessive indexing of malformed tails, and duplicate network comparisons.
|
|
29
|
+
|
|
30
|
+
## 0.2.1 (2026-10-17)
|
|
31
|
+
|
|
32
|
+
- Reject duplicate normalized context keys before policy selection; preserve source lines and cursor captures for scalar NTP and Syslog configuration facts.
|
|
33
|
+
|
|
5
34
|
## 0.2.0 (2026-10-17)
|
|
6
35
|
|
|
7
36
|
### Changed
|
data/README-zh.md
CHANGED
|
@@ -21,7 +21,7 @@ gem "baseline-rb", require: "baseline"
|
|
|
21
21
|
|
|
22
22
|
然后执行 `bundle install`;也可直接执行 `gem install baseline-rb`。Ruby 加载入口为 `baseline`,公开命名空间为 `Baseline`;gem 包名与 Ruby 命名空间分别维护。
|
|
23
23
|
|
|
24
|
-
模块运行依赖:[`ctx_parser`](https://github.com/gatework/ctx_parser)。 gemspec
|
|
24
|
+
模块运行依赖:[`ctx_parser`](https://github.com/gatework/ctx_parser)。 gemspec 声明 `ctx_parser` 依赖但不限制版本,以使用共享配置解析 API;应用应提交自己的 `Gemfile.lock`,保持部署可复现。使用本库不需要启动 Rails 或配置兄弟模块的本地路径。
|
|
25
25
|
|
|
26
26
|
发布产物和校验值见 [GitHub Releases](https://github.com/gatework/baseline-rb/releases),已发布版本以 [RubyGems](https://rubygems.org/gems/baseline-rb) 为准。
|
|
27
27
|
|
|
@@ -67,14 +67,60 @@ puts report.to_text
|
|
|
67
67
|
|
|
68
68
|
## 领域术语
|
|
69
69
|
|
|
70
|
-
`
|
|
70
|
+
`FactBuilder` 汇总配置证据,`Policy` 提供批准值,`Evaluator` 生成合规判定。`Acl#permitted_source_networks` 按有序规则、协议和目标端口计算允许的 IPv4 来源网段:`nil` 表示证据未解决,`[]` 表示没有允许来源。`FactBuilder#record_credential` 记录安全的凭据属性。部分证据可以证明确定违规,但不能证明合规。
|
|
71
71
|
|
|
72
72
|
厂商代码按命名空间组织:`Baseline::Hillstone::Parser` 和 `Baseline::Hillstone::Document` 同放在 `baseline/hillstone/`;Palo Alto 使用相同布局。六个平台解析器复用 `Baseline::Parser`、`Comware::Parser` 或 `Cisco::Parser`。单个平台可用 `require "baseline/hillstone/parser"` 独立加载;完整评估入口仍为 `require "baseline"`。
|
|
73
73
|
|
|
74
|
-
解析辅助方法直接描述提取意图:`matching_blocks`、`configured_values`、`last_configured_value`、`configured_state` 和 `
|
|
74
|
+
解析辅助方法直接描述提取意图:`matching_blocks`、`configured_values`、`last_configured_value`、`configured_state` 和 `parse_acl_source_network`。SNMP 写权限规则统一为 `snmp.write_enabled`,禁止写入时配置 `expected: false`。自定义策略需迁移旧键 `snmp.read_only`;旧类名与规则键不保留兼容别名。
|
|
75
|
+
|
|
76
|
+
上下文允许字符串或符号键,但归一化后重复的键会抛出 `ArgumentError`,避免依赖插入顺序选择设备策略。
|
|
75
77
|
|
|
76
78
|
`complete: true` 表示调用方提供了完整快照。报告通过 `input_complete` 保留这项声明,与解析状态分别记录。不完整的有序 ACL 可能缺少更早的 deny,因此不能仅根据已见 permit 判断来源越界,此时保持 `unknown`。
|
|
77
79
|
|
|
80
|
+
## 跨厂商能力契约
|
|
81
|
+
|
|
82
|
+
各适配器共用管理、NTP、Syslog、SNMP、认证处理流程,输出统一的 `Evidence` / `Report`。厂商语法留在对应命名空间,跨命令权限归约由 `FactBuilder` 负责,`Evaluator` 不按厂商分支。共享 Cisco、Comware 实现时,只合并语义相同的部分。
|
|
83
|
+
|
|
84
|
+
`Baseline::Audit.capabilities(platform: :stoneos)` 返回包含全部公开规则的深冻结 Hash;各项提供 `fact`、`status`(`supported` / `partial` / `unsupported`)与 `reason`。新增事实必须显式声明适配器能力,仅新增策略规则不会自动标记为已支持。查询与审计使用相同别名,`Audit.normalize_platform(name)` 可获取规范名称。支持状态表示已实现的证据提取范围,不代表当前配置证据充分、设备实际可达或覆盖所有固件版本。
|
|
85
|
+
|
|
86
|
+
| 能力 | H3C / Huawei | IOS / NX-OS | Hillstone | Palo Alto |
|
|
87
|
+
| --- | --- | --- | --- | --- |
|
|
88
|
+
| NTP 服务器、认证、源接口 | 支持 | 支持 | 支持 | 支持 |
|
|
89
|
+
| Syslog 服务器、源接口 | 支持 | 支持 | 支持 | 支持 |
|
|
90
|
+
| SNMP 版本、写权限、v3 认证与加密 | 支持 | 支持 | 支持 | 支持 |
|
|
91
|
+
| IPv4 管理与 SNMP 来源范围 | 支持 | 支持 | 支持 | 支持 |
|
|
92
|
+
| SSH 启用状态 | 支持 | 支持 | 支持 | 支持 |
|
|
93
|
+
| 显式 SSH 版本、VTY 检查 | 支持 | 支持 | 尚未建模 | 尚未建模 |
|
|
94
|
+
| 凭据存储、可观察口令强度 | 支持 | 支持 | 支持 | 支持 |
|
|
95
|
+
| TACACS 服务器、密钥、登录 | 支持 | 支持 | 支持 | 支持 |
|
|
96
|
+
| TACACS 授权 | 支持 | 支持 | 支持 | 尚未建模 |
|
|
97
|
+
| TACACS 计费 | 支持 | 支持 | 尚未建模 | 尚未建模 |
|
|
98
|
+
| 非必要服务状态 | 支持 | 支持 | 部分 | 部分 |
|
|
99
|
+
|
|
100
|
+
Hillstone 服务状态覆盖 Telnet、HTTP、HTTPS、FTP,Palo Alto 覆盖 Telnet、HTTP、HTTPS;缺失状态保留未知。原生防火墙端点没有路由器式 VTY 事实,相关规则仍返回 `unknown` 和 `unsupported_capability` 诊断,不会自动排除或当作通过。
|
|
101
|
+
|
|
102
|
+
Hillstone SNMPv3 根据 [StoneOS CLI 手册](https://kb.hillstonenet.com/en/wp-content/uploads/2017/11/StoneOS_CLI_User_Guide_Complete_Book_5.5R5-1.pdf) 的正式组、用户语法解析 `auth-protocol`、`enc-protocol`、组写视图与 IPv4 远端主机。未知算法、IPv6 远端用户、撤销命令、无法解析的组及缺少用户证据的 v3 主机保持未知;组的安全级别要求不能替代用户实际配置的密钥证据。
|
|
103
|
+
|
|
104
|
+
## 命名与对象职责
|
|
105
|
+
|
|
106
|
+
类名表达对象生命周期,方法名表达返回结果或副作用。`FactBuilder` 累积证据,`build` 生成独立的解析结果;`Evidence` 持有用于判定的不可变证据快照;`MultilineDocument` 隔离跨行引号值;`PaloAlto::CommandIndex` 按词元前缀检索配置命令。厂商 `Parser` 与直接对应设备命令的名称保留其领域含义。
|
|
107
|
+
|
|
108
|
+
| 原名称 | 新名称 | 职责 |
|
|
109
|
+
| --- | --- | --- |
|
|
110
|
+
| `Facts`、`baseline/facts` | `FactBuilder`、`baseline/fact_builder` | 可变事实构建 |
|
|
111
|
+
| `Configuration`、`baseline/configuration` | `Evidence`、`baseline/evidence` | 不可变证据快照 |
|
|
112
|
+
| `QuotedDocument`、`baseline/quoted_document` | `MultilineDocument`、`baseline/multiline_document` | 跨行引号值的命令边界 |
|
|
113
|
+
| `PaloAlto::Statements#at` | `PaloAlto::CommandIndex#matching_prefix` | 返回前缀匹配的全部语句 |
|
|
114
|
+
| `Facts#result` | `FactBuilder#build` | 生成新的结果快照 |
|
|
115
|
+
| `Facts#record` / `unknown` | `FactBuilder#record_fact` / `record_unknown_fact` | 记录事实或诊断 |
|
|
116
|
+
| `Facts#management` / `snmp` | `FactBuilder#record_management_access` / `record_snmp_access` | 更新管理或 SNMP 证据 |
|
|
117
|
+
| `Facts#direct_acl` | `FactBuilder#record_source_restriction` | 记录原生来源范围,不要求命名 ACL |
|
|
118
|
+
| `Configuration#value` / `known?` / `scope_known?` | `Evidence#fact` / `fact_known?` / `applicability_fact_known?` | 查询事实及其证据可用性 |
|
|
119
|
+
| `Policy#resolve_with_source` | `Policy#resolve_with_path` | 返回批准值、原因与策略分支路径 |
|
|
120
|
+
| `Acl.address_range` / `network_prefixes` | `Acl.ipv4_range` / `cidrs_from_ranges` | 转换 IPv4 CIDR 与整数区间 |
|
|
121
|
+
|
|
122
|
+
内部解析流程用 `parse_*`,事实和诊断写入用 `record_*`,正则提供方法用 `*_pattern`。三态结果用 `*_state`,避免冒充布尔谓词;解析、校验方法说明解析对象。`Policy`、`Rule`、`Acl`、`Credential`、`Evaluator`、`Report`、`to_h`、`inspect` 等已有清晰含义的名称继续使用。旧名称和旧加载路径不保留别名,规则 ID、事实键和报告 JSON 沿用业务术语。
|
|
123
|
+
|
|
78
124
|
## 开发与测试
|
|
79
125
|
|
|
80
126
|
共享类按实际职责命名,平台信息放在命名空间中。直接对应设备命令的解析器保留文件名和类名。
|
|
@@ -88,7 +134,7 @@ bundle exec rake build
|
|
|
88
134
|
|
|
89
135
|
`bundle exec rake` 执行 RSpec、RuboCop 及离线示例。测试放在 `spec/`,沿用项目 RSpec 约定;样例采用合成或脱敏证据。新增解析格式时补充成功、不完整、不支持及非法输入回归。离线测试不代表所有设备版本均通过实机验证。
|
|
90
136
|
|
|
91
|
-
运行 `bundle exec ruby -Ilib script/benchmark.rb` 可测量合成 ACL
|
|
137
|
+
运行 `bundle exec ruby -Ilib script/benchmark.rb` 可测量合成 ACL 覆盖比较、凭据来源行查询、越界来源报告、PAN-OS 多账号解析及事实快照构建;脚本报告三次运行的中位数,请在同一机器和 Ruby 版本下比较不同修订。
|
|
92
138
|
|
|
93
139
|
使用声明的最低 Ruby 版本检查兼容性。方法用途统一使用简明中文注释;复杂实现还需说明业务规则、实现思路及关键分支。保持公开返回值与错误契约。真实回显和凭据不可进入示例、fixture、日志或发布包。
|
|
94
140
|
|
data/README.md
CHANGED
|
@@ -21,7 +21,7 @@ gem "baseline-rb", require: "baseline"
|
|
|
21
21
|
|
|
22
22
|
Then run `bundle install`, or install directly with `gem install baseline-rb`. The require path is `baseline` and the public namespace is `Baseline`; package names and Ruby namespaces are intentionally separate.
|
|
23
23
|
|
|
24
|
-
Internal runtime dependencies: [`ctx_parser`](https://github.com/gatework/ctx_parser). The gemspec
|
|
24
|
+
Internal runtime dependencies: [`ctx_parser`](https://github.com/gatework/ctx_parser). The gemspec declares `ctx_parser` without a version constraint for the shared configuration API. Applications should commit their own `Gemfile.lock` to make deployments reproducible. No Rails boot or sibling checkout paths are required.
|
|
25
25
|
|
|
26
26
|
Release artifacts and checksums are available from [GitHub Releases](https://github.com/gatework/baseline-rb/releases). Check [RubyGems](https://rubygems.org/gems/baseline-rb) for published versions.
|
|
27
27
|
|
|
@@ -67,14 +67,69 @@ Detailed vendor behavior, historical validation notes, and Motor-only integratio
|
|
|
67
67
|
|
|
68
68
|
## Domain vocabulary
|
|
69
69
|
|
|
70
|
-
`
|
|
70
|
+
`FactBuilder` assembles configuration evidence; `Policy` supplies approved values; `Evaluator` produces compliance findings. `Acl#permitted_source_networks` returns the IPv4 networks permitted by ordered rules for a protocol and destination port: `nil` means unresolved evidence, while `[]` means no permitted sources. `FactBuilder#record_credential` records safe credential attributes. Partial evidence may establish a conclusive violation, but cannot establish compliance.
|
|
71
71
|
|
|
72
72
|
Vendor-specific code lives in a vendor namespace: `Baseline::Hillstone::Parser` and `Baseline::Hillstone::Document` reside in `baseline/hillstone/`; Palo Alto uses the same layout. The six platform parsers inherit shared behavior from `Baseline::Parser`, `Comware::Parser`, or `Cisco::Parser`. Load only one platform with `require "baseline/hillstone/parser"`, or load the assessment API with `require "baseline"`.
|
|
73
73
|
|
|
74
|
-
Parser helpers describe the evidence they extract: `matching_blocks`, `configured_values`, `last_configured_value`, `configured_state`, and `
|
|
74
|
+
Parser helpers describe the evidence they extract: `matching_blocks`, `configured_values`, `last_configured_value`, `configured_state`, and `parse_acl_source_network`. SNMP write permission uses the policy key `snmp.write_enabled` (`expected: false` to prohibit writes). Update custom policies that used `snmp.read_only`; old class names and rule keys have no compatibility aliases.
|
|
75
|
+
|
|
76
|
+
Context accepts string or symbol keys, but rejects duplicate keys after normalization with `ArgumentError` rather than selecting a device policy by insertion order.
|
|
75
77
|
|
|
76
78
|
`complete: true` asserts that the caller supplied the entire snapshot. Reports retain that assertion as `input_complete`, separately from parser status. A partial ordered ACL cannot prove an out-of-policy source: an unseen earlier deny may change its meaning, so the finding stays `unknown`.
|
|
77
79
|
|
|
80
|
+
## Shared vendor capabilities
|
|
81
|
+
|
|
82
|
+
All adapters follow the same management, NTP, Syslog, SNMP, and authentication pipeline and return the same `Evidence` / `Report` contracts. Cisco and Comware families share syntax where it is equivalent; native firewall endpoints use their own syntax and produce the same management-source facts. `FactBuilder` owns cross-command permission and evidence reduction; `Evaluator` does not branch on vendor.
|
|
83
|
+
|
|
84
|
+
Query implementation coverage without supplying a device configuration:
|
|
85
|
+
|
|
86
|
+
```ruby
|
|
87
|
+
Baseline::Audit.capabilities(platform: :stoneos)["snmp.auth_priv"]
|
|
88
|
+
# => { fact: "snmp.v3_auth_priv", status: :supported, reason: nil }
|
|
89
|
+
Baseline::Audit.capabilities(platform: :panos)["tacacs.accounting"]
|
|
90
|
+
# => { fact: "tacacs.accounting", status: :unsupported, reason: :platform_semantics_unresolved }
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The deeply frozen result contains every public rule. New facts require explicit adapter capability declarations; adding a policy rule alone does not advertise implementation support. Status is `supported`, `partial`, or `unsupported`; it describes implemented evidence extraction, not runtime availability or support for every vendor release. The same platform aliases apply to queries and audits. `Audit.normalize_platform(name)` exposes the canonical platform name.
|
|
94
|
+
|
|
95
|
+
| Capability | H3C / Huawei | IOS / NX-OS | Hillstone | Palo Alto |
|
|
96
|
+
| --- | --- | --- | --- | --- |
|
|
97
|
+
| NTP servers, authentication, source | Supported | Supported | Supported | Supported |
|
|
98
|
+
| Syslog servers and source | Supported | Supported | Supported | Supported |
|
|
99
|
+
| SNMP versions, writes, v3 auth/privacy | Supported | Supported | Supported | Supported |
|
|
100
|
+
| IPv4 management / SNMP source ranges | Supported | Supported | Supported | Supported |
|
|
101
|
+
| SSH enabled | Supported | Supported | Supported | Supported |
|
|
102
|
+
| Explicit SSH versions and VTY checks | Supported | Supported | Unmodeled | Unmodeled |
|
|
103
|
+
| Credential storage and observable strength | Supported | Supported | Supported | Supported |
|
|
104
|
+
| TACACS servers, keys, login | Supported | Supported | Supported | Supported |
|
|
105
|
+
| TACACS authorization | Supported | Supported | Supported | Unmodeled |
|
|
106
|
+
| TACACS accounting | Supported | Supported | Unmodeled | Unmodeled |
|
|
107
|
+
| Disabled service set | Supported | Supported | Partial | Partial |
|
|
108
|
+
|
|
109
|
+
Hillstone service state covers Telnet, HTTP, HTTPS, and FTP; Palo Alto covers Telnet, HTTP, and HTTPS. Missing service states remain unknown. Native firewall endpoints do not provide router-style VTY facts. These checks are retained as `unknown` with `unsupported_capability` diagnostics, rather than excluded or treated as compliance. Protocol reachability and opaque password strength remain unobservable across all vendors.
|
|
110
|
+
|
|
111
|
+
Hillstone v3 extraction follows the formal group/user syntax in the [StoneOS CLI guide](https://kb.hillstonenet.com/en/wp-content/uploads/2017/11/StoneOS_CLI_User_Guide_Complete_Book_5.5R5-1.pdf): `auth-protocol` and `enc-protocol` user options, explicit group write views, and IPv4 remote hosts. Unsupported algorithms, IPv6 remote users, removals, unresolved groups, or v3 host entries without user evidence remain unknown. User security comes from configured user evidence, not the group's required security level.
|
|
112
|
+
|
|
113
|
+
## Naming and object responsibilities
|
|
114
|
+
|
|
115
|
+
Names identify the object lifecycle and the method's result or side effect. `FactBuilder` accumulates evidence and `build` returns an independent parser result; `Evidence` owns the immutable snapshot used for evaluation; `MultilineDocument` isolates multiline quoted values; `PaloAlto::CommandIndex` searches commands by token prefix. Vendor `Parser` and command-mapped names retain their domain meaning.
|
|
116
|
+
|
|
117
|
+
| Previous name | Current name | Meaning |
|
|
118
|
+
| --- | --- | --- |
|
|
119
|
+
| `Facts`, `baseline/facts` | `FactBuilder`, `baseline/fact_builder` | Mutable fact assembly |
|
|
120
|
+
| `Configuration`, `baseline/configuration` | `Evidence`, `baseline/evidence` | Immutable evidence snapshot |
|
|
121
|
+
| `QuotedDocument`, `baseline/quoted_document` | `MultilineDocument`, `baseline/multiline_document` | Multiline quoted-value boundaries |
|
|
122
|
+
| `PaloAlto::Statements#at` | `PaloAlto::CommandIndex#matching_prefix` | All statements with a token prefix |
|
|
123
|
+
| `Facts#result` | `FactBuilder#build` | Build a fresh result snapshot |
|
|
124
|
+
| `Facts#record` / `unknown` | `FactBuilder#record_fact` / `record_unknown_fact` | Record facts or diagnostics |
|
|
125
|
+
| `Facts#management` / `snmp` | `FactBuilder#record_management_access` / `record_snmp_access` | Update management or SNMP evidence |
|
|
126
|
+
| `Facts#direct_acl` | `FactBuilder#record_source_restriction` | Record native source ranges, without a named ACL |
|
|
127
|
+
| `Configuration#value` / `known?` / `scope_known?` | `Evidence#fact` / `fact_known?` / `applicability_fact_known?` | Query a fact and its evidence availability |
|
|
128
|
+
| `Policy#resolve_with_source` | `Policy#resolve_with_path` | Return the value, reason, and policy branch path |
|
|
129
|
+
| `Acl.address_range` / `network_prefixes` | `Acl.ipv4_range` / `cidrs_from_ranges` | Convert IPv4 CIDRs and integer ranges |
|
|
130
|
+
|
|
131
|
+
Internal pipeline steps use `parse_*`; writers use `record_*`; regex providers use `*_pattern`. A tristate result uses `*_state` rather than a boolean predicate, and parsing/validation helpers name what they parse. Plain established names such as `Policy`, `Rule`, `Acl`, `Credential`, `Evaluator`, `Report`, `to_h`, and `inspect` remain appropriate. Old names and require paths have no aliases. Rule IDs, fact keys, and report JSON retain their business vocabulary.
|
|
132
|
+
|
|
78
133
|
## Development and tests
|
|
79
134
|
|
|
80
135
|
Name shared classes by their responsibility and use the namespace for platform context. Preserve filenames and class names that directly match device commands.
|
|
@@ -88,7 +143,7 @@ bundle exec rake build
|
|
|
88
143
|
|
|
89
144
|
`bundle exec rake` runs RSpec, RuboCop, and the offline examples. Tests live in `spec/`, following the existing project's RSpec convention; fixtures use synthetic or sanitized evidence. Add regression cases for successful, incomplete, unsupported, and malformed inputs when extending a parser. Offline tests do not certify all device versions or replace live integration checks.
|
|
90
145
|
|
|
91
|
-
Run `bundle exec ruby -Ilib script/benchmark.rb` for synthetic network-coverage, credential-lookup,
|
|
146
|
+
Run `bundle exec ruby -Ilib script/benchmark.rb` for synthetic network-coverage, credential-lookup, rejected-source report, PAN-OS account parsing, and fact snapshot timings. It reports the median of three runs at two input sizes; compare revisions on the same runtime and machine.
|
|
92
147
|
|
|
93
148
|
Use the declared minimum Ruby version for compatibility checks. Document source methods and non-obvious business logic in concise Chinese, preserve public return/error contracts, and never add raw device captures or credentials to examples, fixtures, logs, or release archives.
|
|
94
149
|
|
data/docs/architecture-zh.md
CHANGED
|
@@ -11,10 +11,10 @@
|
|
|
11
11
|
```mermaid
|
|
12
12
|
flowchart LR
|
|
13
13
|
Text[运行配置文本] --> Parser[厂商 Parser]
|
|
14
|
-
Parser -->
|
|
15
|
-
|
|
14
|
+
Parser --> FactBuilder[FactBuilder / Acl / Credential]
|
|
15
|
+
FactBuilder --> Evidence
|
|
16
16
|
YAML[policy.yml] --> Policy[Policy / Rule]
|
|
17
|
-
|
|
17
|
+
Evidence --> Evaluator
|
|
18
18
|
Policy --> Evaluator
|
|
19
19
|
Evaluator --> Report
|
|
20
20
|
Backup[已有加密备份] --> Check[Baseline::Check]
|
|
@@ -31,9 +31,9 @@ flowchart LR
|
|
|
31
31
|
| `Comware::Parser` / `Cisco::Parser` | 分别共享 Comware/VRP 与 IOS/NX-OS 的语法族 |
|
|
32
32
|
| `H3c::Parser` / `Huawei::Parser` / `CiscoIos::Parser` / `CiscoNxos::Parser` / `Hillstone::Parser` / `PaloAlto::Parser` | 厂商差异,不把厂商分支散落到规则求值中 |
|
|
33
33
|
| `Document < CtxParser::Document` | 使用公共游标和缩进树,隔离 banner、接口子配置及不完整输入 |
|
|
34
|
-
| `
|
|
35
|
-
| `
|
|
36
|
-
| `
|
|
34
|
+
| `MultilineDocument` / `Hillstone::Document` / `PaloAlto::Document` | 隔离跨行字符串、证书和 UI 数据,保留厂商命令边界;注释和 banner 不参与字符串扫描 |
|
|
35
|
+
| `FactBuilder` | 每次解析独享的事实集合,归约 VTY、SNMP 组引用、命名 ACL 与原生来源列表、凭据;输出独立的结果快照 |
|
|
36
|
+
| `Evidence` | 不可变事实、输入指纹、完整性和局部解析诊断 |
|
|
37
37
|
| `Acl` | IPv4 地址区间与有序规则,按首次匹配计算允许来源 |
|
|
38
38
|
| `Credential` | 只保留格式、存储类别、明文长度/字符类别/常见弱口令标记 |
|
|
39
39
|
| `Policy` / `Rule::Definition` / `Rule` | YAML 批准值、强类型规则目录、适用范围、比较操作、严重度及选择分支 |
|
|
@@ -43,9 +43,9 @@ flowchart LR
|
|
|
43
43
|
|
|
44
44
|
独立 Ruby 调用只需加载 `baseline`;`Check` 由 Rails 自动加载。持久化使用 `baseline_assessments` 表;纯文本分析不依赖数据库。没有新增外部依赖、HTTP 接口或后台任务。
|
|
45
45
|
|
|
46
|
-
厂商解析器把命令转换为普通 Ruby 值及 `Acl` / `Credential` 对象;`
|
|
46
|
+
厂商解析器把命令转换为普通 Ruby 值及 `Acl` / `Credential` 对象;`FactBuilder` 不读取命令文本,也不操作游标。语法解释成功后由 `CtxParser::Configuration#analyze` 标记当前行,`capture` 关联脱敏数据与来源;未解释的子命令保留原状态。事实中的行号用于判定报告,游标中的捕获用于显式溯源,两者不将原文带入持久化结果。
|
|
47
47
|
|
|
48
|
-
新增厂商时,有相同语法族才继承 `Comware::Parser` 或 `Cisco::Parser`;防火墙直接继承 `Baseline::Parser`,独立解释本机管理语法。新增跨厂商归约逻辑放入 `
|
|
48
|
+
新增厂商时,有相同语法族才继承 `Comware::Parser` 或 `Cisco::Parser`;防火墙直接继承 `Baseline::Parser`,独立解释本机管理语法。新增跨厂商归约逻辑放入 `FactBuilder` 或已有领域对象,批准值仍声明在策略 YAML 中。不要在厂商类中重复维护事实字典、诊断列表或引用解析状态。`FactBuilder#record_source_restriction` 对原生允许来源统一归一化,区分 `nil`(未确认)、`[]`(明确没有允许来源)与 `0.0.0.0/0`(全网);`mark_incomplete!` 使破损声明无法证明合规的缺省状态。
|
|
49
49
|
|
|
50
50
|
## 事实与检查
|
|
51
51
|
|
data/lib/baseline/acl.rb
CHANGED
|
@@ -26,7 +26,7 @@ module Baseline
|
|
|
26
26
|
end
|
|
27
27
|
true
|
|
28
28
|
end
|
|
29
|
-
self.class.
|
|
29
|
+
self.class.cidrs_from_ranges(permitted_ranges(selected))
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
# 返回公开的数据结构,并保留状态与诊断信息。
|
|
@@ -50,7 +50,7 @@ module Baseline
|
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
# 将网络前缀转换为包含首尾地址的整数区间。
|
|
53
|
-
def self.
|
|
53
|
+
def self.ipv4_range(cidr)
|
|
54
54
|
ip = IPAddr.new(cidr)
|
|
55
55
|
raise ArgumentError, "IPv4 ACL required" unless ip.ipv4?
|
|
56
56
|
[ ip.to_range.first.to_i, ip.to_range.last.to_i ]
|
|
@@ -71,8 +71,8 @@ module Baseline
|
|
|
71
71
|
|
|
72
72
|
# 批准区间只解析、合并一次;实际网段按起点顺序与其线性比较。
|
|
73
73
|
def self.each_network_coverage(actual, expected)
|
|
74
|
-
approved = merge_ranges(expected.map { |cidr|
|
|
75
|
-
networks = actual.each_with_index.map { |cidr, index| [
|
|
74
|
+
approved = merge_ranges(expected.map { |cidr| ipv4_range(cidr) })
|
|
75
|
+
networks = actual.each_with_index.map { |cidr, index| [ ipv4_range(cidr), index ] }.sort_by(&:first)
|
|
76
76
|
approved_index = 0
|
|
77
77
|
networks.each do |(first, last), source_index|
|
|
78
78
|
approved_index += 1 while approved_index < approved.size && approved[approved_index].last < first
|
|
@@ -83,7 +83,7 @@ module Baseline
|
|
|
83
83
|
private_class_method :each_network_coverage
|
|
84
84
|
|
|
85
85
|
# 将地址区间转换为数量最少的网络前缀。
|
|
86
|
-
def self.
|
|
86
|
+
def self.cidrs_from_ranges(ranges)
|
|
87
87
|
merge_ranges(ranges).flat_map do |first, last|
|
|
88
88
|
networks = []
|
|
89
89
|
while first <= last
|
|
@@ -114,7 +114,7 @@ module Baseline
|
|
|
114
114
|
def permitted_ranges(selected)
|
|
115
115
|
boundaries = Hash.new { |entries, address| entries[address] = [] }
|
|
116
116
|
selected.each_with_index do |rule, priority|
|
|
117
|
-
first, last = self.class.
|
|
117
|
+
first, last = self.class.ipv4_range(rule.fetch(:source))
|
|
118
118
|
boundaries[first] << [ priority, true ]
|
|
119
119
|
# 将闭区间终点转为下一地址的失效事件,统一处理相邻和重叠网段。
|
|
120
120
|
boundaries[last + 1] << [ priority, false ]
|
data/lib/baseline/audit.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative "
|
|
3
|
+
require_relative "evidence"
|
|
4
4
|
require_relative "evaluator"
|
|
5
5
|
require_relative "h3c/parser"
|
|
6
6
|
require_relative "huawei/parser"
|
|
@@ -22,6 +22,36 @@ module Baseline
|
|
|
22
22
|
"nxos" => "cisco_nxos", "nx_os" => "cisco_nxos", "stoneos" => "hillstone", "stone_os" => "hillstone",
|
|
23
23
|
"paloalto" => "palo_alto", "panos" => "palo_alto", "pan_os" => "palo_alto" }.freeze
|
|
24
24
|
|
|
25
|
+
# 将同一规则目录映射到各厂商的实现覆盖范围;supported 不代表当前证据已知。
|
|
26
|
+
def self.capabilities(platform:)
|
|
27
|
+
parser = PARSERS[normalize_platform(platform)]
|
|
28
|
+
CtxParser::Immutable.copy(Rule::DEFINITIONS.to_h do |id, definition|
|
|
29
|
+
unsupported = parser && parser::UNSUPPORTED_FACTS[definition.fact]
|
|
30
|
+
partial = parser && parser::PARTIAL_FACTS[definition.fact]
|
|
31
|
+
status, reason = if !parser
|
|
32
|
+
[ :unsupported, :unsupported_platform ]
|
|
33
|
+
elsif unsupported
|
|
34
|
+
[ :unsupported, unsupported ]
|
|
35
|
+
elsif partial
|
|
36
|
+
[ :partial, partial ]
|
|
37
|
+
elsif parser::SUPPORTED_FACTS.include?(definition.fact)
|
|
38
|
+
[ :supported, nil ]
|
|
39
|
+
else
|
|
40
|
+
[ :unsupported, :capability_unmodeled ]
|
|
41
|
+
end
|
|
42
|
+
[ id, { fact: definition.fact, status: status, reason: reason } ]
|
|
43
|
+
end)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# 能力查询与实际解析共用平台别名归一化,避免两条入口选择不同适配器。
|
|
47
|
+
def self.normalize_platform(platform)
|
|
48
|
+
unless platform.is_a?(String) || platform.is_a?(Symbol)
|
|
49
|
+
raise ArgumentError, "A platform name is required"
|
|
50
|
+
end
|
|
51
|
+
name = platform.to_s.strip.downcase.tr("-", "_")
|
|
52
|
+
ALIASES.fetch(name, name)
|
|
53
|
+
end
|
|
54
|
+
|
|
25
55
|
# 绑定配置解析与基线评估使用的策略。
|
|
26
56
|
def initialize(policy:)
|
|
27
57
|
@evaluator = Evaluator.new(policy: policy)
|
|
@@ -32,13 +62,12 @@ module Baseline
|
|
|
32
62
|
unless configuration.is_a?(String) && (platform.is_a?(String) || platform.is_a?(Symbol)) && [ true, false ].include?(complete)
|
|
33
63
|
raise ArgumentError, "Configuration text, platform and boolean completeness are required"
|
|
34
64
|
end
|
|
35
|
-
name =
|
|
36
|
-
name = ALIASES.fetch(name, name)
|
|
65
|
+
name = self.class.normalize_platform(platform)
|
|
37
66
|
parser = PARSERS[name]
|
|
38
67
|
result = parser ? parser.parse(configuration, complete: complete) :
|
|
39
68
|
CtxParser::Result.new(status: :unsupported, issues: [ { code: :unsupported_platform } ])
|
|
40
|
-
|
|
41
|
-
@evaluator.call(configuration:
|
|
69
|
+
evidence = Evidence.new(platform: name, sha256: Digest::SHA256.hexdigest(configuration), result: result, input_complete: complete)
|
|
70
|
+
@evaluator.call(configuration: evidence, context: context)
|
|
42
71
|
end
|
|
43
72
|
|
|
44
73
|
# 展示对象身份与状态,避免泄露原始回显或凭据。
|