Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CPE AL: Introduce version specifiers support #9945

Merged
merged 9 commits into from
Dec 16, 2022

Conversation

evgenyz
Copy link
Member

@evgenyz evgenyz commented Dec 7, 2022

Description:

  • Add functions that would handle versions in platform definition. Sample implementation in in package platform's OVAL template.

  • Version notation currently does not support epoch. Supported format: maj.min.micro[.nano...]-release.

Rationale:

  • This change would allow platforms to specify required version of the component (os_linux[rhel]>=8.2, package[grub]>=2.0).

Review Hints:

  • Sample OVAL generated with new template (for platform package[ntp]<=1.99.5-1,>1.1):
<def-group>
  <definition class="inventory" id="platform_package_ntp_le_or_eq_1_99_5_1_gt_1_1"
  version="1">
    <metadata>
        <title>Package ntp is installed</title>
            <affected family="unix">
                <platform>multi_platform_all</platform>
            </affected>
        <description>The RPM package ntp should be installed.</description>
    </metadata>
    <criteria>
      <criterion comment="Platform package ntp of version greater than 1.1 is installed"
      test_ref="platform_test_package_ntp_le_or_eq_1_99_5_1_gt_1_1_gt_1_1_installed" />
      <criterion comment="Platform package ntp of version less than or equal 1.99.5-1 is installed"
      test_ref="platform_test_package_ntp_le_or_eq_1_99_5_1_gt_1_1_le_or_eq_1_99_5_1_installed" />
    </criteria>
  </definition>
  <linux:rpminfo_test check="all" check_existence="all_exist"
  id="platform_test_package_ntp_le_or_eq_1_99_5_1_gt_1_1_gt_1_1_installed" version="1"
  comment="package ntp is installed">
    <linux:object object_ref="obj_platform_test_package_ntp_le_or_eq_1_99_5_1_gt_1_1_gt_1_1_installed" />
      <linux:state state_ref="ste_platform_test_package_ntp_le_or_eq_1_99_5_1_gt_1_1_gt_1_1_installed" />
  </linux:rpminfo_test>
  <linux:rpminfo_object id="obj_platform_test_package_ntp_le_or_eq_1_99_5_1_gt_1_1_gt_1_1_installed" version="1">
    <linux:name>ntp</linux:name>
  </linux:rpminfo_object>
    <linux:rpminfo_state id="ste_platform_test_package_ntp_le_or_eq_1_99_5_1_gt_1_1_gt_1_1_installed" version="1">
      <linux:evr datatype="evr_string" operation="greater than">0:1.1-0</linux:evr>
    </linux:rpminfo_state>
  <linux:rpminfo_test check="all" check_existence="all_exist"
  id="platform_test_package_ntp_le_or_eq_1_99_5_1_gt_1_1_le_or_eq_1_99_5_1_installed" version="1"
  comment="package ntp is installed">
    <linux:object object_ref="obj_platform_test_package_ntp_le_or_eq_1_99_5_1_gt_1_1_le_or_eq_1_99_5_1_installed" />
      <linux:state state_ref="ste_platform_test_package_ntp_le_or_eq_1_99_5_1_gt_1_1_le_or_eq_1_99_5_1_installed" />
  </linux:rpminfo_test>
  <linux:rpminfo_object id="obj_platform_test_package_ntp_le_or_eq_1_99_5_1_gt_1_1_le_or_eq_1_99_5_1_installed" version="1">
    <linux:name>ntp</linux:name>
  </linux:rpminfo_object>
    <linux:rpminfo_state id="ste_platform_test_package_ntp_le_or_eq_1_99_5_1_gt_1_1_le_or_eq_1_99_5_1_installed" version="1">
      <linux:evr datatype="evr_string" operation="less than or equal">0:1.99.5-1</linux:evr>
    </linux:rpminfo_state>
</def-group>
  • TODO:
  • Automatic ID assignment for templated OVAL checks
  • Documentation

