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

OVAL object model #11041

Merged
merged 11 commits into from
Sep 19, 2023
Merged

OVAL object model #11041

merged 11 commits into from
Sep 19, 2023

Conversation

Honny1
Copy link
Collaborator

@Honny1 Honny1 commented Aug 31, 2023

Description:

This PR introduces the OVAL object model into the SSG module. The OVAL object model can currently read XML OVAL documents and save yourself to XML OVAL document. The generated file is a valid XML OVAL document according to the oscap oval validate <file> command. The model can be loaded from OVAL shorthand. Integration into the build system and other features will be introduced in future PRs.

Doc with features ideas

Rationale:

Epic: OPENSCAP-2183

Review Hints:

Class Diagram:

classes_oval_object_model

Test script

pastebin.com/sSGMFREZ
In the root directory execute the test script via the commands below.

source .pyenv.sh # Optional step to avoid import errors.
python3 test.py
Run pytest
source .pyenv.sh  # Optional step to avoid import errors.
pytest tests/unit/ssg-module/test_oval_object_model/

@openshift-ci openshift-ci bot added the do-not-merge/work-in-progress Used by openshift-ci bot. label Aug 31, 2023
@openshift-ci
Copy link

openshift-ci bot commented Aug 31, 2023

Hi @Honny1. Thanks for your PR.

I'm waiting for a ComplianceAsCode member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

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.

@openshift-ci openshift-ci bot added the needs-ok-to-test Used by openshift-ci bot. label Aug 31, 2023
@github-actions
Copy link

github-actions bot commented Aug 31, 2023

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 haven't reviewed the PR thoroughly, but I have some thoughts:

  • this surely needs unit tests
  • some of the constants, eg. namespaces, are already defined in ssg.constants module
  • we will probably need a way to distinguish between different types of OVAL tests, eg. textfilecontent54_object, selinuxboolean_object etc. Ditto for objects and states.

@jan-cerny jan-cerny added enhancement General enhancements to the project. Infrastructure Our content build system labels Aug 31, 2023
@jan-cerny jan-cerny self-assigned this Sep 1, 2023
@Honny1
Copy link
Collaborator Author

Honny1 commented Sep 1, 2023

@jan-cerny
I'll check ssg.constants and try to fix the problems found in Code Climate. But I would like to keep some constants close to the oval_object_model subpackage. A lot of things are TBD. I plan to create unit tests in the next commits.

As for objects, states, and variables, I have created abstract logic. Because these endpoints are very similar. If we are interested in collecting objects, for example, I can create a specific object class that extends the current class. The endpoint type(object/state/variable) can be determined from the class instance of the attribute tag.

@Honny1 Honny1 force-pushed the oval-object-model branch 6 times, most recently from 69e2e1d to af94260 Compare September 6, 2023 15:53
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 like this PR very much, amazing!

I only have nit picks:

  1. please make all the CI jobs green
  2. please resolve the Code Climate problems
  3. see my comments below



def test_content_variable():
assert False
Copy link
Collaborator

Choose a reason for hiding this comment

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

this will always fail

