Last active
February 25, 2022 13:06
-
-
Save garethr/ed4b2848181d7a670e5f42e5fa8ccb25 to your computer and use it in GitHub Desktop.
A quick example of a shim for PURL for the Snyk APIs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
This python scipt is a basic demonstration of providing a shim for the Snyk test APIs for PURL. | |
This provides a nicer, higher level interface. It was predominantly written to demonstrate | |
the simplicity of mapping (most of) PURL to the existing Snyk test APIs. | |
Usage | |
> purl2snyk test pkg:pypi/[email protected] | |
> purl2snyk test pkg:maven/org.apache.logging.log4j/[email protected] | |
Things not done here: | |
* Dealing with qualifiers and subpaths | |
Note that the Snyk test APIs do support repository for the Maven endpoint, but that isn't | |
exposed in pysnyk, which is the only reason it's not implemented here. | |
* No attempt to address output. The output is the straight Snyk API response. | |
* Covering only the core test APIs. It should be relatively simple with a bit more work to | |
extend this to deb, rpm, Go and Nuget using the lower-level DepGraph API. | |
""" | |
import os | |
import sys | |
import urllib.parse | |
import click | |
import snyk | |
from packageurl import PackageURL | |
class UnsupportedPurlTypeError(Exception): | |
pass | |
@click.group() | |
def cli(): | |
pass | |
def maven(purl, org): | |
return org.test_maven(purl.namespace, purl.name, purl.version) | |
def gem(purl, org): | |
return org.test_rubygem(purl.name, purl.version) | |
def pypi(purl, org): | |
return org.test_python(purl.name, purl.version) | |
def encode_npm_package_name(purl): | |
if purl.namespace: | |
return urllib.parse.quote_plus(f"{purl.namespace}/{purl.name}") | |
else: | |
return purl.name | |
def npm(purl, org): | |
return org.test_npm(encode_npm_package_name(purl), purl.version) | |
def tester(repo): | |
TESTERS = { | |
"maven": maven, | |
"gem": gem, | |
"pypi": pypi, | |
"npm": npm, | |
} | |
try: | |
return TESTERS[repo] | |
except KeyError: | |
raise UnsupportedPurlTypeError | |
@cli.command() | |
@click.argument("purl") | |
def test(purl): | |
try: | |
token = os.environ["SNYK_TOKEN"] | |
except KeyError: | |
sys.exit("You must provide a SNYK_TOKEN to run purl2snyk") | |
client = snyk.SnykClient(token) | |
org = client.organizations.first() | |
try: | |
purl_obj = PackageURL.from_string(purl) | |
except ValueError: | |
sys.exit(f"You must provide a valid PURL: {purl}") | |
if purl_obj.qualifiers or purl_obj.subpath: | |
sys.exit(f"PURL qualifiers and subpaths are currently unsupported") | |
try: | |
result = tester(purl_obj.type)(purl_obj, org) | |
except UnsupportedPurlTypeError: | |
sys.exit(f"PURLs of type '{purl_obj.type}' are not currently supported") | |
click.echo(result) | |
if __name__ == "__main__": | |
cli() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[tool.poetry] | |
name = "purl2snyk" | |
version = "0.1.0" | |
description = "" | |
authors = ["Gareth Rushgrove <[email protected]>"] | |
[tool.poetry.dependencies] | |
python = "^3.9" | |
packageurl-python = "^0.9.9" | |
pysnyk = "^0.7.0" | |
click = "^8.0.4" | |
[tool.poetry.dev-dependencies] | |
pytest = "^6.0" | |
pytest-black = "^0.3.12" | |
pytest-isort = "^3.0.0" | |
[tool.poetry.scripts] | |
purl2snyk = 'purl2snyk:cli' | |
[build-system] | |
requires = ["poetry-core>=1.0.0"] | |
build-backend = "poetry.core.masonry.api" | |
[tool.pytest.ini_options] | |
addopts = "--black --isort --verbose" | |
minversion = "6.0" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment