github.com/devseccon/trivy@v0.47.1-0.20231123133102-bd902a0bd996/pkg/cloud/report/convert.go (about) 1 package report 2 3 import ( 4 "fmt" 5 "strings" 6 "time" 7 8 "github.com/aws/aws-sdk-go-v2/aws/arn" 9 10 "github.com/aquasecurity/defsec/pkg/scan" 11 ftypes "github.com/devseccon/trivy/pkg/fanal/types" 12 "github.com/devseccon/trivy/pkg/types" 13 ) 14 15 func ConvertResults(results scan.Results, provider string, scoped []string) map[string]ResultsAtTime { 16 convertedResults := make(map[string]ResultsAtTime) 17 resultsByServiceAndARN := make(map[string]map[string]scan.Results) 18 for _, result := range results { 19 20 service := result.Rule().Service 21 resource := result.Flatten().Resource 22 if service == "" || service == "general" { 23 if parsed, err := arn.Parse(resource); err == nil { 24 service = parsed.Service 25 } 26 } 27 28 existingService, ok := resultsByServiceAndARN[service] 29 if !ok { 30 existingService = make(map[string]scan.Results) 31 } 32 33 existingService[resource] = append(existingService[resource], result) 34 resultsByServiceAndARN[service] = existingService 35 } 36 // ensure we have entries for all scoped services, even if there are no results 37 for _, service := range scoped { 38 if _, ok := resultsByServiceAndARN[service]; !ok { 39 resultsByServiceAndARN[service] = nil 40 } 41 } 42 for service, arnResults := range resultsByServiceAndARN { 43 44 var convertedArnResults []types.Result 45 46 for arn, serviceResults := range arnResults { 47 48 arnResult := types.Result{ 49 Target: arn, 50 Class: types.ClassConfig, 51 Type: ftypes.Cloud, 52 } 53 54 for _, result := range serviceResults { 55 56 var primaryURL string 57 58 // empty namespace implies a go rule from defsec, "builtin" refers to a built-in rego rule 59 // this ensures we don't generate bad links for custom policies 60 if result.RegoNamespace() == "" || strings.HasPrefix(result.RegoNamespace(), "builtin.") { 61 primaryURL = fmt.Sprintf("https://avd.aquasec.com/misconfig/%s", strings.ToLower(result.Rule().AVDID)) 62 } 63 64 status := types.StatusFailure 65 switch result.Status() { 66 case scan.StatusPassed: 67 status = types.StatusPassed 68 case scan.StatusIgnored: 69 status = types.StatusException 70 } 71 72 flat := result.Flatten() 73 74 arnResult.Misconfigurations = append(arnResult.Misconfigurations, types.DetectedMisconfiguration{ 75 Type: provider, 76 ID: result.Rule().AVDID, 77 AVDID: result.Rule().AVDID, 78 Title: result.Rule().Summary, 79 Description: strings.TrimSpace(result.Rule().Explanation), 80 Message: strings.TrimSpace(result.Description()), 81 Namespace: result.RegoNamespace(), 82 Query: result.RegoRule(), 83 Resolution: result.Rule().Resolution, 84 Severity: string(result.Severity()), 85 PrimaryURL: primaryURL, 86 References: []string{primaryURL}, 87 Status: status, 88 CauseMetadata: ftypes.CauseMetadata{ 89 Resource: flat.Resource, 90 Provider: string(flat.RuleProvider), 91 Service: service, 92 StartLine: flat.Location.StartLine, 93 EndLine: flat.Location.EndLine, 94 }, 95 }) 96 } 97 98 convertedArnResults = append(convertedArnResults, arnResult) 99 } 100 convertedResults[service] = ResultsAtTime{ 101 Results: convertedArnResults, 102 CreationTime: time.Now(), 103 } 104 } 105 return convertedResults 106 }