github.com/kubeshop/testkube@v1.17.23/contrib/executor/zap/pkg/runner/zap.go (about) 1 package runner 2 3 import ( 4 "fmt" 5 "os" 6 "strings" 7 8 "github.com/creasty/defaults" 9 "gopkg.in/yaml.v3" 10 ) 11 12 type ApiOptions struct { 13 // target API definition, OpenAPI or SOAP, local file or URL 14 Target string `yaml:"target"` 15 // config file or URL to use to INFO, IGNORE or FAIL warnings 16 Config string `yaml:"config"` 17 // show debug messages 18 Debug bool `default:"false" yaml:"debug"` 19 // short output format - dont show PASSes or example URLs 20 Short bool `default:"false" yaml:"short"` 21 // minimum level to show: PASS, IGNORE, INFO, WARN or FAIL 22 Level string `default:"PASS" yaml:"level"` 23 // context file which will be loaded prior to scanning the target 24 Context string `yaml:"context"` 25 // username to use for authenticated scans - must be defined in the given context file 26 User string `yaml:"user"` 27 // delay in seconds to wait for passive scanning 28 Delay int `yaml:"delay"` 29 // max time in minutes to wait for ZAP to start and the passive scan to run 30 Time int `default:"0" yaml:"time"` 31 // ZAP command line options 32 ZapOptions string `yaml:"zap_options"` 33 // fail the scan on WARN issues, default true 34 FailOnWarn bool `default:"true" yaml:"fail_on_warn"` 35 // openapi, soap, or graphql 36 Format string `yaml:"format"` 37 // the hostname to override in the (remote) OpenAPI spec 38 Hostname string `yaml:"hostname"` 39 // safe mode this will skip the active scan and perform a baseline scan 40 Safe bool `default:"false" yaml:"safe"` 41 } 42 43 type BaselineOptions struct { 44 // target URL including the protocol 45 Target string `yaml:"target"` 46 // config file or URL to use to INFO, IGNORE or FAIL warnings 47 Config string `yaml:"config"` 48 // show debug messages 49 Debug bool `default:"false" yaml:"debug"` 50 // short output format - dont show PASSes or example URLs 51 Short bool `default:"false" yaml:"short"` 52 // minimum level to show: PASS, IGNORE, INFO, WARN or FAIL 53 Level string `default:"PASS" yaml:"level"` 54 // context file which will be loaded prior to scanning the target 55 Context string `yaml:"context"` 56 // username to use for authenticated scans - must be defined in the given context file 57 User string `yaml:"user"` 58 // delay in seconds to wait for passive scanning 59 Delay int `yaml:"delay"` 60 // max time in minutes to wait for ZAP to start and the passive scan to run 61 Time int `default:"0" yaml:"time"` 62 // use the Ajax spider in addition to the traditional one 63 Ajax bool `default:"false" yaml:"ajax"` 64 // ZAP command line options 65 ZapOptions string `yaml:"zap_options"` 66 // fail the scan on WARN issues, default true 67 FailOnWarn bool `default:"true" yaml:"fail_on_warn"` 68 // the number of minutes to spider for (default 1) 69 Minutes int `default:"1" yaml:"minutes"` 70 } 71 72 type FullOptions struct { 73 // target URL including the protocol 74 Target string `yaml:"target"` 75 // config file or URL to use to INFO, IGNORE or FAIL warnings 76 Config string `yaml:"config"` 77 // show debug messages 78 Debug bool `default:"false" yaml:"debug"` 79 // short output format - dont show PASSes or example URLs 80 Short bool `default:"false" yaml:"short"` 81 // minimum level to show: PASS, IGNORE, INFO, WARN or FAIL 82 Level string `default:"PASS" yaml:"level"` 83 // context file which will be loaded prior to scanning the target 84 Context string `yaml:"context"` 85 // username to use for authenticated scans - must be defined in the given context file 86 User string `yaml:"user"` 87 // delay in seconds to wait for passive scanning 88 Delay int `yaml:"delay"` 89 // max time in minutes to wait for ZAP to start and the passive scan to run 90 Time int `default:"0" yaml:"time"` 91 // use the Ajax spider in addition to the traditional one 92 Ajax bool `default:"false" yaml:"ajax"` 93 // ZAP command line options 94 ZapOptions string `yaml:"zap_options"` 95 // fail the scan on WARN issues, default true 96 FailOnWarn bool `default:"true" yaml:"fail_on_warn"` 97 // the number of minutes to spider for (default 1) 98 Minutes int `default:"1" yaml:"minutes"` 99 } 100 101 type Options struct { 102 API ApiOptions `yaml:"api"` 103 Baseline BaselineOptions `yaml:"baseline"` 104 Full FullOptions `yaml:"full"` 105 } 106 107 func (a *Options) UnmarshalYAML(yamlFile string) (err error) { 108 bytes, err := os.ReadFile(yamlFile) 109 if err != nil { 110 return err 111 } 112 113 if err := defaults.Set(a); err != nil { 114 return err 115 } 116 117 if err := yaml.Unmarshal(bytes, a); err != nil { 118 return err 119 } 120 121 return nil 122 } 123 124 func (a *Options) ToFullScanArgs(filename string) (args []string) { 125 args = []string{} 126 // don't fail on warnings 127 args = appendTargetArg(args, a.Full.Target) 128 args = appendConfigArg("full", args, a.Full.Config) 129 args = appendMinutesArg(args, a.Full.Minutes) 130 args = appendDebugArg(args, a.Full.Debug) 131 args = appendDelayArg(args, a.Full.Delay) 132 args = appendFailOnWarnArg(args, a.Full.FailOnWarn) 133 args = appendAjaxSpiderArg(args, a.Full.Ajax) 134 args = appendLevelArg(args, a.Full.Level) 135 args = appendContextArg(args, a.Full.Context) 136 args = appendShortArg(args, a.Full.Short) 137 args = appendTimeArg(args, a.Full.Time) 138 args = appendUserArg(args, a.Full.User) 139 args = appendZapOptionsArg(args, a.Full.ZapOptions) 140 args = appendReportArg(args, filename) 141 return args 142 } 143 144 func (a *Options) ToBaselineScanArgs(filename string) (args []string) { 145 args = []string{} 146 // don't fail on warnings 147 args = appendTargetArg(args, a.Baseline.Target) 148 args = appendConfigArg("baseline", args, a.Baseline.Config) 149 args = appendMinutesArg(args, a.Baseline.Minutes) 150 args = appendDebugArg(args, a.Baseline.Debug) 151 args = appendDelayArg(args, a.Baseline.Delay) 152 args = appendFailOnWarnArg(args, a.Baseline.FailOnWarn) 153 args = appendAjaxSpiderArg(args, a.Baseline.Ajax) 154 args = appendLevelArg(args, a.Baseline.Level) 155 args = appendContextArg(args, a.Baseline.Context) 156 args = appendShortArg(args, a.Baseline.Short) 157 args = appendTimeArg(args, a.Baseline.Time) 158 args = appendUserArg(args, a.Baseline.User) 159 args = appendZapOptionsArg(args, a.Baseline.ZapOptions) 160 args = appendReportArg(args, filename) 161 args = append(args, "--auto") 162 return args 163 } 164 165 func (a *Options) ToApiScanArgs(filename string) (args []string) { 166 args = []string{} 167 // don't fail on warnings 168 args = appendTargetArg(args, a.API.Target) 169 args = appendFormatArg(args, a.API.Format) 170 args = appendConfigArg("api", args, a.API.Config) 171 args = appendDebugArg(args, a.API.Debug) 172 args = appendDelayArg(args, a.API.Delay) 173 args = appendFailOnWarnArg(args, a.API.FailOnWarn) 174 args = appendLevelArg(args, a.API.Level) 175 args = appendContextArg(args, a.API.Context) 176 args = appendShortArg(args, a.API.Short) 177 args = appendSafeArg(args, a.API.Safe) 178 args = appendTimeArg(args, a.API.Time) 179 args = appendUserArg(args, a.API.User) 180 args = appendHostnameArg(args, a.API.Hostname) 181 args = appendZapOptionsArg(args, a.API.ZapOptions) 182 args = appendReportArg(args, filename) 183 return args 184 } 185 186 func appendTargetArg(args []string, target string) []string { 187 return appendStringArg(args, "-t", target) 188 } 189 190 func appendFormatArg(args []string, format string) []string { 191 return appendStringArg(args, "-f", format) 192 } 193 194 func appendContextArg(args []string, context string) []string { 195 return appendStringArg(args, "-n", context) 196 } 197 198 func appendUserArg(args []string, user string) []string { 199 return appendStringArg(args, "-U", user) 200 } 201 202 func appendLevelArg(args []string, level string) []string { 203 return appendStringArg(args, "-l", level) 204 } 205 206 func appendHostnameArg(args []string, hostname string) []string { 207 return appendStringArg(args, "-O", hostname) 208 } 209 210 func appendReportArg(args []string, filename string) []string { 211 return appendStringArg(args, "-r", filename) 212 } 213 214 func appendZapOptionsArg(args []string, options string) []string { 215 return appendStringArg(args, "-z", options) 216 } 217 218 func appendStringArg(args []string, arg string, value string) []string { 219 if len(value) > 0 { 220 return append(args, arg, value) 221 } else { 222 return args 223 } 224 } 225 226 func appendConfigArg(t string, args []string, format string) []string { 227 if len(format) == 0 { 228 return args 229 } 230 231 if strings.Index(format, "http") == 0 { 232 return append(args, "-u", format) 233 } 234 235 if t == "api" { 236 return append(args, "-z", format) 237 } 238 return append(args, "-c", format) 239 } 240 241 func appendDebugArg(args []string, debug bool) []string { 242 return appendBoolArg(args, "-d", debug) 243 } 244 245 func appendShortArg(args []string, short bool) []string { 246 return appendBoolArg(args, "-s", short) 247 } 248 249 func appendSafeArg(args []string, safe bool) []string { 250 return appendBoolArg(args, "-S", safe) 251 } 252 253 func appendFailOnWarnArg(args []string, failOnWarn bool) []string { 254 return appendBoolArg(args, "-I", !failOnWarn) 255 } 256 257 func appendAjaxSpiderArg(args []string, ajax bool) []string { 258 return appendBoolArg(args, "-j", ajax) 259 } 260 261 func appendBoolArg(args []string, arg string, flag bool) []string { 262 if flag { 263 return append(args, arg) 264 } else { 265 return args 266 } 267 } 268 269 func appendMinutesArg(args []string, minutes int) []string { 270 return appendIntArg(args, "-m", minutes) 271 } 272 273 func appendTimeArg(args []string, time int) []string { 274 return appendIntArg(args, "-T", time) 275 } 276 277 func appendDelayArg(args []string, delay int) []string { 278 return appendIntArg(args, "-D", delay) 279 } 280 281 func appendIntArg(args []string, arg string, value int) []string { 282 if value > 0 { 283 return append(args, arg, fmt.Sprint(value)) 284 } else { 285 return args 286 } 287 }