Skip to content

Commit 18fd15b

Browse files
chore: merge and resolve conflicts
2 parents 2eec2d0 + 6c7c56b commit 18fd15b

30 files changed

+1108
-146
lines changed

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ permissions:
3030

3131
jobs:
3232
build:
33-
runs-on: macos-13
33+
runs-on: macos-15-intel
3434
env:
3535
AC_PASSWORD: ${{ secrets.AC_PASSWORD }}
3636
APPLE_DEVELOPER_CERTIFICATE_P12_BASE64: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_P12_BASE64 }}

internal/commands/auth.go

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"log"
66

77
"github.com/MakeNowJust/heredoc"
8+
"github.com/checkmarx/ast-cli/internal/logger"
89
"github.com/checkmarx/ast-cli/internal/params"
910
"github.com/checkmarx/ast-cli/internal/wrappers"
1011
"github.com/google/uuid"
@@ -38,7 +39,7 @@ type ClientCreated struct {
3839
Secret string `json:"secret"`
3940
}
4041

41-
func NewAuthCommand(authWrapper wrappers.AuthWrapper) *cobra.Command {
42+
func NewAuthCommand(authWrapper wrappers.AuthWrapper, telemetryWrapper wrappers.TelemetryWrapper) *cobra.Command {
4243
authCmd := &cobra.Command{
4344
Use: "auth",
4445
Short: "Validate authentication and create OAuth2 credentials",
@@ -110,13 +111,13 @@ func NewAuthCommand(authWrapper wrappers.AuthWrapper) *cobra.Command {
110111
`,
111112
),
112113
},
113-
RunE: validLogin(),
114+
RunE: validLogin(telemetryWrapper),
114115
}
115116
authCmd.AddCommand(createClientCmd, validLoginCmd)
116117
return authCmd
117118
}
118119

119-
func validLogin() func(cmd *cobra.Command, args []string) error {
120+
func validLogin(telemetryWrapper wrappers.TelemetryWrapper) func(cmd *cobra.Command, args []string) error {
120121
return func(cmd *cobra.Command, args []string) error {
121122
clientID := viper.GetString(params.AccessKeyIDConfigKey)
122123
clientSecret := viper.GetString(params.AccessKeySecretConfigKey)
@@ -125,6 +126,19 @@ func validLogin() func(cmd *cobra.Command, args []string) error {
125126
authWrapper := wrappers.NewAuthHTTPWrapper()
126127
authWrapper.SetPath(viper.GetString(params.ScansPathKey))
127128
err := authWrapper.ValidateLogin()
129+
130+
uniqueID := wrappers.GetUniqueID()
131+
if uniqueID != "" {
132+
telemetryErr := telemetryWrapper.SendAIDataToLog(&wrappers.DataForAITelemetry{
133+
UniqueID: uniqueID,
134+
Type: "authentication",
135+
SubType: "authentication",
136+
})
137+
if telemetryErr != nil {
138+
logger.PrintIfVerbose("Failed to send telemetry data: " + telemetryErr.Error())
139+
}
140+
}
141+
128142
if err != nil {
129143
return errors.Errorf("%s", err)
130144
}

internal/commands/predicates.go

Lines changed: 170 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
package commands
22

33
import (
4+
"fmt"
5+
"sort"
46
"strings"
57
"time"
68

9+
"encoding/json"
10+
711
"github.com/MakeNowJust/heredoc"
812
"github.com/checkmarx/ast-cli/internal/commands/util/printer"
13+
"github.com/checkmarx/ast-cli/internal/logger"
914
"github.com/checkmarx/ast-cli/internal/params"
1015
"github.com/checkmarx/ast-cli/internal/wrappers"
1116
"github.com/pkg/errors"
@@ -92,8 +97,8 @@ func triageShowSubCommand(resultsPredicatesWrapper wrappers.ResultsPredicatesWra
9297
triageShowCmd.PersistentFlags().String(params.SimilarityIDFlag, "", "Similarity ID")
9398
triageShowCmd.PersistentFlags().String(params.ProjectIDFlag, "", "Project ID")
9499
triageShowCmd.PersistentFlags().String(params.ScanTypeFlag, "", "Scan Type")
100+
triageShowCmd.PersistentFlags().StringSlice(params.VulnerabilitiesFlag, []string{}, "SCA Vulnerabilities details")
95101

96-
markFlagAsRequired(triageShowCmd, params.SimilarityIDFlag)
97102
markFlagAsRequired(triageShowCmd, params.ProjectIDFlag)
98103
markFlagAsRequired(triageShowCmd, params.ScanTypeFlag)
99104

@@ -117,6 +122,7 @@ func triageUpdateSubCommand(resultsPredicatesWrapper wrappers.ResultsPredicatesW
117122
--scan-type <SAST|IAC-SECURITY>
118123
`,
119124
),
125+
120126
RunE: runTriageUpdate(resultsPredicatesWrapper, featureFlagsWrapper, customStatesWrapper),
121127
}
122128

@@ -127,9 +133,8 @@ func triageUpdateSubCommand(resultsPredicatesWrapper wrappers.ResultsPredicatesW
127133
triageUpdateCmd.PersistentFlags().Int(params.CustomStateIDFlag, -1, "Specify the ID of the states that you would like to apply to this result")
128134
triageUpdateCmd.PersistentFlags().String(params.CommentFlag, "", "Optional comment")
129135
triageUpdateCmd.PersistentFlags().String(params.ScanTypeFlag, "", "Scan Type")
136+
triageUpdateCmd.PersistentFlags().StringSlice(params.VulnerabilitiesFlag, []string{}, "SCA Vulnerabilities details")
130137

131-
markFlagAsRequired(triageUpdateCmd, params.SimilarityIDFlag)
132-
markFlagAsRequired(triageUpdateCmd, params.SeverityFlag)
133138
markFlagAsRequired(triageUpdateCmd, params.ProjectIDFlag)
134139
markFlagAsRequired(triageUpdateCmd, params.ScanTypeFlag)
135140

@@ -145,38 +150,48 @@ func runTriageShow(resultsPredicatesWrapper wrappers.ResultsPredicatesWrapper) f
145150
similarityID, _ := cmd.Flags().GetString(params.SimilarityIDFlag)
146151
scanType, _ := cmd.Flags().GetString(params.ScanTypeFlag)
147152
projectID, _ := cmd.Flags().GetString(params.ProjectIDFlag)
148-
153+
vulnerabilityDetails, _ := cmd.Flags().GetStringSlice(params.VulnerabilitiesFlag)
149154
projectIDs := strings.Split(projectID, ",")
150155
if len(projectIDs) > 1 {
151156
return errors.Errorf("%s", "Multiple project-ids are not allowed.")
152157
}
153158

154-
predicatesCollection, errorModel, err = resultsPredicatesWrapper.GetAllPredicatesForSimilarityID(
155-
similarityID,
156-
projectID,
157-
scanType,
158-
)
159-
160-
if err != nil {
161-
return errors.Wrapf(err, "%s", "Failed showing the predicate")
162-
}
163-
164-
// Checking the response
165-
if errorModel != nil {
166-
return errors.Errorf(
167-
"%s: CODE: %d, %s",
168-
"Failed showing the predicate.",
169-
errorModel.Code,
170-
errorModel.Message,
171-
)
172-
} else if predicatesCollection != nil {
173-
err = printByFormat(cmd, toPredicatesView(*predicatesCollection))
159+
if strings.EqualFold(strings.ToLower(strings.TrimSpace(scanType)), params.ScaType) {
160+
if len(vulnerabilityDetails) == 0 {
161+
return errors.Errorf("%s", "Failed showing the predicate. Vulnerabilities are required for SCA triage")
162+
}
163+
scaPredicates, err := resultsPredicatesWrapper.GetScaPredicates(vulnerabilityDetails, projectID)
164+
if err != nil {
165+
return errors.Wrapf(err, "%s", "Failed showing the predicate")
166+
}
167+
err = printByFormat(cmd, toScaPredicateResultView(scaPredicates))
174168
if err != nil {
175169
return err
176170
}
171+
return nil
172+
} else {
173+
predicatesCollection, errorModel, err = resultsPredicatesWrapper.GetAllPredicatesForSimilarityID(similarityID, projectID, scanType)
174+
if err != nil {
175+
return errors.Wrapf(err, "%s", "Failed showing the predicate")
176+
}
177+
// Checking the response
178+
if errorModel != nil {
179+
return errors.Errorf(
180+
"%s: CODE: %d, %s",
181+
"Failed showing the predicate.",
182+
errorModel.Code,
183+
errorModel.Message,
184+
)
185+
} else if predicatesCollection != nil {
186+
err = printByFormat(cmd, toPredicatesView(*predicatesCollection))
187+
if err != nil {
188+
return err
189+
}
190+
}
191+
192+
return nil
177193
}
178194

179-
return nil
180195
}
181196
}
182197

@@ -191,38 +206,124 @@ func runTriageUpdate(resultsPredicatesWrapper wrappers.ResultsPredicatesWrapper,
191206
scanType, _ := cmd.Flags().GetString(params.ScanTypeFlag)
192207
// check if the current tenant has critical severity available
193208
flagResponse, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.CVSSV3Enabled)
209+
vulnerabilityDetails, _ := cmd.Flags().GetStringSlice(params.VulnerabilitiesFlag)
210+
194211
criticalEnabled := flagResponse.Status
195212
if !criticalEnabled && strings.EqualFold(severity, "critical") {
196213
return errors.Errorf("%s", "Critical severity is not available for your tenant.This severity status will be enabled shortly")
197214
}
198-
199215
var err error
200216
state, customStateID, err = determineSystemOrCustomState(customStatesWrapper, featureFlagsWrapper, state, customStateID)
201217
if err != nil {
202-
return err
218+
return errors.Wrapf(err, "%s", "Failed updating the predicate")
203219
}
204220

205-
predicate := &wrappers.PredicateRequest{
221+
predicate, err := preparePredicateRequest(vulnerabilityDetails, similarityID, projectID, severity, state, customStateID, comment, scanType)
222+
if err != nil {
223+
return errors.Wrapf(err, "%s", "Failed updating the predicate")
224+
}
225+
_, err = resultsPredicatesWrapper.PredicateSeverityAndState(predicate, scanType)
226+
if err != nil {
227+
return errors.Wrapf(err, "%s", "Failed updating the predicate")
228+
}
229+
return nil
230+
}
231+
}
232+
233+
func preparePredicateRequest(vulnerabilityDetails []string, similarityID, projectID, severity, state string, customStateID int, comment, scanType string) (interface{}, error) {
234+
scanType = strings.ToLower(scanType)
235+
scanType = strings.TrimSpace(scanType)
236+
if strings.EqualFold(scanType, Sca) {
237+
state = transformState(state)
238+
payload, err := prepareScaTriagePayload(vulnerabilityDetails, comment, state, projectID)
239+
if err != nil {
240+
return nil, err
241+
}
242+
return payload, nil
243+
} else {
244+
payload := &wrappers.PredicateRequest{
206245
SimilarityID: similarityID,
207246
ProjectID: projectID,
208247
Severity: severity,
209248
Comment: comment,
210249
}
211-
212250
if state != "" {
213-
predicate.State = &state
251+
payload.State = &state
214252
} else {
215-
predicate.CustomStateID = &customStateID
253+
payload.CustomStateID = &customStateID
216254
}
255+
return payload, nil
256+
}
257+
}
217258

218-
_, err = resultsPredicatesWrapper.PredicateSeverityAndState(predicate, scanType)
259+
func transformState(state string) string {
260+
state = strings.ToLower(strings.TrimSpace(state))
261+
switch state {
262+
case strings.ToLower(params.ToVerify):
263+
return wrappers.ToVerify
264+
case strings.ToLower(params.URGENT):
265+
return wrappers.Urgent
266+
case strings.ToLower(params.NotExploitable):
267+
return wrappers.NotExploitable
268+
case strings.ToLower(params.ProposedNotExploitable):
269+
return wrappers.ProposedNotExploitable
270+
case strings.ToLower(params.CONFIRMED):
271+
return wrappers.Confirmed
272+
}
273+
return ""
274+
}
275+
276+
func prepareScaTriagePayload(vulnerabilityDetails []string, comment, state, projectID string) (interface{}, error) {
277+
if len(vulnerabilityDetails) == 0 {
278+
return nil, errors.Errorf("Vulnerabilities details are required.")
279+
}
280+
scaTriageInfo := make(map[string]interface{})
281+
for _, vulnerability := range vulnerabilityDetails {
282+
vulnerabilityKeyVal := strings.Split(vulnerability, "=")
283+
err := validateVulnerabilityDetails(vulnerabilityKeyVal)
219284
if err != nil {
220-
return errors.Wrapf(err, "%s", "Failed updating the predicate")
285+
return nil, err
221286
}
287+
scaTriageInfo[strings.TrimSpace(vulnerabilityKeyVal[0])] = strings.TrimSpace(vulnerabilityKeyVal[1])
288+
}
222289

223-
return nil
290+
if scaTriageInfo["packageName"] == nil && scaTriageInfo["packagename"] == nil {
291+
return nil, errors.Errorf("Package name is required")
224292
}
293+
if scaTriageInfo["packageVersion"] == nil && scaTriageInfo["packageversion"] == nil {
294+
return nil, errors.Errorf("Package version is required")
295+
}
296+
if scaTriageInfo["packageManager"] == nil && scaTriageInfo["packagemanager"] == nil {
297+
return nil, errors.Errorf("Package manager is required")
298+
}
299+
300+
scaTriageInfo["projectIds"] = []string{projectID}
301+
actionInfo := make(map[string]interface{})
302+
actionInfo["actionType"] = params.ChangeState
303+
actionInfo["value"] = state
304+
actionInfo["comment"] = comment
305+
scaTriageInfo["actions"] = []map[string]interface{}{actionInfo}
306+
b, err := json.Marshal(scaTriageInfo)
307+
if err != nil {
308+
logger.PrintIfVerbose(fmt.Sprintf("Failed to serialize vulnerabilities %s", scaTriageInfo))
309+
return nil, errors.Errorf("Failed to prepare SCA triage request")
310+
}
311+
payload := wrappers.ScaPredicateRequest{}
312+
err = json.Unmarshal(b, &payload)
313+
if err != nil {
314+
logger.PrintIfVerbose(fmt.Sprintf("Failed to deserialize vulnerabilities %s", string(b)))
315+
return nil, errors.Errorf("Failed to prepare SCA triage request")
316+
}
317+
return payload, nil
318+
}
319+
320+
func validateVulnerabilityDetails(vulnerability []string) error {
321+
if len(vulnerability) != params.KeyValuePairSize {
322+
return errors.Errorf("Invalid vulnerabilities. It should be in a KEY=VALUE format")
323+
}
324+
return nil
225325
}
326+
226327
func determineSystemOrCustomState(customStatesWrapper wrappers.CustomStatesWrapper, featureFlagsWrapper wrappers.FeatureFlagsWrapper, state string, customStateID int) (string, int, error) {
227328
if !isCustomState(state) {
228329
return state, -1, nil
@@ -284,6 +385,41 @@ type predicateView struct {
284385
CreatedAt time.Time `format:"name:Created at;time:01-02-06 15:04:05"`
285386
}
286387

388+
type scaPredicateResultView struct {
389+
VulnerabilityID string `format:"name:Vulnerability ID"`
390+
PackageName string `format:"name:Package Name"`
391+
PackageVersion string `format:"name:Package Version"`
392+
PackageManager string `format:"name:Package Manager"`
393+
Comment string `format:"name:Comment"`
394+
State string `format:"name:State"`
395+
CreatedBy string `format:"name:Created By"`
396+
CreatedAt time.Time `format:"name:Created at;time:01-02-06 15:04:05"`
397+
}
398+
399+
func toScaPredicateResultView(scaPredicateResult *wrappers.ScaPredicateResult) []scaPredicateResultView {
400+
view := []scaPredicateResultView{}
401+
if len(scaPredicateResult.Actions) > 0 {
402+
for _, action := range scaPredicateResult.Actions {
403+
view = append(view, scaPredicateResultView{
404+
VulnerabilityID: scaPredicateResult.Context.VulnerabilityID,
405+
PackageName: scaPredicateResult.Context.PackageName,
406+
PackageVersion: scaPredicateResult.Context.PackageVersion,
407+
PackageManager: scaPredicateResult.Context.PackageManager,
408+
Comment: action.Message,
409+
State: action.ActionValue,
410+
CreatedBy: action.UserName,
411+
CreatedAt: action.CreatedAt,
412+
})
413+
}
414+
}
415+
416+
sort.Slice(view, func(i, j int) bool {
417+
return view[i].CreatedAt.After(view[j].CreatedAt)
418+
})
419+
420+
return view
421+
}
422+
287423
func toPredicatesView(predicatesCollection wrappers.PredicatesCollectionResponseModel) []predicateView {
288424
projectPredicatesCollection := predicatesCollection.PredicateHistoryPerProject
289425

0 commit comments

Comments
 (0)