@evgenyz evgenyz requested review from jan-cerny, matejak and vojtapolasek and removed request for jan-cerny December 7, 2022 19:06
@evgenyz evgenyz added Infrastructure Our content build system CPE-AL CPE Applicability Language labels Dec 7, 2022
@jan-cerny jan-cerny self-assigned this Dec 8, 2022
@@ -3,9 +3,18 @@
version="1">
{{{ oval_metadata("The " + pkg_system|upper + " package " + PKGNAME + " should be installed.", affected_platforms=["multi_platform_all"]) }}}
<criteria>
<criterion comment="Package {{{ PKGNAME }}} is installed"
{{% for spec in VER_SPECS %}}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a question: Will we do similar changes also in the Bash and Ansible code for the package template platform? My understanding is that Bash is too difficult so we put it out of scope of this year, but what will we do about Ansible?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yeah. There was some code for Ansible. I'll adopt it for package CPE. Added to TODO.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added ansible.template for package platform.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed ansible.template and all new code that supports it.

Comment on lines 164 to 170
res['ver_title'] = ' and '.join(['{0} {1}'.format(
ssg.utils.comparison_to_oval(op), ver)
for op, ver in self.ver_specs])

res['ver_cpe'] = ':'.join(['{0}:{1}'.format(
ssg.utils.escape_comparison(op), ver)
for op, ver in self.ver_specs])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where are the variables ver_title and ver_cpe used? Also, is it a duplicate information from the contents of ver_specs dictionary?

Copy link
Member Author

@evgenyz evgenyz Dec 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's take foo>1.0,<2.0:

The ver_specs is a list of individual specs: op: >, ver: 1.0, etc..., op: <, ver: 2.0, etc..., whereas ver_cpe in that case is a composition cpe:/a:foo:lt:1.0:gt:2.0 (yes, CPE name does not make much sense in this case but we are going to get rid of dictionaries anyway). The ver_title would be greater than 1.0 and less than 2.0.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, and where are they used?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ver_cpe was designed to be used to update name for CPEs. I just missed that part of code because scanner does not care about uniqueness of CPE ID in dictionaries. The title was designed for things like <criteria> titles. I'll add it to the package.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -663,7 +663,7 @@ Generates the :code:`<affected>` tag for OVAL check using correct product platfo
</linux:rpminfo_object>
{{% if evr %}}
<linux:rpminfo_state id="ste_{{{ test_id }}}" version="1">
<linux:evr datatype="evr_string" operation="greater than or equal">{{{ evr }}}</linux:evr>
<linux:evr datatype="evr_string" operation="{{{ evr_op }}}">{{{ evr }}}</linux:evr>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How will the equality operation work with RPM packages? For example, I want to check firefox. I have firefox-107.0-4.fc37.x86_64 installed. I have platform: package[firefox]==107.0-4 in rule.yml. The result is notapplicable. I can't define platform: package[firefox]==107.0-4.fc37 because that causes a build error. The collected items in ARF contain <lin-sys:evr datatype="evr_string">0:107.0-4.fc37</lin-sys:evr>. It seems to me that I can't have == operator for RPM packages in platform definitions. How does that work?

Copy link
Member Author

@evgenyz evgenyz Dec 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also the limitation of distutils as it does not support extra letters in versions. We can work around for now with package[firefox]>=107.0-4,<107.0-5 if we absolutely have to.

Copy link
Member Author

@evgenyz evgenyz Dec 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But in general we might need to think about it and amend OVAL/OpenSCAP in some way because package[firefox]==107.0-4.fc37 makes platform distro-version specific, which we kinda trying to avoid in the content.

Add functions that would handle versions in platform definition.
Sample implementation in in package platform's OVAL template.

Version notation currently does not support epoch. Supported
format: "maj.min.micro-release".
Directly import utils module from ssg.
Extract logic for parsing requirements and versions into separate
requirement_specs.py module. Migrate formatting logic to utils.py.

New VersionSpecifier and VersionSpecifierSet classes are responsible
for representation of requirements and versions specs independently
of parsing module.

The boolean_expression.py now only deals with expressions logic.
CPEItem now uses its id_ as check_id for OVAL templates. The check_id
property is no longer required, but it will override id_ if provided.

The title property is inherited from XCCDFEntity.KEYS.
@evgenyz evgenyz force-pushed the add_platform_versions branch 2 times, most recently from 086c8a2 to 32338af Compare December 12, 2022 07:38
@jan-cerny
Copy link
Collaborator

you are also affected by ComplianceAsCode/content-test-filtering#38

@github-actions
Copy link

