Skip to content

ROX-13794: Make node analyzer return content sets, not cpes - #1055

Merged
jvdm merged 11 commits into
masterfrom
jvdm/ROX-13794/node-analyzer/pull
Jan 20, 2023
Merged

ROX-13794: Make node analyzer return content sets, not cpes#1055
jvdm merged 11 commits into
masterfrom
jvdm/ROX-13794/node-analyzer/pull

Conversation

@jvdm

@jvdm jvdm commented Jan 13, 2023

Copy link
Copy Markdown
Contributor

Description and rationale

Populate RHEL Content Sets in the return value of certified RHEL components detection.

This will be consumed by Compliance node scanning and eventually sent to Central Scanner through scannerV1.Component to be mapped to CPEs. Analysis detection used to perform the CPE mapping on detection, and that is left for backward compatibility. Still, the mapping results in nil gracefully if CPE mapping is not available, which is the case for node scanning.

Tests

  • UTs.

@vikin91

vikin91 commented Jan 16, 2023

Copy link
Copy Markdown
Contributor

We also must make sure that the GetNodeVulnerabilitiesRequest.Components from https://github.com/stackrox/scanner/blob/master/proto/scanner/api/v1/node_scan_service.proto contains the content_sets instead/additionally to CPEs.

Otherwise Central will not be able to pass the content_sets to Scanner through the GetNodeVulnerabilities API.

Base automatically changed from jvdm/ROX-13794/proto-updates/pull to master January 16, 2023 17:33
@jvdm jvdm self-assigned this Jan 16, 2023
@jvdm
jvdm requested review from Maddosaurus and RTann and removed request for RTann January 16, 2023 18:56
@ghost

ghost commented Jan 16, 2023

Copy link
Copy Markdown

Images are ready for the commit at 3d1a547.

To use the images, use the tag 2.27.x-39-g3d1a547e8d.

@jvdm
jvdm requested review from daynewlee and vikin91 January 16, 2023 19:36
@jvdm jvdm changed the title Make node analyzer return content sets, not cpes ROX-13794: Make node analyzer return content sets, not cpes Jan 16, 2023

@RTann RTann left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm not sure we can guarantee there is a single content_manifest per node since its a culmination of all layers of an image. We knew there was one per layer, but there may be more for the image as a whole

Comment thread pkg/analyzer/detection/detection.go
Comment thread pkg/analyzer/detection/detection.go Outdated
var err error

// In the current state, RHCOS will always be handled as certified system.
// If no CPEs are found on RHCOS, a note needs to be added that informs users of it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

this comment may need to be adjusted since we are looking at content sets now

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, it may. Obviously, the comment mentions CPE, which will no longer be handled in RHCOS detection. But other aspects of the comment might still be relevant. What is your suggestion?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

sorry I was referring specifically to the CPE part of this line

@jvdm jvdm Jan 18, 2023

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I reviewed this, and the comment needs to be refactored. Not only the mention of CPE. It is fixed in 3d1a547

