github.com/google/osv-scalibr@v0.4.1/binary/scanrunner/scanrunner.go (about) 1 // Copyright 2025 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package scanrunner provides the main function for running a scan with the SCALIBR binary. 16 package scanrunner 17 18 import ( 19 "context" 20 21 scalibr "github.com/google/osv-scalibr" 22 scalibrlayerimage "github.com/google/osv-scalibr/artifact/image/layerscanning/image" 23 "github.com/google/osv-scalibr/binary/cli" 24 "github.com/google/osv-scalibr/log" 25 "github.com/google/osv-scalibr/plugin" 26 "github.com/google/osv-scalibr/version" 27 ) 28 29 // RunScan executes the scan with the given CLI flags 30 // and returns the exit code passed to os.Exit() in the main binary. 31 func RunScan(flags *cli.Flags) int { 32 if flags.PrintVersion { 33 log.Infof("OSV-SCALIBR v%s", version.ScannerVersion) 34 return 0 35 } 36 37 if flags.Verbose { 38 log.SetLogger(&log.DefaultLogger{Verbose: true}) 39 } 40 41 cfg, err := flags.GetScanConfig() 42 if err != nil { 43 log.Errorf("%v.GetScanConfig(): %v", flags, err) 44 return 1 45 } 46 47 log.Infof("Running scan with %d plugins", len(cfg.Plugins)) 48 if len(cfg.PathsToExtract) > 0 { 49 log.Infof("Paths to extract: %s", cfg.PathsToExtract) 50 } 51 52 var result *scalibr.ScanResult 53 if flags.ImageTarball != "" { 54 layerCfg := scalibrlayerimage.DefaultConfig() 55 log.Infof("Scanning image tarball: %s", flags.ImageTarball) 56 img, err := scalibrlayerimage.FromTarball(flags.ImageTarball, layerCfg) 57 if err != nil { 58 log.Errorf("Failed to create image from tarball: %v", err) 59 return 1 60 } 61 defer func() { 62 if tmpErr := img.CleanUp(); tmpErr != nil { 63 log.Errorf("Failed to clean up image: %v", tmpErr) 64 } 65 }() 66 result, err = scalibr.New().ScanContainer(context.Background(), img, cfg) 67 68 cleanupErr := img.CleanUp() 69 if cleanupErr != nil { 70 log.Errorf("failed to clean up image: %s", err) 71 } 72 73 if err != nil { 74 log.Errorf("Failed to scan tarball: %v", err) 75 return 1 76 } 77 } else if flags.ImageLocal != "" { // We will scan an image in the local hard disk 78 layerCfg := scalibrlayerimage.DefaultConfig() 79 log.Infof("Scanning local image: %s", flags.ImageLocal) 80 img, err := scalibrlayerimage.FromLocalDockerImage(flags.ImageLocal, layerCfg) 81 if err != nil { 82 log.Errorf("Failed to scan local image: %v", err) 83 return 1 84 } 85 defer func() { 86 if tmpErr := img.CleanUp(); tmpErr != nil { 87 log.Errorf("Failed to clean up image: %v", tmpErr) 88 } 89 }() 90 result, err = scalibr.New().ScanContainer(context.Background(), img, cfg) 91 if err != nil { 92 log.Errorf("Failed to scan container: %v", err) 93 return 1 94 } 95 } else { 96 log.Infof("Scan roots: %s", cfg.ScanRoots) 97 result = scalibr.New().Scan(context.Background(), cfg) 98 } 99 100 log.Infof("Scan status: %v", result.Status) 101 for _, p := range result.PluginStatus { 102 if p.Status.Status != plugin.ScanStatusSucceeded { 103 log.Warnf("Plugin '%s' did not succeed. Status: %v, Reason: %s", p.Name, p.Status, p.Status.FailureReason) 104 } 105 } 106 log.Infof( 107 "Found %d software packages, %d security findings", 108 len(result.Inventory.Packages), 109 len(result.Inventory.PackageVulns)+len(result.Inventory.GenericFindings), 110 ) 111 112 if err := flags.WriteScanResults(result); err != nil { 113 log.Errorf("Error writing scan results: %v", err) 114 return 1 115 } 116 117 if result.Status.Status != plugin.ScanStatusSucceeded { 118 log.Errorf("Scan wasn't successful: %s", result.Status.FailureReason) 119 return 1 120 } 121 122 return 0 123 }