Skip to content

Commit

Permalink
Add ScanSbom validator (#30)
Browse files Browse the repository at this point in the history
* testing validator

* test scan validator

* troubleshooting

* extract 'sbom' value

* rollout to other integration tests

* add inspector id

* made step names more consistent

---------

Co-authored-by: Michael Long <mlongii@amazon.com>
  • Loading branch information
bluesentinelsec and Michael Long authored Apr 16, 2024
1 parent ac3c87c commit c0d8680
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 9 deletions.
9 changes: 7 additions & 2 deletions .github/workflows/test_archive.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,18 @@ jobs:
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
# TODO: use an IAM role

- name: Test Repository Scan
- name: Test archive scan
id: inspector
uses: aws/amazon-inspector-github-actions-plugin@main
# TODO: update this to point to public v1.0.0 release
with:
artifact_type: 'archive'
artifact_path: 'entrypoint/tests/test_data/artifacts/archives/testData.zip'
# TODO: read the repository results and validate correctness
- name: Display scan results
run: cat ${{ steps.inspector.outputs.inspector_scan_results }}

- name: Validate scan content
run: python3 validator/validate_inspector_scan.py --file ${{ steps.inspector.outputs.inspector_scan_results }}

# only run if the previous step failed
- name: Notify maintainers of validation failure
Expand Down
9 changes: 7 additions & 2 deletions .github/workflows/test_binary.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,18 @@ jobs:
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
# TODO: use an IAM role

- name: Test Repository Scan
- name: Test binary scan
id: inspector
uses: aws/amazon-inspector-github-actions-plugin@main
# TODO: update this to point to public v1.0.0 release
with:
artifact_type: 'binary'
artifact_path: 'entrypoint/tests/test_data/artifacts/binaries/inspector-sbomgen'
# TODO: read the repository results and validate correctness
- name: Display scan results
run: cat ${{ steps.inspector.outputs.inspector_scan_results }}

- name: Validate scan content
run: python3 validator/validate_inspector_scan.py --file ${{ steps.inspector.outputs.inspector_scan_results }}

# only run if the previous step failed
- name: Notify maintainers of validation failure
Expand Down
13 changes: 11 additions & 2 deletions .github/workflows/test_containers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ jobs:
name: plugin-development

steps:

- name: Checkout this repository
uses: actions/checkout@v4

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
Expand All @@ -26,14 +30,19 @@ jobs:
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
# TODO: use an IAM role

- name: Test Repository Scan
- name: Test container scan
id: inspector
uses: aws/amazon-inspector-github-actions-plugin@main
# TODO: update this to point to public v1.0.0 release
with:
artifact_type: 'container'
artifact_path: 'ubuntu:14.04'

# TODO: read the repository results and validate correctness
- name: Display scan results
run: cat ${{ steps.inspector.outputs.inspector_scan_results }}

- name: Validate scan content
run: python3 validator/validate_inspector_scan.py --file ${{ steps.inspector.outputs.inspector_scan_results }}

# only run if the previous step failed
- name: Notify maintainers of validation failure
Expand Down
14 changes: 11 additions & 3 deletions .github/workflows/test_repository.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ jobs:
name: plugin-development

steps:
- name: Checkout this repository
uses: actions/checkout@v4

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
Expand All @@ -26,14 +29,19 @@ jobs:
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
# TODO: use an IAM role

- name: Test Repository Scan
- name: Test repository scan
id: inspector
uses: aws/amazon-inspector-github-actions-plugin@main
# TODO: update this to point to public v1.0.0 release
with:
artifact_type: 'repository'
artifact_path: './' # TODO: make this a specific sub-directory so we have predictable output
artifact_path: './'

- name: Display scan results
run: cat ${{ steps.inspector.outputs.inspector_scan_results }}

# TODO: read the repository results and validate correctness
- name: Validate scan content
run: python3 validator/validate_inspector_scan.py --file ${{ steps.inspector.outputs.inspector_scan_results }}

# only run if the previous step failed
- name: Notify maintainers of validation failure
Expand Down
98 changes: 98 additions & 0 deletions validator/validate_inspector_scan.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#!/usr/bin/env python3

"""
This script validates the contents of an Inspector ScanSbom
response to ensure that fields needed by the
Inspector GitHub Actions plugin are present.
"""

import argparse
import json
import logging
import sys


def assert_equal(key, want, got):
if want != got:
logging.error(f" expected JSON value of '{want}' from key '{key}', but received '{got}'")
sys.exit(1)


def is_valid_prop_name(prop_name):
if 'amazon:inspector:sbom_scanner:critical_vulnerabilities' in prop_name:
return True
elif 'amazon:inspector:sbom_scanner:high_vulnerabilities' in prop_name:
return True
elif 'amazon:inspector:sbom_scanner:medium_vulnerabilities' in prop_name:
return True
elif 'amazon:inspector:sbom_scanner:low_vulnerabilities' in prop_name:
return True
elif 'amazon:inspector:sbom_scanner:other_vulnerabilities' in prop_name:
return True
else:
logging.error(f"received unhandled property name: '{prop_name}'")
sys.exit(1)


def validate_inspector_scan(scan_sbom_json):
scan_sbom_json = scan_sbom_json.get("sbom")
assert scan_sbom_json != ""

want = "CycloneDX"
key = "bomFormat"
got = scan_sbom_json.get(key)
assert_equal(key, want, got)

want = "1.5"
key = "specVersion"
got = scan_sbom_json.get(key)
assert_equal(key, want, got)

key = "serialNumber"
got = scan_sbom_json.get(key)
assert got != ""

components = scan_sbom_json.get("components")
assert len(components) > 0

vulns = scan_sbom_json.get("vulnerabilities")
assert len(vulns) > 0

props = scan_sbom_json.get("metadata").get("properties")
for each_prop in props:
prop_name = each_prop.get("name")
assert is_valid_prop_name(prop_name)


def open_inspector_scan(filepath):
scan_json = ""
f = None
try:
f = open(filepath, "r")
except Exception as e:
logging.error(f"unable to open file for reading: {filepath}\n{e}")
sys.exit(1)

try:
scan_json = json.load(f)
except Exception as e:
logging.error(f"unable to load file as JSON: {filepath}\n{e}")
sys.exit(1)

return scan_json


def main():
parser = argparse.ArgumentParser(description="Validate the contents of an Inspector ScanSbom JSON payload")
parser.add_argument("--file", type=str, default="", required=True,
help="The filepath to an Inspector ScanSbom JSON file")
args = parser.parse_args()

inspector_scan_json = open_inspector_scan(args.file)
validate_inspector_scan(inspector_scan_json)
logging.info("validation successful")


if __name__ == "__main__":
logging.basicConfig(level=logging.DEBUG)
main()

0 comments on commit c0d8680

Please sign in to comment.