diff --git a/v2/cmd/integration-test/custom-dir.go b/v2/cmd/integration-test/custom-dir.go index 8fa942c2..83f2b1e9 100644 --- a/v2/cmd/integration-test/custom-dir.go +++ b/v2/cmd/integration-test/custom-dir.go @@ -34,5 +34,5 @@ func (h *customConfigDirTest) Execute(filePath string) error { for _, file := range files { fileNames = append(fileNames, file.Name()) } - return expectResultsCount(fileNames, 3) + return expectResultsCount(fileNames, 4) } diff --git a/v2/internal/runner/runner.go b/v2/internal/runner/runner.go index 3da3eb29..b8d7beaa 100644 --- a/v2/internal/runner/runner.go +++ b/v2/internal/runner/runner.go @@ -122,6 +122,9 @@ func New(options *types.Options) (*Runner, error) { } } + if err := reporting.CreateConfigIfNotExists(); err != nil { + return nil, err + } reportingOptions, err := createReportingOptions(options) if err != nil { return nil, err diff --git a/v2/pkg/reporting/exporters/es/elasticsearch.go b/v2/pkg/reporting/exporters/es/elasticsearch.go index de1663ab..e002286c 100644 --- a/v2/pkg/reporting/exporters/es/elasticsearch.go +++ b/v2/pkg/reporting/exporters/es/elasticsearch.go @@ -32,8 +32,9 @@ type Options struct { // Password is the password for elasticsearch instance Password string `yaml:"password" validate:"required"` // IndexName is the name of the elasticsearch index - IndexName string `yaml:"index-name" validate:"required"` - HttpClient *retryablehttp.Client + IndexName string `yaml:"index-name" validate:"required"` + + HttpClient *retryablehttp.Client `yaml:"-"` } type data struct { diff --git a/v2/pkg/reporting/reporting.go b/v2/pkg/reporting/reporting.go index 07531595..2bb3d5e4 100644 --- a/v2/pkg/reporting/reporting.go +++ b/v2/pkg/reporting/reporting.go @@ -1,11 +1,16 @@ package reporting import ( + "os" + "path/filepath" "strings" "github.com/pkg/errors" "go.uber.org/multierr" + "gopkg.in/yaml.v2" + "github.com/projectdiscovery/fileutil" + "github.com/projectdiscovery/nuclei/v2/pkg/catalog/config" "github.com/projectdiscovery/nuclei/v2/pkg/model/types/severity" "github.com/projectdiscovery/nuclei/v2/pkg/model/types/stringslice" "github.com/projectdiscovery/nuclei/v2/pkg/output" @@ -37,7 +42,8 @@ type Options struct { SarifExporter *sarif.Options `yaml:"sarif"` // ElasticsearchExporter contains configuration options for Elasticsearch Exporter Module ElasticsearchExporter *es.Options `yaml:"elasticsearch"` - HttpClient *retryablehttp.Client + + HttpClient *retryablehttp.Client `yaml:"-"` } // Filter filters the received event and decides whether to perform @@ -48,8 +54,8 @@ type Filter struct { } const ( - reportingClientCreationErrorMessage = "could not create reporting client" - exportClientCreationErrorMessage = "could not create exporting client" + reportingClientCreationErrorMessage = "could not create reporting client" + exportClientCreationErrorMessage = "could not create exporting client" ) // GetMatch returns true if a filter matches result event @@ -114,6 +120,7 @@ type Client struct { // New creates a new nuclei issue tracker reporting client func New(options *Options, db string) (*Client, error) { client := &Client{options: options} + if options.GitHub != nil { options.GitHub.HttpClient = options.HttpClient tracker, err := github.New(options.GitHub) @@ -169,6 +176,39 @@ func New(options *Options, db string) (*Client, error) { return client, nil } +// CreateConfigIfNotExists creates report-config if it doesn't exists +func CreateConfigIfNotExists() error { + config, err := config.GetConfigDir() + if err != nil { + return errors.Wrap(err, "could not get config directory") + } + reportingConfig := filepath.Join(config, "report-config.yaml") + + if fileutil.FileExists(reportingConfig) { + return nil + } + values := stringslice.StringSlice{Value: []string{}} + + options := &Options{ + AllowList: &Filter{Tags: values}, + DenyList: &Filter{Tags: values}, + GitHub: &github.Options{}, + GitLab: &gitlab.Options{}, + Jira: &jira.Options{}, + MarkdownExporter: &markdown.Options{}, + SarifExporter: &sarif.Options{}, + ElasticsearchExporter: &es.Options{}, + } + reportingFile, err := os.Create(reportingConfig) + if err != nil { + return errors.Wrap(err, "could not create config file") + } + defer reportingFile.Close() + + err = yaml.NewEncoder(reportingFile).Encode(options) + return err +} + // RegisterTracker registers a custom tracker to the reporter func (c *Client) RegisterTracker(tracker Tracker) { c.trackers = append(c.trackers, tracker) diff --git a/v2/pkg/reporting/trackers/github/github.go b/v2/pkg/reporting/trackers/github/github.go index 41773020..086f9c7e 100644 --- a/v2/pkg/reporting/trackers/github/github.go +++ b/v2/pkg/reporting/trackers/github/github.go @@ -41,7 +41,8 @@ type Options struct { // SeverityAsLabel (optional) sends the severity as the label of the created // issue. SeverityAsLabel bool `yaml:"severity-as-label"` - HttpClient *retryablehttp.Client + + HttpClient *retryablehttp.Client `yaml:"-"` } // New creates a new issue tracker integration client based on options. diff --git a/v2/pkg/reporting/trackers/gitlab/gitlab.go b/v2/pkg/reporting/trackers/gitlab/gitlab.go index 0758141d..68bd477b 100644 --- a/v2/pkg/reporting/trackers/gitlab/gitlab.go +++ b/v2/pkg/reporting/trackers/gitlab/gitlab.go @@ -32,7 +32,8 @@ type Options struct { // SeverityAsLabel (optional) sends the severity as the label of the created // issue. SeverityAsLabel bool `yaml:"severity-as-label"` - HttpClient *retryablehttp.Client + + HttpClient *retryablehttp.Client `yaml:"-"` } // New creates a new issue tracker integration client based on options. diff --git a/v2/pkg/reporting/trackers/jira/jira.go b/v2/pkg/reporting/trackers/jira/jira.go index 715803d7..15f288f9 100644 --- a/v2/pkg/reporting/trackers/jira/jira.go +++ b/v2/pkg/reporting/trackers/jira/jira.go @@ -43,9 +43,9 @@ type Options struct { // SeverityAsLabel (optional) sends the severity as the label of the created // issue. SeverityAsLabel bool `yaml:"severity-as-label"` - HttpClient *retryablehttp.Client -} + HttpClient *retryablehttp.Client `yaml:"-"` +} // New creates a new issue tracker integration client based on options. func New(options *Options) (*Integration, error) {