Start a new ephemeral environment with changes proposed in this pull request:

Fedora Environment
Open in Gitpod

Oracle Linux 8 Environment
Open in Gitpod

@jan-cerny
Copy link
Collaborator

I have checked it again and I think you should move the Ansible code and the code that supports the templated Bash and Ansible conditional to a separate PR. Keep here only the OVAL checks so that we will have narrow scope in this PR and we can focus only on the actual "versioning feature".

@evgenyz
Copy link
Member Author

evgenyz commented Dec 12, 2022

I have checked it again and I think you should move the Ansible code and the code that supports the templated Bash and Ansible conditional to a separate PR. Keep here only the OVAL checks so that we will have narrow scope in this PR and we can focus only on the actual "versioning feature".

Will do.

@evgenyz evgenyz force-pushed the add_platform_versions branch 2 times, most recently from 035b6d1 to ab1ef0a Compare December 12, 2022 21:48
@jan-cerny
Copy link
Collaborator

/retest

@jan-cerny
Copy link
Collaborator

I have checked it again and I think you should move the Ansible code and the code that supports the templated Bash and Ansible conditional to a separate PR. Keep here only the OVAL checks so that we will have narrow scope in this PR and we can focus only on the actual "versioning feature".

I'm sorry for not being clear, when I talked about "the code that supports the templated Bash and Ansible conditional" I meant also the commit CPE/AL Add support for templated Ansible and Bash conditionals . Because I understood that if we don't have the templated Ansible and Bash conditional in this rule we don't need this code urgently and the support for it can be complex and also it has an alternative solution proposed by Vojta. What do you think? Is that a possible way?

@evgenyz
Copy link
Member Author

evgenyz commented Dec 13, 2022

I have checked it again and I think you should move the Ansible code and the code that supports the templated Bash and Ansible conditional to a separate PR. Keep here only the OVAL checks so that we will have narrow scope in this PR and we can focus only on the actual "versioning feature".

I'm sorry for not being clear, when I talked about "the code that supports the templated Bash and Ansible conditional" I meant also the commit CPE/AL Add support for templated Ansible and Bash conditionals . Because I understood that if we don't have the templated Ansible and Bash conditional in this rule we don't need this code urgently and the support for it can be complex and also it has an alternative solution proposed by Vojta. What do you think? Is that a possible way?

That's exactly how I got it. I'll remove that commit. I was fixing problems with versions in our CI yesterday and haven't had time to get rid of it.

…ecs.py

At around v40.8 the `post` attribute of `Version` wasn't available.
@evgenyz
Copy link
Member Author

evgenyz commented Dec 13, 2022

@jan-cerny And it's gone.

@jan-cerny
Copy link
Collaborator

@evgenyz I have a problem when I try to use the versions in some rules

I have created a new package platform for coconut package and then I made rule selinux_state applicable on coconut package and the rule accounts_tmout also on coconut but only on a version greater than 4.5. Here is the full diff of my changes:

jcerny@thinkpad scap-security-guide{pr/9945}]$ git diff
diff --git a/linux_os/guide/system/accounts/accounts-session/accounts_tmout/rule.yml b/linux_os/guide/system/accounts/accounts-session/accounts_tmout/rule.yml
index ed351fcf87..2444cfb07d 100644
--- a/linux_os/guide/system/accounts/accounts-session/accounts_tmout/rule.yml
+++ b/linux_os/guide/system/accounts/accounts-session/accounts_tmout/rule.yml
@@ -84,7 +84,7 @@ ocil: |-
     export TMOUT
     {{% endif %}}
 
-platform: machine
+platform: package[coconut]>=4.5
 
 fixtext: |-
     Configure {{{ full_name }}} to terminate user sessions after {{{ xccdf_value("var_accounts_tmout") }}} seconds of inactivity.
diff --git a/linux_os/guide/system/selinux/selinux_state/rule.yml b/linux_os/guide/system/selinux/selinux_state/rule.yml
index 776909f458..32d08a3b21 100644
--- a/linux_os/guide/system/selinux/selinux_state/rule.yml
+++ b/linux_os/guide/system/selinux/selinux_state/rule.yml
@@ -71,3 +71,5 @@ fixtext: |-
 
 srg_requirement: |-
     {{{ full_name }}} must use a Linux Security Module configured to enforce limits on system services.
