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

[GSOC23] - D - Define RPC endpoints for listing the affected packages regarding a CVE #7570

Draft
wants to merge 53 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
3706544
Add basic oval types
HoussemNasri Jun 21, 2023
10f1ff4
Add OVAL Criteria and Criterion types
HoussemNasri Jun 21, 2023
f879c19
Create OVAL Linux extension types
HoussemNasri Jun 21, 2023
fdc3fd3
Implement the OVAL parser
HoussemNasri Jun 21, 2023
21143b6
Create OVALLookupHelper
HoussemNasri Jun 21, 2023
3517c70
Define database schema
HoussemNasri Sep 11, 2023
e3f67fd
Add SQL migration scripts
HoussemNasri Sep 11, 2023
23a0985
Define SQL queries for OVAL data
HoussemNasri Sep 11, 2023
2b1d0e5
Implement a CPE parser
HoussemNasri Sep 11, 2023
ab5cec0
Create CpeBuilder
HoussemNasri Sep 11, 2023
ca856f6
Add SUSEVulnerablePackageExtractor
HoussemNasri Sep 11, 2023
3460042
Add DebianVulnerablePackagesExtractor
HoussemNasri Sep 11, 2023
cec42da
Implement RedHat vulnerable package extractor
HoussemNasri Sep 11, 2023
a773f4d
Create a factory for vulnerable package extractors
HoussemNasri Sep 11, 2023
38b6ff5
Add cpe column to Server
HoussemNasri Sep 11, 2023
a74eb4f
Add custom grain module for CPE
HoussemNasri Sep 11, 2023
b564bba
Set minion's CPE upon registration
HoussemNasri Sep 11, 2023
8c2de76
Update minion's CPE upon package refresh
HoussemNasri Sep 11, 2023
1b9637d
Create OVALCachingFactory
HoussemNasri Sep 11, 2023
c61beaa
Implement equals() and hashcode() methods for Cve
HoussemNasri Sep 11, 2023
b4e9e34
Define more patch statuses
HoussemNasri Sep 11, 2023
d661e52
Restructure CVEAuditManager to be able to audit one system at a time
HoussemNasri Sep 11, 2023
6a28268
Create a lighter version of PackageListItem called ShallowSystemPackage
HoussemNasri Sep 11, 2023
d4b508b
Implement OVAL-based CVE auditing in CVEAuditManagerOVAL
HoussemNasri Sep 11, 2023
64d2af4
Create OVALCleaner
HoussemNasri Sep 11, 2023
011b7d6
Test CVEAuditManagerOVAL
HoussemNasri Sep 11, 2023
458c85d
Redirect calls from CVEAuditManager to CVEAuditManagerOVAL
HoussemNasri Sep 11, 2023
9eceed5
Update patch statuses in the frontend to prevent mapping error
HoussemNasri Sep 11, 2023
9a384da
Add missing license headers
HoussemNasri Aug 27, 2023
f2ea10c
Fix some checkstyle warnings
HoussemNasri Aug 27, 2023
4673838
Cleanup logging
HoussemNasri Sep 1, 2023
9bfcfee
Fix more checkstyle warnings
HoussemNasri Sep 1, 2023
aca2884
Fix failing tests
HoussemNasri Sep 1, 2023
c209eb8
Keep only the highest ranking patch for each vulnerable package
HoussemNasri Sep 4, 2023
a3998d8
Add test case: testDoAuditSystemPatchedWithIrrelevantErrata
HoussemNasri Sep 4, 2023
dff12f5
Add test case: testDoAuditSystemAffectedPatchInapplicableSuccessorPro…
HoussemNasri Sep 4, 2023
5677c69
Add testcases for when auditing against unknown and known CVEs
HoussemNasri Sep 4, 2023
b7d28bd
Remove OVAL patch definitions if they're not needed
HoussemNasri Sep 4, 2023
26d0420
Add code documentation for Server#cpe
HoussemNasri Sep 7, 2023
6412461
Delete createLeap15_4_Package() in tests
HoussemNasri Sep 14, 2023
973a535
Refactor CVEAuditManagerOVALTest
HoussemNasri Sep 14, 2023
ff1f32d
Vulnerable package extractor checkstyle
HoussemNasri Sep 14, 2023
4dd840e
OVALCachingFactory checkstyle
HoussemNasri Sep 14, 2023
463466a
CVEAuditManager checkstyle
HoussemNasri Sep 14, 2023
0bf1c1a
Checkstyle
HoussemNasri Sep 14, 2023
2a9b455
add todo
HoussemNasri Sep 16, 2023
3bc3e81
Distinguish between zero-day vulnerabilities and vulnerabilities with…
HoussemNasri Sep 17, 2023
1e7b017
Use a more detailed message instead of 'No action required' when patc…
HoussemNasri Sep 17, 2023
1e0d12c
Introduce a query to retrieve the list of packages affected by a spec…
HoussemNasri Sep 12, 2023
5c9603a
Add CVEAuditHandler#listAffectedSystems
HoussemNasri Sep 12, 2023
97abdbd
Implement listAffectedSystemsByCve
HoussemNasri Sep 18, 2023
37ee1a6
Document the 'listAffectedSystems' RPC endpoint
HoussemNasri Sep 18, 2023
4f5a7f4
Document the 'listAffectedSystemsByCve' RPC endpoint
HoussemNasri Sep 18, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,38 @@ SELECT PN.name as NAME,
<elaborator name="package_retracted_and_ptf_details" />
</mode>

