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  }