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

Cdxgen #45

Merged
merged 7 commits into from
Oct 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 34 additions & 17 deletions components/consumers/stdout-json/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ func main() {
}

func getRawIssue(scanStartTime time.Time, res *v1.LaunchToolResponse, iss *v1.Issue) ([]byte, error) {
var sbom map[string]interface{}
if iss.GetCycloneDXSBOM() != "" {
if err := json.Unmarshal([]byte(iss.GetCycloneDXSBOM()), &sbom); err != nil {
log.Fatalf("error unmarshaling cyclonedx sbom, err:%s", err)
}
}
jBytes, err := json.Marshal(&draconDocument{
ScanStartTime: scanStartTime,
ScanID: res.GetScanInfo().GetScanUuid(),
Expand All @@ -64,6 +70,7 @@ func getRawIssue(scanStartTime time.Time, res *v1.LaunchToolResponse, iss *v1.Is
Count: 1,
FalsePositive: false,
CVE: iss.GetCve(),
CycloneDXSBOM: sbom,
})
if err != nil {
return []byte{}, err
Expand All @@ -72,6 +79,12 @@ func getRawIssue(scanStartTime time.Time, res *v1.LaunchToolResponse, iss *v1.Is
}

func getEnrichedIssue(scanStartTime time.Time, res *v1.EnrichedLaunchToolResponse, iss *v1.EnrichedIssue) ([]byte, error) {
var sbom map[string]interface{}
if iss.GetRawIssue().GetCycloneDXSBOM() != "" {
if err := json.Unmarshal([]byte(iss.GetRawIssue().GetCycloneDXSBOM()), &sbom); err != nil {
log.Fatalf("error unmarshaling cyclonedx sbom, err:%s", err)
}
}
firstSeenTime := iss.GetFirstSeen().AsTime()
jBytes, err := json.Marshal(&draconDocument{
ScanStartTime: scanStartTime,
Expand All @@ -91,6 +104,8 @@ func getEnrichedIssue(scanStartTime time.Time, res *v1.EnrichedLaunchToolRespons
SeverityText: enumtransformers.SeverityToText(iss.GetRawIssue().GetSeverity()),
ConfidenceText: enumtransformers.ConfidenceToText(iss.GetRawIssue().GetConfidence()),
CVE: iss.GetRawIssue().GetCve(),
CycloneDXSBOM: sbom,
Annotations: iss.GetAnnotations(),
})
if err != nil {
return []byte{}, err
Expand All @@ -99,21 +114,23 @@ func getEnrichedIssue(scanStartTime time.Time, res *v1.EnrichedLaunchToolRespons
}

type draconDocument struct {
ScanStartTime time.Time `json:"scan_start_time"`
ScanID string `json:"scan_id"`
ToolName string `json:"tool_name"`
Source string `json:"source"`
Target string `json:"target"`
Type string `json:"type"`
Title string `json:"title"`
Severity v1.Severity `json:"severity"`
SeverityText string `json:"severity_text"`
CVSS float64 `json:"cvss"`
Confidence v1.Confidence `json:"confidence"`
ConfidenceText string `json:"confidence_text"`
Description string `json:"description"`
FirstFound time.Time `json:"first_found"`
Count uint64 `json:"count"`
FalsePositive bool `json:"false_positive"`
CVE string `json:"cve"`
ScanStartTime time.Time `json:"scan_start_time"`
ScanID string `json:"scan_id"`
ToolName string `json:"tool_name"`
Source string `json:"source"`
Target string `json:"target"`
Type string `json:"type"`
Title string `json:"title"`
Severity v1.Severity `json:"severity"`
SeverityText string `json:"severity_text"`
CVSS float64 `json:"cvss"`
Confidence v1.Confidence `json:"confidence"`
ConfidenceText string `json:"confidence_text"`
Description string `json:"description"`
FirstFound time.Time `json:"first_found"`
Count uint64 `json:"count"`
FalsePositive bool `json:"false_positive"`
CVE string `json:"cve"`
CycloneDXSBOM map[string]interface{} `json:"CycloneDX_SBOM"`
Annotations map[string]string `json:"annotations"`
}
32 changes: 32 additions & 0 deletions components/producers/cdxgen/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
subinclude(
"//build/defs:buildkit",
"//build/defs:dracon",
)

go_binary(
name = "cdxgen-parser",
srcs = [
"main.go",
],
deps = [
"//api/proto/v1",
"//components/producers",
"//pkg/cyclonedx",
"//pkg/sarif",
],
)

buildkit_distroless_image(
name = "image",
srcs = [":cdxgen-parser"],
)

dracon_component(
name = "cdxgen",
images = [
":image",
"//third_party/docker/cyclonedx/cdxgen",
],
task = "task.yaml",
visibility = ["//examples/pipelines/..."],
)
17 changes: 17 additions & 0 deletions components/producers/cdxgen/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Dracon CDXGEN Producer

This producer runs [CycloneDX/cdxgen](https://github.com/CycloneDX/cdxgen) against the specified filesystem or image.
It then parses the results into the Dracon format and exits.

## Testing without Dracon

You can run this producer outside of dracon for development with

``` bash
plz run //components/producers/cdxgen:cdxgen -- -in <any cyclonedx sbom document> -out ./cdxgen.pb
```
cdxgen can be run as a docker image by pulling `ghcr.io/cyclonedx/cdxgen`

## SBOM mode

The producer will output a `LaunchToolResponse` containing a single issue which will have its `CycloneDXSBOM` field populated with the output from cdxgen.
169 changes: 169 additions & 0 deletions components/producers/cdxgen/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
# DO NOT EDIT. Code generated by:
# github.com/ocurity/dracon//build/tools/kustomize-component-generator.

apiVersion: kustomize.config.k8s.io/v1alpha1
kind: Component
resources:
- task.yaml
patches:
# Add the Task to the Tekton Pipeline.
- patch: |
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: unused
spec:
workspaces:
- name: source-code-ws
tasks:
- name: producer-cdxgen
taskRef:
name: producer-cdxgen
workspaces:
- name: source-code-ws
workspace: source-code-ws
params:
- name: producer-cdxgen-flags
value:
- $(params.producer-cdxgen-flags)
- name: producer-cdxgen-fetch-license
value: $(params.producer-cdxgen-fetch-license)
- name: producer-cdxgen-github-token
value: $(params.producer-cdxgen-github-token)
- name: producer-cdxgen-astgen-ignore-file-pattern
value: $(params.producer-cdxgen-astgen-ignore-file-pattern)
- name: producer-cdxgen-astgen-ignore-dirs
value: $(params.producer-cdxgen-astgen-ignore-dirs)
params:
- name: producer-cdxgen-flags
type: array
default: []
- name: producer-cdxgen-fetch-license
type: string
default: "false"
- name: producer-cdxgen-github-token
type: string
default: ""
- name: producer-cdxgen-astgen-ignore-file-pattern
type: string
default: ""
- name: producer-cdxgen-astgen-ignore-dirs
type: string
default: ""
target:
kind: Pipeline
# Add anchors to Task.
- patch: |
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: producer-cdxgen
labels:
v1.dracon.ocurity.com/component: producer
spec:
params:
- name: anchors
type: array
description: A list of tasks that this task depends on using their anchors.
default: []
results:
- name: anchor
description: An anchor to allow other tasks to depend on this task.
steps:
- name: anchor
image: docker.io/busybox:1.35.0
script: echo "$(context.task.name)" > "$(results.anchor.path)"
target:
kind: Task
name: producer-cdxgen
# If we have a `source` task in the pipeline (added by a `source` component),
# depend on the completion of that source by referencing its anchor.
- patch: |
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: unused
spec:
tasks:
- name: producer-cdxgen
params:
- name: anchors
value:
- $(tasks.source.results.anchor)
target:
kind: Pipeline
annotationSelector: v1.dracon.ocurity.com/has-source=true
# If we have a producer-aggregator task in the pipeline (added by the
# producer-aggregator component), make it depend on the completion of this
# producer.
- patch: |
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: unused
spec:
tasks:
- name: producer-aggregator
params:
- name: anchors
value:
- $(tasks.producer-cdxgen.results.anchor)
target:
kind: Pipeline
annotationSelector: v1.dracon.ocurity.com/has-producer-aggregator=true
# Add scan information to Task.
- patch: |
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: producer-cdxgen
labels:
v1.dracon.ocurity.com/component: producer
spec:
params:
- name: dracon_scan_id
type: string
- name: dracon_scan_start_time
type: string
steps:
- name: run-cdxgen
image: ghcr.io/cyclonedx/cdxgen:v9.8.10
script: node /opt/cdxgen/bin/cdxgen.js -r -p -o /scratch/out.json $(workspaces.source-code-ws.path)/ --spec-version 1.4
env:
- name: FETCH_LICENSE
value: $(params.producer-cdxgen-fetch-license)
- name: GITHUB_TOKEN
value: $(params.producer-cdxgen-github-token)
- name: ASTGEN_IGNORE_FILE_PATTERN
value: $(params.producer-cdxgen-astgen-ignore-file-pattern)
- name: ASTGEN_IGNORE_DIRS
value: $(params.producer-cdxgen-astgen-ignore-dirs)
- name: DRACON_SCAN_TIME
value: $(params.dracon_scan_start_time)
- name: DRACON_SCAN_ID
value: $(params.dracon_scan_id)
- name: produce-issues
image: ghcr.io/ocurity/dracon/components/producers/cdxgen/image:latest
env:
- name: DRACON_SCAN_TIME
value: $(params.dracon_scan_start_time)
- name: DRACON_SCAN_ID
value: $(params.dracon_scan_id)
target:
kind: Task
name: producer-cdxgen
- patch: |
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: unused
spec:
tasks:
- name: producer-cdxgen
params:
- name: dracon_scan_id
value: $(tasks.base.results.dracon-scan-id)
- name: dracon_scan_start_time
value: $(tasks.base.results.dracon-scan-start-time)
target:
kind: Pipeline
35 changes: 35 additions & 0 deletions components/producers/cdxgen/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Package main of the cdxgen producer parses the CycloneDX output of cdxgen and
// create a singular Dracon issue from it
package main
northdpole marked this conversation as resolved.
Show resolved Hide resolved

import (
"log"

v1 "github.com/ocurity/dracon/api/proto/v1"
"github.com/ocurity/dracon/components/producers"
"github.com/ocurity/dracon/pkg/cyclonedx"
)

func main() {
if err := producers.ParseFlags(); err != nil {
log.Fatal(err)
}
var results []*v1.Issue
inFile, err := producers.ReadInFile()
if err != nil {
log.Fatal("could not load file err:%s", err)
}
results, err = handleCycloneDX(inFile)
if err != nil {
log.Fatalf("could not parse cyclonedx document err:%s", err)
}
if err := producers.WriteDraconOut(
"cdxgen", results,
); err != nil {
log.Fatal("could not write dracon out err:%s", err)
}
}

func handleCycloneDX(inFile []byte) ([]*v1.Issue, error) {
return cyclonedx.ToDracon(inFile, "json")
}
57 changes: 57 additions & 0 deletions components/producers/cdxgen/task.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: producer-cdxgen
labels:
v1.dracon.ocurity.com/component: producer
spec:
params:
- name: producer-cdxgen-flags
type: array
default: []
- name: producer-cdxgen-fetch-license
type: string
default: "false"
- name: producer-cdxgen-github-token
type: string
default: ""
- name: producer-cdxgen-astgen-ignore-file-pattern
type: string
default: ""
- name: producer-cdxgen-astgen-ignore-dirs
type: string
default: ""
volumes:
- name: scratch
emptyDir: {}
workspaces:
- name: source-code-ws
description: The workspace containing the source-code to scan.
steps:
- name: run-cdxgen
image: ghcr.io/cyclonedx/cdxgen:v9.8.10
env:
- name: FETCH_LICENSE
value: $(params.producer-cdxgen-fetch-license)
- name: GITHUB_TOKEN
value: $(params.producer-cdxgen-github-token)
- name: ASTGEN_IGNORE_FILE_PATTERN
value: $(params.producer-cdxgen-astgen-ignore-file-pattern)
- name: ASTGEN_IGNORE_DIRS
value: $(params.producer-cdxgen-astgen-ignore-dirs)
script: node /opt/cdxgen/bin/cdxgen.js -r -p -o /scratch/out.json $(workspaces.source-code-ws.path)/ --spec-version 1.4
volumeMounts:
- mountPath: /scratch
name: scratch

- name: produce-issues
imagePullPolicy: IfNotPresent
image: ghcr.io/ocurity/dracon/components/producers/cdxgen/image:latest
command: ["app/components/producers/cdxgen/cdxgen-parser"]
args:
- "-in=/scratch/out.json"
- "-out=$(workspaces.source-code-ws.path)/.dracon/producers/cdxgen.pb"
volumeMounts:
- mountPath: /scratch
name: scratch
Loading
Loading