<mode name="shallow_system_package_list" class="com.suse.oval.ShallowSystemPackage">
<query params="sid">
WITH highest_id_packages AS (
SELECT p.name_id, p.evr_id, p.package_arch_id, max(p.id) AS id
FROM rhnServerPackage sp
INNER JOIN rhnServer s ON sp.server_id = s.id
INNER JOIN rhnServerChannel sc on sc.server_id = s.id
INNER JOIN rhnChannelPackage cp on cp.channel_id = sc.channel_id
INNER JOIN rhnpackage p ON sp.evr_id = p.evr_id AND sp.name_id = p.name_id AND sp.package_arch_id = p.package_arch_id AND p.id = cp.package_id
WHERE sp.server_id = :sid AND (p.org_id = s.org_id or p.org_id is null)
GROUP BY p.name_id, p.evr_id, p.package_arch_id
)
SELECT p.id AS package_id,
pn.id || '|' || pe.id || '|' || pa.id as id_combo,
pn.name as name,
pa.label as arch,
pe.epoch as epoch,
pe.version as version,
pe.release as release,
pe.type AS type
FROM rhnPackageName pn
INNER JOIN rhnServerPackage sp ON sp.name_id = pn.id
INNER JOIN rhnServer s ON sp.server_id = s.id
INNER JOIN rhnPackageEvr pe ON sp.evr_id = pe.id
LEFT JOIN rhnPackageArch pa ON sp.package_arch_id = pa.id
LEFT JOIN highest_id_packages hp ON hp.name_id = sp.name_id AND hp.evr_id = sp.evr_id AND hp.package_arch_id = sp.package_arch_id
LEFT JOIN rhnpackage p ON hp.id = p.id
WHERE sp.server_id = :sid
</query>
</mode>


<mode name="system_canonical_package_list" class="com.redhat.rhn.frontend.dto.PackageListItem">
<query params="sid, org_id">
SELECT PN.id || '|' || SPE.id AS ID_COMBO,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
<template name="cve_audit_queries" filename="xml/cve_audit_queries.xml" />
<template name="ResetPassword_queries" filename="xml/ResetPassword_queries.xml" />
<template name="Product_queries" filename="xml/Product_queries.xml" />
<template name="oval_queries" filename="xml/oval_queries.xml"/>

<!-- Reporting queries -->
<template name="GeneralReport_queries" filename="xml/GeneralReport_queries.xml" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<datasource_modes>
<callable-mode name="add_product_vulnerable_package">
<query params="package_name, fix_version, product_name, cve_name">
call insert_product_vulnerable_packages(:package_name, :fix_version, :product_name, :cve_name)
</query>
</callable-mode>

<mode name="get_vulnerable_packages">
<query params="cve_name, product_cpe">
SELECT vulnerablePkg.name AS vulnerablePkgName, vulnerablePkg.fix_version AS vulnerablePkgFixVersion
FROM suseovalvulnerablepackage vulnerablePkg,
rhncve cve,
suseovalplatform platform,
suseovalplatformvulnerablepackage platVulnerablePkg
WHERE cve.name = :cve_name
AND platform.cpe = :product_cpe
AND platVulnerablePkg.cve_id = cve.id
AND platVulnerablePkg.platform_id = platform.id
AND platVulnerablePkg.vulnerable_pkg_id = vulnerablePkg.id;
</query>
</mode>

