Add JSON output support for list-scan option (#2876)

* Add JSON output support for list-scan option

* Fix typo in cloud JSON output description

* Following changes

- Update status(finished, running) to be lower-case by default
- Convert status to upper-case in DisplayScanList()

* Update status to be lower-case by default

* Remove additional json flag, instead use existing

* Merge conflict

* Accomodate comment changes and restructure code

Co-authored-by: Jaideep K <jaideep@one2n.in>
This commit is contained in:
Siddharth Shashikar 2022-12-12 16:41:28 +05:30 committed by GitHub
parent 82c1e6fef3
commit 1032189b3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 63 additions and 14 deletions

View File

@ -5,7 +5,6 @@ import (
"path/filepath"
"strconv"
"strings"
"time"
"github.com/pkg/errors"
"github.com/projectdiscovery/gologger"
@ -15,7 +14,6 @@ import (
// Get all the scan lists for a user/apikey.
func (r *Runner) getScanList(limit int) error {
loc, _ := time.LoadLocation("Local")
lastTime := "2099-01-02 15:04:05 +0000 UTC"
var e error
@ -30,16 +28,12 @@ func (r *Runner) getScanList(limit int) error {
}
for _, v := range items {
lastTime = v.CreatedAt.String()
status := "FINISHED"
t := v.FinishedAt
duration := t.Sub(v.CreatedAt)
if !v.Finished {
status = "RUNNING"
t = time.Now().UTC()
duration = t.Sub(v.CreatedAt).Round(60 * time.Second)
res := nucleicloud.PrepareScanListOutput(v)
if r.options.JSON {
nucleicloud.DisplayScanListInJson(res)
} else {
nucleicloud.DisplayScanList(res)
}
val := v.CreatedAt.In(loc).Format(DDMMYYYYhhmmss)
gologger.Silent().Msgf("%s [%s] [STATUS: %s] [MATCHED: %d] [TARGETS: %d] [TEMPLATES: %d] [DURATION: %s]\n", v.Id, val, status, v.Matches, v.Targets, v.Templates, duration)
}
}
return e
@ -70,7 +64,7 @@ func (r *Runner) listDatasources() error {
return err
}
for _, source := range datasources {
gologger.Silent().Msgf("[%s] [%d] [%s] [%s] %s", source.Updatedat.Format(DDMMYYYYhhmmss), source.ID, source.Type, source.Repo, source.Path)
gologger.Silent().Msgf("[%s] [%d] [%s] [%s] %s", source.Updatedat.Format(nucleicloud.DDMMYYYYhhmmss), source.ID, source.Type, source.Repo, source.Path)
}
return err
}

View File

@ -23,8 +23,6 @@ import (
"go.uber.org/atomic"
)
const DDMMYYYYhhmmss = "2006-01-02 15:04:05"
// runStandardEnumeration runs standard enumeration
func (r *Runner) runStandardEnumeration(executerOpts protocols.ExecuterOptions, store *loader.Store, engine *core.Engine) (*atomic.Bool, error) {
if r.options.AutomaticScan {

View File

@ -0,0 +1,18 @@
package nucleicloud
import (
"encoding/json"
"os"
"strings"
"github.com/projectdiscovery/gologger"
)
func DisplayScanListInJson(output ListScanOutput) {
bytes, _ := json.Marshal(output)
os.Stdout.Write(bytes)
}
func DisplayScanList(output ListScanOutput) {
gologger.Silent().Msgf("%s [%s] [STATUS: %s] [MATCHED: %d] [TARGETS: %d] [TEMPLATES: %d] [DURATION: %s]\n", output.Timestamp, output.ScanID, strings.ToUpper(output.ScanStatus), output.ScanResult, output.Target, output.Template, output.ScanTime)
}

View File

@ -106,3 +106,13 @@ type GetTemplatesResponse struct {
type AddItemResponse struct {
Ok string `json:"ok"`
}
type ListScanOutput struct {
Timestamp string `json:"timestamp"`
ScanID string `json:"scan_id"`
ScanTime string `json:"scan_time"`
ScanResult int `json:"scan_result"`
ScanStatus string `json:"scan_status"`
Target int `json:"target"`
Template int `json:"template"`
}

View File

@ -5,10 +5,13 @@ import (
"os"
"path/filepath"
"strings"
"time"
"github.com/projectdiscovery/nuclei/v2/pkg/catalog/config"
)
const DDMMYYYYhhmmss = "2006-01-02 15:04:05"
// ReadCatalogChecksum reads catalog checksum from nuclei-templates repository
func ReadCatalogChecksum() map[string]string {
config, _ := config.ReadConfiguration()
@ -38,3 +41,29 @@ func ReadCatalogChecksum() map[string]string {
}
return checksums
}
func PrepareScanListOutput(v GetScanRequest) ListScanOutput {
output := ListScanOutput{}
loc, _ := time.LoadLocation("Local")
status := "finished"
t := v.FinishedAt
duration := t.Sub(v.CreatedAt)
if !v.Finished {
status = "running"
t = time.Now().UTC()
duration = t.Sub(v.CreatedAt).Round(60 * time.Second)
}
val := v.CreatedAt.In(loc).Format(DDMMYYYYhhmmss)
output.Timestamp = val
output.ScanID = v.Id
output.ScanTime = duration.String()
output.ScanResult = int(v.Matches)
output.ScanStatus = status
output.Target = int(v.Targets)
output.Template = int(v.Templates)
return output
}