From dde1d31b480c7cc9e2e80b9420979c05aa1f9c0d Mon Sep 17 00:00:00 2001 From: jfuller Date: Fri, 10 Mar 2023 11:17:22 +0100 Subject: [PATCH 1/3] remove unfinished plugins --- griffon/commands/plugins/exploits.py | 28 ----------- griffon/commands/plugins/mfsa.py | 72 ---------------------------- 2 files changed, 100 deletions(-) delete mode 100644 griffon/commands/plugins/exploits.py delete mode 100644 griffon/commands/plugins/mfsa.py diff --git a/griffon/commands/plugins/exploits.py b/griffon/commands/plugins/exploits.py deleted file mode 100644 index 27d10c2..0000000 --- a/griffon/commands/plugins/exploits.py +++ /dev/null @@ -1,28 +0,0 @@ -""" -exploits plugin: - - -""" -import logging - -import click - -logger = logging.getLogger("griffon") - -api_url = "" - - -# define autocomplete for service names -@click.group(help="(UNDER DEV) exploits plugin") -@click.pass_context -def plugins(ctx): - """exploits plugin""" - pass - - -@plugins.command() -@click.option("--name", "service_name") -@click.pass_context -def stub(ctx, service_name): - """ """ - pass diff --git a/griffon/commands/plugins/mfsa.py b/griffon/commands/plugins/mfsa.py deleted file mode 100644 index cfabc4e..0000000 --- a/griffon/commands/plugins/mfsa.py +++ /dev/null @@ -1,72 +0,0 @@ -""" -Mozila advisories plugin: - - https://github.com/mozilla/foundation-security-advisories plugin - -Run the following to setup the plugin (installs pyyaml and pulls git repo) -> griffon z_mfsa setup - -""" -import logging -import os -import subprocess - -import click - -from griffon import GRIFFON_CONFIG_DIR - -logger = logging.getLogger("griffon") - -api_url = "https://api.osv.dev/v1/query" - - -@click.group(help="(UNDER DEV) MFSA plugin") -@click.pass_context -def plugins(ctx): - """https://github.com/mozilla/foundation-security-advisories plugin""" - pass - - -@plugins.command() -@click.pass_context -def update(ctx): - subprocess.run( - [ - "git", - "log", - "--graph", - "--pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset'", # noqa - "--abbrev-commit", - ], - cwd=os.path.expanduser("~/.griffon/repos/foundation-security-advisories"), - ) - - -@plugins.command(help="Run this first, installs pyyaml amd pulls repo") -@click.pass_context -def setup(ctx): - subprocess.run(["pip", "install", "pyyaml"]) - if not os.path.exists(os.path.expanduser(f"{GRIFFON_CONFIG_DIR}/repos")): - os.makedirs(os.path.expanduser(f"{GRIFFON_CONFIG_DIR}/repos")) - subprocess.run( - ["git", "clone", "https://github.com/mozilla/foundation-security-advisories.git"], - cwd=os.path.expanduser(f"{GRIFFON_CONFIG_DIR}/repos"), - ) - - -@plugins.command() -@click.pass_context -def advisories(ctx): - pass - - -@plugins.command() -@click.pass_context -def get(ctx): - pass - - -@plugins.command() -@click.pass_context -def search(ctx): - pass From deece493e035f66ed8551f1c900ec24bf5002460 Mon Sep 17 00:00:00 2001 From: jfuller Date: Fri, 10 Mar 2023 11:17:34 +0100 Subject: [PATCH 2/3] docs --- docs/tutorial.md | 50 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/docs/tutorial.md b/docs/tutorial.md index 4eb59b7..ccd857e 100644 --- a/docs/tutorial.md +++ b/docs/tutorial.md @@ -1,9 +1,9 @@ ## Tutorial (UNDER DEVELOPMENT) -Find products a (latest) Component is in +Find Products that contain latest root Component(s) > griffon service products-contain-component webkitgtk -One may use the -s flag for strict search +Use -s flag for stricter search > griffon service products-contain-component -s webkitgtk And regex expressions @@ -16,18 +16,58 @@ Use of -v (up to -vvvv) to get more information > griffon -vvv service products-contain-component "^webkitgtk(\d)" > griffon -vvvv service products-contain-component "^webkitgtk(\d)" -Retrieve a product summary +Find Products that contain latest root Component(s) searching both root and dependencies +> griffon service products-contain-component webkitgtk --search-all + +Find Products that contain latest root Component searching both root and related_url +> griffon service products-contain-component webkitgtk --search-related-url + +Retrieve a Product summary > griffon service product-summary -s rhel-7.6.z > griffon --format json service product-summary -s rhel-7.6.z -Retrieve a product manifest +Retrieve a Product manifest containing both latest root Component and dependencies > griffon service product-components rhel-9.0.0.z Retrieve a spdx json formatted product manifest > griffon service product-manifest ansible_automation_platform-2.3 --spdx-json Retrieve component flaws -> griffon service component-flaws is-svg +> griffon service component-flaws Retrieve product flaws > griffon service product-flaws ansible_automation_platform-2 --affectedness AFFECTED --affect-resolution FIX + +## Common questions + +Given a CVE ID, what products are affected? +> griffon service products-affected-by-flaw CVE-2023-25166 + +Given a CVE ID, what components are affected? +> griffon service components-affected-by-flaw CVE-2023-25166 + +What products + version + stream contain a given component (e.g. full +text search)? +> griffon service products-contain-component --purl "pkg:rpm/curl@7.15.5" +> griffon service products-contain-component is-svg --search-all + +Which unfixed CVE are affecting a component ? +> griffon service component-flaws --affectedness AFFECTED webkitgtk + +Which unfixed CVE are affecting a product + version + stream ? +> griffon service product-flaws ansible_platform_2 + +What are the fixed CVE of this a product + version + stream? +> griffon service product-flaws rhel-9 --flaw-state DONE + +What are the fixed CVEs for a component? +> griffon service component-flaws webkitgtk --flaw-state DONE + +What are the won’t fix CVEs for a component? +> griffon service component-flaws webkitgtk --flaw-resolution WONTFIX + +What are the won’t fix CVEs for a product? +> griffon service product-flaws rhel-9 --flaw-resolution WONTFIX + +How many CVE’s are filed against a product + version +> griffon service product-flaws rhel-9 | wc -l From 9b965ce523f9c6a9ec6162b3483ae65c8b14813c Mon Sep 17 00:00:00 2001 From: jfuller Date: Fri, 10 Mar 2023 11:17:52 +0100 Subject: [PATCH 3/3] add some more flags to products-contain-component --- griffon/commands/queries.py | 37 +++++++++++++++--- griffon/output.py | 7 ++++ griffon/services/core_queries.py | 65 ++++++++++++++++++++++++++++++-- scripts/smoke-tests.sh | 1 + 4 files changed, 101 insertions(+), 9 deletions(-) diff --git a/griffon/commands/queries.py b/griffon/commands/queries.py index 798c0c1..ae92fbd 100644 --- a/griffon/commands/queries.py +++ b/griffon/commands/queries.py @@ -103,18 +103,25 @@ def get_product_summary(ctx, product_stream_name, strict_name_search): help="Generate Affects.", ) @click.option( - "--search-all", - "search_all", + "--search-latest", + "search_latest", is_flag=True, default=False, - help="Search root Components and dependencies.", + help="Search root Components (enabled by default).", ) @click.option( "--search-related-url", "search_related_url", is_flag=True, default=False, - help="Search related url.", + help="Search related url (enabled by default).", +) +@click.option( + "--search-all", + "search_all", + is_flag=True, + default=False, + help="Search root Components and dependencies.", ) @click.option( "--search-community", @@ -123,6 +130,13 @@ def get_product_summary(ctx, product_stream_name, strict_name_search): default=False, help="(Not Implemented) Search community Components.", ) +@click.option( + "--search-upstreams", + "search_upstreams", + is_flag=True, + default=False, + help="Search for Components by upstream.", +) @click.pass_context @progress_bar def get_product_contain_component( @@ -134,9 +148,11 @@ def get_product_contain_component( component_type, strict_name_search, affect_mode, - search_all, + search_latest, search_related_url, + search_all, search_community, + search_upstreams, ): """List products of a latest component.""" if not purl and not component_name: @@ -144,6 +160,17 @@ def get_product_contain_component( click.echo("") click.echo("Must supply Component name or --purl.") exit(0) + + if ( + not search_latest + and not search_all + and not search_related_url + and not search_community + and not search_upstreams + ): + ctx.params["search_latest"] = True + ctx.params["search_related_url"] = True + if component_name: q = query_service.invoke(core_queries.products_containing_component_query, ctx.params) cprint(q, ctx=ctx) diff --git a/griffon/output.py b/griffon/output.py index b5d0d2b..1f87e9b 100644 --- a/griffon/output.py +++ b/griffon/output.py @@ -195,6 +195,7 @@ def text_output_products_contain_component(ctx, output, format): if sources: source_purl = PackageURL.from_string(sources[0]["purl"]) root_component = f"{source_purl.name}-{source_purl.version}" + dep_name = name.replace(component_name, f"[b]{component_name}[/b]") dep = f"[white]({dep_name})[/white]" console.print( @@ -229,6 +230,7 @@ def text_output_products_contain_component(ctx, output, format): root_component = f"{source_purl.name}-{source_purl.version}" dep_name = name.replace(component_name, f"[b]{component_name}[/b]") dep = f"[white]({dep_name})[/white]" + related_url = related_url.replace(component_name, f"[b]{component_name}[/b]") console.print( Text(ps, style="magenta b u"), root_component, @@ -259,14 +261,19 @@ def text_output_products_contain_component(ctx, output, format): if sources: source_purl = PackageURL.from_string(sources[0]["purl"]) root_component = f"{source_purl.name}-{source_purl.version}" + upstream = "" + if item["upstream_purl"]: + upstream = f"[cyan]{item['upstream_purl']}[/cyan]" dep_name = name.replace(component_name, f"[b]{component_name}[/b]") dep = f"[white]({dep_name})[/white]" + related_url = related_url.replace(component_name, f"[b]{component_name}[/b]") console.print( Text(ps, style="magenta b u"), root_component, dep, related_url, build_source_url, + upstream, no_wrap=False, ) diff --git a/griffon/services/core_queries.py b/griffon/services/core_queries.py index 6089915..b5c639f 100644 --- a/griffon/services/core_queries.py +++ b/griffon/services/core_queries.py @@ -157,9 +157,11 @@ class products_containing_component_query: "component_type", "strict_name_search", "affect_mode", + "search_latest", "search_all", "search_related_url", "search_community", + "search_upstreams", ] def __init__(self, params: dict) -> None: @@ -170,9 +172,11 @@ def __init__(self, params: dict) -> None: self.strict_name_search = self.params.get("strict_name_search") self.search_deps = self.params.get("search_deps") self.ns = self.params.get("namespace") + self.search_latest = self.params.get("search_latest") self.search_all = self.params.get("search_all") self.search_related_url = self.params.get("search_related_url") self.search_community = self.params.get("search_community") + self.search_upstreams = self.params.get("search_upstreams") def execute(self) -> List[Dict[str, Any]]: cond = {"view": "latest"} @@ -184,15 +188,17 @@ def execute(self) -> List[Dict[str, Any]]: if self.component_type: cond["type"] = self.component_type - result = self.corgi_session.components.retrieve_list(**cond, limit=1000) - results = result.results + results = [] + if self.search_latest: + result = self.corgi_session.components.retrieve_list(**cond, limit=1000) + results = result.results if self.search_related_url: # TODO - not in bindings yet related_url_search = requests.get( f"{CORGI_API_URL}/api/v1/components", params={ - "include_fields": "name,arch,namespace,release,version,nvr,type,link,purl,software_build,product_versions,product_streams,sources", # noqa + "include_fields": "name,arch,namespace,release,version,nvr,type,link,purl,software_build,product_versions,product_streams,sources,upstreams", # noqa "related_url": self.component_name, "limit": 10000, }, @@ -231,6 +237,8 @@ def execute(self) -> List[Dict[str, Any]]: component["build_id"] = c["software_build"]["build_id"] component["build_type"] = c["software_build"]["build_type"] component["build_source_url"] = c["software_build"]["source"] + if c["upstreams"]: + component["upstream_purl"] = c["upstreams"][0]["purl"] results.append(component) if self.search_all: @@ -238,7 +246,7 @@ def execute(self) -> List[Dict[str, Any]]: related_url_search = requests.get( f"{CORGI_API_URL}/api/v1/components", params={ - "include_fields": "name,arch,namespace,release,version,nvr,type,link,purl,software_build,product_versions,product_streams,sources", # noqa + "include_fields": "name,arch,namespace,release,version,nvr,type,link,purl,software_build,product_versions,product_streams,sources,upstreams", # noqa "re_name": self.component_name, "limit": 10000, }, @@ -277,8 +285,57 @@ def execute(self) -> List[Dict[str, Any]]: component["build_id"] = c["software_build"]["build_id"] component["build_type"] = c["software_build"]["build_type"] component["build_source_url"] = c["software_build"]["source"] + if c["upstreams"]: + component["upstream_purl"] = c["upstreams"][0]["purl"] results.append(component) + if self.search_upstreams: + # TODO - not in bindings yet + related_url_search = requests.get( + f"{CORGI_API_URL}/api/v1/components", + params={ + "include_fields": "name,arch,namespace,release,version,nvr,type,link,purl,software_build,product_versions,product_streams,sources,upstreams", # noqa + "upstreams": self.component_name, + "limit": 10000, + }, + ) + + for c in related_url_search.json()["results"]: + for pv in c["product_versions"]: + for ps in c["product_streams"]: + + is_dep = False + if c["arch"] == "src" or c["arch"] == "noarch": + is_dep = True + component = { + "is_dep": is_dep, + "product_version": pv["name"], + "product_version_ofuri": pv["ofuri"], + "product_stream": ps["name"], + "product_stream_ofuri": ps["ofuri"], + "product_active": True, + "purl": c["purl"], + "type": c["type"], + "namespace": c["namespace"], + "name": c["name"], + "arch": c["arch"], + "release": c["release"], + "version": c["version"], + "sources": c["sources"], + "nvr": c["nvr"], + "build_id": None, + "build_type": None, + "build_source_url": None, + "related_url": None, + "upstream_purl": None, + } + if c["software_build"]: + component["build_id"] = c["software_build"]["build_id"] + component["build_type"] = c["software_build"]["build_type"] + component["build_source_url"] = c["software_build"]["source"] + if c["upstreams"]: + component["upstream_purl"] = c["upstreams"][0]["purl"] + results.append(component) return results diff --git a/scripts/smoke-tests.sh b/scripts/smoke-tests.sh index 9b87538..f3e7637 100755 --- a/scripts/smoke-tests.sh +++ b/scripts/smoke-tests.sh @@ -19,6 +19,7 @@ griffon --format text service components-affected-by-flaw CVE-2023-25166 griffon --format text service products-contain-component nmap griffon service products-contain-component --purl "pkg:rpm/curl@7.29.0" +griffon service products-contain-component webkitgtk --search-related-url --search-latest --search-all # reports griffon service report-affects