Skip to content

Commit

Permalink
cpp improvements (#688)
Browse files Browse the repository at this point in the history
* Use generic type for c/c++ instead of conan

Signed-off-by: Prabhu Subramanian <prabhu@appthreat.com>

Updated wrapdb

Signed-off-by: Prabhu Subramanian <prabhu@appthreat.com>

Load evinser dynamically. Fixes #686

Signed-off-by: Prabhu Subramanian <prabhu@appthreat.com>

Update atom to bring improved peformance in header analysis mode

Support for vcpkg.json and dependency tree construction while generating cpp modules

Signed-off-by: Prabhu Subramanian <prabhu@appthreat.com>

Update atom which brings the symlink fix

Signed-off-by: Prabhu Subramanian <prabhu@appthreat.com>

* Bug fix

Signed-off-by: Prabhu Subramanian <prabhu@appthreat.com>

* Added repo tests

Signed-off-by: Prabhu Subramanian <prabhu@appthreat.com>

* Support for BOM profile

Signed-off-by: Prabhu Subramanian <prabhu@appthreat.com>

* Support for BOM profile

Signed-off-by: Prabhu Subramanian <prabhu@appthreat.com>

* Try again with jenkins tests

Signed-off-by: Prabhu Subramanian <prabhu@appthreat.com>

* Use options instead of args

Signed-off-by: Prabhu Subramanian <prabhu@appthreat.com>

---------

Signed-off-by: Prabhu Subramanian <prabhu@appthreat.com>
  • Loading branch information
prabhu authored Nov 6, 2023
1 parent 2825e0b commit 1f7794b
Show file tree
Hide file tree
Showing 13 changed files with 943 additions and 268 deletions.
24 changes: 17 additions & 7 deletions .github/workflows/repotests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ jobs:
with:
repository: 'DefectDojo/django-DefectDojo'
path: 'repotests/django-DefectDojo'
- uses: actions/checkout@v3
with:
repository: 'googleprojectzero/Jackalope'
path: 'repotests/Jackalope'
- uses: dtolnay/rust-toolchain@stable
- name: repotests
run: |
Expand All @@ -162,6 +166,8 @@ jobs:
bin/cdxgen.js -p -t java repotests/java-sec-code -o bomresults/bom-java-sec-code.json --filter postgres --filter json
bin/cdxgen.js -p -t java repotests/java-sec-code -o bomresults/bom-java-sec-code.json --only spring
bin/cdxgen.js -p -t java repotests/java-sec-code -o repotests/java-sec-code/bom.json --deep --evidence
bin/cdxgen.js -p -t java repotests/java-sec-code -o bomresults/bom-java-sec-code.json --profile research
bin/cdxgen.js -p -t java repotests/java-sec-code -o bomresults/bom-java-sec-code.json --profile license-compliance
bin/cdxgen.js -t python repotests/django-DefectDojo -o repotests/django-DefectDojo/bom.json --deep --evidence
bin/cdxgen.js -p -r -t java repotests/shiftleft-java-example -o bomresults/bom-java.json --generate-key-and-sign
node bin/evinse.js -i bomresults/bom-java.json -o bomresults/bom-java.evinse.json -l java --with-data-flow -p repotests/shiftleft-java-example
Expand Down Expand Up @@ -190,6 +196,7 @@ jobs:
bin/cdxgen.js -r -t yaml-manifest repotests/microservices-demo -o bomresults/bom-yaml.json --validate
FETCH_LICENSE=true bin/cdxgen.js -p -r -t js repotests/shiftleft-ts-example -o bomresults/bom-ts.json --validate
bin/cdxgen.js -r -t c repotests/openpbs -o bomresults/bom-openpbs.json
bin/cdxgen.js -r -t c repotests/Jackalope -o bomresults/bom-Jackalope.json -p
cd repotests/ha-android && ./gradlew assembleDebug || true && cd ../..
bin/cdxgen.js -r -t java repotests/ha-android -o bomresults/bom-android.json
CDXGEN_DEBUG_MODE=debug bin/evinse.js -i bomresults/bom-android.json -o bomresults/bom-android.evinse.json -l java repotests/ha-android
Expand All @@ -201,15 +208,18 @@ jobs:
bin/cdxgen.js -p -r -t dotnet repotests/dotnet-paket -o bomresults/bom-dotnet-paket.json --validate
bin/cdxgen.js -p -t python repotests/blint -o bomresults/bom-blint.json
bin/cdxgen.js -p -t python repotests/blint -o bomresults/bom-blint-deep.json --deep
# mkdir -p jenkins
# wget https://updates.jenkins.io/download/plugins/sonar/2.14/sonar.hpi
# wget https://updates.jenkins.io/download/plugins/bouncycastle-api/2.26/bouncycastle-api.hpi
# wget https://updates.jenkins.io/download/plugins/jsch/0.1.55.61.va_e9ee26616e7/jsch.hpi
# wget https://updates.jenkins.io/download/plugins/momentjs/1.1.1/momentjs.hpi
# mv *.hpi jenkins
# CDXGEN_DEBUG_MODE=debug bin/cdxgen.js -p -r -t jenkins jenkins -o bomresults/bom-jenkins.json --validate
ls -ltr bomresults
shell: bash
- name: jenkins plugins
run: |
mkdir -p jenkins
curl -LO https://updates.jenkins.io/download/plugins/sonar/2.14/sonar.hpi
curl -LO https://updates.jenkins.io/download/plugins/bouncycastle-api/2.26/bouncycastle-api.hpi
curl -LO https://updates.jenkins.io/download/plugins/jsch/0.1.55.61.va_e9ee26616e7/jsch.hpi
curl -LO https://updates.jenkins.io/download/plugins/momentjs/1.1.1/momentjs.hpi
mv *.hpi jenkins
CDXGEN_DEBUG_MODE=debug bin/cdxgen.js -p -r -t jenkins jenkins -o bomresults/bom-jenkins.json --validate
shell: bash
- name: repotests 1.4
run: |
bin/cdxgen.js -p -r -t java repotests/shiftleft-java-example -o bomresults/bom-java.json --generate-key-and-sign --spec-version 1.4
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,10 @@ Options:
--author The person(s) who created the BOM. Set this value
if you're intending the modify the BOM and claim
authorship.[array] [default: "OWASP Foundation"]
--profile BOM profile to use for generation. Default generi
c.
[choices: "appsec", "research", "operational", "threat-modeling", "license-com
pliance", "generic"] [default: "generic"]
--auto-compositions Automatically set compositions when the BOM was f
iltered. Defaults to true
[boolean] [default: true]
Expand Down Expand Up @@ -373,7 +377,7 @@ cdxgen can retain the dependency tree under the `dependencies` attribute for a s
| SBOM_SIGN_ALGORITHM | Signature algorithm. Some valid values are RS256, RS384, RS512, PS256, PS384, PS512, ES256 etc |
| SBOM_SIGN_PRIVATE_KEY | Private key to use for signing |
| SBOM_SIGN_PUBLIC_KEY | Optional. Public key to include in the SBOM signature |
| CDX_MAVEN_PLUGIN | CycloneDX Maven plugin to use. Default "org.cyclonedx:cyclonedx-maven-plugin:2.7.8" |
| CDX_MAVEN_PLUGIN | CycloneDX Maven plugin to use. Default "org.cyclonedx:cyclonedx-maven-plugin:2.7.10" |
| CDX_MAVEN_GOAL | CycloneDX Maven plugin goal to use. Default makeAggregateBom. Other options: makeBom, makePackageBom |
| CDX_MAVEN_INCLUDE_TEST_SCOPE | Whether test scoped dependencies should be included from Maven projects, Default: true |
| ASTGEN_IGNORE_DIRS | Comma separated list of directories to ignore while analyzing using babel. The environment variable is also used by atom and astgen. |
Expand Down
88 changes: 67 additions & 21 deletions bin/cdxgen.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import {
import { findUpSync } from "find-up";
import { load as _load } from "js-yaml";
import { postProcess } from "../postgen.js";
import { analyzeProject, createEvinseFile, prepareDB } from "../evinser.js";
import { ATOM_DB } from "../utils.js";

// Support for config files
Expand Down Expand Up @@ -204,6 +203,18 @@ const args = yargs(hideBin(process.argv))
"The person(s) who created the BOM. Set this value if you're intending the modify the BOM and claim authorship.",
default: "OWASP Foundation"
})
.option("profile", {
description: "BOM profile to use for generation. Default generic.",
default: "generic",
choices: [
"appsec",
"research",
"operational",
"threat-modeling",
"license-compliance",
"generic"
]
})
.completion("completion", "Generate bash/zsh completion")
.array("filter")
.array("only")
Expand Down Expand Up @@ -259,15 +270,43 @@ if (process.argv[1].includes("obom") && !args.type) {
args.type = "os";
}

const applyProfile = (options) => {
switch (options.profile) {
case "appsec":
options.deep = true;
break;
case "research":
options.deep = true;
options.evidence = true;
process.env.CDX_MAVEN_INCLUDE_TEST_SCOPE = true;
process.env.ASTGEN_IGNORE_DIRS = "";
process.env.ASTGEN_IGNORE_FILE_PATTERN = "";
break;
case "operational":
options.projectType = options.projectType || "os";
break;
case "threat-modeling": // unused
break;
case "license-compliance":
process.env.FETCH_LICENSE = true;
break;
default:
break;
}
return options;
};

/**
* Command line options
*/
const options = Object.assign({}, args, {
projectType: args.type,
multiProject: args.recurse,
noBabel: args.noBabel || args.babel === false,
project: args.projectId
project: args.projectId,
deep: args.deep || args.evidence
});
applyProfile(options);

/**
* Check for node >= 20 permissions
Expand Down Expand Up @@ -306,7 +345,7 @@ const checkPermissions = (filePath) => {
*/
(async () => {
// Start SBOM server
if (args.server) {
if (options.server) {
const serverModule = await import("../server.js");
return serverModule.start(options);
}
Expand All @@ -323,15 +362,15 @@ const checkPermissions = (filePath) => {
bomNSData = postProcess(bomNSData, options);
}
if (
args.output &&
(typeof args.output === "string" || args.output instanceof String)
options.output &&
(typeof options.output === "string" || options.output instanceof String)
) {
if (bomNSData.bomXmlFiles) {
console.log("BOM files produced:", bomNSData.bomXmlFiles);
} else {
const jsonFile = args.output.replace(".xml", ".json");
const jsonFile = options.output.replace(".xml", ".json");
// Create bom json file
if (!args.output.endsWith(".xml") && bomNSData.bomJson) {
if (!options.output.endsWith(".xml") && bomNSData.bomJson) {
let jsonPayload = undefined;
if (
typeof bomNSData.bomJson === "string" ||
Expand All @@ -345,7 +384,7 @@ const checkPermissions = (filePath) => {
}
if (
jsonPayload &&
(args.generateKeyAndSign ||
(options.generateKeyAndSign ||
(process.env.SBOM_SIGN_ALGORITHM &&
process.env.SBOM_SIGN_ALGORITHM !== "none" &&
process.env.SBOM_SIGN_PRIVATE_KEY &&
Expand All @@ -358,7 +397,7 @@ const checkPermissions = (filePath) => {
let privateKeyToUse = undefined;
let jwkPublicKey = undefined;
let publicKeyFile = undefined;
if (args.generateKeyAndSign) {
if (options.generateKeyAndSign) {
const jdirName = dirname(jsonFile);
publicKeyFile = join(jdirName, "public.key");
const privateKeyFile = join(jdirName, "private.key");
Expand Down Expand Up @@ -468,8 +507,8 @@ const checkPermissions = (filePath) => {
}
}
// Create bom xml file
if (args.output.endsWith(".xml") && bomNSData.bomXml) {
fs.writeFileSync(args.output, bomNSData.bomXml);
if (options.output.endsWith(".xml") && bomNSData.bomXml) {
fs.writeFileSync(options.output, bomNSData.bomXml);
}
//
if (bomNSData.nsMapping && Object.keys(bomNSData.nsMapping).length) {
Expand All @@ -478,7 +517,7 @@ const checkPermissions = (filePath) => {
console.log("Namespace mapping file written to", nsFile);
}
}
} else if (!args.print) {
} else if (!options.print) {
if (bomNSData.bomJson) {
console.log(JSON.stringify(bomNSData.bomJson, null, 2));
} else if (bomNSData.bomXml) {
Expand All @@ -489,7 +528,8 @@ const checkPermissions = (filePath) => {
}
}
// Evidence generation
if (args.evidence) {
if (options.evidence) {
const evinserModule = await import("../evinser.js");
const evinseOptions = {
_: args._,
input: options.output,
Expand All @@ -503,12 +543,18 @@ const checkPermissions = (filePath) => {
dataFlowSlicesFile: options.dataFlowSlicesFile,
reachablesSlicesFile: options.reachablesSlicesFile
};
const dbObjMap = await prepareDB(evinseOptions);
const dbObjMap = await evinserModule.prepareDB(evinseOptions);
if (dbObjMap) {
const sliceArtefacts = await analyzeProject(dbObjMap, evinseOptions);
const evinseJson = createEvinseFile(sliceArtefacts, evinseOptions);
const sliceArtefacts = await evinserModule.analyzeProject(
dbObjMap,
evinseOptions
);
const evinseJson = evinserModule.createEvinseFile(
sliceArtefacts,
evinseOptions
);
bomNSData.bomJson = evinseJson;
if (args.print && evinseJson) {
if (options.print && evinseJson) {
printOccurrences(evinseJson);
printCallStack(evinseJson);
printReachables(sliceArtefacts);
Expand All @@ -517,22 +563,22 @@ const checkPermissions = (filePath) => {
}
}
// Perform automatic validation
if (args.validate) {
if (options.validate) {
if (!validateBom(bomNSData.bomJson)) {
process.exit(1);
}
}
// Automatically submit the bom data
if (args.serverUrl && args.serverUrl != true && args.apiKey) {
if (options.serverUrl && options.serverUrl != true && options.apiKey) {
try {
const dbody = await submitBom(args, bomNSData.bomJson);
const dbody = await submitBom(options, bomNSData.bomJson);
console.log("Response from server", dbody);
} catch (err) {
console.log(err);
}
}

if (args.print && bomNSData.bomJson && bomNSData.bomJson.components) {
if (options.print && bomNSData.bomJson && bomNSData.bomJson.components) {
printDependencyTree(bomNSData.bomJson);
printTable(bomNSData.bomJson);
}
Expand Down
Loading

0 comments on commit 1f7794b

Please sign in to comment.