Code Monkey home page Code Monkey logo

yardstick's Introduction

yardstick

A tool that can parse and compare the results of vulnerability scanner tools.

Manage and explore scan results:

# capture a new scan result for a specific tool and image
yardstick result capture --image ubuntu:20.04 -t [email protected]

# list all scan results that have been captured
yardstick result list

# explore the scan results interactively
yardstick result explore <UUID>

Manage true positive / false positive labels for images:

# explore labels applied to specific scan-result matches for an image and tool pair
yardstick label explore <UUID>

# list all managed labels
yardstick label list

Supported scanners:

  • grype
  • syft

F.A.Q.

"Why is syft on this list? It's not a vulnerability scanner!"

Right you are, however, capturing SBOM results that can be fed into grype or for reference during analysis is quite useful!

"Yardstick doesn't support vulnerability scanner X..."

PR's are welcome! The goal of this tool is to provide the analysis capabilities to understand how we can make these scanners better.

Result Sets

Result sets can be useful to operate on and track results from scans taken at the same time. For instance:

# .yardstick.yaml
result-sets:
  example:
    matrix:
      images:
        - ubuntu:20.04
      tools:
        - name: grype
          version: v0.32.0
        - name: grype
          version: v0.48.0
# capture results for all tools
$ yardstick result capture -r example

# see the specific result details
$ yardstick result list -r example

# perform a label comparison using all tooling
$ yardstick label compare -r example

Configuration

Sample application config:

# .yardstick.yaml

x-ref:
  images: &images
    - docker.io/cloudbees/cloudbees-core-mm:2.346.4.1@sha256:b8ec61aad2f5f9be2dc9c68923eab1de0e8b026176093ad2e0742fca310bf3bf

result-sets:
  pr-vs-latest:
    description: "latest released grype vs grype from the current build"
    matrix:
      images: *images
      tools:
        - name: syft                      # go ahead and capture an SBOM each time to help analysis later
          version: v0.54.0
          produces: SBOM

        - name: grype                     # from the latest published github release
          version: latest
          takes: SBOM

        - name: grype:pr                  # from a local PR checkout install (feed via an environment variable)
          version: env:CURRENT_GRYPE_COMMIT
          takes: SBOM

CLI Commands

  config  show the application config

  label   manage match labels

    add                   add a match label indication for an image
    apply                 see which labels apply to the given image and...
    compare               compare a scan result against labeled data
    compare-by-ecosystem  show TPs/FPs/Precision from label comparison...
    explore               interact with an label results for a single image...
    images                show all images derived from label data
    list                  show all labels
    remove                remove a match label indication for an image
    set-image-parent      set the parent image for a given image
    show-image-lineage    show all parents and children for the given image

  result  manage image scan results

    capture  capture all tool output for the given image
    clear    remove all results and result sets
    compare  show a comparison between tool output
    explore  interact with an image scan result
    images   list images in results
    import   import results for a tool that were run externally
    list     list stored results
    sets     list configured result sets
    show     show a the results for a single scan + tool
    tools    list tools in results

yardstick's People

Contributors

dependabot[bot] avatar juanjsebgarcia avatar kzantow avatar spiffcs avatar tgerla avatar wagoodman avatar westonsteimel avatar willmurphyscode avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

yardstick's Issues

Update documentation to specify what kind of thing an ID or DESCRIPTION is

What would you like to be added:

A lot of yardstick commands accept something like DESCRIPTION or ID, but it's not obvious what this string is. Example:

❯ yardstick label explore --help
Usage: yardstick label explore [OPTIONS] DESCRIPTION

  interact with an label results for a single image scan

Options:
  -y, --year-max-limit TEXT       max year to include in comparison (relative
                                  to the CVE ID)
  -c, --derive-year-from-cve-only
                                  only use the CVE ID year-max-limit
  --help                          Show this message and exit.

In this case, DESCRIPTION is really a result set UUID obtained by running yardstick result list and looking for the image+tool combo the user is interested in. But nothing about DESCRIPTION makes it obvious what to pass in our how to get it.

Why is this needed:

The use of generic parameter names like ID and DESCRIPTION in the docs makes it very hard to come up to speed in yardstick.

Additional context:

`make cli` fails on main on M1 mac

What happened:

Running git clone [email protected]:anchore/yardstick ytest && cd ytest && make bootstrap && poetry install && make all fails because it can't install an old enough grype on main.

What you expected to happen:

All the validation targets should pass on a clean checkout of main.

How to reproduce it (as minimally and precisely as possible):

git clone [email protected]:anchore/yardstick ytest && cd ytest && make bootstrap && poetry install && make all

Anything else we need to know?:

Hypothesis

This is likely because the requested version of grype, https://github.com/anchore/grype/releases/tag/v0.27.0, only has a zip for the darwin_arm64 image, but has a .dmg for darwin_amd64.

