Skip to content

Commit

Permalink
Merge branch 'main' into dependency-track-improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
northdpole authored Oct 18, 2023
2 parents 2eca5da + da3f67a commit ad8403a
Show file tree
Hide file tree
Showing 22 changed files with 738 additions and 39 deletions.
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"`
}
36 changes: 36 additions & 0 deletions components/enrichers/codeowners/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
subinclude(
"//build/defs:dracon",
"//build/defs:buildkit",
)

go_binary(
name = "codeowners",
srcs = [
"main.go",
],
static = True,
deps = [
"//api/proto/v1",
"//pkg/putil",
"//third_party/go/github.com/hairyhenderson/go-codeowners",
"//third_party/go/github.com/package-url/packageurl-go",
"//third_party/go/google.golang.org/protobuf",
],
)

buildkit_distroless_image(
name = "image",
srcs = [":codeowners"],
visibility = [
"//examples/...",
],
)

dracon_component(
name = "codeowners",
images = [
":image",
],
task = "task.yaml",
visibility = ["//examples/pipelines/..."],
)
5 changes: 5 additions & 0 deletions components/enrichers/codeowners/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# CodeOwners Enricher

This enricher scans the cloned source for [CODEOWNERS](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners) files,
For each finding, it adds the following annotation.
"Owner-<incremental number>:<the username of the owner>"
93 changes: 93 additions & 0 deletions components/enrichers/codeowners/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# 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: enricher-codeowners
taskRef:
name: enricher-codeowners
workspaces:
- name: source-code-ws
workspace: source-code-ws
params:
- name: enricher-codeowners-annotation
value: $(params.enricher-codeowners-annotation)
params:
- name: enricher-codeowners-annotation
type: string
default: ""
target:
kind: Pipeline
# Add anchors to Task.
- patch: |
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: enricher-codeowners
labels:
v1.dracon.ocurity.com/component: enricher
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: enricher-codeowners
# If we have an producer-aggregator task in the pipeline (added by the
# producer-aggregator component), make the enricher depend on the completion of
# it.
- patch: |
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: unused
spec:
tasks:
- name: enricher-codeowners
params:
- name: anchors
value:
- $(tasks.producer-aggregator.results.anchor)
target:
kind: Pipeline
annotationSelector: v1.dracon.ocurity.com/has-producer-aggregator=true
# If we have a enricher-aggregator task in the pipeline (added by the
# enricher-aggregator component), make it depend on the completion of this
# enricher.
- patch: |
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: unused
spec:
tasks:
- name: enricher-aggregator
params:
- name: anchors
value:
- $(tasks.enricher-codeowners.results.anchor)
target:
kind: Pipeline
annotationSelector: v1.dracon.ocurity.com/has-enricher-aggregator=true
125 changes: 125 additions & 0 deletions components/enrichers/codeowners/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// Package main of the codeowners enricher
// handles enrichment of individual issues with
// the groups/usernames listed in the github repository
// CODEOWNERS files.
// Owners are matched against the "target" field of the issue
package main

import (
"flag"
"fmt"
"log"
"os"
"path/filepath"
"strings"
"time"

owners "github.com/hairyhenderson/go-codeowners"
v1 "github.com/ocurity/dracon/api/proto/v1"
"github.com/ocurity/dracon/pkg/putil"
)

const defaultAnnotation = "Owner"

var (
readPath string
writePath string
repoBasePath string
annotation string
)

func lookupEnvOrString(key string, defaultVal string) string {
if val, ok := os.LookupEnv(key); ok {
return val
}
return defaultVal
}

func enrichIssue(i *v1.Issue) (*v1.EnrichedIssue, error) {
enrichedIssue := v1.EnrichedIssue{}
annotations := map[string]string{}
targets := []string{}
if i.GetCycloneDXSBOM() != "" {
// shortcut, if there is a CycloneDX BOM then there is no target.
// we get the url from the repoURL parameter
targets = []string{"."}
} else {
target := strings.Split(i.GetTarget(), ":")
if len(target) > 1 {
targets = append(targets, target[0])
} else {
targets = append(targets, i.GetTarget())
}
}
for _, target := range targets {
path := filepath.Join(repoBasePath, target)
c, err := owners.FromFile(repoBasePath)
if err != nil {
log.Println("could not instantiate owners for path", path, "err", err)
continue
}
owners := c.Owners(path)
for _, owner := range owners {
annotations[fmt.Sprintf("Owner-%d", len(annotations))] = owner
}
}

enrichedIssue = v1.EnrichedIssue{
RawIssue: i,
Annotations: annotations,
}
enrichedIssue.Annotations = annotations
return &enrichedIssue, nil
}

