Skip to content

Commit b4fc433

Browse files
committed
Implement AI review for the oval.template
1 parent ba7756b commit b4fc433

1 file changed

Lines changed: 56 additions & 206 deletions

File tree

shared/templates/grub2_bootloader_argument/oval.template

Lines changed: 56 additions & 206 deletions
Original file line numberDiff line numberDiff line change
@@ -234,208 +234,57 @@
234234
DATA FLOW:
235235
==========
236236

237-
Each object extracts the FULL line (or array) as `subexpression`.
238-
Each state uses `pattern match` to check if `arg=value` appears in that captured text.
239-
All `grub`-location tests share one state; `bootc` has its own (quotes around value).
240-
241-
[VISUAL DIAGRAM: 6 object boxes on the left (one per config file location) with
242-
arrows pointing to 3 state boxes on the right (shared grub state, bootc state,
243-
and kernelopts state). Shows which objects feed which states.]
244-
245-
OBJECTS STATES
246-
═══════ ══════
247-
248-
┌─ /boot/loader/entries/ ──────────────────┐
249-
│ path: /boot/loader/entries/ │
250-
│ filename: ^.*\.conf$ │ ┌─ state_grub2_{ARG}_argument ───────────────┐
251-
│ pattern: ^options (.*)$ │─>│ │
252-
│ filter: exclude *rescue.conf │ │ ^(?:.*\s)?{ARG_NAME_VALUE}(?:\s.*)?$ │
253-
│ (uses_boot_loader_entries) │ │ │
254-
└──────────────────────────────────────────┘ │ Shared by ALL objects in this column. │
255-
│ Pattern match: is `{ARG_NAME_VALUE}` │
256-
┌─ {grub2_boot_path}/grubenv ─────────────┐ │ present as a standalone word in the │
257-
│ filepath: {grub2_boot_path}/grubenv │ │ captured line? The regex enforces │
258-
│ pattern: ^kernelopts=(.*)$ │─>│ whitespace/start/end boundaries. │
259-
│ (uses_kernelopts) │ │ │
260-
└──────────────────────────────────────────┘ │ When `ARG_VARIABLE` is set, the regex │
261-
│ cannot be hardcoded at build time (the │
262-
│ value is not known yet). Instead, `oscap` │
263-
│ assembles it at runtime: an `external_ │
264-
│ variable` receives the value from the │
265-
│ `XCCDF` profile, a `local_variable` uses │
266-
│ `<concat>` to join fixed regex fragments │
267-
│ around that value, and the state references │
268-
│ the resulting string via `var_ref`. │
269-
│ │
270-
┌─ {grub2_boot_path}/grub.cfg ────────────┐ │ │
271-
│ filepath: {grub2_boot_path}/grub.cfg │ │ │
272-
│ pattern: ^.*/vmlinuz.*(root=.*)$ │─>│ │
273-
│ (uses_grub_cfg) │ │ │
274-
└──────────────────────────────────────────┘ │ │
275-
│ │
276-
┌─ /etc/default/grub ─────────────────────┐ │ │
277-
│ filepath: /etc/default/grub │ │ │
278-
│ pattern: ^\s*GRUB_CMDLINE_LINUX= │ │ │
279-
│ "(.*)"$ │─>│ │
280-
│ (all products) │ │ │
281-
│ + same for GRUB_CMDLINE_LINUX_DEFAULT │─>│ │
282-
└──────────────────────────────────────────┘ │ │
283-
│ │
284-
┌─ /etc/default/grub.d/*.cfg ─────────────┐ │ │
285-
│ filepath: /etc/default/grub.d/[^/]+\.cfg│ │ │
286-
│ pattern: ^\s*GRUB_CMDLINE_LINUX= │ │ │
287-
│ "(.*)"$ │─>│ │
288-
│ (Ubuntu — uses_etc_default_grub_d) │ │ │
289-
│ + same for GRUB_CMDLINE_LINUX_DEFAULT │─>│ │
290-
└──────────────────────────────────────────┘ └─────────────────────────────────────────────┘
291-
292-
┌─ /usr/lib/bootc/kargs.d/*.toml ─────────┐ ┌─ state_grub2_{ARG}_usr_lib_bootc_kargs_d ──┐
293-
│ path: /usr/lib/bootc/kargs.d/ │ │ │
294-
│ filename: ^.*\.toml$ │ │ ^.*"{ARG_NAME_VALUE}".*$ │
295-
│ pattern: ^kargs = \[([^\]]+)\]$ │─>│ │
296-
│ (bootable_containers_supported) │ │ Separate state: `TOML` wraps values in │
297-
└──────────────────────────────────────────┘ │ double quotes. │
298-
└─────────────────────────────────────────────┘
299-
300-
(uses_kernelopts) -- additional state used with `state_operator` = `OR`:
301-
┌─ state_grub2_{ARG}_argument_is_kernelopts ─┐
302-
│ ^(?:.*\s)?\$kernelopts(?:\s.*)?$ │
303-
│ │
304-
│ Pattern match: is `$kernelopts` present │
305-
│ as a standalone word in the captured │
306-
│ `options` line from │
307-
│ `/boot/loader/entries/*.conf`? │
308-
│ │
309-
│ The RHEL 8 BLS test applies BOTH │
310-
│ `state_grub2_{ARG}_argument` and this │
311-
│ state with `state_operator` = `OR`: │
312-
│ an entry passes if its `options` line │
313-
│ contains `{ARG_NAME_VALUE}` OR contains │
314-
│ `$kernelopts`. │
315-
│ │
316-
│ Same `uses_kernelopts` flag as the │
317-
│ `{grub2_boot_path}/grubenv` object -- │
318-
│ both exist only on RHEL 8 / OL8. │
319-
└─────────────────────────────────────────────┘
320-
321-
LONG DESCRIPTION (text equivalent of the diagram; same information, no box-drawing):
322-
──────────────────────────────────────────────────────────────────────────────────────
323-
324-
There are 6 objects (data collectors) and 3 states (pass/fail conditions).
325-
326-
OBJECTS -- each extracts a line of text from a config file:
327-
328-
A. `/boot/loader/entries/*.conf` (RHEL 8/9/10, Fedora, OL8/9 — `uses_boot_loader_entries`)
329-
OVAL element: `ind:path` + `ind:filename` with `operation` = `pattern match`
330-
Pattern: `^options (.*)$` -- captures the kernel arg list after `options `.
331-
Filter: excludes filenames matching `*rescue.conf`.
332-
Tested against: `state_grub2_{ARG}_argument`.
333-
334-
B. `{grub2_boot_path}/grubenv` (RHEL 8, OL8 — `uses_kernelopts`)
335-
OVAL element: `ind:filepath`
336-
Pattern: `^kernelopts=(.*)$` -- captures the arg list after `kernelopts=`.
337-
Tested against: `state_grub2_{ARG}_argument`.
338-
339-
C. `{grub2_boot_path}/grub.cfg` (OL7, Ubuntu — `uses_grub_cfg`)
340-
OVAL element: `ind:filepath`
341-
Pattern: `^.*/vmlinuz.*(root=.*)$` -- captures from `root=` to end of line.
342-
Tested against: `state_grub2_{ARG}_argument`.
343-
344-
D. `/etc/default/grub` (all products)
345-
OVAL element: `ind:filepath`
346-
Pattern: `^\s*GRUB_CMDLINE_LINUX="(.*)"$` -- captures contents between quotes.
347-
Same pattern repeated for `GRUB_CMDLINE_LINUX_DEFAULT`.
348-
Tested against: `state_grub2_{ARG}_argument`.
349-
350-
E. `/etc/default/grub.d/*.cfg` (Ubuntu — `uses_etc_default_grub_d`)
351-
OVAL element: `ind:filepath` with `operation` = `pattern match`
352-
Pattern: same as D.
353-
Same pattern repeated for `GRUB_CMDLINE_LINUX_DEFAULT`.
354-
Tested against: `state_grub2_{ARG}_argument`.
355-
356-
F. `/usr/lib/bootc/kargs.d/*.toml` (RHEL 9+, RHEL 10 — `bootable_containers_supported`)
357-
OVAL element: `ind:path` + `ind:filename` with `operation` = `pattern match`
358-
Pattern: `^kargs = \[([^\]]+)\]$` -- captures array contents between brackets.
359-
Tested against: `state_grub2_{ARG}_usr_lib_bootc_kargs_d`.
360-
361-
STATES -- each checks the captured text:
362-
363-
1. `state_grub2_{ARG}_argument` (shared by objects A through E)
364-
Checks if `{ARG_NAME_VALUE}` is present as a standalone word (bounded by
365-
whitespace or start/end of string).
366-
When `ARG_VARIABLE` is set, `oscap` assembles the check at runtime: it reads
367-
the value from the `XCCDF` profile, a `local_variable` concatenates it into
368-
the pattern, and the state references it via `var_ref`.
369-
370-
2. `state_grub2_{ARG}_usr_lib_bootc_kargs_d` (used by object F only)
371-
Checks if `{ARG_NAME_VALUE}` appears double-quoted (as per `TOML` syntax).
372-
373-
3. `state_grub2_{ARG}_argument_is_kernelopts` (RHEL 8, OL8 — `uses_kernelopts`)
374-
Checks if `$kernelopts` is present as a standalone word.
375-
Used ONLY by the RHEL 8 BLS test, which applies both state 1 and state 3
376-
with `state_operator="OR"`: an entry passes if it contains `{ARG_NAME_VALUE}`
377-
OR contains `$kernelopts`.
378-
379-
REGEX SEMANTICS (what each `pattern` captures as `subexpression`):
380-
─────────────────────────────────────────────────────────────────
381-
382-
1. ^options (.*)$
383-
Source: `/boot/loader/entries/*.conf`
384-
Input: `options root=UUID=abc ro quiet audit_backlog_limit=8192`
385-
Capture: `root=UUID=abc ro quiet audit_backlog_limit=8192`
386-
(everything after `options ` -- the full space-separated kernel arg list)
387-
388-
2. ^kernelopts=(.*)$
389-
Source: `{grub2_boot_path}/grubenv`
390-
Input: `kernelopts=root=UUID=abc ro quiet audit_backlog_limit=8192`
391-
Capture: `root=UUID=abc ro quiet audit_backlog_limit=8192`
392-
(everything after `kernelopts=` -- same format as #1)
393-
394-
3. ^.*/vmlinuz.*(root=.*)$
395-
Source: `{grub2_boot_path}/grub.cfg`
396-
Input: ` linux /vmlinuz-5.14 root=UUID=abc ro quiet audit_backlog_limit=8192`
397-
Capture: `root=UUID=abc ro quiet audit_backlog_limit=8192`
398-
NOTE: the second `.*` is greedy -- it backtracks to the LAST `root=` in the line.
399-
Only arguments AT or AFTER `root=` are captured. Arguments before `root=` are invisible.
400-
401-
4. ^\s*GRUB_CMDLINE_LINUX="(.*)"$
402-
Source: `/etc/default/grub` (or `/etc/default/grub.d/*.cfg`)
403-
Input: `GRUB_CMDLINE_LINUX="ro quiet audit_backlog_limit=8192"`
404-
Capture: `ro quiet audit_backlog_limit=8192`
405-
(everything between the double quotes -- the full arg list)
406-
Same pattern for `GRUB_CMDLINE_LINUX_DEFAULT`.
407-
408-
5. ^kargs = \[([^\]]+)\]$
409-
Source: `/usr/lib/bootc/kargs.d/*.toml`
410-
Input: `kargs = ["audit_backlog_limit=8192", "nosmt"]`
411-
Capture: `"audit_backlog_limit=8192", "nosmt"`
412-
(everything between `[` and `]` -- quoted comma-separated values)
413-
414-
STATE MATCHING (applied to the captured `subexpression`):
415-
─────────────────────────────────────────────────────────
416-
417-
state_grub2_{ARG}_argument:
418-
^(?:.*\s)?{ARG_NAME_VALUE}(?:\s.*)?$
419-
Checks if `arg=value` appears as a WHOLE WORD (bounded by start/end or whitespace).
420-
Example: `^(?:.*\s)?audit_backlog_limit=8192(?:\s.*)?$`
421-
Matches: `root=UUID=abc ro quiet audit_backlog_limit=8192` (at end)
422-
Matches: `audit_backlog_limit=8192 ro quiet` (at start)
423-
Matches: `ro audit_backlog_limit=8192 quiet` (in middle)
424-
NO match: `foo_audit_backlog_limit=8192` (not word-bounded on left)
425-
426-
state_grub2_{ARG}_usr_lib_bootc_kargs_d:
427-
^.*"{ARG_NAME_VALUE}".*$
428-
Checks if `"arg=value"` appears anywhere (double-quoted, as per `TOML` syntax).
429-
Example: `^.*"audit_backlog_limit=8192".*$`
430-
Matches: `"audit_backlog_limit=8192", "nosmt"`
431-
432-
state_grub2_{ARG}_argument_is_kernelopts:
433-
^(?:.*\s)?\$kernelopts(?:\s.*)?$
434-
Checks if `$kernelopts` appears as a whole word (same word-boundary logic).
435-
Used by RHEL 8 BLS test with `state_operator="OR"`: entry passes if it has
436-
the arg itself OR contains `$kernelopts` (which gets expanded at boot time).
437-
438-
The `uses_*` flags control which locations are verified per product.
237+
Each object extracts ONLY THE ARGUMENT VALUE via a capturing group.
238+
Each state compares that value using OVAL-native operation and datatype
239+
(equals, greater than or equal, pattern match; string or int).
240+
No local_variable, no concat, no runtime regex assembly.
241+
All grub-location tests share one state; bootc shares it too (value
242+
extracted from TOML quotes in the object pattern).
243+
244+
Exception: the RHEL 8 coverage path still captures the full options
245+
line and checks for the argument name via pattern match (needed to
246+
verify coverage across entries that may use $kernelopts).
247+
248+
OBJECTS -- each extracts the value after {ARG_NAME}= from a config file:
249+
250+
A. /boot/loader/entries/*.conf (RHEL 8/9/10, Fedora, OL8/9)
251+
Pattern: ^options\s+(?:.*\s)?{ARG_NAME}=(\S+)
252+
Captures: just the value (e.g. 8192)
253+
254+
B. {grub2_boot_path}/grubenv (RHEL 8, OL8)
255+
Pattern: ^kernelopts=(?:.*\s)?{ARG_NAME}=(\S+)
256+
Captures: just the value
257+
258+
C. {grub2_boot_path}/grub.cfg (OL7, Ubuntu)
259+
Pattern: ^.*/vmlinuz.*\s{ARG_NAME}=(\S+)
260+
Captures: just the value
261+
262+
D. /etc/default/grub (all products)
263+
Pattern: ^\s*GRUB_CMDLINE_LINUX="(?:.*\s)?{ARG_NAME}=([^\s"]+)
264+
Captures: just the value (stops at whitespace or closing quote)
265+
266+
E. /etc/default/grub.d/*.cfg (Ubuntu)
267+
Same patterns as D.
268+
269+
F. /usr/lib/bootc/kargs.d/*.toml (RHEL 9+, RHEL 10 — bootc)
270+
Pattern: ^kargs\s*=\s*\[.*"{ARG_NAME}=([^"]+)".*\]$
271+
Captures: just the value (from within TOML quotes)
272+
273+
For no-value arguments (e.g. nousb), patterns check presence only
274+
(no capturing group, no state).
275+
276+
STATES -- compare the captured value:
277+
278+
1. state_grub2_{ARG}_argument (shared by all objects)
279+
Uses operation and datatype from rule.yml.
280+
arg_value rules: literal comparison (e.g. equals "1")
281+
arg_variable rules: var_ref to XCCDF variable (resolved at scan time)
282+
283+
2. state_grub2_{ARG}_argument_is_kernelopts (RHEL 8, OL8 only)
284+
Pattern match: checks if $kernelopts appears in the full options line.
285+
Used by the RHEL 8 coverage test with state_operator="OR".
286+
287+
The uses_* flags control which locations are verified per product.
439288
-#}}
440289

441290
{{% set uses_boot_loader_entries = product in ["fedora", "ol8", "ol9", "rhel8", "rhel9", "rhel10"] %}}
@@ -699,7 +548,8 @@
699548
{{{ etc_default_grub_object_and_test("GRUB_CMDLINE_LINUX_DEFAULT") }}}
700549

701550

702-
{{# RHEL 8/9/10, Fedora, OL8/9 — uses_boot_loader_entries #}}
551+
{{# RHEL 8/9/10, Fedora, OL8/9 — uses_boot_loader_entries
552+
ID uses _RULE_ID (not ARG_NAME_UNDERSCORED) to guarantee uniqueness across rules. #}}
703553
{{% if uses_boot_loader_entries %}}
704554
<ind:textfilecontent54_state id="state_grub2_{{{ _RULE_ID }}}_is_rescue_entry" version="1"
705555
comment="Match /boot/loader/entries/*rescue.conf filenames for exclusion">
@@ -796,7 +646,7 @@
796646
Used negated in criteria: if no entry has $kernelopts, grubenv check is skipped. #}}
797647
<ind:textfilecontent54_test id="test_grub2_{{{ ARG_NAME_UNDERSCORED }}}_kernelopts_in_any_boot_loader_entry"
798648
comment="Check if any /boot/loader/entries/*.conf references $kernelopts"
799-
check="all" check_existence="at_least_one_exists" version="1">
649+
check="at least one" check_existence="at_least_one_exists" version="1">
800650
<ind:object object_ref="obj_grub2_{{{ ARG_NAME_UNDERSCORED }}}_bls_entries" />
801651
<ind:state state_ref="state_grub2_{{{ ARG_NAME_UNDERSCORED }}}_argument_is_kernelopts" />
802652
</ind:textfilecontent54_test>
@@ -846,9 +696,9 @@
846696
<ind:path>/usr/lib/bootc/kargs.d/</ind:path>
847697
<ind:filename operation="pattern match">^.*\.toml$</ind:filename>
848698
{{%- if has_value %}}
849-
<ind:pattern operation="pattern match">^kargs\s*=\s*\[.*"{{{ ARG_NAME }}}=([^"]+)".*\]$</ind:pattern>
699+
<ind:pattern operation="pattern match">^kargs\s*=\s*\[.*"{{{ ARG_NAME_ESCAPED_DOTS }}}=([^"]+)".*\]$</ind:pattern>
850700
{{%- else %}}
851-
<ind:pattern operation="pattern match">^kargs\s*=\s*\[.*"{{{ ARG_NAME }}}".*\]$</ind:pattern>
701+
<ind:pattern operation="pattern match">^kargs\s*=\s*\[.*"{{{ ARG_NAME_ESCAPED_DOTS }}}".*\]$</ind:pattern>
852702
{{%- endif %}}
853703
<ind:instance datatype="int" operation="greater than or equal">1</ind:instance>
854704
</ind:textfilecontent54_object>

0 commit comments

Comments
 (0)