| 63 | } |
| 64 | |
| 65 | func createRule(name string) error { |
| 66 | data := struct { |
| 67 | *config.FilterConfig |
| 68 | MinEngineVersion string |
| 69 | }{ |
| 70 | &config.FilterConfig{ |
| 71 | Name: name, |
| 72 | ID: uuid.New().String(), |
| 73 | Version: "1.0.0", |
| 74 | }, |
| 75 | version.Get(), |
| 76 | } |
| 77 | |
| 78 | if tacticID != "" { |
| 79 | data.Labels = make(map[string]string) |
| 80 | data.Labels["tactic.id"] = tacticID |
| 81 | data.Labels["tactic.name"] = tactics[tacticID] |
| 82 | data.Labels["tactic.ref"] = fmt.Sprintf("https://attack.mitre.org/tactics/%s/", tacticID) |
| 83 | } |
| 84 | |
| 85 | tmpl, err := template.New("rule").Parse(ruleTemplate) |
| 86 | if err != nil { |
| 87 | return err |
| 88 | } |
| 89 | |
| 90 | n := fmt.Sprintf("%s.yml", strings.ReplaceAll(strings.ToLower(name), " ", "_")) |
| 91 | if tacticID != "" { |
| 92 | n = strings.ReplaceAll(strings.ToLower(tactics[tacticID]), " ", "_") + "_" + n |
| 93 | } |
| 94 | f, err := os.Create(n) |
| 95 | if err != nil { |
| 96 | return err |
| 97 | } |
| 98 | defer f.Close() |
| 99 | if err := tmpl.Execute(f, data); err != nil { |
| 100 | return err |
| 101 | } |
| 102 | |
| 103 | emo("%v created %s. Open the file and craft the rule condition, define an optional action, or fill out other attributes", emoji.Rocket, n) |
| 104 | |
| 105 | return nil |
| 106 | } |