<mode name="can_audit_cve">
<query params="cve_name">
SELECT 1
FROM suseOVALPlatformVulnerablePackage platVul,
rhncve cve
WHERE platVul.cve_id = cve.id
AND cve.name = :cve_name;
</query>
</mode>

<mode name="list_systems_affected_packages">
<query params="cve_name">
SELECT rhnServer.id AS system_id,
rhnServer.name system_name,
rhnpackagename.name package_name,
rhnpackageevr.type package_type,
ovalVulPkg.fix_version patched_version,
rhnpackageevr.epoch installed_epoch,
rhnpackageevr.version installed_version,
rhnpackageevr.release installed_release,
rhncve.name cve
FROM rhnserver,
rhncve,
suseovalplatformvulnerablepackage ovalPlatVulPkg,
suseovalplatform ovalPlat,
suseovalvulnerablepackage ovalVulPkg,
rhnserverpackage serverPkg,
rhnpackagename,
rhnpackageevr
WHERE rhnserver.cpe = ovalPlat.cpe
AND rhnserver.id = serverPkg.server_id
AND rhnpackagename.id = serverPkg.name_id
AND rhnpackageevr.id = serverPkg.evr_id
AND rhnpackagename.name = ovalVulPkg.name
AND ovalPlatVulPkg.cve_id = rhncve.id
AND ovalPlatVulPkg.platform_id = ovalPlat.id
AND ovalPlatVulPkg.vulnerable_pkg_id = ovalVulPkg.id
AND rhncve.name = :cve_name;
</query>
</mode>

<mode name="list_systems_affected_packages_all_cves">
<query>
SELECT rhnServer.id system_id,
rhnServer.name system_name,
rhnpackagename.name package_name,
rhnpackageevr.type package_type,
ovalVulPkg.fix_version patched_version,
rhnpackageevr.epoch installed_epoch,
rhnpackageevr.version installed_version,
rhnpackageevr.release installed_release,
rhncve.name cve
FROM rhnserver,
rhncve,
suseovalplatformvulnerablepackage ovalPlatVulPkg,
suseovalplatform ovalPlat,
suseovalvulnerablepackage ovalVulPkg,
rhnserverpackage serverPkg,
rhnpackagename,
rhnpackageevr
WHERE rhnserver.cpe = ovalPlat.cpe
AND rhnserver.id = serverPkg.server_id
AND rhnpackagename.id = serverPkg.name_id
AND rhnpackageevr.id = serverPkg.evr_id
AND rhnpackagename.name = ovalVulPkg.name
AND ovalPlatVulPkg.cve_id = rhncve.id
AND ovalPlatVulPkg.platform_id = ovalPlat.id
AND ovalPlatVulPkg.vulnerable_pkg_id = ovalVulPkg.id
</query>
</mode>
</datasource_modes>
28 changes: 28 additions & 0 deletions java/code/src/com/redhat/rhn/domain/errata/Cve.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
* in this software or its documentation.
*/
package com.redhat.rhn.domain.errata;

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;

/**
*
*
Expand Down Expand Up @@ -48,4 +52,28 @@ public void setName(String nameIn) {
public String getName() {
return name;
}

/**
* {@inheritDoc}
*/
@Override
public boolean equals(final Object other) {
if (!(other instanceof Cve)) {
return false;
}
Cve castOther = (Cve) other;
return new EqualsBuilder()
.append(id, castOther.id)
.isEquals();
}

/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return new HashCodeBuilder()
.append(id)
.toHashCode();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
*/
package com.redhat.rhn.domain.rhnpackage;

import java.util.EnumSet;

