Skip to content

Commit

Permalink
Add SBOM policy options for prohibited components and licenses (#34)
Browse files Browse the repository at this point in the history
* Add SBOM policy options for prohibited components and licenses

* Update policy readme for SBOM policy section

* Bump to 0.7.0

* Update pyproject.toml

* Update __init__.py

Co-authored-by: Peter Eacmen <[email protected]>
  • Loading branch information
ochimo and eacmen authored Sep 25, 2020
1 parent ce73d86 commit 1232c12
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 4 deletions.
2 changes: 1 addition & 1 deletion centrifuge_cli/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '0.6.3'
__version__ = '0.7.0'
4 changes: 3 additions & 1 deletion centrifuge_cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ def guardian(cli):
@report.command()
@pass_cli
def sbom(cli):
result = cli.do_GET(f'/api/report/{cli.ufid}/components/pathmatches')
result = cli.do_GET(f'/api/report/{cli.ufid}/sbom')
cli.echo(result)
return(result)

Expand Down Expand Up @@ -418,6 +418,7 @@ def check_policy(cli, ctx, policy_yaml, report_template):
code_summary_json = json.loads(ctx.invoke(code_summary))
passhash_json = json.loads(ctx.invoke(passhash))
checklist_json = json.loads(ctx.invoke(security_checklist))
sbom_json = json.loads(ctx.invoke(sbom))
info_json = json.loads(ctx.invoke(info))

policy_obj = CentrifugePolicyCheck(certificates_json,
Expand All @@ -427,6 +428,7 @@ def check_policy(cli, ctx, policy_yaml, report_template):
code_summary_json,
passhash_json,
checklist_json,
sbom_json,
info_json)

policy_obj.check_rules(policy_yaml)
Expand Down
39 changes: 38 additions & 1 deletion centrifuge_cli/policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@
"method": "checkSecurityChecklistRule",
"status": "Fail",
"reasons": []
},
"sbom": {
"name": "SBOM Components",
"method": "checkSBOMRule",
"status": "Fail",
"reasons": []
}
}
POLICIES = [
Expand All @@ -64,7 +70,8 @@
'code',
'guardian',
'binaryHardening',
'securityChecklist'
'securityChecklist',
'sbom'
]


Expand All @@ -80,6 +87,7 @@ def __init__(self,
code_summary_json,
passhash_json,
checklist_json,
sbom_json,
info_json,
verbose=False):
self.certificates_json = certificates_json
Expand All @@ -89,6 +97,7 @@ def __init__(self,
self.code_summary_json = code_summary_json
self.passhash_json = passhash_json
self.checklist_json = checklist_json
self.sbom_json = sbom_json
self.info_json = info_json
self.verbose = verbose

Expand Down Expand Up @@ -300,6 +309,34 @@ def checkPasswordHashRule(self, value):
rule_passed = False
return rule_passed, reasons

def checkSBOMRule(self, value):
self.verboseprint("Checking SBOM Rule...")
rule_passed = True
reasons = []
sbom = self.sbom_json
prohibitedComponents = value.get("prohibitedComponents")
prohibitedLicenses = []
for r in value.get("licenses", {}).get("prohibitedLicenses", []):
prohibitedLicenses.append(re.compile(r))
exceptedLicenseComponents = value.get("licenses", {}).get("exceptions", [])
if sbom.get("count") > 0:
for component in sbom.get("results"):
if component.get("name") in prohibitedComponents:
reason = f'SBOM Component {component["name"]} is prohibited'
reasons.append(reason)
self.verboseprint(f'...failing: {reason}')
rule_passed = False
if not component.get("name") in exceptedLicenseComponents:
licenseUsed = component.get('license')
for r in prohibitedLicenses:
if re.match(r, licenseUsed):
reason = f'SBOM Component {component["name"]} uses prohibited license {component["license"]}'
reasons.append(reason)
self.verboseprint(f'...failing: {reason}')
rule_passed = False
break
return rule_passed, reasons

def call_policy_method(self, policy_name, ruledef):
policy_method = getattr(self, POLICY_DETAIL_MAPPING.get(policy_name).get("method"))
return policy_method(ruledef)
Expand Down
30 changes: 30 additions & 0 deletions docs/POLICY.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,3 +189,33 @@ Checklist results.
securityChecklist:
allowed: false
```

### Rule: SBOM

Software Bill of Materials (SBOM) identifies open source components that are used in firmware images.
`prohbitedComponents` can list components that should not be present in final firmware images, such as gdbserver
or tcpdump.
`prohibitedLicenses` defines software licenses which are prohibited in the identified components in the firmware.
The license identifiers match those in the SPDX standard. A common use case could be to block restrictive licenses
like GPL, but define exceptions for specific components that have been approved for distribution.
```
sbom:
# components that are not allowed in firmware
prohibitedComponents:
- tcpdump
- libpcap
- gdbserver
# components using prohibited licenses
licenses:
# use SPDX license identifiers (https://spdx.org/licenses/)
# can use regex
prohibitedLicenses:
- GPL-1.0-or-later
- GPL-*
# components approved to use prohibited licenses
exceptions:
- busybox
- dnsmasq
```
2 changes: 2 additions & 0 deletions docs/example-policy-simple.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,5 @@ rules:
include: [/opt/vendor/bin/*, /usr/lib/*]
securityChecklist:
allowed: false
sbom:
prohibitedComponents: [tcpdump, libpcap, gdbserver]
20 changes: 20 additions & 0 deletions docs/example-policy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,23 @@ rules:
securityChecklist:
# any security checklist results should result in failure in most policies
allowed: false

sbom:
# components that are not allowed in firmware
prohibitedComponents:
- tcpdump
- libpcap
- gdbserver

# components using prohibited licenses
licenses:
# use SPDX license identifiers (https://spdx.org/licenses/)
# can use regex
prohibitedLicenses:
- GPL-1.0-or-later
- GPL-*

# components approved to use prohibited licenses
exceptions:
- busybox
- dnsmasq
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "centrifuge-cli"
version = "0.6.3"
version = "0.7.0"
description = "A command line utility for interacting with the Centrifuge Firmware Analysis Platform's REST API."
authors = ["Peter Eacmen <[email protected]>"]
readme = 'README.rst'
Expand Down

0 comments on commit 1232c12

Please sign in to comment.