assert text_file_content_object.list_of_property
list_of_property = [
OVALEntityProperty(
"{http://oval.mitre.org/XMLSchema/oval-definitions-5#independent}filepath",
Copy link
Collaborator

Choose a reason for hiding this comment

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

you should use namespace definitions from ssg/constants.py.

if notes_el == child_node_el:
continue
Copy link
Collaborator

Choose a reason for hiding this comment

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

What is the reason for this special handling of notes element?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Because the notes element is represented as a class. The notes element is loaded using the load_notes() function.

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 would need at least a comment there.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I have an idea how to make it clear.

BOOL_TO_STR = {True: "true", False: "false"}

OVAL_NAMESPACES = {
"oval": "http://oval.mitre.org/XMLSchema/oval-common-5",
Copy link
Collaborator

Choose a reason for hiding this comment

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

If this isn't already defined in ssg/constants.py you should put it there and not here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Should I move all constants from the OVAL object model to the ssg/constants.py file?

Copy link
Collaborator

Choose a reason for hiding this comment

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

In general, I would say that constants that have a likelihood of being used elsewhere in the project should be moved to ssg/constants.py. Namespace URLs are an example of constants that should definitely go to ssg/constants.py. On the other hand, you can still keep some constants in this module, but those should be constants that are extremely unique for this module and you don't expect reusing them anywhere else in future.

return "external_variable" in component.tag

@staticmethod
def _add_oval_component(component, component_dict):
Copy link
Collaborator

Choose a reason for hiding this comment

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

This method feels too complex. Also, I'd prefer to build the exception messages using .format() instead of + operators.

)

space = " "
oval_definition_el.set(
Copy link
Collaborator

Choose a reason for hiding this comment

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

This looks really suspicious. The library should declare the namespaces and prefixes automatically without you touching it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

In this case, a special attribute with links to schemas is created. This attribute is intended for the validator. For this purpose, the namespace and attributes are set manually.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Could you give an example of the special attribute? I think we need to take a detailed look into this.

Copy link
Collaborator Author

@Honny1 Honny1 Sep 18, 2023

Choose a reason for hiding this comment

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

The xsi:schemaLocation attribute is with a namespace. I figured out how to add this attribute with namespace correctly. It's nothing special. But in the OVAL context, it's a different type of attribute. (It is not specified by OVAL XSD schemas)

tag,
id_,
version,
list_of_property,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Would properties be a better name for this variable?

"..",
)
OVAL_DOCUMENT_PATH_FROM_BUILD = os.path.join(
PROJECT_ROOT, "build", "ssg-rhel9-oval.xml"
Copy link
Collaborator

Choose a reason for hiding this comment

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

What if a different product would be built? I think that a unit test should never depend on built artifacts.

Comment on lines 53 to 55
@pytest.fixture
def oval_document_from_build():
return _load_oval_document(OVAL_DOCUMENT_PATH_FROM_BUILD)
Copy link
Collaborator

Choose a reason for hiding this comment

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

No, we shouldn't do this, we need to invent a different way. I think that a unit test should never depend on built artifacts. I'm afraid that as the contents of the real products will change the test can start failing.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I can see that you already have other tests testing on test data so I think that you should remove this and move the checks to the test cases that test on the the test data.



def test_content_state():
assert False
Copy link
Collaborator

Choose a reason for hiding this comment

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

dtto

@Honny1 Honny1 force-pushed the oval-object-model branch 2 times, most recently from fcd2c7f to 0cd5600 Compare September 9, 2023 16:20
@openshift-merge-robot openshift-merge-robot added the needs-rebase Used by openshift-ci bot. label Sep 9, 2023
@openshift-merge-robot openshift-merge-robot removed the needs-rebase Used by openshift-ci bot. label Sep 9, 2023
@Honny1 Honny1 force-pushed the oval-object-model branch 9 times, most recently from a89de7d to 4b576b0 Compare September 9, 2023 20:17
assert text_file_content_object.properties

property_file_path = OVALEntityProperty(
"{{{}}}filepath".format(OVAL_NAMESPACES.independent)
Copy link
Collaborator

Choose a reason for hiding this comment

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

I've got an idea to split the constructor parameter to 2 parameters: tag name and namespace. This would help us avoid this ugly format composition repeating frequently. WDYT?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think it's a good idea.

@jan-cerny jan-cerny added this to the 0.1.70 milestone Sep 13, 2023
Comment on lines 18 to 20
def _get_xml_el(tag_name, xml_el):
el = xml_el.find("./{%s}%s" % (OVAL_NAMESPACES.definition, tag_name))
return el if el else []
Copy link
Collaborator

Choose a reason for hiding this comment

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

The name of this function can be a little misleading for someone because the purpose of the function is to supply an iterable over the children, hence the empty list returned if the element isn't found.

"{%s}oval_definitions" % OVAL_NAMESPACES.definition
)

register_namespaces({"xsi": "http://www.w3.org/2001/XMLSchema-instance"})
Copy link
Collaborator

Choose a reason for hiding this comment

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

The URL needs to be moved to ssg/constants.py.

"{1}{2}#linux linux-definitions-schema.xsd"
).format(
OVAL_NAMESPACES.oval,
space,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why is this space here?

Copy link
Collaborator Author

@Honny1 Honny1 Sep 18, 2023

Choose a reason for hiding this comment

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

I checked the documentation and found no specific requirement for a separator between pairs in xsi:schemaLocation. So, I will replace the nine spaces between pairs with two spaces for better visual separation.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I used the same number of spaces as used in documents generated with ./build_product.

Comment on lines 264 to 265
title_tag = "{http://oval.mitre.org/XMLSchema/oval-definitions-5}title"
description_tag = "{http://oval.mitre.org/XMLSchema/oval-definitions-5}description"
Copy link
Collaborator

Choose a reason for hiding this comment

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

You should use the namespace from ssg/constants.py instead of hardcoding the URI here.

DATA_DIR, "minimal_oval_of_oval_ssg-sshd_rekey_limit_def.xml"
)

PROJECT_ROOT = os.path.join(
Copy link
Collaborator

Choose a reason for hiding this comment

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

It looks like this variable is not used anywhere.

Comment on lines 171 to 164
assert not oval_document_from_shorthand.variables
assert not oval_document_from_shorthand.states
Copy link
Collaborator

Choose a reason for hiding this comment

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

Wouldn't it be better to have some variables and states in the document as well? That would help you test them as well.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, I will prepare dog-food and extend the test.

@jan-cerny
Copy link
Collaborator

@Honny1 I'm missing any comment from you. Has every feedback been addressed?

@marcusburghardt
Copy link
Member

/ok-to-test

@openshift-ci openshift-ci bot added ok-to-test Used by openshift-ci bot. and removed needs-ok-to-test Used by openshift-ci bot. labels Sep 18, 2023
@Honny1
Copy link
Collaborator Author

Honny1 commented Sep 18, 2023

@jan-cerny Not yet.

@codeclimate
Copy link

codeclimate bot commented Sep 19, 2023

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

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

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

View more on Code Climate.

@Honny1 Honny1 marked this pull request as ready for review September 19, 2023 14:19
@openshift-ci openshift-ci bot removed the do-not-merge/work-in-progress Used by openshift-ci bot. label Sep 19, 2023
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 have reviewed the code. i have executed the unit tests locally and they passed. I have used your test pastebin but modified it for RHEL 9 and reviewed the generated OVAL and I have compared the input and the output. I have seen that every feedback has been addressed. Thanks for this PR.

@jan-cerny jan-cerny merged commit 9d151bc into ComplianceAsCode:master Sep 19, 2023
38 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement General enhancements to the project. Infrastructure Our content build system ok-to-test Used by openshift-ci bot.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants