Пример #1
0
def test_distromappings(anchore_db):
    _init_distro_mappings()

    c7 = DistroNamespace(name='centos', version='7', like_distro='centos')
    assert c7.mapped_names() == []
    assert c7.like_namespace_names == ['rhel:7']

    r7 = DistroNamespace(name='rhel', version='7', like_distro='centos')
    assert set(r7.mapped_names()) == {'centos', 'fedora', 'rhel'}
    assert r7.like_namespace_names == ['rhel:7']

    assert sorted(DistroMapping.distros_mapped_to('rhel', '7')) == sorted([
        DistroTuple('rhel', '7', 'RHEL'),
        DistroTuple('centos', '7', 'RHEL'),
        DistroTuple('fedora', '7', 'RHEL')
    ])
Пример #2
0
def find_vulnerable_image_packages(vulnerability_obj):
    """
    Given a vulnerability object, find images that are affected via their package manifests.
    Result may have duplicates based on match type, caller must de-dup if desired.

    :param vulnerability_obj:
    :return: list of ImagePackage objects
    """
    db = get_thread_scoped_session()
    distro, version = vulnerability_obj.namespace_name.split(":", 1)
    dist = DistroNamespace(distro, version)
    related_names = (
        dist.mapped_names()
    )  # Returns list of names that map to this one, not including itself necessarily
    # related_names = get_namespace_related_names(distro, version, mapped_names)

    # TODO would like a better way to do the pkg_type <-> namespace_name mapping, with other side in ImagePackage.vulnerabilities_for_package
    likematch = None
    if (":maven" in vulnerability_obj.namespace_name
            or "java" in vulnerability_obj.namespace_name):
        likematch = "java"
    elif (":ruby" in vulnerability_obj.namespace_name
          or "gem" in vulnerability_obj.namespace_name):
        likematch = "gem"
    elif (":js" in vulnerability_obj.namespace_name
          or "npm" in vulnerability_obj.namespace_name):
        likematch = "npm"
    elif "python" in vulnerability_obj.namespace_name:
        likematch = "python"

    try:
        affected = []
        if vulnerability_obj.fixed_in:
            # Check the fixed_in records
            for fix_rec in vulnerability_obj.fixed_in:
                package_candidates = []

                # Find packages of related distro names with compatible versions, this does not have to be precise, just an initial filter.
                pkgs = (db.query(ImagePackage).filter(
                    ImagePackage.distro_name.in_(related_names),
                    ImagePackage.distro_version.like(dist.version + "%"),
                    or_(
                        ImagePackage.name == fix_rec.name,
                        ImagePackage.normalized_src_pkg == fix_rec.name,
                    ),
                ).all())
                package_candidates += pkgs

                # add non distro candidates
                if likematch:
                    pkgs = (db.query(ImagePackage).filter(
                        ImagePackage.pkg_type.in_(nonos_package_types),
                        ImagePackage.pkg_type.like(likematch),
                        or_(
                            ImagePackage.name == fix_rec.name,
                            ImagePackage.normalized_src_pkg == fix_rec.name,
                        ),
                    ).all())
                    package_candidates += pkgs

                for candidate in package_candidates:
                    if fix_rec.match_but_not_fixed(candidate):
                        affected.append(candidate)

        if vulnerability_obj.vulnerable_in:
            # Check the vulnerable_in records
            for vuln_rec in vulnerability_obj.vulnerable_in:
                package_candidates = []
                # Find packages of related distro names with compatible versions, this does not have to be precise, just an initial filter.
                pkgs = (db.query(ImagePackage).filter(
                    ImagePackage.distro_name.in_(related_names),
                    ImagePackage.distro_version.like(dist.version + "%"),
                    or_(
                        ImagePackage.name == vuln_rec.name,
                        ImagePackage.normalized_src_pkg == vuln_rec.name,
                    ),
                ).all())
                package_candidates += pkgs
                for candidate in package_candidates:
                    if vuln_rec.match_and_vulnerable(candidate):
                        affected.append(candidate)

        return affected
    except Exception as e:
        logger.exception(
            "Failed to query and find packages affected by vulnerability: {}".
            format(vulnerability_obj))
        raise
