Skip to content
Snippets Groups Projects
Commit 2f0bf36f authored by ale's avatar ale
Browse files

Merge branch 'modsec-json' into 'master'

Rewrite mod_security output to structured logging

See merge request !181
parents d984e3ff 68e4d651
No related branches found
No related tags found
1 merge request!181Rewrite mod_security output to structured logging
FROM golang:1.19 AS gobuild
COPY modsec_logger.go /src/modsec_logger.go
WORKDIR /src
RUN go build -tags netgo -o modsec_logger modsec_logger.go
FROM composer:2.2.9 as build
ADD . /build
......@@ -15,6 +20,7 @@ COPY docker/wp-config.php /opt/noblogs/www/wp-config.php
COPY docker/wp-cache-config.php /opt/noblogs/www/wp-content/wp-cache-config.php
COPY docker/conf /tmp/conf
COPY docker/build.sh /tmp/build.sh
COPY --from=gobuild /src/modsec_logger /usr/local/bin/modsec_logger
RUN /tmp/build.sh && rm /tmp/build.sh
......
......@@ -6,5 +6,7 @@
SecRuleEngine Off
</Location>
ErrorLog "|/usr/local/bin/modsec_logger"
</IfModule>
</IfModule>
// 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")
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment