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
Introduce platform dependent test scenarios #3627
Conversation
We face a problem that for a single rule we need to have different sets of test scenarios depending on target platform. For example, the rule 'auditd_audispd_encrypt_sent_records' exists on both RHEL 7 and RHEL 8, but on each of them a different file path and a different string is checked. We need to be able to define test scenarios that are applicable only to selected platforms and should be skipped when testing other platforms. This will be achieved by using platform option in scenario script headers. It works similar way we specify platforms in Bash remediations. We can use `multi_platform_rhel`, `multi_platform_fedora`, etc.
Hello @jan-cerny! Thanks for updating the PR.
Comment last updated on November 30, 2018 at 10:59 Hours UTC |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting concept, that the test scenario filtering/selection will be done using the platforms that the content is applicable to.
My main concern is that we will be maintaining another mapping in yet another place.
We should consolidate these mappings, in ssg/products.py
there is already a mapping from platform name to product name going on, I think it makes sense to consolidate it there.
tests/README.md
Outdated
The header consists of comments (starting by `#`). Possible values are: | ||
- `platform` is a comma-separated list of platforms where the test scenario can be run. This is similar to `platform` used in our remediations. Examples of values: `multi_platform_rhel`, `Red Hat Enterprise Linux 7`, `multi_platform_all`. If `platform` is not specified in the header, `multi_platform_all` is assumed. | ||
- `profiles` is a comma-separated list of profiles which are using this scenario. | ||
- `remediation` is a comma-separated list of allowed remediation types (eg. `bash`, `ansible`). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There can be none
option too, which specifies that a rule has no fix implemented at all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great catch! I'll update that.
tests/ssg_test_suite/common.py
Outdated
"Fedora": [ | ||
"cpe:/o:fedoraproject:fedora:28", | ||
"cpe:/o:fedoraproject:fedora:29", | ||
"cpe:/o:fedoraproject:fedora:30" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be possible to source these cpes from a place where we already track it?
For example the product.yml
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This mapping of product name to cpe could be outsourced to ssg/products.py
tests/ssg_test_suite/common.py
Outdated
} | ||
|
||
# Keys are strings used in test scenario header in 'platform' list | ||
TEST_MULTI_PLATFORMS = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In ssg/products.py
we already maintain a mapping of platforms to names.
I'd rather avoid maintaining a separate mapping, and extend that functionality to map from platforms to cpes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yuumasato Yes, I like the idea to have it defined at single place.
There are multiple problems with that:
- The CPEs for each product are defined in the product-specific
product.yml
. We probably shouldn't parse these files in the test suite. It would be better to change the content build system to source it from a single place as well. - The CPEs for derivatives (CentOS, Scientific Linux) are not defined in
product.yml
butssg/constants.py
. - The code in
ssg/products.py
maps shortened names of products (eg.rhel7
) to official names, eg. when you buildrhel7
product you need to know that you should also include remediations marked as one of['multi_platform_rhel','multi_platform_all', 'Red Hat Enterprise Linux 7']
. But we need kind of opposite mapping - eg. when we specifymulti_platform_rhel
we would like to expand it to['rhel6','rhel7']
and then convert it a list of CPEs.
I would like to have all the mappings defined at a single point. But I'm not sure if it's not a scope creep. Should it be done in a separate PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- The CPEs for each product are defined in the product-specific
product.yml
. We probably shouldn't parse these files in the test suite. It would be better to change the content build system to source it from a single place as well.
I'm not sure it would be better, for someone writing content, or adding a new product, it wouldn't be straight forward to go into ssg/constants.py
and add the mappings there.
I'm okay to go take this path for now, but in the end, I think all data specific for the product should be in its product.yml
, for example, the product tag name, full name, and cpes.
And the build system would know what products are part of which multi_platform_
label, and it gathers the data and builds the mappings.
This mapping of product could even be extended to something else, something not tied to the product name, but feature based. This could be a "label" defined in the product.yml
, that would aggregate rules, to products that provide the feature.
Some labels I can imagine:crypto_policy
, fips
, grub_legacy
, grub2
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yuumasato But that means that if we want to use it in test suite the test suite would have to parse all the product.yml
s.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jan-cerny yes. In the future we could.
tests/ssg_test_suite/rule.py
Outdated
platform_cpes = set(common.TEST_PLATFORMS[platform]) | ||
except KeyError: | ||
raise ValueError( | ||
"Platform '%s' is not supported by the test suite." % platform) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the reason a platform is not supported for testing?
Is it because there wouldn't be a mapping from the product name to its cpe?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it's exactly that. I agree it's kind of stupid. It is related to previous comment. Basically the problem is that it isn't easy to get such a mapping now and we'll need to change the way we define product names and CPEs to prevent maintaining a separate list of mappings for the test suite.
Gather CPEs from product.yml to a single location. We can reuse the mapping in our SSG test suite, which would be difficult if they're not in a single place.
@jan-cerny If you have surplus, you may consider testing some of the newly introduced functionality in the SSG unit-testing framework. In that case, check out the |
@matejak I have added a basic unit test for that. |
Putting it to rule module was a problem if you don't have docker. Addressing: _____ ERROR collecting tests/unit/ssg_test_suite/test_matches_platform.py ______ ImportError while importing test module '/home/jenkins/workspace/scap-security-guide-pull-requests/label/fedora/tests/unit/ssg_test_suite/test_matches_platform.py'. Hint: make sure your test modules/packages have valid Python names. Traceback: ../../tests/unit/ssg_test_suite/test_matches_platform.py:3: in <module> from ssg_test_suite import rule ../../tests/ssg_test_suite/rule.py:12: in <module> import ssg_test_suite.oscap as oscap ../../tests/ssg_test_suite/oscap.py:13: in <module> from ssg_test_suite import test_env ../../tests/ssg_test_suite/test_env.py:8: in <module> import docker E ModuleNotFoundError: No module named 'docker'
Unfortunately, I have discovered that in build_remediations.py we have a different logic that reuses the fact that build_remediations.py knows which product directory (eg. I have noticed that we could reuse my new code in the test suite and ssg.constants to refactor build_remediations.py and similar scripts. But I vote against doing this refactoring in this PR because that would be a scope creep. |
tests/ssg_test_suite/common.py
Outdated
scenario_cpes = set() | ||
for p in scenario_platforms: | ||
scenario_cpes |= _get_platform_cpes(p) | ||
print(scenario_cpes) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove this!
The inspection completed: 28 updated code elements |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The tests look good to me.
|
||
|
||
def test_wrong_multi_platform(): | ||
scenario_platforms = ["multi_platform_fidorka"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fidorka! :)
We face a problem that for a single rule we need to have different sets
of test scenarios depending on target platform. For example, the rule
'auditd_audispd_encrypt_sent_records' exists on both RHEL 7 and RHEL 8,
but on each of them a different file path and a different string
is checked. We need to be able to define test scenarios that are
applicable only to selected platforms and should be skipped when testing
other platforms.
This will be achieved by using platform option in scenario script headers.
It works similar way we specify platforms in Bash remediations. We can
use
multi_platform_rhel
,multi_platform_fedora
, etc.