contrib: Use return
instead of os.Exit(1)
in analyze-local-images
In order to cleanup properly the allocated resources (`defer`). Fixes #117
This commit is contained in:
parent
6883cb9b01
commit
1040dbbff9
@ -45,10 +45,10 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
endpoint = flag.String("endpoint", "http://127.0.0.1:6060", "Address to Clair API")
|
flagEndpoint = flag.String("endpoint", "http://127.0.0.1:6060", "Address to Clair API")
|
||||||
myAddress = flag.String("my-address", "127.0.0.1", "Address from the point of view of Clair")
|
flagMyAddress = flag.String("my-address", "127.0.0.1", "Address from the point of view of Clair")
|
||||||
minimumSeverity = flag.String("minimum-severity", "Negligible", "Minimum severity of vulnerabilities to show (Unknown, Negligible, Low, Medium, High, Critical, Defcon1)")
|
flagMinimumSeverity = flag.String("minimum-severity", "Negligible", "Minimum severity of vulnerabilities to show (Unknown, Negligible, Low, Medium, High, Critical, Defcon1)")
|
||||||
colorMode = flag.String("color", "auto", "Colorize the output (always, auto, never)")
|
flagColorMode = flag.String("color", "auto", "Colorize the output (always, auto, never)")
|
||||||
)
|
)
|
||||||
|
|
||||||
type vulnerabilityInfo struct {
|
type vulnerabilityInfo struct {
|
||||||
@ -98,25 +98,31 @@ func main() {
|
|||||||
}
|
}
|
||||||
imageName := flag.Args()[0]
|
imageName := flag.Args()[0]
|
||||||
|
|
||||||
minSeverity := types.Priority(*minimumSeverity)
|
minSeverity := types.Priority(*flagMinimumSeverity)
|
||||||
if !minSeverity.IsValid() {
|
if !minSeverity.IsValid() {
|
||||||
flag.Usage()
|
flag.Usage()
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if *colorMode == "never" {
|
if *flagColorMode == "never" {
|
||||||
color.NoColor = true
|
color.NoColor = true
|
||||||
} else if *colorMode == "always" {
|
} else if *flagColorMode == "always" {
|
||||||
color.NoColor = false
|
color.NoColor = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err := AnalyzeLocalImage(imageName, minSeverity, *flagEndpoint, *flagMyAddress)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AnalyzeLocalImage(imageName string, minSeverity types.Priority, endpoint, myAddress string) error {
|
||||||
// Save image.
|
// Save image.
|
||||||
log.Printf("Saving %s to local disk (this may take some time)", imageName)
|
log.Printf("Saving %s to local disk (this may take some time)", imageName)
|
||||||
path, err := save(imageName)
|
path, err := save(imageName)
|
||||||
defer os.RemoveAll(path)
|
defer os.RemoveAll(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Could not save image: %s\n", err)
|
return fmt.Errorf("Could not save image: %s", err)
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve history.
|
// Retrieve history.
|
||||||
@ -126,22 +132,29 @@ func main() {
|
|||||||
layerIDs, err = historyFromCommand(imageName)
|
layerIDs, err = historyFromCommand(imageName)
|
||||||
}
|
}
|
||||||
if err != nil || len(layerIDs) == 0 {
|
if err != nil || len(layerIDs) == 0 {
|
||||||
log.Printf("Could not get image's history: %s\n", err)
|
return fmt.Errorf("Could not get image's history: %s", err)
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup a simple HTTP server if Clair is not local.
|
// Setup a simple HTTP server if Clair is not local.
|
||||||
if !strings.Contains(*endpoint, "127.0.0.1") && !strings.Contains(*endpoint, "localhost") {
|
if !strings.Contains(endpoint, "127.0.0.1") && !strings.Contains(endpoint, "localhost") {
|
||||||
allowedHost := strings.TrimPrefix(*endpoint, "http://")
|
allowedHost := strings.TrimPrefix(endpoint, "http://")
|
||||||
portIndex := strings.Index(allowedHost, ":")
|
portIndex := strings.Index(allowedHost, ":")
|
||||||
if portIndex >= 0 {
|
if portIndex >= 0 {
|
||||||
allowedHost = allowedHost[:portIndex]
|
allowedHost = allowedHost[:portIndex]
|
||||||
}
|
}
|
||||||
|
|
||||||
go listenHTTP(path, allowedHost)
|
log.Printf("Setting up HTTP server (allowing: %s)\n", allowedHost)
|
||||||
|
|
||||||
path = "http://" + *myAddress + ":" + strconv.Itoa(httpPort)
|
ch := make(chan error)
|
||||||
time.Sleep(200 * time.Millisecond)
|
go listenHTTP(path, allowedHost, ch)
|
||||||
|
select {
|
||||||
|
case err := <-ch:
|
||||||
|
return fmt.Errorf("An error occured when starting HTTP server: %s", err)
|
||||||
|
case <-time.After(100 * time.Millisecond):
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
path = "http://" + myAddress + ":" + strconv.Itoa(httpPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Analyze layers.
|
// Analyze layers.
|
||||||
@ -151,22 +164,20 @@ func main() {
|
|||||||
|
|
||||||
var err error
|
var err error
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
err = analyzeLayer(*endpoint, path+"/"+layerIDs[i]+"/layer.tar", layerIDs[i], layerIDs[i-1])
|
err = analyzeLayer(endpoint, path+"/"+layerIDs[i]+"/layer.tar", layerIDs[i], layerIDs[i-1])
|
||||||
} else {
|
} else {
|
||||||
err = analyzeLayer(*endpoint, path+"/"+layerIDs[i]+"/layer.tar", layerIDs[i], "")
|
err = analyzeLayer(endpoint, path+"/"+layerIDs[i]+"/layer.tar", layerIDs[i], "")
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Could not analyze layer: %s\n", err)
|
return fmt.Errorf("Could not analyze layer: %s", err)
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get vulnerabilities.
|
// Get vulnerabilities.
|
||||||
log.Println("Retrieving image's vulnerabilities")
|
log.Println("Retrieving image's vulnerabilities")
|
||||||
layer, err := getLayer(*endpoint, layerIDs[len(layerIDs)-1])
|
layer, err := getLayer(endpoint, layerIDs[len(layerIDs)-1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Could not get layer information: %s\n", err)
|
return fmt.Errorf("Could not get layer information: %s", err)
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print report.
|
// Print report.
|
||||||
@ -174,7 +185,7 @@ func main() {
|
|||||||
|
|
||||||
if len(layer.Features) == 0 {
|
if len(layer.Features) == 0 {
|
||||||
fmt.Printf("%s No features have been detected in the image. This usually means that the image isn't supported by Clair.\n", color.YellowString("NOTE:"))
|
fmt.Printf("%s No features have been detected in the image. This usually means that the image isn't supported by Clair.\n", color.YellowString("NOTE:"))
|
||||||
os.Exit(0)
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
isSafe := true
|
isSafe := true
|
||||||
@ -231,11 +242,11 @@ func main() {
|
|||||||
|
|
||||||
if isSafe {
|
if isSafe {
|
||||||
fmt.Printf("%s No vulnerabilities were detected in your image\n", color.GreenString("Success!"))
|
fmt.Printf("%s No vulnerabilities were detected in your image\n", color.GreenString("Success!"))
|
||||||
os.Exit(0)
|
|
||||||
} else if !hasVisibleVulnerabilities {
|
} else if !hasVisibleVulnerabilities {
|
||||||
fmt.Printf("%s No vulnerabilities matching the minimum severity level were detected in your image\n", color.YellowString("NOTE:"))
|
fmt.Printf("%s No vulnerabilities matching the minimum severity level were detected in your image\n", color.YellowString("NOTE:"))
|
||||||
os.Exit(0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func save(imageName string) (string, error) {
|
func save(imageName string) (string, error) {
|
||||||
@ -330,9 +341,7 @@ func historyFromCommand(imageName string) ([]string, error) {
|
|||||||
return layers, nil
|
return layers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func listenHTTP(path, allowedHost string) {
|
func listenHTTP(path, allowedHost string, ch chan error) {
|
||||||
log.Printf("Setting up HTTP server (allowing: %s)\n", allowedHost)
|
|
||||||
|
|
||||||
restrictedFileServer := func(path, allowedHost string) http.Handler {
|
restrictedFileServer := func(path, allowedHost string) http.Handler {
|
||||||
fc := func(w http.ResponseWriter, r *http.Request) {
|
fc := func(w http.ResponseWriter, r *http.Request) {
|
||||||
host, _, err := net.SplitHostPort(r.RemoteAddr)
|
host, _, err := net.SplitHostPort(r.RemoteAddr)
|
||||||
@ -345,11 +354,7 @@ func listenHTTP(path, allowedHost string) {
|
|||||||
return http.HandlerFunc(fc)
|
return http.HandlerFunc(fc)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := http.ListenAndServe(":"+strconv.Itoa(httpPort), restrictedFileServer(path, allowedHost))
|
ch <- http.ListenAndServe(":"+strconv.Itoa(httpPort), restrictedFileServer(path, allowedHost))
|
||||||
if err != nil {
|
|
||||||
log.Printf("An error occurs with the HTTP server: %s\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func analyzeLayer(endpoint, path, layerName, parentLayerName string) error {
|
func analyzeLayer(endpoint, path, layerName, parentLayerName string) error {
|
||||||
|
Loading…
Reference in New Issue
Block a user