Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add Dockerfile support #691

Closed
wants to merge 11 commits into from
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ Most SBOM tools are like barcode scanners. They can scan a few package manifest
| Gradle Cache | $HOME/caches/modules-2/files-2.1/\*\*/\*.jar | N/A | |
| Helm Index | $HOME/.cache/helm/repository/\*\*/\*.yaml | N/A | |
| Docker compose | docker-compose\*.yml. Images would also be scanned. | N/A | |
| Dockerfile | `*Dockerfile*`. Images would also be scanned. | N/A | |
| Containerfile | `*Containerfile*`. Images would also be scanned. | N/A | |
| Google CloudBuild configuration | cloudbuild.yaml | N/A | |
| OpenAPI | openapi\*.json, openapi\*.yaml | N/A | |

Expand Down
2 changes: 2 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ cdxgen -t java -o bom.json --server-url https://deptrack.server.com --api-key "t
| Gradle Cache | $HOME/caches/modules-2/files-2.1/\*\*/\*.jar | N/A | |
| Helm Index | $HOME/.cache/helm/repository/\*\*/\*.yaml | N/A | |
| Docker compose | docker-compose\*.yml. Images would also be scanned. | N/A | |
| Dockerfile | `*Dockerfile*`. Images would also be scanned. | N/A | |
| Containerfile | `*Containerfile*`. Images would also be scanned. | N/A | |
| Google CloudBuild configuration | cloudbuild.yaml | N/A | |
| OpenAPI | openapi\*.json, openapi\*.yaml | N/A | |

Expand Down
76 changes: 69 additions & 7 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3669,6 +3669,14 @@ export const createContainerSpecLikeBom = async (path, options) => {
path,
(options.multiProject ? "**/" : "") + "*.yml"
);
let dfFiles = getAllFiles(
path,
(options.multiProject ? "**/" : "") + "*Dockerfile*"
);
const cfFiles = getAllFiles(
path,
(options.multiProject ? "**/" : "") + "*Containerfile*"
);
const yamlFiles = getAllFiles(
path,
(options.multiProject ? "**/" : "") + "*.yaml"
Expand All @@ -3689,14 +3697,52 @@ export const createContainerSpecLikeBom = async (path, options) => {
}
// Privado.ai json files
const privadoFiles = getAllFiles(path, ".privado/" + "*.json");
// parse yaml manifest files
if (dcFiles.length) {
for (const f of dcFiles) {

// Parse yaml manifest files, dockerfiles or containerfiles
if (dcFiles.length || dfFiles.length || cfFiles.length) {
for (const f of [...dcFiles, ...dfFiles, ...cfFiles]) {
if (DEBUG_MODE) {
console.log(`Parsing ${f}`);
}
const dcData = readFileSync(f, { encoding: "utf-8" });
const imglist = parseContainerSpecData(dcData);
const dData = readFileSync(f, { encoding: "utf-8" });
let imglist = [];
// parse yaml manifest files
if (f.endsWith(".yml") || f.endsWith(".yaml")) {
imglist = parseContainerSpecData(dData);
} else {
// dockerfile or containerfile
let buildStageNames = [];
for (const dfLine of dData.split("\n")) {
if (dfLine.trim().startsWith("#")) {
continue; // skip commented out lines
}

if (dfLine.includes("FROM")) {
const fromStatement = dfLine.split("FROM")[1].split("AS");

const imageStatement = fromStatement[0].trim();
const buildStageName = fromStatement[1]?.trim();

if (buildStageNames.includes(imageStatement)) {
if (DEBUG_MODE) {
console.log(
`Skipping image ${imageStatement} which uses previously seen build stage name.`
);
}
continue;
}

imglist.push({
image: imageStatement
});

if (buildStageName) {
buildStageNames.push(buildStageName);
}
}
}
}

if (imglist && imglist.length) {
if (DEBUG_MODE) {
console.log("Images identified in", f, "are", imglist);
Expand Down Expand Up @@ -5094,11 +5140,19 @@ export const createXBom = async (path, options) => {
return createHelmBom(path, options);
}

// Docker compose, kubernetes and skaffold
// Docker compose, dockerfile, kubernetes and skaffold
const dcFiles = getAllFiles(
path,
(options.multiProject ? "**/" : "") + "docker-compose*.yml"
);
const dfFiles = getAllFiles(
path,
(options.multiProject ? "**/" : "") + "*Dockerfile*"
);
const cfFiles = getAllFiles(
path,
(options.multiProject ? "**/" : "") + "*Containerfile*"
);
const skFiles = getAllFiles(
path,
(options.multiProject ? "**/" : "") + "skaffold.yaml"
Expand All @@ -5107,7 +5161,13 @@ export const createXBom = async (path, options) => {
path,
(options.multiProject ? "**/" : "") + "deployment.yaml"
);
if (dcFiles.length || skFiles.length || deplFiles.length) {
if (
dcFiles.length ||
dfFiles.length ||
cfFiles.length ||
skFiles.length ||
deplFiles.length
) {
return await createContainerSpecLikeBom(path, options);
}

Expand Down Expand Up @@ -5370,7 +5430,9 @@ export const createBom = async (path, options) => {
options
);
case "universal":
case "containerfile":
case "docker-compose":
case "dockerfile":
case "swarm":
case "tekton":
case "kustomize":
Expand Down
Loading