// Tool to rewrite mod_security2 logs (very difficult to parse // although they are in semi-structured format) to JSON. // package main import ( "bufio" "bytes" "encoding/json" "fmt" "io" "os" "regexp" ) var ( outerRx = regexp.MustCompile(`\[[^\]]+]`) innerRx = regexp.MustCompile(`\[([^ ]+) \"?(.*)\"\]$`) needle = []byte("ModSecurity: ") ) func parseModSec(w io.Writer, line []byte) bool { if !bytes.Contains(line, needle) { return false } fields := make(map[string]interface{}) var tags []string for _, inner := range outerRx.FindAll(line, -1) { for _, matches := range innerRx.FindAllSubmatch(inner, -1) { field := string(matches[1]) value := string(matches[2]) switch field { case "tag": tags = append(tags, value) case "client", "unique_id", "file", "line": // Suppress these tags. default: fields[field] = value } } } if len(fields) == 0 { return false } if len(tags) > 0 { fields["tag"] = tags } data, _ := json.Marshal(fields) fmt.Fprintf(w, "@cee:{\"modsec\":%s}\n", data) return true } func main() { outw := os.Stdout scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { line := scanner.Bytes() if !parseModSec(outw, line) { outw.Write(line) io.WriteString(outw, "\n") } } }