github.com/devseccon/trivy@v0.47.1-0.20231123133102-bd902a0bd996/pkg/rpc/client/client.go (about) 1 package client 2 3 import ( 4 "context" 5 "crypto/tls" 6 "net/http" 7 8 "golang.org/x/xerrors" 9 10 ftypes "github.com/devseccon/trivy/pkg/fanal/types" 11 r "github.com/devseccon/trivy/pkg/rpc" 12 "github.com/devseccon/trivy/pkg/types" 13 xstrings "github.com/devseccon/trivy/pkg/x/strings" 14 rpc "github.com/devseccon/trivy/rpc/scanner" 15 ) 16 17 type options struct { 18 rpcClient rpc.Scanner 19 } 20 21 type Option func(*options) 22 23 // WithRPCClient takes rpc client for testability 24 func WithRPCClient(c rpc.Scanner) Option { 25 return func(opts *options) { 26 opts.rpcClient = c 27 } 28 } 29 30 // ScannerOption holds options for RPC client 31 type ScannerOption struct { 32 RemoteURL string 33 Insecure bool 34 CustomHeaders http.Header 35 } 36 37 // Scanner implements the RPC scanner 38 type Scanner struct { 39 customHeaders http.Header 40 client rpc.Scanner 41 } 42 43 // NewScanner is the factory method to return RPC Scanner 44 func NewScanner(scannerOptions ScannerOption, opts ...Option) Scanner { 45 httpClient := &http.Client{ 46 Transport: &http.Transport{ 47 Proxy: http.ProxyFromEnvironment, 48 TLSClientConfig: &tls.Config{ 49 InsecureSkipVerify: scannerOptions.Insecure, 50 }, 51 }, 52 } 53 54 c := rpc.NewScannerProtobufClient(scannerOptions.RemoteURL, httpClient) 55 56 o := &options{rpcClient: c} 57 for _, opt := range opts { 58 opt(o) 59 } 60 61 return Scanner{ 62 customHeaders: scannerOptions.CustomHeaders, 63 client: o.rpcClient, 64 } 65 } 66 67 // Scan scans the image 68 func (s Scanner) Scan(ctx context.Context, target, artifactKey string, blobKeys []string, opts types.ScanOptions) (types.Results, ftypes.OS, error) { 69 ctx = WithCustomHeaders(ctx, s.customHeaders) 70 71 // Convert to the rpc struct 72 licenseCategories := make(map[string]*rpc.Licenses) 73 for category, names := range opts.LicenseCategories { 74 licenseCategories[string(category)] = &rpc.Licenses{Names: names} 75 } 76 77 var res *rpc.ScanResponse 78 err := r.Retry(func() error { 79 var err error 80 res, err = s.client.Scan(ctx, &rpc.ScanRequest{ 81 Target: target, 82 ArtifactId: artifactKey, 83 BlobIds: blobKeys, 84 Options: &rpc.ScanOptions{ 85 VulnType: opts.VulnType, 86 Scanners: xstrings.ToStringSlice(opts.Scanners), 87 ListAllPackages: opts.ListAllPackages, 88 LicenseCategories: licenseCategories, 89 IncludeDevDeps: opts.IncludeDevDeps, 90 }, 91 }) 92 return err 93 }) 94 if err != nil { 95 return nil, ftypes.OS{}, xerrors.Errorf("failed to detect vulnerabilities via RPC: %w", err) 96 } 97 98 return r.ConvertFromRPCResults(res.Results), r.ConvertFromRPCOS(res.Os), nil 99 }