Skip to content

Commit

Permalink
Python cbom (CycloneDX#1026)
Browse files Browse the repository at this point in the history
* Python cbom

Signed-off-by: Prabhu Subramanian <[email protected]>

* cbom repl improvements

Signed-off-by: Prabhu Subramanian <[email protected]>

* cbom print improvements

Signed-off-by: Prabhu Subramanian <[email protected]>

* Fixes test

Signed-off-by: Prabhu Subramanian <[email protected]>

* Fixes test

Signed-off-by: Prabhu Subramanian <[email protected]>

* Update packages

Signed-off-by: Prabhu Subramanian <[email protected]>

---------

Signed-off-by: Prabhu Subramanian <[email protected]>
  • Loading branch information
prabhu authored Apr 30, 2024
1 parent 17b83f9 commit b1def86
Show file tree
Hide file tree
Showing 20 changed files with 280 additions and 247 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/repotests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ jobs:
shell: bash
- name: repotests django-DefectDojo
run: |
bin/cdxgen.js -p -t python repotests/django-DefectDojo -o bomresults/django-DefectDojo.json --deep --evidence
bin/cdxgen.js -t python repotests/django-DefectDojo -o bomresults/django-DefectDojo.json --deep --include-crypto --spec-version 1.6
shell: bash
- name: repotests shiftleft-java-example
run: |
Expand Down
6 changes: 6 additions & 0 deletions bin/cdxgen.js
Original file line number Diff line number Diff line change
Expand Up @@ -666,5 +666,11 @@ const checkPermissions = (filePath) => {
if (options.print && bomNSData.bomJson && bomNSData.bomJson.components) {
printDependencyTree(bomNSData.bomJson);
printTable(bomNSData.bomJson);
// CBOM related print
if (options.includeCrypto) {
console.log("*** Cryptography BOM ***");
printTable(bomNSData.bomJson, ["cryptographic-asset"]);
printDependencyTree(bomNSData.bomJson, "provides");
}
}
})();
39 changes: 39 additions & 0 deletions bin/repl.js
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,32 @@ cdxgenRepl.defineCommand("print", {
this.displayPrompt();
},
});
cdxgenRepl.defineCommand("cryptos", {
help: "print the components of type cryptographic-asset as a table",
action() {
if (sbom) {
printTable(sbom, ["cryptographic-asset"]);
} else {
console.log(
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
);
}
this.displayPrompt();
},
});
cdxgenRepl.defineCommand("frameworks", {
help: "print the components of type framework as a table",
action() {
if (sbom) {
printTable(sbom, ["framework"]);
} else {
console.log(
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
);
}
this.displayPrompt();
},
});
cdxgenRepl.defineCommand("tree", {
help: "display the dependency tree",
action() {
Expand All @@ -257,6 +283,19 @@ cdxgenRepl.defineCommand("tree", {
this.displayPrompt();
},
});
cdxgenRepl.defineCommand("provides", {
help: "display the provides tree",
action() {
if (sbom) {
printDependencyTree(sbom, "provides");
} else {
console.log(
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
);
}
this.displayPrompt();
},
});
cdxgenRepl.defineCommand("validate", {
help: "validate the bom using jsonschema",
action() {
Expand Down
Binary file modified bun.lockb
Binary file not shown.
2 changes: 1 addition & 1 deletion ci/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ LABEL maintainer="cyclonedx" \
org.opencontainers.image.authors="Prabhu Subramanian <[email protected]>" \
org.opencontainers.image.source="https://github.com/cyclonedx/cdxgen" \
org.opencontainers.image.url="https://github.com/cyclonedx/cdxgen" \
org.opencontainers.image.version="10.4.x" \
org.opencontainers.image.version="10.5.x" \
org.opencontainers.image.vendor="cyclonedx" \
org.opencontainers.image.licenses="Apache-2.0" \
org.opencontainers.image.title="cdxgen" \
Expand Down
2 changes: 1 addition & 1 deletion ci/Dockerfile-bun
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ LABEL maintainer="cyclonedx" \
org.opencontainers.image.authors="Prabhu Subramanian <[email protected]>" \
org.opencontainers.image.source="https://github.com/cyclonedx/cdxgen" \
org.opencontainers.image.url="https://github.com/cyclonedx/cdxgen" \
org.opencontainers.image.version="10.4.x" \
org.opencontainers.image.version="10.5.x" \
org.opencontainers.image.vendor="cyclonedx" \
org.opencontainers.image.licenses="Apache-2.0" \
org.opencontainers.image.title="cdxgen" \
Expand Down
2 changes: 1 addition & 1 deletion ci/Dockerfile-deno
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ LABEL maintainer="cyclonedx" \
org.opencontainers.image.authors="Prabhu Subramanian <[email protected]>" \
org.opencontainers.image.source="https://github.com/cyclonedx/cdxgen" \
org.opencontainers.image.url="https://github.com/cyclonedx/cdxgen" \
org.opencontainers.image.version="10.4.x" \
org.opencontainers.image.version="10.5.x" \
org.opencontainers.image.vendor="cyclonedx" \
org.opencontainers.image.licenses="Apache-2.0" \
org.opencontainers.image.title="cdxgen" \
Expand Down
2 changes: 1 addition & 1 deletion ci/Dockerfile-fedora
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ LABEL maintainer="cyclonedx" \
org.opencontainers.image.authors="Prabhu Subramanian <[email protected]>" \
org.opencontainers.image.source="https://github.com/cyclonedx/cdxgen" \
org.opencontainers.image.url="https://github.com/cyclonedx/cdxgen" \
org.opencontainers.image.version="10.4.x" \
org.opencontainers.image.version="10.5.x" \
org.opencontainers.image.vendor="cyclonedx" \
org.opencontainers.image.licenses="Apache-2.0" \
org.opencontainers.image.title="cdxgen" \
Expand Down
2 changes: 1 addition & 1 deletion ci/Dockerfile-ppc64
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ LABEL maintainer="cyclonedx" \
org.opencontainers.image.authors="Prabhu Subramanian <[email protected]>" \
org.opencontainers.image.source="https://github.com/cyclonedx/cdxgen" \
org.opencontainers.image.url="https://github.com/cyclonedx/cdxgen" \
org.opencontainers.image.version="10.4.x" \
org.opencontainers.image.version="10.5.x" \
org.opencontainers.image.vendor="cyclonedx" \
org.opencontainers.image.licenses="Apache-2.0" \
org.opencontainers.image.title="cdxgen" \
Expand Down
32 changes: 32 additions & 0 deletions data/crypto-oid.json
Original file line number Diff line number Diff line change
Expand Up @@ -1946,5 +1946,37 @@
"sm2sign_with_": {
"oid": "1.2.156.10197.1.501",
"description": "Chinese Cryptography Standardization Technology Committee (CCSTC)"
},
"PBKDF2": {
"oid": "1.2.840.113549.1.5.12",
"description": "PBKDF2 key derivation algorithm"
},
"pbeWithMD2AndDES-CBC": {
"oid": "1.2.840.113549.1.5.1",
"description": "Password Based Encryption Algorithm"
},
"pbeWithMD5AndDES-CBC": {
"oid": "1.2.840.113549.1.5.3",
"description": "Password Based Encryption Algorithm"
},
"pbeWithMD2AndRC2-CBC": {
"oid": "1.2.840.113549.1.5.4",
"description": "Password Based Encryption Algorithm. Uses RC2 in Cipher Block Chaining Mode (RC2-CBC)"
},
"pbeWithMD5AndRC2-CBC": {
"oid": "1.2.840.113549.1.5.6",
"description": "Password Based Encryption Algorithm. Uses RC2 in Cipher Block Chaining Mode (RC2-CBC)"
},
"pbeWithMD5AndXOR": {
"oid": "1.2.840.113549.1.5.9",
"description": "Password Based Encryption Algorithm. Uses XOR. Uses MD5 to hash a password & salt to get Key and IV."
},
"pbeWithSHA1AndDES-CBC": {
"oid": "1.2.840.113549.1.5.10",
"description": "Password Based Encryption Algorithm. Uses Data Encryption Standard in Cipher Block Chaining Mode (DES-CBC)"
},
"pbeWithSHA1AndRC2-CBC": {
"oid": "1.2.840.113549.1.5.11",
"description": "Password Based Encryption Algorithm. Uses RC2 in Cipher Block Chaining Mode (RC2-CBC)."
}
}
15 changes: 12 additions & 3 deletions data/lic-mapping.json
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@
"LGPL v3.0",
"LGPL-3.0",
"LGPL3.0",
"LGPL 3",
"GNU Lesser General Public License (LGPL), version 3",
"GNU Lesser General Public License (LGPL), version 3.0",
"GNU Lesser General Public License v3.0",
Expand All @@ -203,9 +204,15 @@
"names": [
"GNU Lesser General Public License (LGPL), version 3 or later",
"GNU Lesser General Public License (LGPL), version 3.0 or later",
"GNU Lesser General Public License v3.0 or later"
"GNU Lesser General Public License v3.0 or later",
"GNU Lesser General Public License v3 or later (LGPLv3+)",
"LGPLv3+"
]
},
{
"exp": "GPL-1.0-only",
"names": ["GNU General Public License (GPL)"]
},
{
"exp": "GPL-2.0-only",
"names": [
Expand All @@ -217,7 +224,8 @@
"GNU General Public License v2.0",
"GNU General Public License Version 2",
"GNU General Public License, version 2",
"GNU General Public License as published by the Free Software Foundation; version 2."
"GNU General Public License as published by the Free Software Foundation; version 2.",
"GNU General Public License v2 (GPLv2)"
]
},
{
Expand Down Expand Up @@ -251,7 +259,8 @@
"GNU General Public License v3.0",
"GNU General Public License as published by the Free Software Foundation, version 3.",
"GPL-3",
"GPL-3.0"
"GPL-3.0",
"GNU GPL 3"
]
},
{
Expand Down
10 changes: 5 additions & 5 deletions deno.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@cyclonedx/cdxgen",
"version": "10.4.3",
"version": "10.5.0",
"exports": "./index.js",
"compilerOptions": {
"allowJs": true,
Expand Down Expand Up @@ -41,11 +41,11 @@
"exe": "deno compile --allow-read --allow-env --allow-run --allow-sys=uid,systemMemoryInfo,gid --allow-write --allow-net --output build/cdxgenx-devel bin/cdxgen.js"
},
"imports": {
"@appthreat/atom": "npm:@appthreat/[email protected].9",
"@appthreat/atom": "npm:@appthreat/[email protected].11",
"@appthreat/cdx-proto": "npm:@appthreat/[email protected]",
"@babel/parser": "npm:@babel/parser@^7.24.4",
"@babel/traverse": "npm:@babel/traverse@^7.24.1",
"@npmcli/arborist": "npm:@npmcli/arborist@7.4.2",
"@babel/parser": "npm:@babel/parser@^7.24.5",
"@babel/traverse": "npm:@babel/traverse@^7.24.5",
"@npmcli/arborist": "npm:@npmcli/arborist@7.5.0",
"ajv": "npm:ajv@^8.12.0",
"ajv-formats": "npm:ajv-formats@^3.0.1",
"cheerio": "npm:cheerio@^1.0.0-rc.12",
Expand Down
71 changes: 50 additions & 21 deletions display.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const SYMBOLS_ANSI = {

const MAX_TREE_DEPTH = 6;

export const printTable = (bomJson) => {
export const printTable = (bomJson, filterTypes = undefined) => {
if (!bomJson || !bomJson.components) {
return;
}
Expand All @@ -35,23 +35,46 @@ export const printTable = (bomJson) => {
],
};
const stream = createStream(config);
stream.write(["Group", "Name", "Version", "Scope"]);
stream.write([
filterTypes?.includes("cryptographic-asset")
? "Asset Type / Group"
: "Group",
"Name",
filterTypes?.includes("cryptographic-asset") ? "Version / oid" : "Version",
"Scope",
]);
for (const comp of bomJson.components) {
stream.write([
comp.group || "",
comp.name,
`\x1b[1;35m${comp.version || ""}\x1b[0m`,
comp.scope || "",
]);
if (filterTypes && !filterTypes.includes(comp.type)) {
continue;
}
if (comp.type === "cryptographic-asset") {
stream.write([
comp.cryptoProperties?.assetType || comp.group || "",
comp.name,
`\x1b[1;35m${comp.cryptoProperties?.oid || ""}\x1b[0m`,
comp.scope || "",
]);
} else {
stream.write([
comp.group || "",
comp.name,
`\x1b[1;35m${comp.version || ""}\x1b[0m`,
comp.scope || "",
]);
}
}
console.log();
console.log(
"BOM includes",
bomJson.components.length,
"components and",
bomJson.dependencies.length,
"dependencies",
);
if (!filterTypes) {
console.log(
"BOM includes",
bomJson.components.length,
"components and",
bomJson.dependencies.length,
"dependencies",
);
} else {
console.log(`Components filtered based on type: ${filterTypes.join(", ")}`);
}
};
const formatProps = (props) => {
const retList = [];
Expand Down Expand Up @@ -192,27 +215,33 @@ export const printCallStack = (bomJson) => {
console.log(table(data, config));
}
};
export const printDependencyTree = (bomJson) => {
export const printDependencyTree = (bomJson, mode = "dependsOn") => {
const dependencies = bomJson.dependencies || [];
if (!dependencies.length) {
return;
}
const depMap = {};
const shownList = [];
for (const d of dependencies) {
if (d.dependsOn?.length) {
depMap[d.ref] = d.dependsOn.sort();
if (d[mode]?.length) {
depMap[d.ref] = d[mode].sort();
} else {
if (mode === "provides") {
shownList.push(d.ref);
}
}
}
const shownList = [];
const treeGraphics = [];
recursePrint(depMap, dependencies, 0, shownList, treeGraphics);
// table library is too slow for display large lists.
// Fixes #491
if (treeGraphics.length < 100) {
if (treeGraphics.length && treeGraphics.length < 100) {
const treeType =
mode && mode === "provides" ? "Crypto Implementation" : "Dependency";
const config = {
header: {
alignment: "center",
content: "Dependency Tree\nGenerated with \u2665 by cdxgen",
content: `${treeType} Tree\nGenerated with \u2665 by cdxgen`,
},
};
console.log(table([[treeGraphics.join("\n")]], config));
Expand Down
17 changes: 12 additions & 5 deletions evinser.js
Original file line number Diff line number Diff line change
Expand Up @@ -1281,15 +1281,22 @@ export const collectReachableFrames = (language, reachablesSlice) => {
if (tagStr.includes("crypto")) {
isCryptoFlow = true;
}
if (tagStr.includes("crypto-generate")) {
if (isCryptoFlow && fnode.code) {
codeSnippets = `${codeSnippets}\\n${fnode.code}`;
}
if (
tagStr.includes("crypto-generate") ||
fnode.code.includes("encrypt") ||
fnode.code.includes("decrypt") ||
fnode.code.includes("sign")
) {
cpurls = tagStr.split(", ").filter((t) => t.startsWith("pkg:"));
for (const cpurl of cpurls) {
cryptoGeneratePurls[cpurl] = new Set();
if (!cryptoGeneratePurls[cpurl]) {
cryptoGeneratePurls[cpurl] = new Set();
}
}
}
if (isCryptoFlow && fnode.code) {
codeSnippets = `${codeSnippets}\\n${fnode.code}`;
}
if (!fnode.parentFileName || fnode.parentFileName === "<unknown>") {
continue;
}
Expand Down
6 changes: 2 additions & 4 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1292,9 +1292,7 @@ export async function createJavaBom(path, options) {
// These could be due to a range of reasons that are covered below.
if (pomFiles.length === 1 || DEBUG_MODE) {
console.error(result.stdout, result.stderr);
console.log(
"Resolve the above maven error. This could be due to the following:\n",
);
console.log("The above build errors could be due to:\n");
if (
result.stdout &&
(result.stdout.includes("Non-resolvable parent POM") ||
Expand Down Expand Up @@ -2642,7 +2640,7 @@ export async function createPythonBom(path, options) {
if (reqFiles?.length) {
if (options.installDeps && DEBUG_MODE) {
console.log(
"cdxgen will now attempt to generate an SBOM for 'build' lifecycle phase for Python. This would take some time ...\nTo speed up this step, invoke cdxgen from within a virtual environment with all the dependencies installed.\nAlternatively, pass the argument '--lifecycle pre-build' to generate a faster but less precise SBOM without installing the dependencies in case of any build issues.",
"cdxgen will now attempt to generate an SBOM for 'build' lifecycle phase for Python. This would take some time ...\nTo speed up this step, invoke cdxgen from within a virtual environment with all the dependencies installed.\nAlternatively, pass the argument '--lifecycle pre-build' to generate a faster but less precise SBOM.",
);
}
for (const f of reqFiles) {
Expand Down
2 changes: 1 addition & 1 deletion jsr.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@cyclonedx/cdxgen",
"version": "10.4.3",
"version": "10.5.0",
"exports": "./index.js",
"include": ["*.js", "bin/**", "data/**", "types/**"],
"exclude": ["test/", "docs/", "contrib/", "ci/", "tools_config/"]
Expand Down
Loading

0 comments on commit b1def86

Please sign in to comment.