Skip to content

Commit

Permalink
close #409, refactor Jira consumer, remove addToDescription, instead …
Browse files Browse the repository at this point in the history
…offer a default template
  • Loading branch information
northdpole committed Oct 11, 2024
1 parent 4de4d7f commit c50bd6a
Show file tree
Hide file tree
Showing 13 changed files with 201 additions and 89 deletions.
13 changes: 10 additions & 3 deletions components/consumers/jira/task.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ spec:
type: string
- name: consumer-jira-user
type: string
- name: consumer-jira-config
- name: consumer-jira-project-name
type: string
default: ""
workspaces:
Expand All @@ -30,7 +30,15 @@ spec:
script: |
mkdir -p $(workspaces.output.path)/.dracon/consumers/jira
cat <<'EOF' > $(workspaces.output.path)/.dracon/consumers/jira/config.json
$(params.consumer-jira-config)
{
"defaultValues": {
"project": "$(params.consumer-jira-project-name)",
"issueType": "Task",
"customFields": null
},
"descriptionTemplate": "",
"mappings": null
}
EOF
cat $(workspaces.output.path)/.dracon/consumers/jira/config.json
- name: run-consumer
Expand All @@ -46,7 +54,6 @@ spec:
value: $(params.consumer-jira-url)
- name: DRACON_JIRA_CONFIG_PATH
value: $(workspaces.output.path)/.dracon/consumers/jira/config.json

args: [
"-in",
"$(workspaces.output.path)/.dracon/enrichers/",
Expand Down
4 changes: 0 additions & 4 deletions components/consumers/jira/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,6 @@ func ProcessMessages(allowDuplicates, allowFP bool, sevThreshold int) ([]documen
return nil, 0, err
}
messages, discarded := ProcessEnrichedMessages(responses, allowDuplicates, allowFP, sevThreshold)
if err != nil {
log.Print("Could not Process Enriched messages: ", err)
return nil, 0, err
}
return messages, discarded, nil
}

Expand Down
14 changes: 14 additions & 0 deletions examples/pipelines/jira-project/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
nameSuffix: -jira-project
components:
- pkg:helm/dracon-oss-components/base
- pkg:helm/dracon-oss-components/git-clone
- pkg:helm/dracon-oss-components/producer-golang-gosec
- pkg:helm/dracon-oss-components/producer-golang-nancy
- pkg:helm/dracon-oss-components/producer-aggregator
- pkg:helm/dracon-oss-components/enricher-custom-annotation
- pkg:helm/dracon-oss-components/enricher-aggregator
- pkg:helm/dracon-oss-components/consumer-stdout-json
- pkg:helm/dracon-oss-components/consumer-jira
37 changes: 37 additions & 0 deletions examples/pipelines/jira-project/pipelinerun.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
generateName: dracon-jira-project-
spec:
pipelineRef:
name: dracon-jira-project
params:
- name: git-clone-url
value: https://github.com/ocurity/e2e-monorepo.git
- name: consumer-jira-url
value: "$jira_url"
- name: consumer-jira-api-token
value: "$jira_token"
- name: consumer-jira-user
value: "$jira_user"
- name: consumer-jira-project-name
value: $jira_project_name
- name: enricher-custom-annotation-base-annotation
value: |
{
"found by other tools": "semgrep,toolmctoolface",
"training": "some training",
"knowledgebase": "cheatsheets"
}
- name: enricher-custom-annotation-name
value: "magic"
workspaces:
- name: output
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
14 changes: 0 additions & 14 deletions pkg/jira/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,6 @@ defaultValues:
## simple-value: will translate to the special jira use case of "customfield_id":"value"
## simple-value is provided as a workaround when single-value does not work with your jira setup

## Uncomment the fields you want included in the Issue's Description
addToDescription:
- scan_start_time
# - scan_id
- tool_name
# - source
- target
- type
# - severity_text
# - cvss
- confidence_text
# - first_found
# - false_positive

## You can map fields from the Dracon Result into customfields specific to your Jira Workspace
## Note: You don't have to map all (or any) of the fields
mappings:
Expand Down
9 changes: 0 additions & 9 deletions pkg/jira/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,6 @@ var sampleConfig = Config{
JiraField: "customfield_10001",
FieldType: "float",
}},
DescriptionExtras: []string{
"scan_start_time",
"tool_name",
"target",
"type",
"confidence_text",
"annotations",
"hash",
},
SyncMappings: []JiraToDraconVulnMappings{
{
JiraStatus: "Test",
Expand Down
1 change: 0 additions & 1 deletion pkg/jira/config/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ package config
type Config struct {
DefaultValues DefaultValues `json:"defaultValues"`
Mappings []Mappings `json:"mappings"`
DescriptionExtras []string `json:"addToDescription"`
DescriptionTemplate string `json:"descriptionTemplate"`
SyncMappings []JiraToDraconVulnMappings `json:"syncMappings"`
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/jira/jira/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func (c Client) assembleIssue(draconResult document.Document) *jira.Issue {
}
}
summary, extra := makeSummary(draconResult)
description := makeDescription(draconResult, c.Config.DescriptionExtras, c.Config.DescriptionTemplate)
description := makeDescription(draconResult, c.Config.DescriptionTemplate)
if extra != "" {
description = fmt.Sprintf(".... %s\n%s", extra, description)
}
Expand Down
21 changes: 6 additions & 15 deletions pkg/jira/jira/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,8 @@ var (
JiraField: "customfield_10001",
FieldType: "float",
}},
DescriptionExtras: []string{"target", "tool_name"},
}
t, _ = time.Parse("0001-01-01T00:00:00Z", "0001-01-01T00:00:00Z")
t, _ = time.Parse(time.RFC3339, "2024-10-10T20:06:33Z")
sampleResult = document.Document{
ScanStartTime: t,
ScanID: "babbb83-4627-41c6-8ba0-70ee866290e9",
Expand All @@ -50,6 +49,8 @@ var (
FirstFound: t,
FalsePositive: "true",
CVE: "CVE-0000-99999",
Annotations: map[string]string{"foo": "bar", "foobar": "baz"},
Count: "2",
}

expIssue = jira.Issue{
Expand All @@ -60,18 +61,8 @@ var (
Type: jira.IssueType{
Name: "Vulnerability",
},
Description: "Dracon found 'Unit Test Title'" +
" at '//foo1/bar1:baz2'," +
" severity 'SEVERITY_INFO'," +
" rule id: 'test type'," +
" CVSS '0'" +
" Confidence 'CONFIDENCE_INFO'" +
" Original Description: this is a test description," +
" Cve CVE-0000-99999,\n" +
"{code:}\n" +
"target: //foo1/bar1:baz2\n" +
"tool_name: spotbugs\n{code}\n",
Summary: "bar1:baz2 Unit Test Title",
Description: "spotbugs detected 'Unit Test Title' at //foo1/bar1:baz2 during scan started at: 2024-10-10T20:06:33Z with id babbb83-4627-41c6-8ba0-70ee866290e9.\nConfidence: Info\nThis issue has been detected 2 times before, first found on 2024-10-10T20:06:33Z\nOriginal Description is: 'this is a test description'\nspotbugs reported severity as Info\nSmithy enrichers added the following annotations:\nfoo:bar\nfoobar:baz\n\n",
Summary: "bar1:baz2 Unit Test Title",
Components: []*jira.Component{
{Name: "c1"},
{Name: "c2"},
Expand Down Expand Up @@ -109,7 +100,7 @@ func TestAuthJiraClient(t *testing.T) {

func TestAssembleIssue(t *testing.T) {
issue := sampleClient.assembleIssue(sampleResult)
assert.EqualValues(t, issue, &expIssue)
assert.EqualValues(t, &expIssue, issue)
}

func TestCreateIssue(t *testing.T) {
Expand Down
32 changes: 17 additions & 15 deletions pkg/jira/jira/apiutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package jira

import (
"bytes"
_ "embed"
"encoding/json"
"fmt"
"log"
"path/filepath"
"strconv"
Expand All @@ -30,6 +30,9 @@ type defaultJiraFields struct {
CustomFields tcontainer.MarshalMap
}

//go:embed issueTemplate.txt
var defaultTemplate string

// getDefaultFields creates the fields for Project, IssueType, Components, AffectsVersions, Labels and CustomFields
// with the default values specified in config.yaml and serializes them into Jira Fields.
func getDefaultFields(config config.Config) defaultJiraFields {
Expand Down Expand Up @@ -112,7 +115,11 @@ func draconResultToSTRMaps(draconResult document.Document) (map[string]string, s
}

// makeDescription creates the description of an issue's enhanced with extra information from the Dracon Result.
func makeDescription(draconResult document.Document, extras []string, template string) string {
func makeDescription(draconResult document.Document, template string) string {

if template == "" {
template = defaultTemplate
}
if draconResult.Count == "" {
draconResult.Count = "0"
}
Expand All @@ -131,6 +138,7 @@ func makeDescription(draconResult document.Document, extras []string, template s
if err != nil {
log.Fatal("could not template enriched issue ", err)
}

description, err := templating.TemplateStringEnriched(template,
&v1.EnrichedIssue{
Annotations: draconResult.Annotations,
Expand All @@ -150,24 +158,18 @@ func makeDescription(draconResult document.Document, extras []string, template s
Type: draconResult.Type,
},
},
templating.EnrichedIssueWithToolName(draconResult.ToolName),
templating.EnrichedIssueWithScanStartTime(draconResult.ScanStartTime),
templating.EnrichedIssueWithScanID(draconResult.ScanID),
templating.EnrichedIssueWithConfidenceText(draconResult.ConfidenceText),
templating.EnrichedIssueWithCount(uint(count)),
templating.EnrichedIssueWithFirstFound(draconResult.FirstFound),
templating.EnrichedIssueWithSeverityText(draconResult.SeverityText),
)
if err != nil {
log.Fatal("Could not template enriched issue ", err)
}
desc := *description
// Append the extra fields to the description
strMap, annotations := draconResultToSTRMaps(draconResult)
if len(extras) > 0 {
desc += "{code:}" + "\n"
for _, s := range extras {
if s == "annotations" {
desc += fmt.Sprintf("%s: %*s\n", s, 25-len(s)+len(annotations), annotations)
} else {
desc += fmt.Sprintf("%s: %*s\n", s, 25-len(s)+len(strMap[s]), strMap[s])
}
}
desc += "{code}" + "\n"
}
return desc
}

Expand Down
38 changes: 13 additions & 25 deletions pkg/jira/jira/apiutils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"testing"

jira "github.com/andygrunwald/go-jira"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/trivago/tgo/tcontainer"
)

Expand Down Expand Up @@ -33,7 +33,7 @@ func TestSetDefaultFields(t *testing.T) {
},
}

assert.EqualValues(t, res, exp)
require.EqualValues(t, res, exp)
}

func TestMakeCustomField(t *testing.T) {
Expand All @@ -53,35 +53,23 @@ func TestMakeCustomField(t *testing.T) {
res4 := makeCustomField("simple-value", []string{"test-value"})
exp4 := "test-value"

assert.EqualValues(t, res1, exp1)
assert.EqualValues(t, res2, exp2)
assert.Equal(t, res3, exp3)
assert.Equal(t, res4, exp4)
require.EqualValues(t, res1, exp1)
require.EqualValues(t, res2, exp2)
require.Equal(t, res3, exp3)
require.Equal(t, res4, exp4)
}

func TestMakeDescription(t *testing.T) {
extras := []string{"tool_name", "target", "confidence_text"}
res := makeDescription(sampleResult, extras, "")
exp := "Dracon found 'Unit Test Title' at '//foo1/bar1:baz2'," +
" severity 'SEVERITY_INFO'," +
" rule id: 'test type'," +
" CVSS '0' " +
"Confidence 'CONFIDENCE_INFO'" +
" Original Description: this is a test description," +
" Cve CVE-0000-99999,\n" +
"{code:}\n" +
"tool_name: spotbugs\n" +
"target: //foo1/bar1:baz2\n" +
"confidence_text: Info\n" +
"{code}\n"
assert.Equal(t, res, exp)
res := makeDescription(sampleResult, "")
exp := "spotbugs detected 'Unit Test Title' at //foo1/bar1:baz2 during scan started at: 2024-10-10T20:06:33Z with id babbb83-4627-41c6-8ba0-70ee866290e9.\nConfidence: Info\nThis issue has been detected 2 times before, first found on 2024-10-10T20:06:33Z\nOriginal Description is: 'this is a test description'\nspotbugs reported severity as Info\nSmithy enrichers added the following annotations:\nfoo:bar\nfoobar:baz\n\n"
require.Equal(t, res, exp)
}

func TestMakeSummary(t *testing.T) {
res, extra := makeSummary(sampleResult)
exp := "bar1:baz2 Unit Test Title"
assert.Equal(t, res, exp)
assert.Equal(t, extra, "")
require.Equal(t, res, exp)
require.Equal(t, extra, "")

longTitle := make([]rune, 300)
truncatedSummary := make([]rune, 254)
Expand All @@ -107,7 +95,7 @@ func TestMakeSummary(t *testing.T) {
sampleResult.Title = string(longTitle)

res, extra = makeSummary(sampleResult)
assert.Equal(t, string(truncatedSummary), res)
require.Equal(t, string(truncatedSummary), res)

assert.Equal(t, string(expectedExtra), extra)
require.Equal(t, string(expectedExtra), extra)
}
8 changes: 8 additions & 0 deletions pkg/jira/jira/issueTemplate.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{{.ToolName}} detected '{{.RawIssue.Title}}' at {{.RawIssue.Target}} during scan started at: {{.ScanStartTime}} with id {{.ScanID}}.
Confidence: {{.ConfidenceText}}
{{ if gt .Count 0 }}This issue has been detected {{.Count}} times before, first found on {{.FirstFound}}{{ end }}
Original Description is: '{{.RawIssue.Description}}'
{{.ToolName}} reported severity as {{.SeverityText}}
Smithy enrichers added the following annotations:
{{ range $key, $value := .Annotations }}{{ $key }}:{{ $value }}
{{ end }}
Loading

0 comments on commit c50bd6a

Please sign in to comment.