Skip to content

Commit

Permalink
Add hide args in report option (#261)
Browse files Browse the repository at this point in the history
* Fix Makefile

* Add new flag

* Fix report pkg

* Fix report validator

* Update new arg name
  • Loading branch information
svkirillov authored Oct 21, 2024
1 parent 338000b commit 9088260
Show file tree
Hide file tree
Showing 9 changed files with 42 additions and 29 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
GOTESTWAF_VERSION := $(shell git describe)
GOTESTWAF_VERSION := $(shell git describe --tags)

gotestwaf:
DOCKER_BUILDKIT=1 docker build --force-rm -t gotestwaf .
Expand Down
21 changes: 11 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -363,41 +363,42 @@ Usage: ./gotestwaf [OPTIONS] --url <URL>
Options:
--addDebugHeader Add header with a hash of the test information in each request
--addHeader string An HTTP header to add to requests
--blockConnReset If true, connection resets will be considered as block
--blockConnReset If present, connection resets will be considered as block
--blockRegex string Regex to detect a blocking page with the same HTTP response status code as a not blocked request
--blockStatusCodes ints HTTP status code that WAF uses while blocking requests (default [403])
--configPath string Path to the config file (default "config.yaml")
--email string E-mail to which the report will be sent
--followCookies If true, use cookies sent by the server. May work only with --maxIdleConns=1 (gohttp only)
--followCookies If present, use cookies sent by the server. May work only with --maxIdleConns=1 (gohttp only)
--graphqlURL string GraphQL URL to check
--grpcPort uint16 gRPC port to check
--httpClient string Which HTTP client use to send requests: chrome, gohttp (default "gohttp")
--hideArgsInReport If present, GoTestWAF CLI arguments will not be displayed in the report
--httpClient string Which HTTP client use to send requests: gohttp, chrome (default "gohttp")
--idleConnTimeout int The maximum amount of time a keep-alive connection will live (gohttp only) (default 2)
--ignoreUnresolved If true, unresolved test cases will be considered as bypassed (affect score and results)
--includePayloads If true, payloads will be included in HTML/PDF report
--ignoreUnresolved If present, unresolved test cases will be considered as bypassed (affect score and results)
--includePayloads If present, payloads will be included in HTML/PDF report
--logFormat string Set logging format: text, json (default "text")
--logLevel string Logging level: panic, fatal, error, warn, info, debug, trace (default "info")
--maxIdleConns int The maximum number of keep-alive connections (gohttp only) (default 2)
--maxRedirects int The maximum number of handling redirects (gohttp only) (default 50)
--noEmailReport Save report locally
--nonBlockedAsPassed If true, count requests that weren't blocked as passed. If false, requests that don't satisfy to PassStatusCodes/PassRegExp as blocked
--nonBlockedAsPassed If present, count requests that weren't blocked as passed. If false, requests that don't satisfy to PassStatusCodes/PassRegExp as blocked
--openapiFile string Path to openAPI file
--passRegex string Regex to a detect normal (not blocked) web page with the same HTTP status code as a blocked request
--passStatusCodes ints HTTP response status code that WAF uses while passing requests (default [200,404])
--proxy string Proxy URL to use
--quiet If true, disable verbose logging
--quiet If present, disable verbose logging
--randomDelay int Random delay in ms in addition to the delay between requests (default 400)
--renewSession Renew cookies before each test. Should be used with --followCookies flag (gohttp only)
--reportFormat string Export report to one of the following formats: none, pdf, html, json (default "pdf")
--reportFormat strings Export report in the following formats: json, html, pdf, none (default [pdf])
--reportName string Report file name. Supports `time' package template format (default "waf-evaluation-report-2006-January-02-15-04-05")
--reportPath string A directory to store reports (default "reports")
--sendDelay int Delay in ms between requests (default 400)
--skipWAFBlockCheck If true, WAF detection tests will be skipped
--skipWAFBlockCheck If present, WAF detection tests will be skipped
--skipWAFIdentification Skip WAF identification
--testCase string If set then only this test case will be run
--testCasesPath string Path to a folder with test cases (default "testcases")
--testSet string If set then only this test set's cases will be run
--tlsVerify If true, the received TLS certificate will be verified
--tlsVerify If present, the received TLS certificate will be verified
--url string URL to check
--version Show GoTestWAF version and exit
--wafName string Name of the WAF product (default "generic")
Expand Down
17 changes: 9 additions & 8 deletions cmd/gotestwaf/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func parseFlags() (args []string, err error) {

// General parameters
flag.StringVar(&configPath, "configPath", defaultConfigPath, "Path to the config file")
flag.BoolVar(&quiet, "quiet", false, "If true, disable verbose logging")
flag.BoolVar(&quiet, "quiet", false, "If present, disable verbose logging")
logLvl := flag.String("logLevel", "info", "Logging level: panic, fatal, error, warn, info, debug, trace")
flag.StringVar(&logFormat, "logFormat", textLogFormat, "Set logging format: "+strings.Join(logFormats, ", "))
showVersion := flag.Bool("version", false, "Show GoTestWAF version and exit")
Expand All @@ -111,7 +111,7 @@ func parseFlags() (args []string, err error) {

// HTTP client settings
httpClient := flag.String("httpClient", gohttpClient, "Which HTTP client use to send requests: "+strings.Join(httpClients, ", "))
flag.Bool("tlsVerify", false, "If true, the received TLS certificate will be verified")
flag.Bool("tlsVerify", false, "If present, the received TLS certificate will be verified")
flag.String("proxy", "", "Proxy URL to use")
flag.String("addHeader", "", "An HTTP header to add to requests")
flag.Bool("addDebugHeader", false, "Add header with a hash of the test information in each request")
Expand All @@ -120,7 +120,7 @@ func parseFlags() (args []string, err error) {
flag.Int("maxIdleConns", 2, "The maximum number of keep-alive connections (gohttp only)")
flag.Int("maxRedirects", 50, "The maximum number of handling redirects (gohttp only)")
flag.Int("idleConnTimeout", 2, "The maximum amount of time a keep-alive connection will live (gohttp only)")
flag.Bool("followCookies", false, "If true, use cookies sent by the server. May work only with --maxIdleConns=1 (gohttp only)")
flag.Bool("followCookies", false, "If present, use cookies sent by the server. May work only with --maxIdleConns=1 (gohttp only)")
flag.Bool("renewSession", false, "Renew cookies before each test. Should be used with --followCookies flag (gohttp only)")

// Performance settings
Expand All @@ -129,7 +129,7 @@ func parseFlags() (args []string, err error) {
flag.Int("randomDelay", 400, "Random delay in ms in addition to the delay between requests")

// Analysis settings
flag.Bool("skipWAFBlockCheck", false, "If true, WAF detection tests will be skipped")
flag.Bool("skipWAFBlockCheck", false, "If present, WAF detection tests will be skipped")
flag.Bool("skipWAFIdentification", false, "Skip WAF identification")
flag.IntSlice("blockStatusCodes", []int{403}, "HTTP status code that WAF uses while blocking requests")
flag.IntSlice("passStatusCodes", []int{200, 404}, "HTTP response status code that WAF uses while passing requests")
Expand All @@ -138,18 +138,19 @@ func parseFlags() (args []string, err error) {
passRegex := flag.String("passRegex", "",
"Regex to a detect normal (not blocked) web page with the same HTTP status code as a blocked request")
flag.Bool("nonBlockedAsPassed", false,
"If true, count requests that weren't blocked as passed. If false, requests that don't satisfy to PassStatusCodes/PassRegExp as blocked")
flag.Bool("ignoreUnresolved", false, "If true, unresolved test cases will be considered as bypassed (affect score and results)")
flag.Bool("blockConnReset", false, "If true, connection resets will be considered as block")
"If present, count requests that weren't blocked as passed. If false, requests that don't satisfy to PassStatusCodes/PassRegExp as blocked")
flag.Bool("ignoreUnresolved", false, "If present, unresolved test cases will be considered as bypassed (affect score and results)")
flag.Bool("blockConnReset", false, "If present, connection resets will be considered as block")

// Report settings
flag.String("wafName", wafName, "Name of the WAF product")
flag.Bool("includePayloads", false, "If true, payloads will be included in HTML/PDF report")
flag.Bool("includePayloads", false, "If present, payloads will be included in HTML/PDF report")
flag.String("reportPath", reportPath, "A directory to store reports")
reportName := flag.String("reportName", defaultReportName, "Report file name. Supports `time' package template format")
reportFormat := flag.StringSlice("reportFormat", []string{report.PdfFormat}, "Export report in the following formats: "+strings.Join(report.ReportFormats, ", "))
noEmailReport := flag.Bool("noEmailReport", false, "Save report locally")
email := flag.String("email", "", "E-mail to which the report will be sent")
flag.Bool("hideArgsInReport", false, "If present, GoTestWAF CLI arguments will not be displayed in the report")

flag.Parse()

Expand Down
5 changes: 4 additions & 1 deletion cmd/gotestwaf/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,10 @@ func main() {
logger.WithError(err).Error("couldn't load config")
os.Exit(1)
}
cfg.Args = args

if !cfg.HideArgsInReport {
cfg.Args = args
}

if err := run(ctx, cfg, logger); err != nil {
logger.WithError(err).Error("caught error in main function")
Expand Down
15 changes: 8 additions & 7 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,14 @@ type Config struct {
BlockConnReset bool `mapstructure:"blockConnReset"`

// Report settings
WAFName string `mapstructure:"wafName"`
IncludePayloads bool `mapstructure:"includePayloads"`
ReportPath string `mapstructure:"reportPath"`
ReportName string `mapstructure:"reportName"`
ReportFormat []string `mapstructure:"reportFormat"`
NoEmailReport bool `mapstructure:"noEmailReport"`
Email string `mapstructure:"email"`
WAFName string `mapstructure:"wafName"`
IncludePayloads bool `mapstructure:"includePayloads"`
ReportPath string `mapstructure:"reportPath"`
ReportName string `mapstructure:"reportName"`
ReportFormat []string `mapstructure:"reportFormat"`
NoEmailReport bool `mapstructure:"noEmailReport"`
Email string `mapstructure:"email"`
HideArgsInReport bool `mapstructure:"hideArgsInReport"`

// config.yaml
HTTPHeaders map[string]string `mapstructure:"headers"`
Expand Down
2 changes: 1 addition & 1 deletion pkg/report/html.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type HtmlReport struct {
GtwVersion string `json:"gtw_version" validate:"required,gtw_version"`
TestCasesFP string `json:"test_cases_fp" validate:"required,fp"`
OpenApiFile string `json:"open_api_file" validate:"omitempty,printascii,max=512"`
Args []string `json:"args" validate:"required,max=50,dive,args,max=200"`
Args []string `json:"args" validate:"omitempty,max=50,dive,args,max=200"`

ApiSecChartData struct {
Indicators []string `json:"indicators" validate:"omitempty,max=100,dive,indicator"`
Expand Down
2 changes: 2 additions & 0 deletions pkg/report/report_template.html
Original file line number Diff line number Diff line change
Expand Up @@ -399,10 +399,12 @@ <h4 class="grade__title">Overall grade:</h4>
<span class="row__content">{{.OpenApiFile}}</span>
<br>
{{end}}
{{$length := len $.Args}}{{if ne $length 0}}
<span class="row__name">Used arguments</span>
:
<span class="row__args mono">{{StringsJoin .Args " "}}</span>
<br>
{{end}}
</div>
</div>
<!--<div class="desc__text">
Expand Down
5 changes: 5 additions & 0 deletions pkg/report/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ func validateIndicator(fl validator.FieldLevel) bool {

func validateArgs(fl validator.FieldLevel) bool {
args := fl.Field().String()

if len(args) == 0 {
return true
}

result := argsRegex.MatchString(args)

return result
Expand Down
2 changes: 1 addition & 1 deletion pkg/report/validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ func TestCustomValidators(t *testing.T) {
{tag: "indicator", field: "ApiSecChartData.Indicators", setter: setIndicator, value: "some indicator (100.0%)", isBad: false},

// args, bad
{tag: "args", field: "Args", setter: setArgs, value: "", isBad: true},
{tag: "args", field: "Args", setter: setArgs, value: "", isBad: false},
{tag: "args", field: "Args", setter: setArgs, value: "lkajdf", isBad: true},
{tag: "args", field: "Args", setter: setArgs, value: "-a", isBad: true},
{tag: "args", field: "Args", setter: setArgs, value: "-lkajdf", isBad: true},
Expand Down

0 comments on commit 9088260

Please sign in to comment.