diff --git a/applications/openshift-virtualization/kubevirt-restrict-vnc-access-to-workloads/rule.yml b/applications/openshift-virtualization/kubevirt-restrict-vnc-access-to-workloads/rule.yml new file mode 100644 index 000000000000..b2429e30b0c2 --- /dev/null +++ b/applications/openshift-virtualization/kubevirt-restrict-vnc-access-to-workloads/rule.yml @@ -0,0 +1,32 @@ +documentation_complete: true + +title: 'Restrict VNC Access to Cluster Workloads' + +description: |- + Only authorized subjects should be granted roles that allow VNC + access to virtual machines. VNC access is controlled through + Kubernetes RBAC by binding the token.kubevirt.io:generate + role. Unrestricted VNC access allows any bound subject to open a + graphical console session to running virtual machines, potentially + exposing sensitive workload data and enabling unauthorized + interaction with the guest operating system. + +rationale: |- + VNC provides direct graphical console access to a running virtual + machine. In an OpenShift Virtualization environment, this access is + gated by the token.kubevirt.io:generate role. If this role + is bound too broadly, unauthorized users can view and interact with + VM desktops, capture screen contents, and input commands. Restricting + VNC access through careful role binding review ensures that only + approved subjects can establish console sessions to cluster + workloads. + +severity: medium + +ocil_clause: 'unauthorized subjects have VNC access to cluster workloads' + +ocil: |- + Run the following command to list role bindings that grant VNC access: +
$ oc get rolebinding -ojson | jq -c '.items[] | select(.roleRef.name | contains("token.kubevirt.io:generate"))'
+ Verify that only authorized subjects are bound to the + token.kubevirt.io:generate role. diff --git a/build-scripts/build_cel_content.py b/build-scripts/build_cel_content.py index 74786b6b9185..c58f3820bc51 100755 --- a/build-scripts/build_cel_content.py +++ b/build-scripts/build_cel_content.py @@ -339,8 +339,10 @@ def generate_cel_content(cel_rules, profiles): for rule_id in profile.selected: if rule_id not in cel_rule_ids: rule_name = rule_id_to_name(rule_id) - raise ValueError( - f"profile '{profile_name}' references unknown rule '{rule_name}'" + logging.warning( + "profile '%s' references rule '%s' without CEL checks " + "(manual rule) - skipping from CEL content", + profile_name, rule_name, ) cel_profile = profile_to_cel_dict(profile, cel_rule_ids) diff --git a/docs/manual/developer/13_cel_content.md b/docs/manual/developer/13_cel_content.md index 91cbddf9c15d..3724857dd9e1 100644 --- a/docs/manual/developer/13_cel_content.md +++ b/docs/manual/developer/13_cel_content.md @@ -141,7 +141,7 @@ selections: - kubevirt-persistent-reservation-disabled ``` -**Important:** CEL profiles can only select CEL rules. If a profile includes both CEL and OVAL rules, only the CEL rules will be included in the generated CEL content file. +**Important:** CEL profiles can select both CEL rules and manual rules (rules without `cel/shared.yml`). Manual rules are skipped during CEL content generation with a warning — only CEL rules are included in the generated CEL content file. ## Creating a CEL Rule @@ -347,8 +347,8 @@ The build system validates CEL content automatically: **Profile Validation:** - `selected` field must contain at least one rule -- All selected rules must exist in CEL rules -- Profile cannot reference OVAL rules +- Rules without CEL checks (manual rules) are skipped with a warning during CEL content generation +- No error is raised for manual rules referenced by CEL profiles **Content Validation:** - No duplicate rule names (after underscore-to-hyphen conversion) @@ -434,9 +434,9 @@ cel-spec '{"resource": {"spec": {"enabled": true}}}' 'resource.spec.enabled == t **Error: `CEL profile 'profile-name' has no rules`** - Add rules to the `selections` field in the profile -**Error: `profile 'profile-name' references unknown rule 'rule-name'`** -- Verify the rule exists and has CEL checks (has `cel/shared.yml` with `expression` and `inputs`) -- Check the rule ID matches the profile selection +**Warning: `profile 'profile-name' references rule 'rule-name' without CEL checks (manual rule)`** +- This is expected for manual rules without `cel/shared.yml` — they are skipped from CEL content +- If the rule should have CEL checks, add `cel/shared.yml` with `expression` and `inputs` ### CEL Content Not Generated diff --git a/products/ocp4/profiles/cis-vm-extension.profile b/products/ocp4/profiles/cis-vm-extension.profile index a835ac42f886..b6d58d412849 100644 --- a/products/ocp4/profiles/cis-vm-extension.profile +++ b/products/ocp4/profiles/cis-vm-extension.profile @@ -28,3 +28,4 @@ selections: - kubevirt-persistent-reservation-disabled - kubevirt-no-vms-overcommitting-guest-memory - kubevirt-enforce-trusted-tls-registries + - kubevirt-restrict-vnc-access-to-workloads