Skip to content

Commit 9fde596

Browse files
committed
Move the CEL fields out of the rule.yml
Keeps the fields pertainint to CEL scanning engine separate from the rule.yml, which can remain agnostic. This facilitates the implementation of templates later on. 'scanner_type' is completely removed from rules, and inferred by presence of 'cel' directory or presence of 'expression' and 'input' keys.
1 parent ae5afb0 commit 9fde596

File tree

15 files changed

+237
-219
lines changed

15 files changed

+237
-219
lines changed

.claude/CLAUDE.md

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -158,14 +158,22 @@ template:
158158
pkgname@ubuntu2204: avahi-daemon # Platform-specific overrides
159159
```
160160

161-
## CEL Rules (Kubernetes/OpenShift)
161+
## CEL Checking Engine (Kubernetes/OpenShift)
162162

163-
CEL (Common Expression Language) rules provide native Kubernetes resource evaluation without requiring shell access or OVAL checks. CEL rules are used by the compliance-operator for Kubernetes and OpenShift compliance scanning.
163+
CEL (Common Expression Language) provides native Kubernetes resource evaluation without requiring shell access or OVAL checks. Rules using the CEL checking engine are used by the compliance-operator for Kubernetes and OpenShift compliance scanning.
164164

165-
**Important:** CEL rules are **excluded** from XCCDF/OVAL DataStreams and are generated as a separate `${PRODUCT}-cel-content.yaml` file.
165+
**Important:** Rules with CEL checks are **excluded** from XCCDF/OVAL DataStreams and are generated as a separate `${PRODUCT}-cel-content.yaml` file.
166166

167-
### Required Fields for CEL Rules
167+
### Rule Structure for CEL Checks
168168

169+
Rules using CEL checks use a **split-file structure** to separate metadata from CEL-specific content:
170+
171+
- **`rule.yml`** - Contains metadata (title, description, rationale, severity, references, etc.)
172+
- **`cel/shared.yml`** - Contains CEL-specific fields (check_type, inputs, expression)
173+
174+
This allows rules to support **both CEL and OVAL** checks during migration from OVAL to CEL.
175+
176+
**Example rule.yml:**
169177
```yaml
170178
documentation_complete: true
171179
@@ -179,8 +187,20 @@ rationale: |-
179187
180188
severity: medium
181189
182-
scanner_type: CEL # REQUIRED: Marks this as a CEL rule
190+
ocil: |- # Optional: Manual check instructions
191+
Run the following command:
192+
<pre>$ oc get pods</pre>
193+
194+
failure_reason: |- # Optional: Custom failure message
195+
The resource is not properly configured.
196+
197+
references: # Optional: Same as regular rules
198+
cis@ocp4: 1.2.3
199+
nist: CM-6
200+
```
183201

202+
**Example cel/shared.yml:**
203+
```yaml
184204
check_type: Platform # Usually Platform for K8s checks
185205
186206
expression: |- # REQUIRED: CEL expression (must evaluate to boolean)
@@ -193,19 +213,10 @@ inputs: # REQUIRED: Kubernetes resources to evaluate
193213
resource: pods
194214
resource_name: my-pod # Optional: specific resource
195215
resource_namespace: default # Optional: specific namespace
196-
197-
ocil: |- # Optional: Manual check instructions
198-
Run the following command:
199-
<pre>$ oc get pods</pre>
200-
201-
failure_reason: |- # Optional: Custom failure message
202-
The resource is not properly configured.
203-
204-
references: # Optional: Same as regular rules
205-
cis@ocp4: 1.2.3
206-
nist: CM-6
207216
```
208217

218+
**Note:** The build system automatically detects rules with CEL checks by the presence of the `cel/` directory.
219+
209220
### CEL Expression Examples
210221

211222
Simple boolean check:
@@ -228,7 +239,7 @@ expression: |-
228239

229240
### CEL Profile Format
230241

231-
Profiles that use CEL rules must have `scannerType: CEL`:
242+
Profiles that select rules using CEL checks must have `scanner_type: CEL`:
232243

233244
```yaml
234245
documentation_complete: true
@@ -238,14 +249,16 @@ title: 'CIS VM Extension Benchmark'
238249
description: |-
239250
Profile description.
240251
241-
scanner_type: CEL # REQUIRED: Marks this as a CEL profile
252+
scanner_type: CEL # REQUIRED: Marks this as a CEL profile (excluded from XCCDF)
242253
243254
selections:
244255
- kubevirt-nonroot-feature-gate-is-enabled
245256
- kubevirt-no-permitted-host-devices
246257
```
247258

248-
**Note:** CEL profiles can only select CEL rules and are excluded from XCCDF generation.
259+
**Note:**
260+
- Profiles use `scanner_type: CEL` to indicate they target the CEL checking engine and should be excluded from XCCDF/datastream builds.
261+
- A rule can have both `cel/` (for CEL checks) and `template:` (for OVAL checks) to support both checking engines during migration.
249262

250263
**Important:** Use hyphens rule IDs (Kubernetes naming convention), not underscores.
251264

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
check_type: Platform
2+
3+
inputs:
4+
- name: hco
5+
kubernetes_input_spec:
6+
api_version: hco.kubevirt.io/v1beta1
7+
resource: hyperconvergeds
8+
resource_name: kubevirt-hyperconverged
9+
resource_namespace: openshift-cnv
10+
11+
expression: |-
12+
!has(hco.spec.storageImport) ||
13+
hco.spec.storageImport.insecureRegistries.size() == 0

applications/openshift-virtualization/kubevirt-enforce-trusted-tls-registries/rule.yml

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,3 @@ ocil: |-
3030
Run the following command to check for insecure registries:
3131
<pre>$ oc get hyperconverged kubevirt-hyperconverged -n openshift-cnv -o jsonpath='{.spec.storageImport.insecureRegistries}'</pre>
3232
The output should be empty or the field should not exist.
33-
34-
check_type: Platform
35-
36-
scanner_type: CEL
37-
38-
inputs:
39-
- name: hco
40-
kubernetes_input_spec:
41-
api_version: hco.kubevirt.io/v1beta1
42-
resource: hyperconvergeds
43-
resource_name: kubevirt-hyperconverged
44-
resource_namespace: openshift-cnv
45-
46-
expression: |-
47-
!has(hco.spec.storageImport) ||
48-
hco.spec.storageImport.insecureRegistries.size() == 0
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
check_type: Platform
2+
3+
inputs:
4+
- name: hcoList
5+
kubernetes_input_spec:
6+
api_version: hco.kubevirt.io/v1beta1
7+
resource: hyperconvergeds
8+
9+
expression: |
10+
hcoList.items.filter(h,
11+
h.metadata.name == 'kubevirt-hyperconverged' &&
12+
h.metadata.namespace == 'openshift-cnv'
13+
).size() == 1 &&
14+
hcoList.items.filter(h,
15+
h.metadata.name == 'kubevirt-hyperconverged' &&
16+
h.metadata.namespace == 'openshift-cnv'
17+
).all(h,
18+
!has(h.spec.permittedHostDevices) ||
19+
h.spec.permittedHostDevices == null ||
20+
(has(h.spec.permittedHostDevices.pciHostDevices) && size(h.spec.permittedHostDevices.pciHostDevices) == 0) &&
21+
(has(h.spec.permittedHostDevices.mediatedDevices) && size(h.spec.permittedHostDevices.mediatedDevices) == 0)
22+
)

applications/openshift-virtualization/kubevirt-no-permitted-host-devices/rule.yml

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -33,28 +33,3 @@ ocil: |-
3333
Run the following command to check the HyperConverged configuration:
3434
<pre>$ oc get hyperconverged kubevirt-hyperconverged -n openshift-cnv -o jsonpath='{.spec.permittedHostDevices}'</pre>
3535
The output should be empty or show empty lists for both <tt>pciHostDevices</tt> and <tt>mediatedDevices</tt>.
36-
37-
check_type: Platform
38-
39-
scanner_type: CEL
40-
41-
inputs:
42-
- name: hcoList
43-
kubernetes_input_spec:
44-
api_version: hco.kubevirt.io/v1beta1
45-
resource: hyperconvergeds
46-
47-
expression: |
48-
hcoList.items.filter(h,
49-
h.metadata.name == 'kubevirt-hyperconverged' &&
50-
h.metadata.namespace == 'openshift-cnv'
51-
).size() == 1 &&
52-
hcoList.items.filter(h,
53-
h.metadata.name == 'kubevirt-hyperconverged' &&
54-
h.metadata.namespace == 'openshift-cnv'
55-
).all(h,
56-
!has(h.spec.permittedHostDevices) ||
57-
h.spec.permittedHostDevices == null ||
58-
(has(h.spec.permittedHostDevices.pciHostDevices) && size(h.spec.permittedHostDevices.pciHostDevices) == 0) &&
59-
(has(h.spec.permittedHostDevices.mediatedDevices) && size(h.spec.permittedHostDevices.mediatedDevices) == 0)
60-
)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
check_type: Platform
2+
3+
inputs:
4+
- name: vms
5+
kubernetes_input_spec:
6+
api_version: kubevirt.io/v1
7+
resource: VirtualMachine
8+
9+
expression: |
10+
vms.all(h,
11+
!has(h.spec.template.spec.domain.resources) ||
12+
!has(h.spec.template.spec.domain.resources.overcommitGuestOverhead) ||
13+
(has(h.spec.template.spec.domain.resources.overcommitGuestOverhead) &&
14+
h.spec.template.spec.domain.resources.overcommitGuestOverhead == false)
15+
)

applications/openshift-virtualization/kubevirt-no-vms-overcommitting-guest-memory/rule.yml

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -32,21 +32,3 @@ ocil: |-
3232
Run the following command to check VirtualMachine configurations:
3333
<pre>$ oc get virtualmachines -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"/"}{.metadata.name}{": "}{.spec.template.spec.domain.resources.overcommitGuestOverhead}{"\n"}{end}'</pre>
3434
Make sure no VirtualMachine has <tt>overcommitGuestOverhead</tt> set to <tt>true</tt>.
35-
36-
check_type: Platform
37-
38-
scanner_type: CEL
39-
40-
inputs:
41-
- name: vms
42-
kubernetes_input_spec:
43-
api_version: kubevirt.io/v1
44-
resource: VirtualMachine
45-
46-
expression: |
47-
vms.all(h,
48-
!has(h.spec.template.spec.domain.resources) ||
49-
!has(h.spec.template.spec.domain.resources.overcommitGuestOverhead) ||
50-
(has(h.spec.template.spec.domain.resources.overcommitGuestOverhead) &&
51-
h.spec.template.spec.domain.resources.overcommitGuestOverhead == false)
52-
)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
check_type: Platform
2+
3+
inputs:
4+
- name: hcoList
5+
kubernetes_input_spec:
6+
api_version: hco.kubevirt.io/v1beta1
7+
resource: hyperconvergeds
8+
9+
expression: |
10+
hcoList.items.filter(h,
11+
h.metadata.name == 'kubevirt-hyperconverged' &&
12+
h.metadata.namespace == 'openshift-cnv'
13+
).size() == 1 &&
14+
hcoList.items.filter(h,
15+
h.metadata.name == 'kubevirt-hyperconverged' &&
16+
h.metadata.namespace == 'openshift-cnv'
17+
).all(h,
18+
has(h.spec.featureGates) &&
19+
has(h.spec.featureGates.nonRoot) &&
20+
h.spec.featureGates.nonRoot == true
21+
)

applications/openshift-virtualization/kubevirt-nonroot-feature-gate-is-enabled/rule.yml

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -30,27 +30,3 @@ ocil: |-
3030
Run the following command to check the feature gate configuration:
3131
<pre>$ oc get hyperconverged kubevirt-hyperconverged -n openshift-cnv -o jsonpath='{.spec.featureGates.nonRoot}'</pre>
3232
The output should be <tt>true</tt>.
33-
34-
check_type: Platform
35-
36-
scanner_type: CEL
37-
38-
inputs:
39-
- name: hcoList
40-
kubernetes_input_spec:
41-
api_version: hco.kubevirt.io/v1beta1
42-
resource: hyperconvergeds
43-
44-
expression: |
45-
hcoList.items.filter(h,
46-
h.metadata.name == 'kubevirt-hyperconverged' &&
47-
h.metadata.namespace == 'openshift-cnv'
48-
).size() == 1 &&
49-
hcoList.items.filter(h,
50-
h.metadata.name == 'kubevirt-hyperconverged' &&
51-
h.metadata.namespace == 'openshift-cnv'
52-
).all(h,
53-
has(h.spec.featureGates) &&
54-
has(h.spec.featureGates.nonRoot) &&
55-
h.spec.featureGates.nonRoot == true
56-
)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
check_type: Platform
2+
3+
inputs:
4+
- name: hcoList
5+
kubernetes_input_spec:
6+
api_version: hco.kubevirt.io/v1beta1
7+
resource: hyperconvergeds
8+
9+
expression: |
10+
hcoList.items.filter(h,
11+
h.metadata.name == 'kubevirt-hyperconverged' &&
12+
h.metadata.namespace == 'openshift-cnv'
13+
).size() == 1 &&
14+
hcoList.items.filter(h,
15+
h.metadata.name == 'kubevirt-hyperconverged' &&
16+
h.metadata.namespace == 'openshift-cnv'
17+
).all(h,
18+
has(h.spec.featureGates) &&
19+
has(h.spec.featureGates.persistentReservation) &&
20+
h.spec.featureGates.persistentReservation == false
21+
)

0 commit comments

Comments
 (0)