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

Export specific format versions (SPDX) #1228

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -325,12 +325,26 @@ Many compliance tools are compatible with SPDX. Tern follows the [SPDX specifica
```
$ tern report -f spdxtagvalue -i golang:1.12-alpine -o spdx.txt
```
By default, the report will be in SPDX version 2.2 (ISO SPDX).

The following syntax will output SPDX 2.3:
```
$ tern report -f [email protected] -i golang:1.12-alpine -o spdx.txt
```


## SPDX JSON Format<a name="report-spdxjson">
The SPDX JSON format contains the same information that an SPDX Tag-value document does. The only difference between these two formats is the way the information is represented. The 'spdxjson' format represents the container information as a collection of key-value pairs. In some cases, the SPDX JSON format may be more interoperable between cloud native compliance tools.
```
$ tern report -f spdxjson -i golang:1.12-alpine -o spdx.json
```
By default, the report will be in SPDX version 2.2 (ISO SPDX).

The following syntax will output SPDX 2.3:
```
$ tern report -f [email protected] -i golang:1.12-alpine -o spdx.json
```


## CycloneDX JSON Format<a name="report-cyclonedxjson">
[OWASP CycloneDX](https://cyclonedx.org/) is a lightweight software bill of materials standard designed for use in application security contexts and supply chain component analysis. The National Telecommunications and Information Administration (NTIA) [recognizes CycloneDX](https://www.ntia.gov/files/ntia/publications/sbom_options_and_decision_points_20210427-1.pdf) as one of three valid SBOM formats that satisfies the minimum viable requirements for an SBOM in accordance with President Biden's [Executive Order on Improving the Nation's Cybersecurity](https://www.whitehouse.gov/briefing-room/presidential-actions/2021/05/12/executive-order-on-improving-the-nations-cybersecurity/).
Expand Down
2 changes: 1 addition & 1 deletion tern/formats/spdx/spdxjson/formats.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@


# document level strings
spdx_version = 'SPDX-2.2'
spdx_version = 'SPDX-'
data_license = 'CC0-1.0'
spdx_id = 'SPDXRef-DOCUMENT'
document_name = 'Tern report for {image_name}'
Expand Down
8 changes: 4 additions & 4 deletions tern/formats/spdx/spdxjson/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ def get_document_namespace_snapshot(timestamp):
timestamp=timestamp, uuid=spdx_common.get_uuid())


def get_document_dict(image_obj, template):
def get_document_dict(image_obj, template, spdxv):
'''Return document info as a dictionary'''
docu_dict = {
'SPDXID': json_formats.spdx_id,
'spdxVersion': json_formats.spdx_version,
'spdxVersion': json_formats.spdx_version+spdxv,
'creationInfo': {
'created': json_formats.created.format(
timestamp=spdx_common.get_timestamp()),
Expand Down Expand Up @@ -140,7 +140,7 @@ def get_document_dict_snapshot(layer_obj, template):


class SpdxJSON(generator.Generate):
def generate(self, image_obj_list, print_inclusive=False):
def generate(self, image_obj_list, print_inclusive=False, spdxv='2.2'):
'''Generate an SPDX document
WARNING: This assumes that the list consists of one image or the base
image and a stub image, in which case, the information in the stub
Expand All @@ -159,7 +159,7 @@ def generate(self, image_obj_list, print_inclusive=False):
# input is a list of length 1
image_obj = image_obj_list[0]
template = SPDX()
report = get_document_dict(image_obj, template)
report = get_document_dict(image_obj, template, spdxv)

return json.dumps(report)

Expand Down
2 changes: 1 addition & 1 deletion tern/formats/spdx/spdxtagvalue/formats.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
block_text = '<text>\n{message}\n</text>'

# document level strings
spdx_version = 'SPDXVersion: SPDX-2.2'
spdx_version = 'SPDXVersion: SPDX-'
data_license = 'DataLicense: CC0-1.0'
spdx_id = 'SPDXID: SPDXRef-DOCUMENT'
document_name = 'DocumentName: Tern report for {image_name}'
Expand Down
8 changes: 4 additions & 4 deletions tern/formats/spdx/spdxtagvalue/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ def get_document_namespace(image_obj):
uuid=spdx_common.get_uuid())


def get_document_block(image_obj):
def get_document_block(image_obj, spdxv):
'''Return document related SPDX tag-values'''
block = spdx_formats.spdx_version + '\n'
block = spdx_formats.spdx_version + spdxv + '\n'
block = block + spdx_formats.data_license + '\n'
block = block + spdx_formats.spdx_id + '\n'
block = block + spdx_formats.document_name.format(
Expand All @@ -51,7 +51,7 @@ def get_document_block(image_obj):


class SpdxTagValue(generator.Generate):
def generate(self, image_obj_list, print_inclusive=False):
def generate(self, image_obj_list, print_inclusive=False, spdxv='2.2'):
'''Generate an SPDX document
WARNING: This assumes that the list consists of one image or the base
image and a stub image, in which case, the information in the stub
Expand Down Expand Up @@ -134,7 +134,7 @@ def generate(self, image_obj_list, print_inclusive=False):

# first part is the document tag-value
# this doesn't change at all
report += get_document_block(image_obj) + '\n'
report += get_document_block(image_obj, spdxv) + '\n'

# this is the image part
# this will bring in layer and package information
Expand Down
15 changes: 11 additions & 4 deletions tern/report/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,20 @@ def clean_image_tars(image_obj):

def generate_report(args, *images):
'''Generate a report based on the command line options'''
args.spdxv = '2.2'
if args.report_format and (args.report_format == '[email protected]'):
args.report_format = 'spdxtagvalue'
args.spdxv = '2.3'
if args.report_format and (args.report_format == '[email protected]'):
args.report_format = 'spdxjson'
args.spdxv = '2.3'
if args.report_format:
return generate_format(
images, args.report_format, args.print_inclusive)
return generate_format(images, 'default', args.print_inclusive)
images, args.report_format, args.print_inclusive, args.spdxv)
return generate_format(images, 'default', args.print_inclusive, args.spdxv)


def generate_format(images, format_string, print_inclusive):
def generate_format(images, format_string, print_inclusive, spdxv):
'''Generate a report in the format of format_string given one or more
image objects. Here we will load the required module and run the generate
function to get back a report'''
Expand All @@ -53,7 +60,7 @@ def generate_format(images, format_string, print_inclusive):
name=format_string,
invoke_on_load=True,
)
return mgr.driver.generate(images, print_inclusive)
return mgr.driver.generate(images, print_inclusive, spdxv)
except NoMatches:
return None

Expand Down