Пример #3
0
def find_vulnerable_image_packages(vulnerability_obj):
    """
    Given a vulnerability object, find images that are affected via their package manifests.
    Result may have duplicates based on match type, caller must de-dup if desired.

    :param vulnerability_obj:
    :return: list of ImagePackage objects
    """
    db = get_thread_scoped_session()
    distro, version = vulnerability_obj.namespace_name.split(':', 1)
    dist = DistroNamespace(distro, version)
    related_names = dist.mapped_names() # Returns list of names that map to this one, not including itself necessarily

    # Filter related_names down based on the presence of actual feeds/cve data. If there is an actual feed for a name, remove it from the list.
    # Only do this if the list of related names is not just the name itself. (e.g. alpine = [alpine]).
    if related_names != [distro]:
        # Ensure we don't include any names that actually have a feed (can happen when new feeds arrive before the mapped_names() source
        # is updated to break the 'like' relation between the distros.
        related_names = [x for x in related_names if namespace_has_no_feed(x, version)]

        # This is a weird case because it basically means that this distro doesn't map to itself as far as mapped_names() is
        # concerned, but since that could be code lagging data (e.g. new feed group added for a new distro), add the name itself
        # back into the list.
        if distro not in related_names and not namespace_has_no_feed(distro, version):
            related_names.append(distro)

    # TODO would like a better way to do the pkg_type <-> namespace_name mapping, with other side in ImagePackage.vulnerabilities_for_package
    likematch = None
    if ':maven' in vulnerability_obj.namespace_name or 'java' in vulnerability_obj.namespace_name:
        likematch = 'java'
    elif ':ruby' in vulnerability_obj.namespace_name or 'gem' in vulnerability_obj.namespace_name:
        likematch = 'gem'
    elif ':js' in vulnerability_obj.namespace_name or 'npm' in vulnerability_obj.namespace_name:
        likematch = 'npm'
    elif 'python' in vulnerability_obj.namespace_name:
        likematch = 'python'

    try:
        affected = []
        if vulnerability_obj.fixed_in:
            # Check the fixed_in records
            for fix_rec in vulnerability_obj.fixed_in:
                package_candidates = []

                # Find packages of related distro names with compatible versions, this does not have to be precise, just an initial filter.
                pkgs = db.query(ImagePackage).filter(ImagePackage.distro_name.in_(related_names), ImagePackage.distro_version.like(dist.version + '%'), or_(ImagePackage.name == fix_rec.name, ImagePackage.normalized_src_pkg == fix_rec.name)).all()
                package_candidates += pkgs

                # add non distro candidates
                if likematch:
                    pkgs = db.query(ImagePackage).filter(ImagePackage.pkg_type.in_(nonos_package_types), ImagePackage.pkg_type.like(likematch), or_(ImagePackage.name == fix_rec.name, ImagePackage.normalized_src_pkg == fix_rec.name)).all()
                    package_candidates += pkgs

                for candidate in package_candidates:
                    if fix_rec.match_but_not_fixed(candidate):
                        affected.append(candidate)

#        if vulnerability_obj.vulnerable_in:
#            # Check the vulnerable_in records
#            for vuln_rec in vulnerability_obj.vulnerable_in:
#                package_candidates = []
#                # Find packages of related distro names with compatible versions, this does not have to be precise, just an initial filter.
#                pkgs = db.query(ImagePackage).filter(ImagePackage.distro_name.in_(related_names),
#                                                    ImagePackage.distro_version.like(dist.version + '%'),
#                                                    or_(ImagePackage.name == fix_rec.name,
#                                                        ImagePackage.normalized_src_pkg == fix_rec.name)).all()
#               package_candidates += pkgs
#               for candidate in package_candidates:
#                   if vuln_rec.match_and_vulnerable(candidate):
#                       affected.append(candidate)

        return affected
    except Exception as e:
        log.exception('Failed to query and find packages affected by vulnerability: {}'.format(vulnerability_obj))
        raise