Skip to content

Commit

Permalink
(feat) add static report generation
Browse files Browse the repository at this point in the history
this is a reimplementation of #98 (thanks @sea-erkin) to match the
current base branch as well as the overall reporting style.
  • Loading branch information
leonjza committed Jun 7, 2022
1 parent 6769e88 commit 3e459eb
Show file tree
Hide file tree
Showing 13 changed files with 9,916 additions and 8 deletions.
209 changes: 209 additions & 0 deletions cmd/report_export.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
package cmd

import (
"archive/zip"
"bytes"
"html/template"
"io"
"io/ioutil"
"os"
"path/filepath"
"strings"

"github.com/sensepost/gowitness/storage"
"github.com/spf13/cobra"
)

// reportExportCmd represents the reportExport command
var reportExportCmd = &cobra.Command{
Use: "export",
Short: "Export an HTML report of all screenshots",
Long: `Export an HTML report of all screenshots.
`,
Run: func(cmd *cobra.Command, args []string) {
log := options.Logger

if options.File == "" {
log.Fatal().Msg("a target file must be specified with --file / -f")
}

tmpl := template.Must(template.ParseFS(Embedded, "web/static-templates/*.html"))
t := tmpl.Lookup("gallery.html")

// db
dbh, err := db.Get()
if err != nil {
log.Fatal().Err(err).Msg("could not get db handle")
}

var urls []storage.URL
dbh.Preload("Technologies").Find(&urls)

if len(urls) == 0 {
log.Error().Msg("there are no urls in the database")
return
}

// create a temp working directory
tempDir, err := ioutil.TempDir("", "")
if err != nil {
log.Fatal().Err(err).Msg("could not create temp working directory")
}
defer os.RemoveAll(tempDir)
log.Debug().Str("tempdir", tempDir).Msg("created temp working directory")

// create the screenshots directory
if err := os.MkdirAll(tempDir+"/screenshots", 0755); err != nil {
log.Fatal().Err(err).Msg("could not create screenshots directory")
}
screenshotDir := tempDir + "/screenshots"

log.Info().Msg("preparing screenshots and other assets")

// copy screenshot files to the new path
if err := filepath.Walk(options.ScreenshotPath, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}

if info.IsDir() {
return nil
}

dest := screenshotDir + "/" + info.Name()
log.Debug().Str("destination", dest).Str("source", path).Msg("copying screenshot file to temp directory")

if err := copyFile(path, dest); err != nil {
return err
}

return nil

}); err != nil {
log.Fatal().Str("screenshot-path", options.ScreenshotPath).Err(err).Msg("could not walk screenshot path and copy screenshots")
}

// copy template css & js to new path
js, err := Embedded.ReadFile("web/assets/js/tabler.min.js")
if err != nil {
log.Fatal().Err(err).Msg("could not open embedded javascript")
}
if err := copyByte(js, tempDir+"/"+"tabler.min.js"); err != nil {
log.Fatal().Err(err).Msg("failed to write tabler.min.js to file")
}

css, err := Embedded.ReadFile("web/assets/css/tabler.min.css")
if err != nil {
log.Fatal().Err(err).Msg("could not open embedded css")
}
if err := copyByte(css, tempDir+"/"+"tabler.min.css"); err != nil {
log.Fatal().Err(err).Msg("failed to write tabler.min.css to file")
}

// write and generate the template
f, err := os.Create(tempDir + "/index.html")
if err != nil {
log.Fatal().Err(err).Msg("failed to create index.html")
}

if err := t.Execute(f, urls); err != nil {
log.Fatal().Err(err).Msg("failed to generate template")
}

// create the destination archive
target, err := os.Create(options.File)
if err != nil {
log.Fatal().Err(err).Str("target-file", options.File).Msg("failed to open target file")
}
defer target.Close()

log.Info().Str("target-file", options.File).Msg("writing zip archive")

// create the zip file...
w := zip.NewWriter(target)
defer w.Close()
// .. and add the files to it
if err := filepath.Walk(tempDir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}

if info.IsDir() {
return nil
}

f, err := os.Open(path)
if err != nil {
return err
}
defer f.Close()

// create the file in the archive
relPath := "gowitness/" + strings.TrimPrefix(path, tempDir+"/")
df, err := w.Create(relPath)
if err != nil {
return err
}

_, err = io.Copy(df, f)
if err != nil {
return err
}

return nil

}); err != nil {
log.Fatal().Str("target-file", options.File).Err(err).Msg("failed to create report archive")
}

log.Info().Msg("done")
},
}

func init() {
reportCmd.AddCommand(reportExportCmd)

reportExportCmd.Flags().StringVarP(&options.File, "file", "f", "", "the target file to save the zipped report to")

cobra.MarkFlagRequired(reportExportCmd.Flags(), "file")
}

// copyFile well, copies a file
func copyFile(from string, to string) error {

s, err := os.Open(from)
if err != nil {
return err
}
defer s.Close()

d, err := os.Create(to)
if err != nil {
return err
}
defer d.Close()

_, err = io.Copy(d, s)
if err != nil {
return err
}

return nil
}

// copyByte copies bytes to a file
func copyByte(b []byte, to string) error {
d, err := os.Create(to)
if err != nil {
return err
}
defer d.Close()

_, err = io.Copy(d, bytes.NewReader(b))
if err != nil {
return err
}

return nil
}
2 changes: 1 addition & 1 deletion cmd/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ $ gowitness server --addr 127.0.0.1:9000 --allow-insecure-uri`,

r := gin.Default()

tmpl := template.Must(template.New("").ParseFS(Embedded, "web/templates/*.html"))
tmpl := template.Must(template.New("").ParseFS(Embedded, "web/ui-templates/*.html"))
r.SetHTMLTemplate(tmpl)

// web ui routes
Expand Down
6 changes: 0 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.8.0 h1:4WFH5yycBMA3za5Hnl425yd9ymdw1XPm4666oab+hv4=
github.com/gin-gonic/gin v1.8.0/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk=
github.com/gin-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8=
github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
Expand Down Expand Up @@ -93,8 +91,6 @@ github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsK
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/projectdiscovery/wappalyzergo v0.0.44 h1:L1CpNYHZF5RP/uNR83L3EkZGW13cP0WkVEgDk3vN1Sk=
github.com/projectdiscovery/wappalyzergo v0.0.44/go.mod h1:vS+npIOANv7eKsEtODsyRQt2n1v8VofCwj2gjmq72EM=
github.com/projectdiscovery/wappalyzergo v0.0.45 h1:b2OJ4/FrQg6YBDwuK+xMJj/3+h6u+uHuZYURGYPqw3I=
github.com/projectdiscovery/wappalyzergo v0.0.45/go.mod h1:vS+npIOANv7eKsEtODsyRQt2n1v8VofCwj2gjmq72EM=
github.com/remeh/sizedwaitgroup v1.0.0 h1:VNGGFwNo/R5+MJBf6yrsr110p0m4/OX4S3DCy7Kyl5E=
Expand Down Expand Up @@ -139,8 +135,6 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220531201128-c960675eff93 h1:MYimHLfoXEpOhqd/zgoA/uoXzHB86AEky4LAx5ij9xA=
golang.org/x/net v0.0.0-20220531201128-c960675eff93/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220607020251-c690dde0001d h1:4SFsTMi4UahlKoloni7L4eYzhFRifURQLw+yv0QDCx8=
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
Expand Down
Loading

0 comments on commit 3e459eb

Please sign in to comment.