This commit is contained in:
Ice3man 2022-12-04 20:43:19 +05:30
parent 9164839e21
commit b52254bb74
8 changed files with 198 additions and 175 deletions

View File

@ -33,7 +33,7 @@ require (
github.com/projectdiscovery/nuclei-updatecheck-api v0.0.0-20211006155443-c0a8d610a4df
github.com/projectdiscovery/rawhttp v0.1.2
github.com/projectdiscovery/retryabledns v1.0.17
github.com/projectdiscovery/retryablehttp-go v1.0.3-0.20220506110515-811d938bd26d
github.com/projectdiscovery/retryablehttp-go v1.0.5-0.20221203124408-1d25b06b0572
github.com/projectdiscovery/stringsutil v0.0.2 // indirect
github.com/projectdiscovery/yamldoc-go v1.0.3-0.20211126104922-00d2c6bb43b6
github.com/remeh/sizedwaitgroup v1.0.0
@ -81,14 +81,16 @@ require (
github.com/projectdiscovery/nvd v1.0.9
github.com/projectdiscovery/ratelimit v0.0.0-20221004232058-7b82379157fa
github.com/projectdiscovery/rdap v0.9.1-0.20221108103045-9865884d1917
github.com/projectdiscovery/tlsx v0.0.9
github.com/projectdiscovery/utils v0.0.2
github.com/projectdiscovery/tlsx v0.0.7
github.com/projectdiscovery/utils v0.0.4-0.20221201124851-f8524345b6d3
github.com/projectdiscovery/wappalyzergo v0.0.67
github.com/stretchr/testify v1.8.1
gopkg.in/src-d/go-git.v4 v4.13.1
gopkg.in/yaml.v3 v3.0.1
)
require github.com/projectdiscovery/asnmap v0.0.1 // indirect
require (
git.mills.io/prologic/smtpd v0.0.0-20210710122116-a525b76c287a // indirect
github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 // indirect
@ -225,7 +227,6 @@ require (
github.com/mattn/go-colorable v0.1.11 // indirect
github.com/nwaples/rardecode v1.1.2 // indirect
github.com/pierrec/lz4 v2.6.1+incompatible // indirect
github.com/projectdiscovery/asnmap v0.0.1 // indirect
github.com/projectdiscovery/cryptoutil v0.0.0-20210805184155-b5d2512f9345 // indirect; indirectdev
github.com/projectdiscovery/fileutil v0.0.3
github.com/projectdiscovery/iputil v0.0.2 // indirect
@ -234,6 +235,5 @@ require (
github.com/src-d/gcfg v1.4.0 // indirect
github.com/xanzy/ssh-agent v0.3.0 // indirect
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
github.com/zmap/zcertificate v0.0.0-20180516150559-0e3d58b1bac4 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
)

View File

@ -114,8 +114,8 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkY
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ=
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.44.133 h1:+pWxt9nyKc0jf33rORBaQ93KPjYpmIIy3ozVXdJ82Oo=
github.com/aws/aws-sdk-go v1.44.133/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.134 h1:TzFxjVHPPsibtkD7y6KHI4V00rEKg4yzNlMNGy2ZHeg=
github.com/aws/aws-sdk-go v1.44.134/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go-v2 v1.17.1 h1:02c72fDJr87N8RAC2s3Qu0YuvMRZKNZJ9F+lAehCazk=
github.com/aws/aws-sdk-go-v2 v1.17.1/go.mod h1:JLnGeGONAyi2lWXI1p0PCIOIy333JMVK1U7Hf0aRFLw=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.9 h1:RKci2D7tMwpvGpDNZnGQw9wk6v7o/xSwFcUAuNPoB8k=
@ -154,8 +154,6 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.17.1 h1:KRAix/KHvjGODaHAMXnxRk9t0D+4
github.com/aws/aws-sdk-go-v2/service/sts v1.17.1/go.mod h1:bXcN3koeVYiJcdDU89n3kCYILob7Y34AeLopUbZgLT4=
github.com/aws/smithy-go v1.13.4 h1:/RN2z1txIJWeXeOkzX+Hk/4Uuvv7dWtCjbmVJcrskyk=
github.com/aws/smithy-go v1.13.4/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
github.com/aws/aws-sdk-go v1.44.134 h1:TzFxjVHPPsibtkD7y6KHI4V00rEKg4yzNlMNGy2ZHeg=
github.com/aws/aws-sdk-go v1.44.134/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
@ -696,8 +694,8 @@ github.com/projectdiscovery/retryabledns v1.0.17 h1:XKzI26UKYt2g7YLJ/EcyYmM04sfD
github.com/projectdiscovery/retryabledns v1.0.17/go.mod h1:Dyhq/f0sGmXueso0+Ah3LbJfsX4PXpBrpfiyjZZ8SDk=
github.com/projectdiscovery/retryablehttp-go v1.0.1/go.mod h1:SrN6iLZilNG1X4neq1D+SBxoqfAF4nyzvmevkTkWsek=
github.com/projectdiscovery/retryablehttp-go v1.0.2/go.mod h1:dx//aY9V247qHdsRf0vdWHTBZuBQ2vm6Dq5dagxrDYI=
github.com/projectdiscovery/retryablehttp-go v1.0.3-0.20220506110515-811d938bd26d h1:VR+tDkedzHIp1pGKIDcfPFt7J8KjcjxGsJvBAP6RXFQ=
github.com/projectdiscovery/retryablehttp-go v1.0.3-0.20220506110515-811d938bd26d/go.mod h1:t4buiLTB0HtI+62iHfGDqQVTv/i+8OhAKwaX93TGsFE=
github.com/projectdiscovery/retryablehttp-go v1.0.5-0.20221203124408-1d25b06b0572 h1:Klpsn4TcgarK2hkX5U8vLn4GePXM7gevJw1gIh3kmCA=
github.com/projectdiscovery/retryablehttp-go v1.0.5-0.20221203124408-1d25b06b0572/go.mod h1:Z9FoXiCxITq+Wt6VzqJAu8xA/xDTVrgBFaDk+Xsfgw4=
github.com/projectdiscovery/sliceutil v0.0.1 h1:YoCqCMcdwz+gqNfW5hFY8UvNHoA6SfyBSNkVahatleg=
github.com/projectdiscovery/sliceutil v0.0.1/go.mod h1:0wBmhU5uTDwMfrEZfvwH9qa5k60Q4shPVOC9E6LGsDI=
github.com/projectdiscovery/stringsutil v0.0.0-20210804142656-fd3c28dbaafe/go.mod h1:oTRc18WBv9t6BpaN9XBY+QmG28PUpsyDzRht56Qf49I=
@ -706,10 +704,10 @@ github.com/projectdiscovery/stringsutil v0.0.0-20210830151154-f567170afdd9/go.mo
github.com/projectdiscovery/stringsutil v0.0.0-20220208075244-7c05502ca8e9/go.mod h1:oTRc18WBv9t6BpaN9XBY+QmG28PUpsyDzRht56Qf49I=
github.com/projectdiscovery/stringsutil v0.0.2 h1:uzmw3IVLJSMW1kEg8eCStG/cGbYYZAja8BH3LqqJXMA=
github.com/projectdiscovery/stringsutil v0.0.2/go.mod h1:EJ3w6bC5fBYjVou6ryzodQq37D5c6qbAYQpGmAy+DC0=
github.com/projectdiscovery/tlsx v0.0.9 h1:wUC8GYUIo5jd+enqE1lnEJ3Ew7m+N6eRmFBjbSJLomU=
github.com/projectdiscovery/tlsx v0.0.9/go.mod h1:bPKwgeGRMZaDpOQCy6TjQWr3bQ7d9lW2lVH5BnWlWMI=
github.com/projectdiscovery/utils v0.0.2 h1:lif4OYBqd8jCf0glRBfSs2lT4nMtNjHjeysRw8HIW8M=
github.com/projectdiscovery/utils v0.0.2/go.mod h1:PEYYkpCedmtydQRUvfWLPw0VRWpaFms4GFqNAziBANI=
github.com/projectdiscovery/tlsx v0.0.7 h1:McoDo4Ju7aetogatU4lVTRcQpxkf0qgQSoWgtkDavCk=
github.com/projectdiscovery/tlsx v0.0.7/go.mod h1:/ZCk/zzyuDdXx2E511yhNIj3LERnGUXghqkASBbdh5M=
github.com/projectdiscovery/utils v0.0.4-0.20221201124851-f8524345b6d3 h1:sOvfN3xHLiBMb6GJ3yDxBmPnN0dh3xllaQXQYo7CFUo=
github.com/projectdiscovery/utils v0.0.4-0.20221201124851-f8524345b6d3/go.mod h1:PCwA5YuCYWPgHaGiZmr53/SA9iGQmAnw7DSHuhr8VPQ=
github.com/projectdiscovery/wappalyzergo v0.0.67 h1:4ckerDUmT/OiU+O3XZ0ZGGEJ4DDPVAlsYtXFIzLtfjQ=
github.com/projectdiscovery/wappalyzergo v0.0.67/go.mod h1:HvYuW0Be4JCjVds/+XAEaMSqRG9yrI97UmZq0TPk6A0=
github.com/projectdiscovery/yamldoc-go v1.0.2/go.mod h1:7uSxfMXaBmzvw8m5EhOEjB6nhz0rK/H9sUjq1ciZu24=
@ -883,7 +881,6 @@ github.com/zclconf/go-cty v1.8.4/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUA
github.com/zclconf/go-cty v1.10.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk=
github.com/zmap/rc2 v0.0.0-20131011165748-24b9757f5521 h1:kKCF7VX/wTmdg2ZjEaqlq99Bjsoiz7vH6sFniF/vI4M=
github.com/zmap/rc2 v0.0.0-20131011165748-24b9757f5521/go.mod h1:3YZ9o3WnatTIZhuOtot4IcUfzoKVjUHqu6WALIyI0nE=
github.com/zmap/zcertificate v0.0.0-20180516150559-0e3d58b1bac4 h1:17HHAgFKlLcZsDOjBOUrd5hDihb1ggf+1a5dTbkgkIY=
github.com/zmap/zcertificate v0.0.0-20180516150559-0e3d58b1bac4/go.mod h1:5iU54tB79AMBcySS0R2XIyZBAVmeHranShAFELYx7is=
github.com/zmap/zcrypto v0.0.0-20211005224000-2d0ffdec8a9b/go.mod h1:5nID//bFGkx3/+iHcFIFRHQ54EOPJ0iSj0IGKpMElvw=
github.com/zmap/zcrypto v0.0.0-20220803033029-557f3e4940be h1:M5QjuCbUeNZsup53dlJkI/cx6pVdnDOPzyy+XppoowY=

View File

@ -2,12 +2,76 @@ package runner
import (
"strings"
"time"
"github.com/pkg/errors"
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/nuclei/v2/internal/runner/nucleicloud"
"github.com/projectdiscovery/nuclei/v2/pkg/output"
)
// 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
for {
items, err := r.cloudClient.GetScans(limit, lastTime)
if err != nil {
e = err
break
}
if len(items) == 0 {
break
}
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)
}
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
}
func (r *Runner) deleteScan(id string) error {
deleted, err := r.cloudClient.DeleteScan(id)
if !deleted.OK {
gologger.Info().Msgf("Error in deleting the scan %s.", id)
} else {
gologger.Info().Msgf("Scan deleted %s.", id)
}
return err
}
func (r *Runner) getResults(id string, limit int) error {
err := r.cloudClient.GetResults(id, func(re *output.ResultEvent) {
if outputErr := r.output.Write(re); outputErr != nil {
gologger.Warning().Msgf("Could not write output: %s", outputErr)
}
}, false, limit)
return err
}
func (r *Runner) listDatasources() error {
datasources, err := r.cloudClient.ListDatasources()
if err != nil {
return err
}
for _, source := range datasources {
gologger.Silent().Msgf("[%s] [%s] [%s] %s", source.Updatedat.Format(DDMMYYYYhhmmss), source.ID, source.Type, source.Repo)
}
return err
}
// initializeCloudDataSources initializes cloud data sources
func (r *Runner) initializeCloudDataSources() ([]string, error) {
var ids []string

View File

@ -33,60 +33,6 @@ func (r *Runner) runStandardEnumeration(executerOpts protocols.ExecuterOptions,
return r.executeTemplatesInput(store, engine)
}
// 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
for {
items, err := r.cloudClient.GetScans(limit, lastTime)
if err != nil {
e = err
break
}
if len(items) == 0 {
break
}
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)
}
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
}
func (r *Runner) deleteScan(id string) error {
deleted, err := r.cloudClient.DeleteScan(id)
if !deleted.OK {
gologger.Info().Msgf("Error in deleting the scan %s.", id)
} else {
gologger.Info().Msgf("Scan deleted %s.", id)
}
return err
}
func (r *Runner) getResults(id string, limit int) error {
err := r.cloudClient.GetResults(id, func(re *output.ResultEvent) {
if outputErr := r.output.Write(re); outputErr != nil {
gologger.Warning().Msgf("Could not write output: %s", outputErr)
}
}, false, limit)
return err
}
// runCloudEnumeration runs cloud based enumeration
func (r *Runner) runCloudEnumeration(store *loader.Store, cloudTemplates, cloudTargets []string, nostore bool, limit int) (*atomic.Bool, error) {
now := time.Now()

View File

@ -2,6 +2,7 @@ package nucleicloud
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
@ -23,15 +24,16 @@ type Client struct {
}
const (
pollInterval = 1 * time.Second
defaultBaseURL = "http://webapp.localhost"
pollInterval = 3 * time.Second
resultSize = 100
defaultBaseURL = "https://cloud-dev.nuclei.sh"
)
// New returns a nuclei-cloud API client
func New(baseURL, apiKey string) *Client {
options := retryablehttp.DefaultOptionsSingle
options.Timeout = 15 * time.Second
options.NoAdjustTimeout = true
options.Timeout = 60 * time.Second
client := retryablehttp.NewClient(options)
baseAppURL := baseURL
@ -45,29 +47,23 @@ func New(baseURL, apiKey string) *Client {
func (c *Client) AddScan(req *AddScanRequest) (string, error) {
var buf bytes.Buffer
if err := jsoniter.NewEncoder(&buf).Encode(req); err != nil {
return "", errors.Wrap(err, "could not json encode scan request")
return "", errors.Wrap(err, "could not encode request")
}
httpReq, err := retryablehttp.NewRequest(http.MethodPost, fmt.Sprintf("%s/scan", c.baseURL), bytes.NewReader(buf.Bytes()))
if err != nil {
return "", errors.Wrap(err, "could not make request")
}
httpReq.Header.Set("X-API-Key", c.apiKey)
resp, err := c.httpclient.Do(httpReq)
resp, err := c.sendRequest(httpReq)
if err != nil {
return "", errors.Wrap(err, "could not do add scan request")
}
if resp.StatusCode != 200 {
data, _ := io.ReadAll(resp.Body)
resp.Body.Close()
return "", errors.Errorf("could not do request %d: %s", resp.StatusCode, string(data))
return "", errors.Wrap(err, "could not do request")
}
defer resp.Body.Close()
var data map[string]string
if err := jsoniter.NewDecoder(resp.Body).Decode(&data); err != nil {
resp.Body.Close()
return "", errors.Wrap(err, "could not decode resp")
}
resp.Body.Close()
id := data["id"]
return id, nil
}
@ -83,17 +79,12 @@ func (c *Client) GetResults(ID string, callback func(*output.ResultEvent), check
if err != nil {
return errors.Wrap(err, "could not make request")
}
httpReq.Header.Set("X-API-Key", c.apiKey)
resp, err := c.httpclient.Do(httpReq)
resp, err := c.sendRequest(httpReq)
if err != nil {
return errors.Wrap(err, "could not do ger result request")
}
if resp.StatusCode != 200 {
data, _ := io.ReadAll(resp.Body)
resp.Body.Close()
return errors.Errorf("could not do request %d: %s", resp.StatusCode, string(data))
return errors.Wrap(err, "could not do request")
}
var items GetResultsResponse
if err := jsoniter.NewDecoder(resp.Body).Decode(&items); err != nil {
resp.Body.Close()
@ -131,26 +122,16 @@ func (c *Client) GetScans(limit int, from string) ([]GetScanRequest, error) {
if err != nil {
return items, errors.Wrap(err, "could not make request")
}
httpReq.Header.Set("X-API-Key", c.apiKey)
resp, err := c.httpclient.Do(httpReq)
resp, err := c.sendRequest(httpReq)
if err != nil {
return items, errors.Wrap(err, "could not make request.")
}
if err != nil {
return items, errors.Wrap(err, "could not do get response.")
}
if resp.StatusCode != 200 {
data, _ := io.ReadAll(resp.Body)
resp.Body.Close()
return items, errors.Errorf("could not do request %d: %s", resp.StatusCode, string(data))
return nil, errors.Wrap(err, "could not do request")
}
defer resp.Body.Close()
if err := jsoniter.NewDecoder(resp.Body).Decode(&items); err != nil {
resp.Body.Close()
return items, errors.Wrap(err, "could not decode results")
}
resp.Body.Close()
return items, nil
}
@ -161,26 +142,16 @@ func (c *Client) DeleteScan(id string) (DeleteScanResults, error) {
if err != nil {
return deletescan, errors.Wrap(err, "could not make request")
}
httpReq.Header.Set("X-API-Key", c.apiKey)
resp, err := c.httpclient.Do(httpReq)
resp, err := c.sendRequest(httpReq)
if err != nil {
return deletescan, errors.Wrap(err, "could not make request")
}
if err != nil {
return deletescan, errors.Wrap(err, "could not do get result request")
}
if resp.StatusCode != 200 {
data, _ := io.ReadAll(resp.Body)
resp.Body.Close()
return deletescan, errors.Errorf("could not do request %d: %s", resp.StatusCode, string(data))
return deletescan, errors.Wrap(err, "could not do request")
}
defer resp.Body.Close()
if err := jsoniter.NewDecoder(resp.Body).Decode(&deletescan); err != nil {
resp.Body.Close()
return deletescan, errors.Wrap(err, "could not delete scan")
}
resp.Body.Close()
return deletescan, nil
}
@ -188,33 +159,23 @@ func (c *Client) DeleteScan(id string) (DeleteScanResults, error) {
func (c *Client) StatusDataSource(statusRequest StatusDataSourceRequest) (string, error) {
var buf bytes.Buffer
if err := jsoniter.NewEncoder(&buf).Encode(statusRequest); err != nil {
return "", errors.Wrap(err, "could not json encode scan request")
return "", errors.Wrap(err, "could not encode request")
}
httpReq, err := retryablehttp.NewRequest(http.MethodPost, fmt.Sprintf("%s/datasources/status", c.baseURL), bytes.NewReader(buf.Bytes()))
if err != nil {
return "", errors.Wrap(err, "could not make request")
}
httpReq.Header.Set("X-API-Key", c.apiKey)
resp, err := c.httpclient.Do(httpReq)
resp, err := c.sendRequest(httpReq)
if err != nil {
return "", errors.Wrap(err, "could not make request")
}
if err != nil {
return "", errors.Wrap(err, "could not do get result request")
}
if resp.StatusCode != 200 {
data, _ := io.ReadAll(resp.Body)
resp.Body.Close()
return "", errors.Errorf("invalid status code recieved %d: %s", resp.StatusCode, string(data))
return "", errors.Wrap(err, "could not do request")
}
defer resp.Body.Close()
var data map[string]interface{}
if err := jsoniter.NewDecoder(resp.Body).Decode(&data); err != nil {
resp.Body.Close()
return "", errors.Wrap(err, "could not decode resp")
}
resp.Body.Close()
id := data["id"].(string)
return id, nil
}
@ -223,33 +184,22 @@ func (c *Client) StatusDataSource(statusRequest StatusDataSourceRequest) (string
func (c *Client) AddDataSource(req AddDataSourceRequest) (string, string, error) {
var buf bytes.Buffer
if err := jsoniter.NewEncoder(&buf).Encode(req); err != nil {
return "", "", errors.Wrap(err, "could not json encode request")
return "", "", errors.Wrap(err, "could not encode request")
}
httpReq, err := retryablehttp.NewRequest(http.MethodPost, fmt.Sprintf("%s/datasources", c.baseURL), bytes.NewReader(buf.Bytes()))
if err != nil {
return "", "", errors.Wrap(err, "could not make request")
}
httpReq.Header.Set("X-API-Key", c.apiKey)
resp, err := c.httpclient.Do(httpReq)
resp, err := c.sendRequest(httpReq)
if err != nil {
return "", "", errors.Wrap(err, "could not make request")
}
if err != nil {
return "", "", errors.Wrap(err, "could not do get result request")
}
if resp.StatusCode != 200 {
data, _ := io.ReadAll(resp.Body)
resp.Body.Close()
return "", "", errors.Errorf("could not do request %d: %s", resp.StatusCode, string(data))
return "", "", errors.Wrap(err, "could not do request")
}
defer resp.Body.Close()
var data map[string]interface{}
if err := jsoniter.NewDecoder(resp.Body).Decode(&data); err != nil {
resp.Body.Close()
return "", "", errors.Wrap(err, "could not decode resp")
}
resp.Body.Close()
id := data["id"].(string)
secret, _ := data["secret"].(string)
return id, secret, nil
@ -258,24 +208,17 @@ func (c *Client) AddDataSource(req AddDataSourceRequest) (string, string, error)
// SyncDataSource syncs contents for a data source. The call blocks until
// update is completed.
func (c *Client) SyncDataSource(ID string) error {
httpReq, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/datasources/%s/sync", c.baseURL, ID), nil)
httpReq, err := retryablehttp.NewRequest(http.MethodGet, fmt.Sprintf("%s/datasources/%s/sync", c.baseURL, ID), nil)
if err != nil {
return errors.Wrap(err, "could not make request")
}
httpReq.Header.Set("X-API-Key", c.apiKey)
resp, err := http.DefaultClient.Do(httpReq)
resp, err := c.sendRequest(httpReq)
if err != nil {
return errors.Wrap(err, "could not make request")
}
if err != nil {
return errors.Wrap(err, "could not do get result request")
}
if resp.StatusCode != 200 {
data, _ := io.ReadAll(resp.Body)
resp.Body.Close()
return errors.Errorf("could not do request %d: %s", resp.StatusCode, string(data))
return errors.Wrap(err, "could not do request")
}
defer resp.Body.Close()
_, _ = io.Copy(io.Discard, resp.Body)
return nil
}
@ -283,25 +226,71 @@ func (c *Client) SyncDataSource(ID string) error {
func (c *Client) ExistsDataSourceItem(req ExistsDataSourceItemRequest) error {
var buf bytes.Buffer
if err := jsoniter.NewEncoder(&buf).Encode(req); err != nil {
return errors.Wrap(err, "could not json encode request")
return errors.Wrap(err, "could not encode request")
}
httpReq, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/datasources/exists", c.baseURL), bytes.NewReader(buf.Bytes()))
httpReq, err := retryablehttp.NewRequest(http.MethodPost, fmt.Sprintf("%s/datasources/exists", c.baseURL), bytes.NewReader(buf.Bytes()))
if err != nil {
return errors.Wrap(err, "could not make request")
}
httpReq.Header.Set("X-API-Key", c.apiKey)
resp, err := http.DefaultClient.Do(httpReq)
resp, err := c.sendRequest(httpReq)
if err != nil {
return errors.Wrap(err, "could not make request")
}
if err != nil {
return errors.Wrap(err, "could not do get result request")
}
if resp.StatusCode != 200 {
data, _ := io.ReadAll(resp.Body)
resp.Body.Close()
return errors.Errorf("could not do request %d: %s", resp.StatusCode, string(data))
return errors.Wrap(err, "could not do request")
}
defer resp.Body.Close()
_, _ = io.Copy(io.Discard, resp.Body)
return nil
}
func (c *Client) ListDatasources() ([]GetDataSourceResponse, error) {
var items []GetDataSourceResponse
httpReq, err := retryablehttp.NewRequest(http.MethodGet, fmt.Sprintf("%s/datasources", c.baseURL), nil)
if err != nil {
return items, errors.Wrap(err, "could not make request")
}
resp, err := c.sendRequest(httpReq)
if err != nil {
return nil, errors.Wrap(err, "could not do request")
}
defer resp.Body.Close()
if err := jsoniter.NewDecoder(resp.Body).Decode(&items); err != nil {
return items, errors.Wrap(err, "could not decode results")
}
return items, nil
}
/*
-lds, -list-ds list cloud datasources
-rds, -remove-ds remove cloud datasources
-atr, -add-target add target(s) list to cloud
-lt, -list-target list cloud target
-atm, -add-template add template(s) to cloud
-tl, -list-template list cloud templates
-rm, -remove remove specficed cloud data
*/
const apiKeyParameter = "X-API-Key"
type errorResponse struct {
Message string `json:"message"`
}
func (c *Client) sendRequest(req *retryablehttp.Request) (*http.Response, error) {
req.Header.Set(apiKeyParameter, c.apiKey)
resp, err := c.httpclient.Do(req)
if err != nil {
return nil, errors.Wrap(err, "could not do request")
}
if resp.StatusCode < http.StatusOK || resp.StatusCode >= http.StatusBadRequest {
data, _ := io.ReadAll(resp.Body)
resp.Body.Close()
var errRes errorResponse
if err = json.NewDecoder(bytes.NewReader(data)).Decode(&errRes); err == nil {
return nil, errors.New(errRes.Message)
}
return nil, fmt.Errorf("unknown error, status code: %d=%s", resp.StatusCode, string(data))
}
return resp, nil
}

View File

@ -69,3 +69,26 @@ type ExistsDataSourceItemRequest struct {
Type string `json:"type"`
Contents string `json:"contents"`
}
// GetDataSourceResponse is response for a get data source request
type GetDataSourceResponse struct {
ID string `json:"id"`
Type string `json:"type"`
Path string `json:"path"`
Repo string `json:"repo"`
Updatedat time.Time `json:"updated_at"`
}
// GetTargetResponse is the response for a get target request
type GetTargetResponse struct {
ID int64 `json:"id"`
Reference string `json:"reference"`
Type string `json:"type"`
}
// GetTemplatesResponse is the response for a get templates request
type GetTemplatesResponse struct {
ID int64 `json:"id"`
Reference string `json:"reference"`
Type string `json:"type"`
}

View File

@ -470,6 +470,8 @@ func (r *Runner) RunEnumeration() error {
err = r.deleteScan(r.options.DeleteScan)
} else if r.options.ScanOutput != "" {
err = r.getResults(r.options.ScanOutput, r.options.OutputLimit)
} else if r.options.ListDatasources {
err = r.listDatasources()
} else {
gologger.Info().Msgf("Running scan on cloud with URL %s", r.options.CloudURL)
results, err = r.runCloudEnumeration(store, cloudTemplates, cloudTargets, r.options.NoStore, r.options.OutputLimit)

View File

@ -97,6 +97,8 @@ type Options struct {
CloudAPIKey string
// Scanlist feature to get all the scan ids for a user
ScanList bool
// ListDatasources enables listing of datasources for user
ListDatasources bool
// Limit the number of items at a time
OutputLimit int
// Nostore