github.com/devseccon/trivy@v0.47.1-0.20231123133102-bd902a0bd996/pkg/scanner/scan.go (about) 1 package scanner 2 3 import ( 4 "context" 5 6 "github.com/google/wire" 7 "golang.org/x/xerrors" 8 9 "github.com/devseccon/trivy/pkg/clock" 10 "github.com/devseccon/trivy/pkg/fanal/artifact" 11 aimage "github.com/devseccon/trivy/pkg/fanal/artifact/image" 12 flocal "github.com/devseccon/trivy/pkg/fanal/artifact/local" 13 "github.com/devseccon/trivy/pkg/fanal/artifact/repo" 14 "github.com/devseccon/trivy/pkg/fanal/artifact/sbom" 15 "github.com/devseccon/trivy/pkg/fanal/artifact/vm" 16 "github.com/devseccon/trivy/pkg/fanal/image" 17 ftypes "github.com/devseccon/trivy/pkg/fanal/types" 18 "github.com/devseccon/trivy/pkg/log" 19 "github.com/devseccon/trivy/pkg/report" 20 "github.com/devseccon/trivy/pkg/rpc/client" 21 "github.com/devseccon/trivy/pkg/scanner/local" 22 "github.com/devseccon/trivy/pkg/types" 23 ) 24 25 /////////////// 26 // Standalone 27 /////////////// 28 29 // StandaloneSuperSet is used in the standalone mode 30 var StandaloneSuperSet = wire.NewSet( 31 local.SuperSet, 32 wire.Bind(new(Driver), new(local.Scanner)), 33 NewScanner, 34 ) 35 36 // StandaloneDockerSet binds docker dependencies 37 var StandaloneDockerSet = wire.NewSet( 38 image.NewContainerImage, 39 aimage.NewArtifact, 40 StandaloneSuperSet, 41 ) 42 43 // StandaloneArchiveSet binds archive scan dependencies 44 var StandaloneArchiveSet = wire.NewSet( 45 image.NewArchiveImage, 46 aimage.NewArtifact, 47 StandaloneSuperSet, 48 ) 49 50 // StandaloneFilesystemSet binds filesystem dependencies 51 var StandaloneFilesystemSet = wire.NewSet( 52 flocal.NewArtifact, 53 StandaloneSuperSet, 54 ) 55 56 // StandaloneRepositorySet binds repository dependencies 57 var StandaloneRepositorySet = wire.NewSet( 58 repo.NewArtifact, 59 StandaloneSuperSet, 60 ) 61 62 // StandaloneSBOMSet binds sbom dependencies 63 var StandaloneSBOMSet = wire.NewSet( 64 sbom.NewArtifact, 65 StandaloneSuperSet, 66 ) 67 68 // StandaloneVMSet binds vm dependencies 69 var StandaloneVMSet = wire.NewSet( 70 vm.NewArtifact, 71 StandaloneSuperSet, 72 ) 73 74 ///////////////// 75 // Client/Server 76 ///////////////// 77 78 // RemoteSuperSet is used in the client mode 79 var RemoteSuperSet = wire.NewSet( 80 client.NewScanner, 81 wire.Value([]client.Option(nil)), 82 wire.Bind(new(Driver), new(client.Scanner)), 83 NewScanner, 84 ) 85 86 // RemoteFilesystemSet binds filesystem dependencies for client/server mode 87 var RemoteFilesystemSet = wire.NewSet( 88 flocal.NewArtifact, 89 RemoteSuperSet, 90 ) 91 92 // RemoteRepositorySet binds repository dependencies for client/server mode 93 var RemoteRepositorySet = wire.NewSet( 94 repo.NewArtifact, 95 RemoteSuperSet, 96 ) 97 98 // RemoteSBOMSet binds sbom dependencies for client/server mode 99 var RemoteSBOMSet = wire.NewSet( 100 sbom.NewArtifact, 101 RemoteSuperSet, 102 ) 103 104 // RemoteVMSet binds vm dependencies for client/server mode 105 var RemoteVMSet = wire.NewSet( 106 vm.NewArtifact, 107 RemoteSuperSet, 108 ) 109 110 // RemoteDockerSet binds remote docker dependencies 111 var RemoteDockerSet = wire.NewSet( 112 aimage.NewArtifact, 113 image.NewContainerImage, 114 RemoteSuperSet, 115 ) 116 117 // RemoteArchiveSet binds remote archive dependencies 118 var RemoteArchiveSet = wire.NewSet( 119 aimage.NewArtifact, 120 image.NewArchiveImage, 121 RemoteSuperSet, 122 ) 123 124 // Scanner implements the Artifact and Driver operations 125 type Scanner struct { 126 driver Driver 127 artifact artifact.Artifact 128 } 129 130 // Driver defines operations of scanner 131 type Driver interface { 132 Scan(ctx context.Context, target, artifactKey string, blobKeys []string, options types.ScanOptions) ( 133 results types.Results, osFound ftypes.OS, err error) 134 } 135 136 // NewScanner is the factory method of Scanner 137 func NewScanner(driver Driver, ar artifact.Artifact) Scanner { 138 return Scanner{ 139 driver: driver, 140 artifact: ar, 141 } 142 } 143 144 // ScanArtifact scans the artifacts and returns results 145 func (s Scanner) ScanArtifact(ctx context.Context, options types.ScanOptions) (types.Report, error) { 146 artifactInfo, err := s.artifact.Inspect(ctx) 147 if err != nil { 148 return types.Report{}, xerrors.Errorf("failed analysis: %w", err) 149 } 150 defer func() { 151 if err := s.artifact.Clean(artifactInfo); err != nil { 152 log.Logger.Warnf("Failed to clean the artifact %q: %v", artifactInfo.Name, err) 153 } 154 }() 155 156 results, osFound, err := s.driver.Scan(ctx, artifactInfo.Name, artifactInfo.ID, artifactInfo.BlobIDs, options) 157 if err != nil { 158 return types.Report{}, xerrors.Errorf("scan failed: %w", err) 159 } 160 161 ptros := &osFound 162 if osFound.Detected() && osFound.Eosl { 163 log.Logger.Warnf("This OS version is no longer supported by the distribution: %s %s", osFound.Family, osFound.Name) 164 log.Logger.Warnf("The vulnerability detection may be insufficient because security updates are not provided") 165 } else if !osFound.Detected() { 166 ptros = nil 167 } 168 169 // Layer makes sense only when scanning container images 170 if artifactInfo.Type != ftypes.ArtifactContainerImage { 171 removeLayer(results) 172 } 173 174 return types.Report{ 175 SchemaVersion: report.SchemaVersion, 176 CreatedAt: clock.Now(), 177 ArtifactName: artifactInfo.Name, 178 ArtifactType: artifactInfo.Type, 179 Metadata: types.Metadata{ 180 OS: ptros, 181 182 // Container image 183 ImageID: artifactInfo.ImageMetadata.ID, 184 DiffIDs: artifactInfo.ImageMetadata.DiffIDs, 185 RepoTags: artifactInfo.ImageMetadata.RepoTags, 186 RepoDigests: artifactInfo.ImageMetadata.RepoDigests, 187 ImageConfig: artifactInfo.ImageMetadata.ConfigFile, 188 }, 189 CycloneDX: artifactInfo.CycloneDX, 190 Results: results, 191 }, nil 192 } 193 194 func removeLayer(results types.Results) { 195 for i := range results { 196 result := results[i] 197 198 for j := range result.Packages { 199 result.Packages[j].Layer = ftypes.Layer{} 200 } 201 for j := range result.Vulnerabilities { 202 result.Vulnerabilities[j].Layer = ftypes.Layer{} 203 } 204 for j := range result.Misconfigurations { 205 result.Misconfigurations[j].Layer = ftypes.Layer{} 206 } 207 } 208 }