logrus.WithFields(logrus.Fields{LogLayerName: name, "feature count": len(featureVersions)}).Debug("detected features")
}
logrus.WithFields(logrus.Fields{
LogLayerName: name,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm actually not familiar with this key

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Do you mean we should change it or remove it? Not clear what your suggestion is.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

oh I was hoping you'd tell me what it was 😄 I just checked, and it's the word "Layer"

rhelfeatures := &database.RHELv2Components{
Dist: namespace.Name,
Packages: packages,
// CPEs are mapped and returned with content sets for backward compatibility.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Needed for scanning images in OCR. Perhaps we can update that path, too, which would also eliminate the need to pass those over from Central -> Sensor -> Scanner in another PR, if it works out

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I see where you coming from. When looking at this patch, it is natural to try to eliminate CPE mapping in detection altogether. But the handling outside RHCOS scanning might be more complex.

I intentionally haven't investigated further. Perhaps database models need to be adjusted in Central Scanner, for example. In any case, I already created an issue ROX-14414 to track this, as we should consider it in a different context.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

sounds good! Yeah definitely not in the scope of this PR

ContentSets: contentSets,
}
if err := rpm.AnnotateComponentsWithPackageManagerInfo(files, languageComponents); err != nil {
logrus.WithError(err).Errorf("Failed to analyze package manager info for language components: %s", name)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I wonder if we should make this a warning since we do ignore it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It could be a warning. What is your suggestion?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

hmmm I'm thinking maybe keep it as an Error log, but maybe we also mention that we are going to continue with the analysis? That being said, this log is not new, so perhaps this is out-of-scope

Comment thread pkg/rhelv2/rpm/rpm.go Outdated
Comment on lines +27 to +31
// AllRHELRequiredFiles lists all the names of the files required to identify RHEL-based releases.
var AllRHELRequiredFiles set.StringSet

// contentManifests set with all known directories that might contain content manifest files.
var contentManifestDirs set.StringSet

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
// AllRHELRequiredFiles lists all the names of the files required to identify RHEL-based releases.
var AllRHELRequiredFiles set.StringSet
// contentManifests set with all known directories that might contain content manifest files.
var contentManifestDirs set.StringSet
var (
// AllRHELRequiredFiles lists all the names of the files required to identify RHEL-based releases.
var AllRHELRequiredFiles set.StringSet
// contentManifests set with all known directories that might contain content manifest files.
var contentManifestDirs set.StringSet
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

also nit: comment name should start with the variable's name

@jvdm jvdm Jan 18, 2023

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed at 0ee2223

Comment thread pkg/rhelv2/rpm/rpm.go Outdated
for _, prefix := range contentManifestDirs.AsSlice() {
for name, file := range files.GetFilesPrefix(prefix) {
if strings.HasSuffix(name, ".json") {
// Return the first one found, as there should be only one dir per layer/node.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: file not dir

Also, I'm not 100% sure we can guarantee it's 1 per node. An image can have more than one (I've seen up to three in the wild), and if a node is essentially a running container, then I think it's possible a node can have more than one.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Oh, interesting. The logic was kept the same as in the previous patch. If, in fact, there can be multiple Content Sets per image/node, we need to know how to process all these content sets.

I noticed that there is some other metadata associated with each content set file, so it might be possible that when working with multiple, we need to process them differently. Or maybe concatenating them on a list. Hopefully.

I am going to keep the original data and follow up separately.

@jvdm jvdm Jan 18, 2023

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I actually noticed that in the proposed patch we were actually returning the last content set instead of the first one. This was fixed at e096fa7

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Maybe we should update this to allow for more than one content set per image layer (therefore node as well). That should not hurt image scanning results, and will allow for multiple content sets per node (maybe in a separate PR if we mark this with a TODO or something). I believe just appending each file's ContentSets into a slice is sufficient.

You bring up another point: are we sure RHCOS nodes' content_sets use the same format we are currently expecting? I'm not sure. Has this been discussed?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Maybe we should update this to allow for more than one content set per image layer (therefore, node as well).

Maybe. Another possibility is leaving the content set detection unchanged as we collect more information on the multiple contents sets scenario. For example, we need to know how RHCOS content sets are created in their builds or how multiple content sets map to packages and layers used in the final container to decide the correct approach.

Perhaps it is also unnecessary to keep this PR blocked and hold potential demos while we gather these answers. Instead, maybe it's even better to have a functioning scanning in which we can start doing E2E/manual testing and enrich our questions.

You bring up another point: are we sure RHCOS nodes' content_sets use the same format we are currently expecting?

I thought content sets have a schema. Or are you referring to RHCOS using a new version of the schema?

// Expected values for assertion.
sampleExpectedPkgs []*database.RHELv2Package
unexpectedPkgs []*database.RHELv2Package
expectedCPEs []string

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

do we test the mapping from content set to CPE in repo2cpe? If not, we should do that there, so we don't lose this test

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Do you mean

func TestMapping(t *testing.T) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

yep 😄

@jvdm
jvdm requested a review from RTann January 18, 2023 00:15
Comment thread pkg/analyzer/detection/detection.go Outdated
var err error

// In the current state, RHCOS will always be handled as certified system.
// If no CPEs are found on RHCOS, a note needs to be added that informs users of it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

sorry I was referring specifically to the CPE part of this line

logrus.WithFields(logrus.Fields{LogLayerName: name, "feature count": len(featureVersions)}).Debug("detected features")
}
logrus.WithFields(logrus.Fields{
LogLayerName: name,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

oh I was hoping you'd tell me what it was 😄 I just checked, and it's the word "Layer"

Comment thread pkg/analyzer/detection/detection.go
rhelfeatures := &database.RHELv2Components{
Dist: namespace.Name,
Packages: packages,
// CPEs are mapped and returned with content sets for backward compatibility.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

sounds good! Yeah definitely not in the scope of this PR

ContentSets: contentSets,
}
if err := rpm.AnnotateComponentsWithPackageManagerInfo(files, languageComponents); err != nil {
logrus.WithError(err).Errorf("Failed to analyze package manager info for language components: %s", name)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

hmmm I'm thinking maybe keep it as an Error log, but maybe we also mention that we are going to continue with the analysis? That being said, this log is not new, so perhaps this is out-of-scope

// Expected values for assertion.
sampleExpectedPkgs []*database.RHELv2Package
unexpectedPkgs []*database.RHELv2Package
expectedCPEs []string

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

yep 😄

Dist: namespace.Name,
Packages: packages,
// CPEs are mapped and returned with content sets for backward compatibility.
CPEs: repo2cpe.Singleton().Get(contentSets),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Just realized this may panic if it attempts to load a file and fails. It won't panic as long as REPO_TO_CPE_DIR is not defined (or is empty). Maybe we should reconsider the panic. It made sense before Scanner started to be used as a library like this, but now if we mess up, Compliance pods can panic. At the moment, it won't, but it could in the future if we aren't careful

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah, maybe. It depends on how the final container layout will be, how compliance consumes the Scanner library and the coupling between them. See ROX-13934, which captures this work.

Comment thread pkg/rhelv2/rpm/rpm.go
Comment on lines +100 to +102
if contents != nil {
break
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

So if we have multiple locations to search for - len(contentManifestDirs.AsSlice()) > 1 and we find a content in the first location contentManifestDirs[0], why are we are breaking the search here? Shouldn't we check also the other ones - i.e., contentManifestDirs[1], contentManifestDirs[2] and so on?

The current behavior would suggest that we are searching all location but we expect that the first hit is correct. Is it safe to assume that?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Shouldn't we check also the other ones - i.e., contentManifestDirs[1], contentManifestDirs[2] and so on?

We want to check all the contentManifestDirs but stop on the first file found. That is because we don't expect to find content sets in more than one directory.

Initially, this code would only search in one directory, the default directory for content sets in certified RHEL-based images. Now we are adding RHCOS, which uses a different location -- they have a limitation in their build that prevents them from writing to /root at compose time -- but we don't expect to see content sets in both locations.

The current behavior would suggest that we are searching all locations but we expect that the first hit is correct. Is it safe to assume that?

For RHCOS node scanning, we are starting to debate that assumption.

Based on the original discussion, it seems the image build would collect all repos used and populate one single file. But there are some reports of multiple content sets found "in the wild". Which might be caused by RHCOS customizations? We are not sure, but we are planning to follow up. In any case, maybe we should not try to capture that scenario without knowing more about it.

What do you think, @vikin91?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Okay this convinces me. I understand that the potential case of multiple content sets json files will be handled in a separate PR.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I haven't seen it in RHCOS, but I have in RHEL-based images, which makes me think it could always be possible in RHCOS unless told otherwise. For example, in https://catalog.redhat.com/software/containers/redhat-openjdk-18/openjdk18-openshift/58ada5701fbe981673cd6b10?container-tabs=overview I see this:

[jboss@3ae40f064f3c ~]$ ls /root/buildinfo/content_manifests/
redhat-openjdk-18-openjdk18-openshift-container-1.15-2.json
rhel-server-container-7.9-848.1669829396.json

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

we are planning to follow up

Do we have a ticket to track this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

we are planning to follow up

https://issues.redhat.com/browse/ROX-13794

@stackrox stackrox deleted a comment from RTann Jan 18, 2023
@stackrox stackrox deleted a comment from RTann Jan 18, 2023
@jvdm
jvdm requested a review from RTann January 18, 2023 19:51
@jvdm
jvdm requested a review from vikin91 January 18, 2023 20:45

@vikin91 vikin91 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good to me!

I would love to see it in action on OpenShift to see that it works - we can make such test before of after this is merged as this feat is behind a feature flag, so I am leaving the choice to you.

@jvdm

jvdm commented Jan 19, 2023

Copy link
Copy Markdown
Contributor Author

@vikin91:

I would love to see it in action on OpenShift to see that it works - we can make such test before of after this is merged as this feat is behind a feature flag, so I am leaving the choice to you.

I was planning to do that after working on the Scanner APIs. Glad you pushed towards it already. I will explore once that PR is merged.

Comment thread pkg/rhelv2/rpm/rpm.go
Comment on lines +100 to +102
if contents != nil {
break
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I haven't seen it in RHCOS, but I have in RHEL-based images, which makes me think it could always be possible in RHCOS unless told otherwise. For example, in https://catalog.redhat.com/software/containers/redhat-openjdk-18/openjdk18-openshift/58ada5701fbe981673cd6b10?container-tabs=overview I see this:

[jboss@3ae40f064f3c ~]$ ls /root/buildinfo/content_manifests/
redhat-openjdk-18-openjdk18-openshift-container-1.15-2.json
rhel-server-container-7.9-848.1669829396.json

Comment thread pkg/rhelv2/rpm/rpm.go
Comment on lines +100 to +102
if contents != nil {
break
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

we are planning to follow up

Do we have a ticket to track this?

@jvdm
jvdm merged commit cb0acb4 into master Jan 20, 2023
@jvdm
jvdm deleted the jvdm/ROX-13794/node-analyzer/pull branch January 20, 2023 01:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants