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

Add new command sbom:cyclonedx #66

Merged
merged 48 commits into from
Sep 26, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
754904f
Add new command recipe:create-sbom
hedtke Aug 3, 2023
31b701c
Use cyclonedx package instead of creating the BOM by hand
hedtke Aug 8, 2023
1b00c9d
Set qualifier repository_url only when non-default
hedtke Aug 8, 2023
146ff48
Use conan_api instead of parsing the graph JSON
hedtke Aug 8, 2023
04fe713
Update readme
hedtke Aug 8, 2023
8180214
Add qualifier repository_url only for nodes with a remote
hedtke Aug 8, 2023
9d9c97d
Test new command
hedtke Aug 8, 2023
6598768
Add missing newline
hedtke Aug 8, 2023
556d658
Simplify main method
hedtke Aug 8, 2023
f1cbb03
Make new command work with conanfile.txt and graph --requires
hedtke Aug 9, 2023
3d32812
Test more variants for the call of the new command
hedtke Aug 9, 2023
a181c97
Drop old reference to the Conan graph JSON in the doc string
hedtke Aug 9, 2023
35ba8d8
Enforce a format option
hedtke Aug 9, 2023
f4b0482
Use try except for imports of external libs
hedtke Aug 9, 2023
6729dd4
Install optonal packages for new sbom command in tests
hedtke Aug 9, 2023
c4866de
Drop the usage of global variables
hedtke Aug 9, 2023
db9438d
Mention dependencies in README
hedtke Aug 9, 2023
4d6cd25
Import from conans only then TYPE_CHECKING is enabled
hedtke Aug 9, 2023
a580461
Fix linter warnings
hedtke Aug 9, 2023
3315b1d
Rename helper method in test_create_sbom
hedtke Aug 9, 2023
fde2a3d
Do not sys.exit when imports are not found
hedtke Aug 9, 2023
ddbe204
Import external packages locally
hedtke Aug 10, 2023
7f96f14
Replace auxiliary dictionary by a static variable
hedtke Aug 10, 2023
207daee
Set language in markdown code blocks
hedtke Aug 10, 2023
ba38915
Do not explicitly depend on packageurl-python as this a requirement o…
hedtke Aug 10, 2023
dcd6f0b
Change type of code blocks in readme from shell to shellSession
hedtke Aug 11, 2023
e271e68
Add myself as tool
hedtke Aug 11, 2023
b9a1291
Add type annotation to licenses() method
hedtke Aug 14, 2023
ebb5737
restructured for maintenance
jkowalleck Aug 14, 2023
a1b2b1e
fix test formatter
jkowalleck Aug 14, 2023
0ab8c10
additional ignores from dev-processes
jkowalleck Aug 14, 2023
be76b9f
decouple and simplify name gathering
jkowalleck Aug 14, 2023
97f38c2
Merge pull request #1 from jkowalleck/hedtke-sbom-restructure1
hedtke Aug 15, 2023
ee19212
Add comma in print command
hedtke Aug 15, 2023
4ce29c0
Comply with PIP8
hedtke Aug 15, 2023
42b44d7
Support all output formats
hedtke Aug 15, 2023
0bdd800
Fix typo in list of formatters
hedtke Aug 16, 2023
cec1afb
fix call of new command in tests
hedtke Aug 16, 2023
da78b7d
Also make stdout in tools.run a parameter
hedtke Aug 17, 2023
21634ca
Test all output formats
hedtke Aug 17, 2023
4002763
Support also python 3.6
hedtke Aug 24, 2023
a14672d
Rename recipe:create-sbom to sbom:cyclonedx
hedtke Sep 12, 2023
82a6bfc
Drop argument sbom_format and use format
hedtke Sep 12, 2023
2d4ff1a
Rename tests
hedtke Sep 12, 2023
3f752a6
Chrry-pick 96fb5a7c0a5a56b736e7582ef98511a96b917ddb
hedtke Sep 13, 2023
eb5a8e1
Add SBOM section to README
hedtke Sep 13, 2023
a434963
Fix group of new conan command
hedtke Sep 13, 2023
766df4d
Update extensions/commands/sbom/cmd_cyclonedx.py
memsharded Sep 26, 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
70 changes: 70 additions & 0 deletions extensions/commands/recipe/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,73 @@ updating moltenvk/1.2.0 to moltenvk/1.2.2 in conan-center-index/recipes/qt/6.x.x
updating libjpeg-turbo/2.1.4 to libjpeg-turbo/2.1.5 in conan-center-index/recipes/qt/6.x.x/conanfile.py:386
Successfully bumped the dependencies of recipe conan-center-index/recipes/qt/6.x.x/conanfile.py
```

#### [Create SBOM](cmd_create_sbom.py)

For the graph JSON passed as parameter it creates an SBOM in CycloneDX 1.4 JSON format.

**Parameters**
- **graph_json**: Path to Conan generated graph JSON output file.

```
$ conan graph info -f json --requires=openssl/3.1.1 > openssl_graph.json
hedtke marked this conversation as resolved.
Show resolved Hide resolved
$ conan recipe:create-sbom ./openssl_graph.json
{
"$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json",
"bomFormat": "CycloneDX",
"specVersion": "1.4",
"version": 1,
"dependencies": [
{
"ref": "1"
},
{
"ref": "2"
}
],
"components": [
{
"type": "library",
"bom-ref": "1",
"purl": "pkg:conan/[email protected]?repository_url=conancenter&rref=3a25e05b364f335633143656dc265841",
"licenses": [
{
"license": {
"id": "Apache-2.0"
}
}
],
"name": "openssl",
"version": "3.1.1",
"description": "A toolkit for the Transport Layer Security (TLS) and Secure Sockets Layer (SSL) protocols",
"externalReferences": [
{
"url": "https://github.com/openssl/openssl",
"type": "website"
}
]
},
{
"type": "library",
"bom-ref": "2",
"purl": "pkg:conan/[email protected]?prev=724b61ab750aa7f88abacafc926395d3&repository_url=https://center.conan.io&rref=13c96f538b52e1600c40b88994de240f",
"licenses": [
{
"license": {
"id": "Zlib"
}
}
],
"name": "zlib",
"version": "1.2.13",
"description": "A Massively Spiffy Yet Delicately Unobtrusive Compression Library (Also Free, Not to Mention Unencumbered by Patents)",
"externalReferences": [
{
"url": "https://zlib.net",
"type": "website"
}
]
}
]
}
```
86 changes: 86 additions & 0 deletions extensions/commands/recipe/cmd_create_sbom.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import json
from packageurl import PackageURL
hedtke marked this conversation as resolved.
Show resolved Hide resolved

from conan.api.output import cli_out_write
from conan.api.conan_api import ConanAPI
from conan.cli.command import conan_command


def licenses(id):
"""
see https://cyclonedx.org/docs/1.4/json/#components_items_licenses
"""
if id is None:
return []
else:
return [{"license": {
"id": id
hedtke marked this conversation as resolved.
Show resolved Hide resolved
}}]


def package_url(node: dict) -> PackageURL:
"""
Creates a PURL following https://github.com/package-url/purl-spec/blob/master/PURL-TYPES.rst#conan
"""
qualifiers = {
"prev": node["prev"]
}
if node["user"]:
qualifiers["user"] = node["user"]
if node["channel"]:
qualifiers["channel"] = node["channel"]
if "#" in node["ref"]:
qualifiers["rref"] = node["ref"].split("#")[1]
hedtke marked this conversation as resolved.
Show resolved Hide resolved
qualifiers["repository_url"] = node["remote"] if node["remote"] else "https://center.conan.io"
hedtke marked this conversation as resolved.
Show resolved Hide resolved
return PackageURL(
type="conan",
name=node["name"],
version=node["version"],
qualifiers=qualifiers)


def component(n: dict) -> dict:
"""
see https://cyclonedx.org/docs/1.4/json/#components
"""
result = {
"type": "library",
"bom-ref": n["id"],
hedtke marked this conversation as resolved.
Show resolved Hide resolved
"purl": package_url(n).to_string(),
"licenses": licenses(n["license"]),
"name": n["name"],
"version": n["version"]
}
if n["description"]:
result["description"] = n["description"]
if n["homepage"]:
result["externalReferences"] = [{
"url": n["homepage"],
"type": "website"
}]
return result


@conan_command(group="Recipe")
def create_sbom(conan_api: ConanAPI, parser, *args):
"""
creates an SBOM in CycloneDX 1.4 JSON format from a Conan graph JSON
hedtke marked this conversation as resolved.
Show resolved Hide resolved
"""
parser.add_argument("graph_json", help="Path to Conan generated graph JSON output file.")
args = parser.parse_args(*args)
with open(args.graph_json, 'r') as f:
data = json.load(f)
hedtke marked this conversation as resolved.
Show resolved Hide resolved
deps = data["graph"]["nodes"]
deps.pop("0")
cyclonedx = {
"$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json", # https not allowed here, see schema
"bomFormat": "CycloneDX",
"specVersion": "1.4",
"version": 1,
"dependencies": [{
"ref": n
} for n in deps],
"components": [component(n) for n in deps.values()]
}
json_result = json.dumps(cyclonedx, indent=4)
cli_out_write(json_result)