forked from ppll0p1s/SigmaShooter
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsigmaShooter.go
226 lines (195 loc) · 5.31 KB
/
sigmaShooter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
package main
import (
"fmt"
"log"
"strconv"
"strings"
"bufio"
"io"
"os/exec"
"os"
"SigmaShooter/web"
)
const (
version = "v0.01"
)
// Main function
func main() {
// Init log headers
log.SetPrefix("[●] ")
log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds)
// Read config file
config, err := ReadConfig(`sigmaShooter.conf`)
if err != nil {
log.Println(err)
}
// Write log file
logDir := config["logDir"]
f, err := os.OpenFile(logDir, os.O_RDWR | os.O_CREATE | os.O_APPEND, 0666)
if err != nil {
log.Println("main: error opening log path or file: " + err.Error())
}
defer f.Close()
log.SetOutput(f)
log.Printf("Starting SigmaShooter server %s", version)
// Check requirements
check, repo := checkRequirements(config)
if check == "" {
log.Println("checkRequirements: checking reqs... OK")
} else {
fmt.Println("main: checking reqs... FAIL.\nCheck requirements to run the app. \nChecks: " + check)
log.Fatal("main: checking reqs... FAIL.\nCheck requirements to run the app. \nChecks: " + check)
}
// Set variables from config
addr := config["addr"]
port := config["port"]
// Set variables for web handler
web.RulePath = config["rulePath"]
web.RuleBakPath = config["ruleBakPath"]
if repo {
web.Repo = true
} else {
if config["siem"] == "graylog" {
web.Version = version
web.Siem = config["siem"]
web.SiemAddr = config["siemAddr"]
web.SiemPortApi = config["siemPortApi"]
web.SiemUrlApi = config["siemUrlApi"]
web.SiemToken = config["siemToken"]
siemPortInputu64, err := strconv.ParseUint(config["siemPortInput"], 10, 64)
if err != nil {
log.Println("main - SiemPortInput "+err.Error())
}
web.SiemPortInput = uint(siemPortInputu64)
} else if config["siem"] == "X" {
log.Println("In construction...")
os.Exit(3)
} else {
log.Println("In construction...")
os.Exit(3)
}
}
// Start Web router goroutine
web.Router(addr, port)
}
// ====================
// = Helper functions =
// ====================
// ReadConfig: read variables from sigmaShooter.conf file
type Config map[string]string
func ReadConfig(filename string) (Config, error) {
// init with some bogus data
config := Config{
"addr": "",
"port": "",
"repo": "",
"rulePath": "",
"ruleBakPath": "",
"logDir": "",
"siem": "",
"siemAddr": "",
"siemPortApi": "",
"siemUrlApi": "",
"siemPortInput": "",
"siemToken": "",
}
if len(filename) == 0 {
return config, nil
}
file, err := os.Open(filename)
if err != nil {
return nil, err
}
defer file.Close()
reader := bufio.NewReader(file)
for {
line, err := reader.ReadString('\n')
// check if the line has = sign
// and process the line. Ignore the rest.
if equal := strings.Index(line, "="); equal >= 0 {
if key := strings.TrimSpace(line[:equal]); len(key) > 0 {
value := ""
if len(line) > equal {
value = strings.TrimSpace(line[equal+1:])
}
// assign the config map
config[key] = value
}
}
if err == io.EOF {
break
}
if err != nil {
return nil, err
}
}
return config, nil
}
// checkRequirements: check requirements to run the app correctly
func checkRequirements(config Config) (string, bool) {
log.Println("checkRequirements: checking reqs...")
check := ""
repo := false
// Check requirements.txt
// NOTE: Check commands will return errors, but we assume them to check if the command is in the system or not.
// sigmac command
_, err := exec.Command("sigmac").Output()
if err != nil {
if strings.Contains(err.Error(), "executable file not found") {
check = check + "ERROR: sigmac not found.\n"
}
}
// Check config vars
if config["addr"] == "" {
check = check + "ERROR: addr empty value.\n"
}
if config["port"] == "" {
check = check + "ERROR: port empty value.\n"
}
if config["rulePath"] == "" {
check = check + "ERROR: rulePath empty value.\n"
} else {
if _, err := os.Stat(config["rulePath"]); os.IsNotExist(err) {
check = check + "ERROR: rulePath value does not exist. Create it to continue.\n"
}
}
if config["ruleBakPath"] == "" {
check = check + "ERROR: ruleBakPath empty value.\n"
} else {
if _, err := os.Stat(config["ruleBakPath"]); os.IsNotExist(err) {
check = check + "ERROR: ruleBakPath value does not exist. Create it to continue.\n"
}
}
if config["repo"] != "true" {
if config["siem"] == "" {
check = check + "ERROR: siem empty value.\n"
}
if config["siemAddr"] == "" {
check = check + "ERROR: siemAddr empty value.\n"
}
if config["siemPortApi"] == "" {
check = check + "ERROR: siemPortApi empty value.\n"
}
if config["siemUrlApi"] == "" {
check = check + "ERROR: siemUrlApi empty value.\n"
}
if config["siemPortInput"] == "" {
check = check + "ERROR: siemPortInput empty value.\n"
}
if config["siemToken"] == "" {
check = check + "ERROR: siemToken empty value.\n"
}
} else {
repo = true
}
// Check paths
// tmp/ path for tmp files used by the app (p.e. content rule)
if _, err := os.Stat("tmp/"); os.IsNotExist(err) {
if err := os.MkdirAll("tmp/", 0755); err != nil {
log.Println("checkRequirements: "+err.Error())
} else {
log.Println("checkRequirements: INFO: tmp/ path created for SigmaShooter App.")
}
}
return check, repo
}