new template

Signed-off-by: Jess Frazelle <acidburn@google.com>
This commit is contained in:
Jess Frazelle 2017-03-21 15:47:47 -07:00
parent 8850850631
commit 0c96eab540
No known key found for this signature in database
GPG key ID: 18F3685C0022BFF3
2 changed files with 66 additions and 94 deletions

View file

@ -4,8 +4,6 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"html/template" "html/template"
"io"
"io/ioutil"
"net/http" "net/http"
"os" "os"
"path/filepath" "path/filepath"
@ -43,32 +41,6 @@ func preload(c *cli.Context) (err error) {
return nil return nil
} }
func moveFile(src, dest string) (err error) {
srcfile, err := os.Open(src)
if err != nil {
return err
}
defer srcfile.Close()
defer os.Remove(src)
destfile, err := os.Create(dest)
if err != nil {
return err
}
defer destfile.Close()
if _, err := io.Copy(destfile, srcfile); err != nil {
return err
}
srcinfo, err := os.Stat(src)
if err != nil {
return err
}
return os.Chmod(dest, srcinfo.Mode())
}
func main() { func main() {
app := cli.NewApp() app := cli.NewApp()
app.Name = "reg-server" app.Name = "reg-server"
@ -158,6 +130,7 @@ func main() {
updating = false updating = false
} }
wg.Wait() wg.Wait()
logrus.Info("finished waiting for vulns wait group")
} }
} }
}() }()
@ -259,7 +232,7 @@ func createStaticIndex(r *registry.Registry, staticDir, clairURI string) error {
go func(repo, tag string, i, j int) { go func(repo, tag string, i, j int) {
defer wg.Done() defer wg.Done()
throttle := time.Tick(time.Duration(time.Duration((i+1)*(j+1)*3) * time.Second)) throttle := time.Tick(time.Duration(time.Duration((i+1)*(j+1)*4) * time.Second))
<-throttle <-throttle
logrus.Infof("creating vulns.txt for %s:%s", repo, tag) logrus.Infof("creating vulns.txt for %s:%s", repo, tag)
@ -276,41 +249,34 @@ func createStaticIndex(r *registry.Registry, staticDir, clairURI string) error {
} }
} }
// create temporoary file to save template to
logrus.Info("creating temporary file for template")
f, err := ioutil.TempFile("", "reg-server")
if err != nil {
return fmt.Errorf("creating temp file failed: %v", err)
}
defer f.Close()
defer os.Remove(f.Name())
// parse & execute the template
logrus.Info("parsing and executing the template")
templateDir := filepath.Join(staticDir, "../templates")
lp := filepath.Join(templateDir, "layout.html")
d := data{ d := data{
RegistryURL: r.Domain, RegistryURL: r.Domain,
Repos: repos, Repos: repos,
LastUpdated: time.Now().Local().Format(time.RFC1123), LastUpdated: time.Now().Local().Format(time.RFC1123),
} }
tmpl := template.Must(template.New("").ParseFiles(lp))
if err := tmpl.ExecuteTemplate(f, "layout", d); err != nil {
return fmt.Errorf("execute template failed: %v", err)
}
f.Close()
index := filepath.Join(staticDir, "index.html") if err := renderTemplate(staticDir, "layout.html", "index.html", d); err != nil {
logrus.Infof("renaming the temporary file %s to %s", f.Name(), index) return err
if err := moveFile(f.Name(), index); err != nil {
return fmt.Errorf("renaming result from %s to %s failed: %v", f.Name(), index, err)
} }
updating = false updating = false
return nil return nil
} }
type vulnsReport struct {
Repo string
Tag string
Date string
Vulns []clair.Vulnerability
VulnsBySeverity map[string][]clair.Vulnerability
BadVulns int
}
func createVulnStaticPage(r *registry.Registry, staticDir, clairURI, repo, tag string, m schema1.SignedManifest) error { func createVulnStaticPage(r *registry.Registry, staticDir, clairURI, repo, tag string, m schema1.SignedManifest) error {
report := vulnsReport{
Repo: repo,
Tag: tag,
}
// filter out the empty layers // filter out the empty layers
var filteredLayers []schema1.FSLayer var filteredLayers []schema1.FSLayer
for _, layer := range m.FSLayers { for _, layer := range m.FSLayers {
@ -349,26 +315,12 @@ func createVulnStaticPage(r *registry.Registry, staticDir, clairURI, repo, tag s
} }
// get the vulns // get the vulns
var vulns []clair.Vulnerability
for _, f := range vl.Features { for _, f := range vl.Features {
for _, v := range f.Vulnerabilities { for _, v := range f.Vulnerabilities {
vulns = append(vulns, v) report.Vulns = append(report.Vulns, v)
} }
} }
path := filepath.Join(staticDir, repo, tag, "vulns.txt")
if err := os.MkdirAll(filepath.Dir(path), 0644); err != nil {
return err
}
file, err := os.Create(path)
if err != nil {
return err
}
defer file.Close()
fmt.Fprintf(file, "Found %d vulnerabilities \n", len(vulns))
fmt.Fprintln(file, "")
vulnsBy := func(sev string, store map[string][]clair.Vulnerability) []clair.Vulnerability { vulnsBy := func(sev string, store map[string][]clair.Vulnerability) []clair.Vulnerability {
items, found := store[sev] items, found := store[sev]
if !found { if !found {
@ -379,40 +331,40 @@ func createVulnStaticPage(r *registry.Registry, staticDir, clairURI, repo, tag s
} }
// group by severity // group by severity
store := make(map[string][]clair.Vulnerability) for _, v := range report.Vulns {
for _, v := range vulns { sevRow := vulnsBy(v.Severity, report.VulnsBySeverity)
sevRow := vulnsBy(v.Severity, store) report.VulnsBySeverity[v.Severity] = append(sevRow, v)
store[v.Severity] = append(sevRow, v)
} }
// iterate over the priorities list path := filepath.Join(repo, tag, "vulns.txt")
iteratePriorities := func(f func(sev string)) { if err := renderTemplate(staticDir, "vulns.txt", path, report); err != nil {
for _, sev := range clair.Priorities { return err
if len(store[sev]) != 0 {
f(sev)
}
}
} }
return nil
}
iteratePriorities(func(sev string) { func renderTemplate(staticDir, src, dest string, data interface{}) error {
fmt.Fprintf(file, "%s: %d\n", sev, len(store[sev])) // parse & execute the template
}) logrus.Info("parsing and executing the template %s", src)
fmt.Fprintln(file, "") templateDir := filepath.Join(staticDir, "../templates")
lp := filepath.Join(templateDir, src)
// return an error if there are more than 10 bad vulns path := filepath.Join(staticDir, dest)
lenBadVulns := len(store["High"]) + len(store["Critical"]) + len(store["Defcon1"]) if err := os.MkdirAll(filepath.Dir(path), 0644); err != nil {
if lenBadVulns > 10 { return err
fmt.Fprintln(file, "--------------- ALERT ---------------")
fmt.Fprintf(file, "%d bad vunerabilities found", lenBadVulns)
} }
fmt.Fprintln(file, "") logrus.Info("creating/opening file %s", path)
f, err := os.Create(path)
if err != nil {
return err
}
defer f.Close()
iteratePriorities(func(sev string) { tmpl := template.Must(template.New("").ParseFiles(lp))
for _, v := range store[sev] { if err := tmpl.ExecuteTemplate(f, "layout", data); err != nil {
fmt.Fprintf(file, "%s: [%s] \n%s\n%s\n", v.Name, v.Severity, v.Description, v.Link) f.Close()
fmt.Fprintln(file, "-----------------------------------------") return fmt.Errorf("execute template %s failed: %v", src, err)
} }
})
return nil return nil
} }

View file

@ -0,0 +1,20 @@
CVE Report for {{.Repo}}:{{.Tag}}
Generated on: {{.Date}}
Vulnerabilities Found: {{len .Vulns}}
{{range $key, $value := .VulnsBySeverity}}
{{$key}}: {{len $value}}
{{end}}
{{if gt .BadVulns 10}}
----------------- ALERT -----------------
{{.BadVulns}} High, Critical, and/or Defcon1 vulnerabilities found
{{end}}
{{range $key, $value := .VulnsBySeverity}}
{{$value.Name}}: [{{$value.Severity}}]
{{$value.Description}}
{{$value.Link}}
-----------------------------------------
{{end}}