Later releases of grype, such as https://github.com/anchore/grype/releases/tag/v0.50.2, have a .tar.gz for both versions.

Stacktrace of failure:

one
[info] checking github for release tag='v0.27.0'
[info] fetching release script for tag='v0.27.0'
anchore/grype info checking GitHub for tag 'v0.27.0'
anchore/grype info found version: 0.27.0 for v0.27.0/darwin/arm64
Traceback (most recent call last):
  File "/private/tmp/ytest/tests/cli/venv/bin/yardstick", line 8, in <module>
    sys.exit(cli())
  File "/private/tmp/ytest/tests/cli/venv/lib/python3.9/site-packages/click/core.py", line 1130, in __call__
    return self.main(*args, **kwargs)
  File "/private/tmp/ytest/tests/cli/venv/lib/python3.9/site-packages/click/core.py", line 1055, in main
    rv = self.invoke(ctx)
  File "/private/tmp/ytest/tests/cli/venv/lib/python3.9/site-packages/click/core.py", line 1657, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/private/tmp/ytest/tests/cli/venv/lib/python3.9/site-packages/click/core.py", line 1657, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/private/tmp/ytest/tests/cli/venv/lib/python3.9/site-packages/click/core.py", line 1404, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/private/tmp/ytest/tests/cli/venv/lib/python3.9/site-packages/click/core.py", line 760, in invoke
    return __callback(*args, **kwargs)
  File "/private/tmp/ytest/tests/cli/venv/lib/python3.9/site-packages/click/decorators.py", line 38, in new_func
    return f(get_current_context().obj, *args, **kwargs)
  File "/private/tmp/ytest/src/yardstick/cli/result.py", line 45, in capture_results
    capture.result_set(
  File "/private/tmp/ytest/src/yardstick/capture.py", line 164, in result_set
    scan_config = one(scan_request, producer_state=producer_data_path, profiles=profiles)
  File "/private/tmp/ytest/src/yardstick/capture.py", line 105, in one
    match_results, raw_json = run_scan(config=scan_config, profile=profile_obj)
  File "/private/tmp/ytest/src/yardstick/capture.py", line 32, in run_scan
    tool = tool_cls.install(version=config.tool_version, path=path, use_cache=not reinstall, **kwargs)
  File "/private/tmp/ytest/src/yardstick/tool/grype.py", line 207, in install
    tool_obj = cls._install_from_installer(version=version, path=path, use_cache=use_cache, **kwargs)
  File "/private/tmp/ytest/src/yardstick/tool/grype.py", line 65, in _install_from_installer
    os.chmod(f"{path}/grype", 0o755)
FileNotFoundError: [Errno 2] No such file or directory: '.yardstick/tools/grype/v0.27.0/grype'
Exited with 1
make[1]: *** [test] Error 1
make: *** [cli] Error 2

Environment:

  • Output of yardstick version: yardstick 0.0.0 (using a dev build off main)
  • OS (e.g: cat /etc/os-release or similar): M1 macbook pro

`yardstick label explore ...` should provide way to focus on unlabeled matches

What would you like to be added:

When I run yardstick label explore <some-uuid> I should be able to quickly find any matches that are not labeled.

Why is this needed:

Otherwise, when labeling results for an image with a lot of matches, many of which are already labeled, searching for unlabeled matches involves a lot of additional scrolling.

Additional context:

`yardstick label remove $ID` doesn't remove any label but exits zero and logs success

What happened:

Running yardstick label remove 73bd6255-d663-4a07-8eca-a7555902898f from test/quality directory in Grype doesn't remove the label with that ID, but does log [INFO] removed 1 labels and exit zero

❯ yardstick label remove 73bd6255-d663-4a07-8eca-a7555902898f                                                                                                                               
/Users/willmurphy/work/grype1373/test/quality/venv/lib/python3.9/site-packages/urllib3/__init__.py:34: NotOpenSSLWarning: urllib3 v2.0 only supports OpenSSL 1.1.1+, currently the 'ssl' module is compiled with 'LibreSSL 2.8.3'. See: https://github.com/urllib3/urllib3/issues/3020
  warnings.warn(
2023-07-26 10:06:59,182 [INFO] removed 1 labels
❯ echo $? 
0
❯ jq . ./vulnerability-match-labels/labels/registry.access.redhat.com+ubi8@sha256:68fecea0d255ee253acbf0c860eaebb7017ef5ef007c25bee9eeffd29ce85b29/73bd6255-d663-4a07-8eca-a7555902898f.json
{
  "ID": "73bd6255-d663-4a07-8eca-a7555902898f",
  "effective_cve": "CVE-2020-26137",
  "image": {
    "exact": "registry.access.redhat.com/ubi8@sha256:68fecea0d255ee253acbf0c860eaebb7017ef5ef007c25bee9eeffd29ce85b29"
  },
  "label": "TP",
  "package": {
    "name": "urllib3",
    "version": "1.24.2"
  },
  "timestamp": "2022-09-15T19:43:11-04:00",
  "user": "wagoodman",
  "vulnerability_id": "GHSA-wqvq-5m8c-6g24"
}

What you expected to happen:

I expected the label to be removed or, if something is wrong, the log of an error and a non-zero exit code.

How to reproduce it (as minimally and precisely as possible):

git clone [email protected]:anchore/grype --recurse-submodules /tmp/repro-yardstick-issue
cd /tmp/repro-yardstick-issue
cd ./test/quality
. venv/bin/activate
yardstick label remove 73bd6255-d663-4a07-8eca-a7555902898f
cd ./vulnerability-match-labels
git status

If the removal succeeded, the last git status should have printed the diff indicating that the label was removed, specifically the file at labels/registry.access.redhat.com+ubi8@sha256:68fecea0d255ee253acbf0c860eaebb7017ef5ef007c25bee9eeffd29ce85b29/73bd6255-d663-4a07-8eca-a7555902898f.json should have been deleted.

Anything else we need to know?:

Environment:

  • Output of yardstick version:
❯ yardstick version
/Users/willmurphy/work/grype1373/test/quality/venv/lib/python3.9/site-packages/urllib3/__init__.py:34: NotOpenSSLWarning: urllib3 v2.0 only supports OpenSSL 1.1.1+, currently the 'ssl' module is compiled with 'LibreSSL 2.8.3'. See: https://github.com/urllib3/urllib3/issues/3020
  warnings.warn(
yardstick 0.7.0 (/Users/willmurphy/work/grype1373/test/quality/venv/lib/python3.9/site-packages)
  • OS (e.g: cat /etc/os-release or similar):
❯ uname -m -s -r -v
Darwin 22.5.0 Darwin Kernel Version 22.5.0: Thu Jun  8 22:22:20 PDT 2023; root:xnu-8796.121.3~7/RELEASE_ARM64_T6000 arm64

yardstick should know about quality gates

What would you like to be added:

Right now, yardstick can capture the difference between different tool outputs, but it has no notion of a label provider, and tools that compare yardstick results to known labels implement two mechanisms on their own:

  1. A mechanism to fetch some labels to use in comparison. (grype uses git submodules for this mechanism.)
  2. A mechanism to run a quality gate, for example so that too great a deviation from known labels fails a job in CI. Grype's gate.py is an example.

The core request is: a yardstick.yaml file should be able to configure two additional things: where do my labels come from? And what comparison methods and thresholds are considered success vs failure.

One way we've discussed this is: a label source and a comparator should be sort of like "tools" in yardstick's config model.

Why is this needed:

Right now, we're maintaining a fair amount of python code in different repos that fetches labels and runs different comparisons. All of these comparison codes fetch labels and run comparisons in similar, but not identical ways. We should promote this duplicated code into a new configurable section in yardstick.

Additional context:

Want to capture similar labels that don't affect statistics negatively

Today you can find the same match more than one way, when labeling these matches there tends to be one match that is "most correct" and others that "are technically correct". For instance, what if in one version of grype we don't consider RPM epoch but in a future version we do consider the epoch... the label for the match with the epoch included is more correct, but that doesn't mean that the original label without the epoch is wrong.

The problem with this situation is that without choosing to label the match as either TP or FP then quality gates will start failing over time due to a high number of indeterminate matches. An indeterminate match is a match that is either:

  • unlabeled
  • has been explicitly labeled as unclear
  • has multiple labels that conflict (TP and FP labels for example)

There are a couple paths forward here:

  1. don't count unclear labels as indeterminate. The advantage is that gating can still pass, but if the behavior regresses and the pairing TP match is not made (but the unclear match is) then the F1 score goes down, which is ultimately a good behavior.
  2. add the concept of a TP alias label, where the label can stand in as a TP for another label, but if it's missing it won't count as a FN. This has the advantage of allowing the F1 score to remain unchanged in either matching scenario (even if a match is "better" or "not as good" if at least one is found then it does not matter, nothing will be counted against you).

Support tools that are both SBOM generators and vulnerability scanners

What would you like to be added:

Support for tools that are both SBOM generators and vulnerability scanners. Currently we could work around this by adding two unique entries for the tool, and this may be the easiest path forward for now, but would be nice to discuss if there is some design enhancement we can make for a single tool to support both.

make it possible to install grype from a local path

What would you like to be added:

Right now, you can installed tools from a release or a pushed commit somewhere on GH. We should enable yardstick to "install" a tool by building it from a path.

Why is this needed:

Running make quality in grype has 2 unexpected behaviors right now:

  1. If your local commit isn't pushed to a remote, it will fail
  2. If you have uncommitted local changes, the tests will succeed, but will use grype built without those changes (because yardstick downloaded the last commit from GitHub.)

Number 2 could be especially frustrating to debug, and might surprise contributors.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.