public enum PackageType {
RPM("rpm"),
DEB("deb");
Expand All @@ -27,4 +29,10 @@ public enum PackageType {
public String getDbString() {
return dbString;
}

public static PackageType fromDbString(String dbString) {
return EnumSet.allOf(PackageType.class).stream()
.filter(packageType -> packageType.dbString.equals(dbString))
.findAny().orElseThrow();
}
}
19 changes: 19 additions & 0 deletions java/code/src/com/redhat/rhn/domain/server/Server.java
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ public class Server extends BaseDomainHelper implements Identifiable {
private MaintenanceSchedule maintenanceSchedule;
private Boolean hasConfigFeature;

private String cpe;

public static final String VALID_CNAMES = "valid_cnames_";

/**
Expand Down Expand Up @@ -2459,4 +2461,21 @@ public void setOsFamily(String osFamilyIn) {
this.osFamily = osFamilyIn;
}

/**
* Getter for CPE (Common Platform Enumeration)
*
* @return cpe
* */
public String getCpe() {
return cpe;
}

/**
* Setter for CPE (Common Platform Enumeration)
*
* @param cpeIn to set
* */
public void setCpe(String cpeIn) {
this.cpe = cpeIn;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
<property name="digitalServerId" column="digital_server_id" type="string"
length="1024"/>
<property name="os" column="os" type="string" length="64"/>
<property name="cpe" column="cpe" type="string" length="64"/>
<property name="release" column="release" type="string" length="64"/>
<property name="name" column="name" type="string" length="128"/>
<property name="description" column="description" type="string"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Copyright (c) 2023 SUSE LLC
*
* This software is licensed to you under the GNU General Public License,
* version 2 (GPLv2). There is NO WARRANTY for this software, express or
* implied, including the implied warranties of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
* along with this software; if not, see
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*
* Red Hat trademarks are not licensed under GPLv2. No permission is
* granted to use or replicate Red Hat trademarks that are incorporated
* in this software or its documentation.
*/

package com.redhat.rhn.frontend.xmlrpc.audit;

import com.redhat.rhn.domain.rhnpackage.PackageEvr;
import com.redhat.rhn.domain.rhnpackage.PackageType;

import java.util.Objects;

/**
* A package that is affected by a vulnerability .i.e. CVE, but not necessarily vulnerable if the installed version is
* patched.
*/
public class CVEAffectedPackage {
private String packageName;
private String installedVersion;
private String patchedVersion;
private PackageType packageType;
private Status status;

public CVEAffectedPackage(String packageName, String installedVersion, String patchedVersion,
PackageType packageType) {
Objects.requireNonNull(packageName);
Objects.requireNonNull(packageType);
Objects.requireNonNull(installedVersion);

this.packageName = packageName;
this.installedVersion = installedVersion;
this.patchedVersion = patchedVersion;
this.packageType = packageType;

updateStatus();
}

public String getPackageName() {
return packageName;
}


public String getInstalledVersion() {
return installedVersion;
}

public String getPatchedVersion() {
return patchedVersion;
}

public Status getStatus() {
return status;
}

public PackageType getPackageType() {
return packageType;
}

private void updateStatus() {
// No patches are currently available for this package; therefore, if it is installed,
// it must be running on a vulnerable version.
if (patchedVersion == null) {
status = Status.VULNERABLE;
return;
}

boolean isPackagePatched = PackageEvr.parsePackageEvr(packageType, installedVersion)
.compareTo(PackageEvr.parsePackageEvr(packageType, patchedVersion)) >= 0;

status = isPackagePatched ? Status.PATCHED : Status.VULNERABLE;
}

public enum Status {
PATCHED, VULNERABLE
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright (c) 2023 SUSE LLC
*
* This software is licensed to you under the GNU General Public License,
* version 2 (GPLv2). There is NO WARRANTY for this software, express or
* implied, including the implied warranties of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
* along with this software; if not, see
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*
* Red Hat trademarks are not licensed under GPLv2. No permission is
* granted to use or replicate Red Hat trademarks that are incorporated
* in this software or its documentation.
*/

package com.redhat.rhn.frontend.xmlrpc.audit;

import java.util.ArrayList;
import java.util.List;

/**
* A server that is affected by a CVE
* */
public class CVEAffectedServer {
private Long id;
private String name;
private List<CVEAffectedPackage> affectedPackages;

public CVEAffectedServer(Long id, String name, List<CVEAffectedPackage> affectedPackages) {
this.id = id;
this.name = name;
this.affectedPackages = new ArrayList<>(affectedPackages);
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public List<CVEAffectedPackage> getAffectedPackages() {
return affectedPackages;
}

public void setAffectedPackages(List<CVEAffectedPackage> affectedPackages) {
this.affectedPackages = affectedPackages;
}
}
Loading
Loading