func run() {
res, err := putil.LoadTaggedToolResponse(readPath)
if err != nil {
log.Fatalf("could not load tool response from path %s , error:%v", readPath, err)
}
if annotation == "" {
annotation = defaultAnnotation
}
for _, r := range res {
enrichedIssues := []*v1.EnrichedIssue{}
for _, i := range r.GetIssues() {
eI, err := enrichIssue(i)
if err != nil {
log.Println(err)
continue
}
enrichedIssues = append(enrichedIssues, eI)
}
if len(enrichedIssues) > 0 {
if err := putil.WriteEnrichedResults(r, enrichedIssues,
filepath.Join(writePath, fmt.Sprintf("%s.depsdev.enriched.pb", r.GetToolName())),
); err != nil {
log.Fatal(err)
}
} else {
log.Println("no enriched issues were created for", r.GetToolName())
}
if len(r.GetIssues()) > 0 {
scanStartTime := r.GetScanInfo().GetScanStartTime().AsTime()
if err := putil.WriteResults(
r.GetToolName(),
r.GetIssues(),
filepath.Join(writePath, fmt.Sprintf("%s.raw.pb", r.GetToolName())),
r.GetScanInfo().GetScanUuid(),
scanStartTime.Format(time.RFC3339),
); err != nil {
log.Fatalf("could not write results: %s", err)
}
}

}
}

func main() {
flag.StringVar(&readPath, "read_path", lookupEnvOrString("READ_PATH", ""), "where to find producer results")
flag.StringVar(&writePath, "write_path", lookupEnvOrString("WRITE_PATH", ""), "where to put enriched results")
flag.StringVar(&annotation, "annotation", lookupEnvOrString("ANNOTATION", defaultAnnotation), "what is the annotation this enricher will add to the issues, by default `Enriched Licenses`")
flag.StringVar(&repoBasePath, "repoBasePath", lookupEnvOrString("REPO_BASE_PATH", ""), `the base path of the repository, this is most likely an internally set variable`)
flag.Parse()
run()
}
30 changes: 30 additions & 0 deletions components/enrichers/codeowners/task.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: enricher-codeowners
labels:
v1.dracon.ocurity.com/component: enricher
spec:
params:
- name: enricher-codeowners-annotation
type: string
default: ""

workspaces:
- name: source-code-ws
description: The workspace containing the source-code to scan.
steps:
- name: run-enricher
imagePullPolicy: IfNotPresent
image: ghcr.io/ocurity/dracon/components/enrichers/codeowners/image:latest
command: ["app/components/enrichers/codeowners/codeowners"]
env:
- name: READ_PATH
value: $(workspaces.source-code-ws.path)/.dracon/producers
- name: WRITE_PATH
value: "$(workspaces.source-code-ws.path)/.dracon/enrichers/codeowners"
- name: REPO_BASE_PATH
value: "$(workspaces.source-code-ws.path)/"
- name: ANNOTATION
value: "$(params.enricher-codeowners-annotation)"
5 changes: 5 additions & 0 deletions components/enrichers/depsdev/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,17 @@ patches:
params:
- name: enricher-depsdev-licenses-in-evidence
value: $(params.enricher-depsdev-licenses-in-evidence)
- name: enricher-depsdev-scorecard-info
value: $(params.enricher-depsdev-scorecard-info)
- name: enricher-depsdev-annotation
value: $(params.enricher-depsdev-annotation)
params:
- name: enricher-depsdev-licenses-in-evidence
type: string
default: "false"
- name: enricher-depsdev-scorecard-info
type: string
default: "true"
- name: enricher-depsdev-annotation
type: string
default: ""
Expand Down
Loading

0 comments on commit ad8403a

Please sign in to comment.