github.com/crowdsecurity/crowdsec@v1.6.1/pkg/hubtest/hubtest_item.go (about) 1 package hubtest 2 3 import ( 4 "errors" 5 "fmt" 6 "net/url" 7 "os" 8 "os/exec" 9 "path/filepath" 10 "strings" 11 12 log "github.com/sirupsen/logrus" 13 "gopkg.in/yaml.v2" 14 15 "github.com/crowdsecurity/crowdsec/pkg/csconfig" 16 "github.com/crowdsecurity/crowdsec/pkg/cwhub" 17 "github.com/crowdsecurity/crowdsec/pkg/parser" 18 ) 19 20 type HubTestItemConfig struct { 21 Parsers []string `yaml:"parsers,omitempty"` 22 Scenarios []string `yaml:"scenarios,omitempty"` 23 PostOverflows []string `yaml:"postoverflows,omitempty"` 24 AppsecRules []string `yaml:"appsec-rules,omitempty"` 25 NucleiTemplate string `yaml:"nuclei_template,omitempty"` 26 ExpectedNucleiFailure bool `yaml:"expect_failure,omitempty"` 27 LogFile string `yaml:"log_file,omitempty"` 28 LogType string `yaml:"log_type,omitempty"` 29 Labels map[string]string `yaml:"labels,omitempty"` 30 IgnoreParsers bool `yaml:"ignore_parsers,omitempty"` // if we test a scenario, we don't want to assert on Parser 31 OverrideStatics []parser.ExtraField `yaml:"override_statics,omitempty"` //Allow to override statics. Executed before s00 32 } 33 34 type HubTestItem struct { 35 Name string 36 Path string 37 38 CrowdSecPath string 39 CscliPath string 40 41 RuntimePath string 42 RuntimeHubPath string 43 RuntimeDataPath string 44 RuntimePatternsPath string 45 RuntimeConfigFilePath string 46 RuntimeProfileFilePath string 47 RuntimeSimulationFilePath string 48 RuntimeAcquisFilePath string 49 RuntimeHubConfig *csconfig.LocalHubCfg 50 51 ResultsPath string 52 ParserResultFile string 53 ScenarioResultFile string 54 BucketPourResultFile string 55 56 HubPath string 57 HubTestPath string 58 HubIndexFile string 59 TemplateConfigPath string 60 TemplateProfilePath string 61 TemplateSimulationPath string 62 TemplateAcquisPath string 63 TemplateAppsecProfilePath string 64 HubIndex *cwhub.Hub 65 66 Config *HubTestItemConfig 67 68 Success bool 69 ErrorsList []string 70 71 AutoGen bool 72 ParserAssert *ParserAssert 73 ScenarioAssert *ScenarioAssert 74 75 CustomItemsLocation []string 76 77 NucleiTargetHost string 78 AppSecHost string 79 } 80 81 const ( 82 ParserAssertFileName = "parser.assert" 83 ParserResultFileName = "parser-dump.yaml" 84 85 ScenarioAssertFileName = "scenario.assert" 86 ScenarioResultFileName = "bucket-dump.yaml" 87 88 BucketPourResultFileName = "bucketpour-dump.yaml" 89 90 TestBouncerApiKey = "this_is_a_bad_password" 91 92 DefaultNucleiTarget = "http://127.0.0.1:7822/" 93 DefaultAppsecHost = "127.0.0.1:4241" 94 ) 95 96 func NewTest(name string, hubTest *HubTest) (*HubTestItem, error) { 97 testPath := filepath.Join(hubTest.HubTestPath, name) 98 runtimeFolder := filepath.Join(testPath, "runtime") 99 runtimeHubFolder := filepath.Join(runtimeFolder, "hub") 100 configFilePath := filepath.Join(testPath, "config.yaml") 101 resultPath := filepath.Join(testPath, "results") 102 103 // read test configuration file 104 configFileData := &HubTestItemConfig{} 105 106 yamlFile, err := os.ReadFile(configFilePath) 107 if err != nil { 108 log.Printf("no config file found in '%s': %v", testPath, err) 109 } 110 111 err = yaml.Unmarshal(yamlFile, configFileData) 112 if err != nil { 113 return nil, fmt.Errorf("unmarshal: %v", err) 114 } 115 116 parserAssertFilePath := filepath.Join(testPath, ParserAssertFileName) 117 ParserAssert := NewParserAssert(parserAssertFilePath) 118 119 scenarioAssertFilePath := filepath.Join(testPath, ScenarioAssertFileName) 120 ScenarioAssert := NewScenarioAssert(scenarioAssertFilePath) 121 122 return &HubTestItem{ 123 Name: name, 124 Path: testPath, 125 CrowdSecPath: hubTest.CrowdSecPath, 126 CscliPath: hubTest.CscliPath, 127 RuntimePath: filepath.Join(testPath, "runtime"), 128 RuntimeHubPath: runtimeHubFolder, 129 RuntimeDataPath: filepath.Join(runtimeFolder, "data"), 130 RuntimePatternsPath: filepath.Join(runtimeFolder, "patterns"), 131 RuntimeConfigFilePath: filepath.Join(runtimeFolder, "config.yaml"), 132 RuntimeProfileFilePath: filepath.Join(runtimeFolder, "profiles.yaml"), 133 RuntimeSimulationFilePath: filepath.Join(runtimeFolder, "simulation.yaml"), 134 RuntimeAcquisFilePath: filepath.Join(runtimeFolder, "acquis.yaml"), 135 ResultsPath: resultPath, 136 ParserResultFile: filepath.Join(resultPath, ParserResultFileName), 137 ScenarioResultFile: filepath.Join(resultPath, ScenarioResultFileName), 138 BucketPourResultFile: filepath.Join(resultPath, BucketPourResultFileName), 139 RuntimeHubConfig: &csconfig.LocalHubCfg{ 140 HubDir: runtimeHubFolder, 141 HubIndexFile: hubTest.HubIndexFile, 142 InstallDir: runtimeFolder, 143 InstallDataDir: filepath.Join(runtimeFolder, "data"), 144 }, 145 Config: configFileData, 146 HubPath: hubTest.HubPath, 147 HubTestPath: hubTest.HubTestPath, 148 HubIndexFile: hubTest.HubIndexFile, 149 TemplateConfigPath: hubTest.TemplateConfigPath, 150 TemplateProfilePath: hubTest.TemplateProfilePath, 151 TemplateSimulationPath: hubTest.TemplateSimulationPath, 152 TemplateAcquisPath: hubTest.TemplateAcquisPath, 153 TemplateAppsecProfilePath: hubTest.TemplateAppsecProfilePath, 154 HubIndex: hubTest.HubIndex, 155 ScenarioAssert: ScenarioAssert, 156 ParserAssert: ParserAssert, 157 CustomItemsLocation: []string{hubTest.HubPath, testPath}, 158 NucleiTargetHost: hubTest.NucleiTargetHost, 159 AppSecHost: hubTest.AppSecHost, 160 }, nil 161 } 162 163 func (t *HubTestItem) installHubItems(names []string, installFunc func(string) error) error { 164 for _, name := range names { 165 if name == "" { 166 continue 167 } 168 169 if err := installFunc(name); err != nil { 170 return err 171 } 172 } 173 174 return nil 175 } 176 177 func (t *HubTestItem) InstallHub() error { 178 if err := t.installHubItems(t.Config.Parsers, t.installParser); err != nil { 179 return err 180 } 181 182 if err := t.installHubItems(t.Config.Scenarios, t.installScenario); err != nil { 183 return err 184 } 185 186 if err := t.installHubItems(t.Config.PostOverflows, t.installPostoverflow); err != nil { 187 return err 188 } 189 190 if err := t.installHubItems(t.Config.AppsecRules, t.installAppsecRule); err != nil { 191 return err 192 } 193 194 if len(t.Config.OverrideStatics) > 0 { 195 n := parser.Node{ 196 Name: "overrides", 197 Filter: "1==1", 198 Statics: t.Config.OverrideStatics, 199 } 200 201 b, err := yaml.Marshal(n) 202 if err != nil { 203 return fmt.Errorf("unable to marshal overrides: %s", err) 204 } 205 206 tgtFilename := fmt.Sprintf("%s/parsers/s00-raw/00_overrides.yaml", t.RuntimePath) 207 if err := os.WriteFile(tgtFilename, b, os.ModePerm); err != nil { 208 return fmt.Errorf("unable to write overrides to '%s': %s", tgtFilename, err) 209 } 210 } 211 212 // load installed hub 213 hub, err := cwhub.NewHub(t.RuntimeHubConfig, nil, false, nil) 214 if err != nil { 215 log.Fatal(err) 216 } 217 218 // install data for parsers if needed 219 ret := hub.GetItemMap(cwhub.PARSERS) 220 for parserName, item := range ret { 221 if item.State.Installed { 222 if err := item.DownloadDataIfNeeded(true); err != nil { 223 return fmt.Errorf("unable to download data for parser '%s': %+v", parserName, err) 224 } 225 226 log.Debugf("parser '%s' installed successfully in runtime environment", parserName) 227 } 228 } 229 230 // install data for scenarios if needed 231 ret = hub.GetItemMap(cwhub.SCENARIOS) 232 for scenarioName, item := range ret { 233 if item.State.Installed { 234 if err := item.DownloadDataIfNeeded(true); err != nil { 235 return fmt.Errorf("unable to download data for parser '%s': %+v", scenarioName, err) 236 } 237 238 log.Debugf("scenario '%s' installed successfully in runtime environment", scenarioName) 239 } 240 } 241 242 // install data for postoverflows if needed 243 ret = hub.GetItemMap(cwhub.POSTOVERFLOWS) 244 for postoverflowName, item := range ret { 245 if item.State.Installed { 246 if err := item.DownloadDataIfNeeded(true); err != nil { 247 return fmt.Errorf("unable to download data for parser '%s': %+v", postoverflowName, err) 248 } 249 250 log.Debugf("postoverflow '%s' installed successfully in runtime environment", postoverflowName) 251 } 252 } 253 254 return nil 255 } 256 257 func (t *HubTestItem) Clean() error { 258 return os.RemoveAll(t.RuntimePath) 259 } 260 261 func (t *HubTestItem) RunWithNucleiTemplate() error { 262 crowdsecLogFile := fmt.Sprintf("%s/log/crowdsec.log", t.RuntimePath) 263 264 testPath := filepath.Join(t.HubTestPath, t.Name) 265 if _, err := os.Stat(testPath); os.IsNotExist(err) { 266 return fmt.Errorf("test '%s' doesn't exist in '%s', exiting", t.Name, t.HubTestPath) 267 } 268 269 if err := os.Chdir(testPath); err != nil { 270 return fmt.Errorf("can't 'cd' to '%s': %s", testPath, err) 271 } 272 273 //machine add 274 cmdArgs := []string{"-c", t.RuntimeConfigFilePath, "machines", "add", "testMachine", "--force", "--auto"} 275 cscliRegisterCmd := exec.Command(t.CscliPath, cmdArgs...) 276 277 output, err := cscliRegisterCmd.CombinedOutput() 278 if err != nil { 279 if !strings.Contains(string(output), "unable to create machine: user 'testMachine': user already exist") { 280 fmt.Println(string(output)) 281 return fmt.Errorf("fail to run '%s' for test '%s': %v", cscliRegisterCmd.String(), t.Name, err) 282 } 283 } 284 285 //hardcode bouncer key 286 cmdArgs = []string{"-c", t.RuntimeConfigFilePath, "bouncers", "add", "appsectests", "-k", TestBouncerApiKey} 287 cscliBouncerCmd := exec.Command(t.CscliPath, cmdArgs...) 288 289 output, err = cscliBouncerCmd.CombinedOutput() 290 if err != nil { 291 if !strings.Contains(string(output), "unable to create bouncer: bouncer appsectests already exists") { 292 fmt.Println(string(output)) 293 return fmt.Errorf("fail to run '%s' for test '%s': %v", cscliRegisterCmd.String(), t.Name, err) 294 } 295 } 296 297 //start crowdsec service 298 cmdArgs = []string{"-c", t.RuntimeConfigFilePath} 299 crowdsecDaemon := exec.Command(t.CrowdSecPath, cmdArgs...) 300 301 crowdsecDaemon.Start() 302 303 //wait for the appsec port to be available 304 if _, err := IsAlive(t.AppSecHost); err != nil { 305 crowdsecLog, err2 := os.ReadFile(crowdsecLogFile) 306 if err2 != nil { 307 log.Errorf("unable to read crowdsec log file '%s': %s", crowdsecLogFile, err) 308 } else { 309 log.Errorf("crowdsec log file '%s'", crowdsecLogFile) 310 log.Errorf("%s\n", string(crowdsecLog)) 311 } 312 313 return fmt.Errorf("appsec is down: %s", err) 314 } 315 316 // check if the target is available 317 nucleiTargetParsedURL, err := url.Parse(t.NucleiTargetHost) 318 if err != nil { 319 return fmt.Errorf("unable to parse target '%s': %s", t.NucleiTargetHost, err) 320 } 321 322 nucleiTargetHost := nucleiTargetParsedURL.Host 323 if _, err := IsAlive(nucleiTargetHost); err != nil { 324 return fmt.Errorf("target is down: %s", err) 325 } 326 327 nucleiConfig := NucleiConfig{ 328 Path: "nuclei", 329 OutputDir: t.RuntimePath, 330 CmdLineOptions: []string{"-ev", //allow variables from environment 331 "-nc", //no colors in output 332 "-dresp", //dump response 333 "-j", //json output 334 }, 335 } 336 337 err = nucleiConfig.RunNucleiTemplate(t.Name, t.Config.NucleiTemplate, t.NucleiTargetHost) 338 if t.Config.ExpectedNucleiFailure { 339 if err != nil && errors.Is(err, ErrNucleiTemplateFail) { 340 log.Infof("Appsec test %s failed as expected", t.Name) 341 t.Success = true 342 } else { 343 log.Errorf("Appsec test %s failed: %s", t.Name, err) 344 crowdsecLog, err := os.ReadFile(crowdsecLogFile) 345 if err != nil { 346 log.Errorf("unable to read crowdsec log file '%s': %s", crowdsecLogFile, err) 347 } else { 348 log.Errorf("crowdsec log file '%s'", crowdsecLogFile) 349 log.Errorf("%s\n", string(crowdsecLog)) 350 } 351 } 352 } else { 353 if err == nil { 354 log.Infof("Appsec test %s succeeded", t.Name) 355 t.Success = true 356 } else { 357 log.Errorf("Appsec test %s failed: %s", t.Name, err) 358 crowdsecLog, err := os.ReadFile(crowdsecLogFile) 359 if err != nil { 360 log.Errorf("unable to read crowdsec log file '%s': %s", crowdsecLogFile, err) 361 } else { 362 log.Errorf("crowdsec log file '%s'", crowdsecLogFile) 363 log.Errorf("%s\n", string(crowdsecLog)) 364 } 365 } 366 } 367 368 crowdsecDaemon.Process.Kill() 369 370 return nil 371 } 372 373 func (t *HubTestItem) RunWithLogFile() error { 374 testPath := filepath.Join(t.HubTestPath, t.Name) 375 if _, err := os.Stat(testPath); os.IsNotExist(err) { 376 return fmt.Errorf("test '%s' doesn't exist in '%s', exiting", t.Name, t.HubTestPath) 377 } 378 379 currentDir, err := os.Getwd() //xx 380 if err != nil { 381 return fmt.Errorf("can't get current directory: %+v", err) 382 } 383 384 // create runtime folder 385 if err = os.MkdirAll(t.RuntimePath, os.ModePerm); err != nil { 386 return fmt.Errorf("unable to create folder '%s': %+v", t.RuntimePath, err) 387 } 388 389 // create runtime data folder 390 if err = os.MkdirAll(t.RuntimeDataPath, os.ModePerm); err != nil { 391 return fmt.Errorf("unable to create folder '%s': %+v", t.RuntimeDataPath, err) 392 } 393 394 // create runtime hub folder 395 if err = os.MkdirAll(t.RuntimeHubPath, os.ModePerm); err != nil { 396 return fmt.Errorf("unable to create folder '%s': %+v", t.RuntimeHubPath, err) 397 } 398 399 if err = Copy(t.HubIndexFile, filepath.Join(t.RuntimeHubPath, ".index.json")); err != nil { 400 return fmt.Errorf("unable to copy .index.json file in '%s': %s", filepath.Join(t.RuntimeHubPath, ".index.json"), err) 401 } 402 403 // create results folder 404 if err = os.MkdirAll(t.ResultsPath, os.ModePerm); err != nil { 405 return fmt.Errorf("unable to create folder '%s': %+v", t.ResultsPath, err) 406 } 407 408 // copy template config file to runtime folder 409 if err = Copy(t.TemplateConfigPath, t.RuntimeConfigFilePath); err != nil { 410 return fmt.Errorf("unable to copy '%s' to '%s': %v", t.TemplateConfigPath, t.RuntimeConfigFilePath, err) 411 } 412 413 // copy template profile file to runtime folder 414 if err = Copy(t.TemplateProfilePath, t.RuntimeProfileFilePath); err != nil { 415 return fmt.Errorf("unable to copy '%s' to '%s': %v", t.TemplateProfilePath, t.RuntimeProfileFilePath, err) 416 } 417 418 // copy template simulation file to runtime folder 419 if err = Copy(t.TemplateSimulationPath, t.RuntimeSimulationFilePath); err != nil { 420 return fmt.Errorf("unable to copy '%s' to '%s': %v", t.TemplateSimulationPath, t.RuntimeSimulationFilePath, err) 421 } 422 423 crowdsecPatternsFolder := csconfig.DefaultConfigPath("patterns") 424 425 // copy template patterns folder to runtime folder 426 if err = CopyDir(crowdsecPatternsFolder, t.RuntimePatternsPath); err != nil { 427 return fmt.Errorf("unable to copy 'patterns' from '%s' to '%s': %s", crowdsecPatternsFolder, t.RuntimePatternsPath, err) 428 } 429 430 // install the hub in the runtime folder 431 if err = t.InstallHub(); err != nil { 432 return fmt.Errorf("unable to install hub in '%s': %s", t.RuntimeHubPath, err) 433 } 434 435 logFile := t.Config.LogFile 436 logType := t.Config.LogType 437 dsn := fmt.Sprintf("file://%s", logFile) 438 439 if err = os.Chdir(testPath); err != nil { 440 return fmt.Errorf("can't 'cd' to '%s': %s", testPath, err) 441 } 442 443 logFileStat, err := os.Stat(logFile) 444 if err != nil { 445 return fmt.Errorf("unable to stat log file '%s': %s", logFile, err) 446 } 447 448 if logFileStat.Size() == 0 { 449 return fmt.Errorf("log file '%s' is empty, please fill it with log", logFile) 450 } 451 452 cmdArgs := []string{"-c", t.RuntimeConfigFilePath, "machines", "add", "testMachine", "--force", "--auto"} 453 cscliRegisterCmd := exec.Command(t.CscliPath, cmdArgs...) 454 log.Debugf("%s", cscliRegisterCmd.String()) 455 456 output, err := cscliRegisterCmd.CombinedOutput() 457 if err != nil { 458 if !strings.Contains(string(output), "unable to create machine: user 'testMachine': user already exist") { 459 fmt.Println(string(output)) 460 return fmt.Errorf("fail to run '%s' for test '%s': %v", cscliRegisterCmd.String(), t.Name, err) 461 } 462 } 463 464 cmdArgs = []string{"-c", t.RuntimeConfigFilePath, "-type", logType, "-dsn", dsn, "-dump-data", t.ResultsPath, "-order-event"} 465 466 for labelKey, labelValue := range t.Config.Labels { 467 arg := fmt.Sprintf("%s:%s", labelKey, labelValue) 468 cmdArgs = append(cmdArgs, "-label", arg) 469 } 470 471 crowdsecCmd := exec.Command(t.CrowdSecPath, cmdArgs...) 472 log.Debugf("%s", crowdsecCmd.String()) 473 output, err = crowdsecCmd.CombinedOutput() 474 475 if log.GetLevel() >= log.DebugLevel || err != nil { 476 fmt.Println(string(output)) 477 } 478 479 if err != nil { 480 return fmt.Errorf("fail to run '%s' for test '%s': %v", crowdsecCmd.String(), t.Name, err) 481 } 482 483 if err := os.Chdir(currentDir); err != nil { 484 return fmt.Errorf("can't 'cd' to '%s': %s", currentDir, err) 485 } 486 487 // assert parsers 488 if !t.Config.IgnoreParsers { 489 _, err := os.Stat(t.ParserAssert.File) 490 if os.IsNotExist(err) { 491 parserAssertFile, err := os.Create(t.ParserAssert.File) 492 if err != nil { 493 return err 494 } 495 496 parserAssertFile.Close() 497 } 498 499 assertFileStat, err := os.Stat(t.ParserAssert.File) 500 if err != nil { 501 return fmt.Errorf("error while stats '%s': %s", t.ParserAssert.File, err) 502 } 503 504 if assertFileStat.Size() == 0 { 505 assertData, err := t.ParserAssert.AutoGenFromFile(t.ParserResultFile) 506 if err != nil { 507 return fmt.Errorf("couldn't generate assertion: %s", err) 508 } 509 510 t.ParserAssert.AutoGenAssertData = assertData 511 t.ParserAssert.AutoGenAssert = true 512 } else { 513 if err := t.ParserAssert.AssertFile(t.ParserResultFile); err != nil { 514 return fmt.Errorf("unable to run assertion on file '%s': %s", t.ParserResultFile, err) 515 } 516 } 517 } 518 519 // assert scenarios 520 nbScenario := 0 521 522 for _, scenario := range t.Config.Scenarios { 523 if scenario == "" { 524 continue 525 } 526 527 nbScenario++ 528 } 529 530 if nbScenario > 0 { 531 _, err := os.Stat(t.ScenarioAssert.File) 532 if os.IsNotExist(err) { 533 scenarioAssertFile, err := os.Create(t.ScenarioAssert.File) 534 if err != nil { 535 return err 536 } 537 538 scenarioAssertFile.Close() 539 } 540 541 assertFileStat, err := os.Stat(t.ScenarioAssert.File) 542 if err != nil { 543 return fmt.Errorf("error while stats '%s': %s", t.ScenarioAssert.File, err) 544 } 545 546 if assertFileStat.Size() == 0 { 547 assertData, err := t.ScenarioAssert.AutoGenFromFile(t.ScenarioResultFile) 548 if err != nil { 549 return fmt.Errorf("couldn't generate assertion: %s", err) 550 } 551 552 t.ScenarioAssert.AutoGenAssertData = assertData 553 t.ScenarioAssert.AutoGenAssert = true 554 } else { 555 if err := t.ScenarioAssert.AssertFile(t.ScenarioResultFile); err != nil { 556 return fmt.Errorf("unable to run assertion on file '%s': %s", t.ScenarioResultFile, err) 557 } 558 } 559 } 560 561 if t.ParserAssert.AutoGenAssert || t.ScenarioAssert.AutoGenAssert { 562 t.AutoGen = true 563 } 564 565 if (t.ParserAssert.Success || t.Config.IgnoreParsers) && (nbScenario == 0 || t.ScenarioAssert.Success) { 566 t.Success = true 567 } 568 569 return nil 570 } 571 572 func (t *HubTestItem) Run() error { 573 var err error 574 575 t.Success = false 576 t.ErrorsList = make([]string, 0) 577 578 // create runtime folder 579 if err = os.MkdirAll(t.RuntimePath, os.ModePerm); err != nil { 580 return fmt.Errorf("unable to create folder '%s': %+v", t.RuntimePath, err) 581 } 582 583 // create runtime data folder 584 if err = os.MkdirAll(t.RuntimeDataPath, os.ModePerm); err != nil { 585 return fmt.Errorf("unable to create folder '%s': %+v", t.RuntimeDataPath, err) 586 } 587 588 // create runtime hub folder 589 if err = os.MkdirAll(t.RuntimeHubPath, os.ModePerm); err != nil { 590 return fmt.Errorf("unable to create folder '%s': %+v", t.RuntimeHubPath, err) 591 } 592 593 if err = Copy(t.HubIndexFile, filepath.Join(t.RuntimeHubPath, ".index.json")); err != nil { 594 return fmt.Errorf("unable to copy .index.json file in '%s': %s", filepath.Join(t.RuntimeHubPath, ".index.json"), err) 595 } 596 597 // create results folder 598 if err = os.MkdirAll(t.ResultsPath, os.ModePerm); err != nil { 599 return fmt.Errorf("unable to create folder '%s': %+v", t.ResultsPath, err) 600 } 601 602 // copy template config file to runtime folder 603 if err = Copy(t.TemplateConfigPath, t.RuntimeConfigFilePath); err != nil { 604 return fmt.Errorf("unable to copy '%s' to '%s': %v", t.TemplateConfigPath, t.RuntimeConfigFilePath, err) 605 } 606 607 // copy template profile file to runtime folder 608 if err = Copy(t.TemplateProfilePath, t.RuntimeProfileFilePath); err != nil { 609 return fmt.Errorf("unable to copy '%s' to '%s': %v", t.TemplateProfilePath, t.RuntimeProfileFilePath, err) 610 } 611 612 // copy template simulation file to runtime folder 613 if err = Copy(t.TemplateSimulationPath, t.RuntimeSimulationFilePath); err != nil { 614 return fmt.Errorf("unable to copy '%s' to '%s': %v", t.TemplateSimulationPath, t.RuntimeSimulationFilePath, err) 615 } 616 617 crowdsecPatternsFolder := csconfig.DefaultConfigPath("patterns") 618 619 // copy template patterns folder to runtime folder 620 if err = CopyDir(crowdsecPatternsFolder, t.RuntimePatternsPath); err != nil { 621 return fmt.Errorf("unable to copy 'patterns' from '%s' to '%s': %s", crowdsecPatternsFolder, t.RuntimePatternsPath, err) 622 } 623 624 // create the appsec-configs dir 625 if err = os.MkdirAll(filepath.Join(t.RuntimePath, "appsec-configs"), os.ModePerm); err != nil { 626 return fmt.Errorf("unable to create folder '%s': %+v", t.RuntimePath, err) 627 } 628 629 //if it's an appsec rule test, we need acquis and appsec profile 630 if len(t.Config.AppsecRules) > 0 { 631 // copy template acquis file to runtime folder 632 log.Debugf("copying %s to %s", t.TemplateAcquisPath, t.RuntimeAcquisFilePath) 633 634 if err = Copy(t.TemplateAcquisPath, t.RuntimeAcquisFilePath); err != nil { 635 return fmt.Errorf("unable to copy '%s' to '%s': %v", t.TemplateAcquisPath, t.RuntimeAcquisFilePath, err) 636 } 637 638 log.Debugf("copying %s to %s", t.TemplateAppsecProfilePath, filepath.Join(t.RuntimePath, "appsec-configs", "config.yaml")) 639 // copy template appsec-config file to runtime folder 640 if err = Copy(t.TemplateAppsecProfilePath, filepath.Join(t.RuntimePath, "appsec-configs", "config.yaml")); err != nil { 641 return fmt.Errorf("unable to copy '%s' to '%s': %v", t.TemplateAppsecProfilePath, filepath.Join(t.RuntimePath, "appsec-configs", "config.yaml"), err) 642 } 643 } else { //otherwise we drop a blank acquis file 644 if err = os.WriteFile(t.RuntimeAcquisFilePath, []byte(""), os.ModePerm); err != nil { 645 return fmt.Errorf("unable to write blank acquis file '%s': %s", t.RuntimeAcquisFilePath, err) 646 } 647 } 648 649 // install the hub in the runtime folder 650 if err = t.InstallHub(); err != nil { 651 return fmt.Errorf("unable to install hub in '%s': %s", t.RuntimeHubPath, err) 652 } 653 654 if t.Config.LogFile != "" { 655 return t.RunWithLogFile() 656 } else if t.Config.NucleiTemplate != "" { 657 return t.RunWithNucleiTemplate() 658 } else { 659 return fmt.Errorf("log file or nuclei template must be set in '%s'", t.Name) 660 } 661 }