+
+platform: package[coconut]
diff --git a/shared/applicability/package.yml b/shared/applicability/package.yml
index 85c11cebdb..14f5b43abd 100644
--- a/shared/applicability/package.yml
+++ b/shared/applicability/package.yml
@@ -8,3 +8,5 @@ args:
   ntp:
     pkgname: ntp
     title: NTP daemon and utilities
+  coconut:
+    pkgname: coconut

Now I build the fedora product. and I take a look into the built data stream ssg-fedora-ds.xml. I have 2 <cpe-lang:platform> elements: <cpe-lang:platform id="package_coconut_gt_or_eq_4_5"> and <cpe-lang:platform id="package_coconut"> but they both have <cpe-lang:fact-ref name="cpe:/a:coconut"/> child element and there is only a single <cpe-dict:cpe-item> element related to the coconut package and that is a <cpe-dict:cpe-item name="cpe:/a:coconut">. This element points to "oval:ssg-package_coconut_gt_or_eq_4_5:def:1". That means the package platform definition for rule selinux_state in my example is broken because the platform for that rule points to an OVAL that checks for a specific version which it shouldn't. OTOH the CPE OVAL definition oval:ssg-package_coconut:def:1 is orphan in my example and isn't used in a platform definition. I think it's a bug.

Use VER_SPECS_TITLE in OVAL template.
Use ver_specs_cpe in applicability/package.yml
Wrap confusing get_symbols in CPEItem.
Cosmetic fixes.
@evgenyz
Copy link
Member Author

evgenyz commented Dec 13, 2022

Removed a bit too much, huh. Should be fixed now.

@jan-cerny
Copy link
Collaborator

/retest

Copy link
Collaborator

@jan-cerny jan-cerny left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that now the code climate issues remain to be solved.

}

if self.requirement.has_version_specs():
for ver_spec in sorted(self.requirement.ver_specs):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should be self.ver_specs

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nah, Symbol.ver_specs doesn't make sense.

test_ref="platform_test_{{{ _RULE_ID }}}_installed" />
{{% for spec in VER_SPECS %}}
<criterion comment="Platform package {{{ PKGNAME }}} of version {{{ spec.evr_op }}} {{{ spec.ver }}} is installed"
test_ref="inventory_test_{{{ _RULE_ID }}}_{{{ spec.id }}}_installed" />
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we add the spec.id to the test ID? It's already a part of the rule_id. That leads to a weird ID like "oval:ssg-inventory_test_package_coconut_gt_or_eq_4_5_gt_or_eq_4_5_installed:tst:1".

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general it's for package[coconut]>=4.5,<5.

@evgenyz
Copy link
Member Author

evgenyz commented Dec 14, 2022

I think that now the code climate issues remain to be solved.

Code Climate is happy now.

@evgenyz
Copy link
Member Author

evgenyz commented Dec 14, 2022

@jan-cerny
If we are happy with variables and config structure and all that stuff I'll document it.

@jan-cerny
Copy link
Collaborator

@evgenyz I hope we're OK with that, let's see how the documentation will look like.

@codeclimate
Copy link

codeclimate bot commented Dec 14, 2022

Code Climate has analyzed commit 82a174f and detected 0 issues on this pull request.

The test coverage on the diff in this pull request is 94.3% (50% is the threshold).

This pull request will bring the total coverage in the repository to 49.8% (1.0% change).

View more on Code Climate.

@jan-cerny
Copy link
Collaborator

/retest

…t them

The 'versioned' property of a CPE entity indicates if it can process
version specifier in a sensible way. It is False by default.
@jan-cerny
Copy link
Collaborator

/retest

1 similar comment
@jan-cerny
Copy link
Collaborator

/retest

@openshift-ci
Copy link

openshift-ci bot commented Dec 15, 2022

@evgenyz: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/e2e-aws-ocp4-stig 2534113 link true /test e2e-aws-ocp4-stig

Full PR test history. Your PR dashboard.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here.

@jan-cerny jan-cerny merged commit e65cab6 into ComplianceAsCode:master Dec 16, 2022
@jan-cerny jan-cerny added this to the 0.1.66 milestone Dec 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CPE-AL CPE Applicability Language Infrastructure Our content build system
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants