66 lines
2.6 KiB
Python
66 lines
2.6 KiB
Python
#!/usr/bin/env python3
|
|
|
|
import importlib.util
|
|
import json
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
SPEC = importlib.util.spec_from_file_location("supply_chain", ROOT / "scripts" / "supply-chain.py")
|
|
assert SPEC and SPEC.loader
|
|
SUPPLY_CHAIN = importlib.util.module_from_spec(SPEC)
|
|
SPEC.loader.exec_module(SUPPLY_CHAIN)
|
|
|
|
|
|
class SecretScanTests(unittest.TestCase):
|
|
def test_detects_canaries_without_returning_secret_values(self):
|
|
canaries = [
|
|
"-----BEGIN " + "PRIVATE KEY-----",
|
|
"eyJ" + "a" * 12 + "." + "b" * 12 + "." + "c" * 12,
|
|
"AKIA" + "A" * 16,
|
|
"ghp_" + "a" * 36,
|
|
"AIza" + "a" * 35,
|
|
"xoxb-" + "a" * 24,
|
|
"sk_" + "live_" + "a" * 20,
|
|
]
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
root = Path(directory)
|
|
(root / "fixture.txt").write_text("\n".join(canaries), encoding="utf-8")
|
|
findings = SUPPLY_CHAIN.scan_files(root, ["fixture.txt"])
|
|
|
|
self.assertEqual(len(SUPPLY_CHAIN.SECRET_PATTERNS), len(findings))
|
|
rendered = "\n".join(f"{kind} {path}:{line}" for kind, path, line in findings)
|
|
for canary in canaries:
|
|
self.assertNotIn(canary, rendered)
|
|
|
|
def test_ignores_binary_and_oversized_files(self):
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
root = Path(directory)
|
|
binary_canary = b"\0-----BEGIN " + b"PRIVATE KEY-----"
|
|
(root / "binary.dat").write_bytes(binary_canary)
|
|
(root / "large.txt").write_bytes(b"a" * (SUPPLY_CHAIN.MAX_SCANNED_FILE_BYTES + 1))
|
|
self.assertEqual([], SUPPLY_CHAIN.scan_files(root, ["binary.dat", "large.txt"]))
|
|
|
|
|
|
class SbomTests(unittest.TestCase):
|
|
def test_generates_deterministic_multi_ecosystem_cyclonedx(self):
|
|
first = SUPPLY_CHAIN.generate_sbom(ROOT)
|
|
second = SUPPLY_CHAIN.generate_sbom(ROOT)
|
|
self.assertEqual(first, second)
|
|
self.assertEqual("CycloneDX", first["bomFormat"])
|
|
self.assertEqual("1.5", first["specVersion"])
|
|
|
|
components = first["components"]
|
|
purls = {component["purl"] for component in components}
|
|
self.assertTrue(any(purl.startswith("pkg:npm/react@") for purl in purls))
|
|
self.assertTrue(any(purl.startswith("pkg:nuget/Microsoft.EntityFrameworkCore@") for purl in purls))
|
|
self.assertTrue(any(purl.startswith("pkg:pypi/fastapi@") for purl in purls))
|
|
self.assertEqual(len(purls), len(components))
|
|
json.dumps(first)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|