Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

contrib: Use return instead of os.Exit(1) in analyze-local-images #118

Merged
merged 1 commit into from
Mar 25, 2016
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 39 additions & 34 deletions contrib/analyze-local-images/main.go
Original file line number Diff line number Diff line change
@@ -45,10 +45,10 @@ const (
)

var (
endpoint = 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")
minimumSeverity = 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)")
flagEndpoint = flag.String("endpoint", "http://127.0.0.1:6060", "Address to Clair API")
flagMyAddress = flag.String("my-address", "127.0.0.1", "Address from the point of view of Clair")
flagMinimumSeverity = flag.String("minimum-severity", "Negligible", "Minimum severity of vulnerabilities to show (Unknown, Negligible, Low, Medium, High, Critical, Defcon1)")
flagColorMode = flag.String("color", "auto", "Colorize the output (always, auto, never)")
)

type vulnerabilityInfo struct {
@@ -98,25 +98,31 @@ func main() {
}
imageName := flag.Args()[0]

minSeverity := types.Priority(*minimumSeverity)
minSeverity := types.Priority(*flagMinimumSeverity)
if !minSeverity.IsValid() {
flag.Usage()
os.Exit(1)
}

if *colorMode == "never" {
if *flagColorMode == "never" {
color.NoColor = true
} else if *colorMode == "always" {
} else if *flagColorMode == "always" {
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.
log.Printf("Saving %s to local disk (this may take some time)", imageName)
path, err := save(imageName)
defer os.RemoveAll(path)
if err != nil {
fmt.Printf("Could not save image: %s\n", err)
os.Exit(1)
return fmt.Errorf("Could not save image: %s", err)
}

// Retrieve history.
@@ -126,22 +132,29 @@ func main() {
layerIDs, err = historyFromCommand(imageName)
}
if err != nil || len(layerIDs) == 0 {
log.Printf("Could not get image's history: %s\n", err)
os.Exit(1)
return fmt.Errorf("Could not get image's history: %s", err)
}

// Setup a simple HTTP server if Clair is not local.
if !strings.Contains(*endpoint, "127.0.0.1") && !strings.Contains(*endpoint, "localhost") {
allowedHost := strings.TrimPrefix(*endpoint, "http://")
if !strings.Contains(endpoint, "127.0.0.1") && !strings.Contains(endpoint, "localhost") {
allowedHost := strings.TrimPrefix(endpoint, "http://")
portIndex := strings.Index(allowedHost, ":")
if portIndex >= 0 {
allowedHost = allowedHost[:portIndex]
}

go listenHTTP(path, allowedHost)
log.Printf("Setting up HTTP server (allowing: %s)\n", allowedHost)

ch := make(chan error)
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)
time.Sleep(200 * time.Millisecond)
path = "http://" + myAddress + ":" + strconv.Itoa(httpPort)
}

// Analyze layers.
@@ -151,30 +164,28 @@ func main() {

var err error
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 {
err = analyzeLayer(*endpoint, path+"/"+layerIDs[i]+"/layer.tar", layerIDs[i], "")
err = analyzeLayer(endpoint, path+"/"+layerIDs[i]+"/layer.tar", layerIDs[i], "")
}
if err != nil {
log.Printf("Could not analyze layer: %s\n", err)
os.Exit(1)
return fmt.Errorf("Could not analyze layer: %s", err)
}
}

// Get 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 {
log.Printf("Could not get layer information: %s\n", err)
os.Exit(1)
return fmt.Errorf("Could not get layer information: %s", err)
}

// Print report.
fmt.Printf("Clair report for image %s (%s)\n", imageName, time.Now().UTC())

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:"))
os.Exit(0)
return nil
}

isSafe := true
@@ -231,11 +242,11 @@ func main() {

if isSafe {
fmt.Printf("%s No vulnerabilities were detected in your image\n", color.GreenString("Success!"))
os.Exit(0)
} else if !hasVisibleVulnerabilities {
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) {
@@ -330,9 +341,7 @@ func historyFromCommand(imageName string) ([]string, error) {
return layers, nil
}

func listenHTTP(path, allowedHost string) {
log.Printf("Setting up HTTP server (allowing: %s)\n", allowedHost)

func listenHTTP(path, allowedHost string, ch chan error) {
restrictedFileServer := func(path, allowedHost string) http.Handler {
fc := func(w http.ResponseWriter, r *http.Request) {
host, _, err := net.SplitHostPort(r.RemoteAddr)
@@ -345,11 +354,7 @@ func listenHTTP(path, allowedHost string) {
return http.HandlerFunc(fc)
}

err := 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)
}
ch <- http.ListenAndServe(":"+strconv.Itoa(httpPort), restrictedFileServer(path, allowedHost))
}

func analyzeLayer(endpoint, path, layerName, parentLayerName string) error {