From 47d92171e4e946d77d2a6e897ab8e718aeaf71b8 Mon Sep 17 00:00:00 2001 From: foobar Date: Sun, 17 Mar 2024 13:15:37 +0000 Subject: [PATCH] add DT orchestration --- components/producers/dependency-track/BUILD | 50 ---------------- components/producers/dependency-track/main.go | 58 ++++++++++++++++--- .../producers/dependency-track/task.yaml | 17 ++++++ 3 files changed, 68 insertions(+), 57 deletions(-) delete mode 100644 components/producers/dependency-track/BUILD diff --git a/components/producers/dependency-track/BUILD b/components/producers/dependency-track/BUILD deleted file mode 100644 index 5c28337e3..000000000 --- a/components/producers/dependency-track/BUILD +++ /dev/null @@ -1,50 +0,0 @@ -subinclude( - "//build/defs:buildkit", - "///k8s//build/defs:k8s", - "//build/defs:dracon", -) - -go_binary( - name = "dependency-track-parser", - srcs = [ - "main.go", - ], - deps = [ - "//api/proto/v1", - "//components/producers", - "//pkg/context", - ], -) - -go_test( - name = "dependency-track_test", - srcs = [ - "main.go", - "main_test.go", - ], - deps = [ - "//api/proto/v1", - "//components/producers", - "//pkg/context", - "//pkg/testutil", - "//third_party/go/github.com/stretchr/testify", - ], -) - -buildkit_distroless_image( - name = "image", - srcs = [":dependency-track-parser"], - visibility = [ - "//examples/...", - ], -) - -dracon_component( - name = "dependency-track", - images = [ - ":image", - "//third_party/docker/securego/gosec", - ], - task = "task.yaml", - visibility = ["//examples/pipelines/..."], -) diff --git a/components/producers/dependency-track/main.go b/components/producers/dependency-track/main.go index 0427094e7..84616e2b9 100644 --- a/components/producers/dependency-track/main.go +++ b/components/producers/dependency-track/main.go @@ -2,27 +2,58 @@ package main import ( + "context" "encoding/json" + "flag" "fmt" "log" + dtrack "github.com/DependencyTrack/client-go" + "github.com/google/uuid" v1 "github.com/ocurity/dracon/api/proto/v1" "github.com/ocurity/dracon/components/producers" ) +var ( + // Fetch is a boolean flag that instructs the DT producer to fetch all vulnerabilities from a specific project + Fetch bool + // ProjectID is only used with "Fetch", if fetch is defined, vulnerabilities of the specific projectID will be fetched + ProjectID string + + // APIKey is the DT api key + APIKey string + + // URL is the URL of the remote DT + URL string +) + func main() { + flag.BoolVar(&Fetch, "fetchVulnerabilities", false, "a boolean flag that instructs the DT producer to fetch all vulnerabilities from a specific project") + flag.StringVar(&ProjectID, "projectID", "", "only used with \"Fetch\", if fetch is defined, vulnerabilities of the specific projectID will be fetched") + flag.StringVar(&APIKey, "apiKey", "", "only used with \"Fetch\", if fetch is defined, vulnerabilities of the specific projectID will be fetched using this API Key") + flag.StringVar(&URL, "url", "", "only used with \"Fetch\", if fetch is defined, vulnerabilities of the specific projectID will be fetched using this URL and the supplied API Key") + if err := producers.ParseFlags(); err != nil { log.Fatal(err) } - inFile, err := producers.ReadInFile() - if err != nil { - log.Fatal(err) + var inFile []byte + if Fetch { + input, err := readFromDependencyTrack(APIKey, URL, ProjectID) + if err != nil { + log.Fatal(err) + } + inFile = input + } else { + input, err := producers.ReadInFile() + if err != nil { + log.Fatal(err) + } + inFile = input } - var results DependencyTrackOut - if err := producers.ParseJSON(inFile, &results); err != nil { + if err := json.Unmarshal(inFile, &results); err != nil { log.Fatal(err) } @@ -31,13 +62,26 @@ func main() { log.Fatal(err) } if err := producers.WriteDraconOut( - "gosec", + "Dependency Track", issues, ); err != nil { log.Fatal(err) } } +func readFromDependencyTrack(apiKey, url, projectID string) ([]byte, error) { + client, err := dtrack.NewClient(url, dtrack.WithAPIKey(apiKey)) + if err != nil { + return nil, fmt.Errorf("could not instantiate client err: %#v", err) + } + findings, err := dtrack.FetchAll(func(po dtrack.PageOptions) (dtrack.Page[dtrack.Finding], error) { + return client.Finding.GetAll(context.Background(), uuid.MustParse(projectID), false, po) + }) + if err != nil { + return nil, err + } + return json.Marshal(findings) +} func parseIssues(out *DependencyTrackOut) ([]*v1.Issue, error) { issues := []*v1.Issue{} for _, element := range *out { @@ -128,7 +172,7 @@ type Vulnerability struct { Recommendation string `json:"recommendation"` } -// DependencyTrackOut is an export from DT +// DependencyTrackOut is an export from DT findings API type DependencyTrackOut []struct { Component Component `json:"component"` Vulnerability Vulnerability `json:"vulnerability"` diff --git a/components/producers/dependency-track/task.yaml b/components/producers/dependency-track/task.yaml index 707c8782c..e447b8f11 100644 --- a/components/producers/dependency-track/task.yaml +++ b/components/producers/dependency-track/task.yaml @@ -6,6 +6,19 @@ metadata: labels: v1.dracon.ocurity.com/component: producer spec: + params: + - name: producer-dependency-track-project-id + type: string + default: "" + - name: producer-dependency-track-fetch-vulnerabilities + type: string + default: "" + - name: producer-dependency-track-url + type: string + default: "" + - name: producer-dependency-track-api-key + type: string + default: "" volumes: - name: scratch emptyDir: {} @@ -18,6 +31,10 @@ spec: image: ghcr.io/ocurity/dracon/components/producers/dependency-track/image:latest command: ["app/components/producers/dependency-track/dependency-track-parser"] args: + - "-fetchVulnerabilities=$(params.producer-dependency-track-fetch-vulnerabilities)" + - "-projectID=$(params.producer-dependency-track-project-id)" + - "-apiKey=$(params.producer-dependency-track-api-key)" + - "-url=$(params.producer-dependency-track-url)" - "-in=/scratch/out.json" - "-out=$(workspaces.source-code-ws.path)/.dracon/producers/dependency-track.pb" volumeMounts: