Skip to content

Commit

Permalink
RELEASE (#189)
Browse files Browse the repository at this point in the history
* minor: Adding new flag: canAutoPR (#187)

Thi is to address #182

Co-authored-by: Troy Havelock <[email protected]>

* minor: Added DueDate support for creating Jira (#185)

Added the optional flag for the due date built-in flag.
Updated README with instructions

Co-authored-by: Alexandre Vallières-Lagacé <[email protected]>

Co-authored-by: Troy Havelock <[email protected]>
Co-authored-by: Alexandre Vallières-Lagacé <[email protected]>
  • Loading branch information
3 people authored Dec 16, 2022
1 parent 4c6d1bf commit 8886de1
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 12 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ dist/
jira-ticket-for-new-vulns*
ErrorsFile*
listOfTicketCreated*
.DS_Store
.idea/
21 changes: 13 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Aimed to be executed at regular interval or with a trigger of your choice (webho
**This repository is in maintenance mode, no new features are being developed. Bug & security fixes will continue to be delivered. Open source contributions are welcome for small features & fixes (no breaking changes)**

## Installation
You can either download the binaries fron the from [the release page](https://github.com/snyk-tech-services/jira-tickets-for-new-vulns/releases)
You can either download the binaries from the [the release page](https://github.com/snyk-tech-services/jira-tickets-for-new-vulns/releases)
or
Use `go install github.com/snyk-tech-services/jira-tickets-for-new-vulns@latest`

Expand Down Expand Up @@ -115,6 +115,12 @@ Use `go install github.com/snyk-tech-services/jira-tickets-for-new-vulns@latest`

*Example*: `--labels=app-1234`

- `--dueDate` *optional*

Set [Jira ticket labels](https://confluence.atlassian.com/jirasoftwareserver/editing-and-collaborating-on-issues-939938928.html)

*Example*: `--dueDate=2022-12-01`
-
- `--priorityScoreThreshold` *optional*

Your minimum [Snyk priority score](https://docs.snyk.io/features/fixing-and-prioritizing-issues/starting-to-fix-vulnerabilities/snyk-priority-score) threshold. Can be a number between `0` and `1000`.
Expand Down Expand Up @@ -183,12 +189,12 @@ The tool does not support IAC project. It will open issue only for code and open
Option to get the JIRA ticket priority set based on issue severity.
Defaults map to:

Issue severity | JIRA Priority
----- | -----
critical | Highest
high | High
medium | Medium
low | Low
| Issue severity | JIRA priority |
|:----------------:|:-------------:|
| critical | Highest |
| high | High |
| medium | Medium |
| low | Low |

Use `SNYK_JIRA_PRIORITY_FOR_XXX_VULN` env var to override the default an set your value.
> *Example*:
Expand Down Expand Up @@ -319,4 +325,3 @@ Notes:
Using the config file above, running `./snyk-jira-sync-macOs --Org=1234 --configFile=./path/to/folder --token=123`
the org ID used by the tool will be `1234` and not `a1b2c3de-99b1-4f3f-bfdb-6ee4b4990513`
- See 'Extended options' for default values
4 changes: 2 additions & 2 deletions end_to_end_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func TestEndToEndFunc(t *testing.T) {
os.Args = append(os.Args, "--jiraProjectID=123")
os.Args = append(os.Args, "--api="+server.URL)

// Keeping the line below => useful for debug but print too much things
// Keeping the line below => useful for debug but print too many things
// os.Args = append(os.Args, "-debug=true")

// Get the console output
Expand All @@ -48,7 +48,7 @@ func TestEndToEndFunc(t *testing.T) {
assert.True(t, found)

// check if the json is valid
file, err := ioutil.ReadFile(path)
file, err := os.ReadFile(path)
if err != nil {
panic(err)
}
Expand Down
5 changes: 5 additions & 0 deletions jira.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type Field struct {
Assignees *Assignee `json:"assignee,omitempty"`
Priority *PriorityType `json:"priority,omitempty"`
Labels []string `json:"labels,omitempty"`
DueDate string `json:"dueDate,omitempty"`
}

// Assignee is the account ID of the Jira user to assign tickets to
Expand Down Expand Up @@ -130,6 +131,10 @@ func openJiraTicket(flags flags, projectInfo jsn.Json, vulnForJira interface{},
jiraTicket.Fields.Labels = strings.Split(flags.optionalFlags.labels, ",")
}

if flags.optionalFlags.dueDate != "" {
jiraTicket.Fields.DueDate = flags.optionalFlags.dueDate
}

if flags.optionalFlags.assigneeID != "" {
var assignee Assignee
assignee.AccountId = flags.optionalFlags.assigneeID
Expand Down
56 changes: 56 additions & 0 deletions jira_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1047,3 +1047,59 @@ func TestOpenJiraTicketError50xAndRetryFunc(t *testing.T) {

return
}

// Test openJiraTickets function
func TestOpenJiraTicketWithDueDateFunc(t *testing.T) {
assert := assert.New(t)
server := HTTPResponseCheckOpenJiraTickets("/v1/org/123/project/12345678-1234-1234-1234-123456789012/issue/SNYK-JS-MINIMIST-559764/jira-issue")

defer server.Close()

projectInfo, _ := jsn.NewJson(readFixture("./fixtures/project.json"))
vulnsForJira := make(map[string]interface{})
err := json.Unmarshal(readFixture("./fixtures/vulnsForJira.json"), &vulnsForJira)
if err != nil {
panic(err)
}

// setting mandatory options
Mf := MandatoryFlags{}
Mf.orgID = "123"
Mf.endpointAPI = server.URL
Mf.apiToken = "123"
Mf.jiraProjectID = "123"
Mf.jiraProjectKey = ""

// setting optional options
Of := optionalFlags{}
Of.severity = ""
Of.priorityScoreThreshold = 0
Of.issueType = ""
Of.debug = false
Of.jiraTicketType = "Bug"
Of.assigneeID = ""
Of.labels = ""
Of.dueDate = "2029-01-01"
Of.priorityIsSeverity = false
Of.projectID = ""
Of.maturityFilterString = ""
Of.dryRun = false
Of.ifUpgradeAvailableOnly = false

flags := flags{}
flags.mandatoryFlags = Mf
flags.optionalFlags = Of

// setting debug
cD := debug{}
cD.setDebug(false)

numberIssueCreated, jiraResponse, NotCreatedIssueId, tickets := openJiraTickets(flags, projectInfo, vulnsForJira, cD)

assert.Equal("", NotCreatedIssueId)
assert.NotNil(tickets)
assert.Equal(string(readFixture("./fixtures/results/jiraTicketsOpeningResults")), jiraResponse)
fmt.Println("numberIssueCreated :", numberIssueCreated)

return
}
17 changes: 15 additions & 2 deletions utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ func (Of *optionalFlags) setOptionalFlags(debugPtr bool, dryRunPtr bool, v viper
Of.maturityFilterString = v.GetString("snyk.maturityFilter")
Of.assigneeID = v.GetString("jira.assigneeID")
Of.labels = v.GetString("jira.labels")
Of.dueDate = v.GetString("jira.dueDate")
Of.priorityIsSeverity = v.GetBool("jira.priorityIsSeverity")
Of.priorityScoreThreshold = v.GetInt("snyk.priorityScoreThreshold")
Of.debug = debugPtr
Expand Down Expand Up @@ -156,8 +157,9 @@ func (opt *flags) setOption(args []string) {
fs.String("severity", "low", "Optional. Your severity threshold")
fs.String("maturityFilter", "", "Optional. include only maturity level(s) separated by commas [mature,proof-of-concept,no-known-exploit,no-data]")
fs.String("type", "all", "Optional. Your issue type (all|vuln|license)")
fs.String("assigneeId", "", "Optional. The Jira user accountId to assign issues to.")
fs.String("assigneeId", "", "Optional. The Jira user accountId to assign issues to")
fs.String("labels", "", "Optional. Jira ticket labels")
fs.String("dueDate", "", "Optional. The built-in Due Date field")
fs.Bool("priorityIsSeverity", false, "Boolean. Use issue severity as priority")
fs.Int("priorityScoreThreshold", 0, "Optional. Your min priority score threshold [INT between 0 and 1000]")
debugPtr = fs.Bool("debug", false, "Optional. Boolean. enable debug mode")
Expand All @@ -166,7 +168,11 @@ func (opt *flags) setOption(args []string) {
fs.Bool("ifUpgradeAvailableOnly", false, "Optional. Boolean. Opens tickets only for upgradable issues")
fs.Bool("ifAutoFixableOnly", false, "Optional. Boolean. Opens tickets for issues that are fixable (no effect when using ifUpgradeAvailableOnly)")
configFilePtr = fs.String("configFile", "", "Optional. Config file path. Use config file to set parameters")
fs.Parse(args)
errParse := fs.Parse(args)
if errParse != nil {
log.Println("*** ERROR *** Error parsing command line arguments: ", errParse.Error())
os.Exit(1)
}

// Have to set one by one because the name in the config file doesn't correspond to the flag name
// This can be done at any time
Expand All @@ -186,6 +192,7 @@ func (opt *flags) setOption(args []string) {
v.BindPFlag("jira.assigneeID", fs.Lookup("assigneeId"))
v.BindPFlag("jira.labels", fs.Lookup("labels"))
v.BindPFlag("jira.cveInTitle", fs.Lookup("cveInTitle"))
v.BindPFlag("jira.dueDate", fs.Lookup("dueDate"))
v.BindPFlag("jira.priorityIsSeverity", fs.Lookup("priorityIsSeverity"))
v.BindPFlag("snyk.priorityScoreThreshold", fs.Lookup("priorityScoreThreshold"))
v.BindPFlag("snyk.ifUpgradeAvailableOnly", fs.Lookup("ifUpgradeAvailableOnly"))
Expand Down Expand Up @@ -676,6 +683,12 @@ func checkJiraValue(JiraValues interface{}) (bool, map[string]interface{}) {
log.Printf("*** ERROR *** Please check the format config file, %s is of type %s when it should be a string", key, reflect.TypeOf(value).String())
return false, nil
}
case "dueDate":
valueType := reflect.TypeOf(value).String()
if valueType != "string" {
log.Printf("*** ERROR *** Please check the format config file, %s is of type %s when it should be a string", key, reflect.TypeOf(value).String())
return false, nil
}
case "priorityIsSeverity":
valueType := reflect.TypeOf(value).String()
if valueType != "bool" {
Expand Down
1 change: 1 addition & 0 deletions utils_def.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type optionalFlags struct {
maturityFilterString string
assigneeID string
labels string
dueDate string
priorityIsSeverity bool
priorityScoreThreshold int
debug bool
Expand Down

0 comments on commit 8886de1

Please sign in to comment.