Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .github/workflows/go.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# This workflow will build a golang project
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go

name: Go

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

jobs:

build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.22.2'

- name: Make
run: |
cd testdata/plugins
make

- name: Test
run: go test -v ./...
16 changes: 8 additions & 8 deletions configstore/configstore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ logpath: "/dev/stderr"
loglevel: "DEBUG"
modelplugins:
- id: "trivial"
path: "../_plugins/model/trivial.so"
path: "../testdata/plugins/model/trivial.so"
weight: 1
threshold: 0.5
params:
Expand All @@ -23,7 +23,7 @@ modelplugins:
plugintype: "RequestHeaders"
mode: "sync"
- id: "trivial2"
path: "../_plugins/model/trivial2.so"
path: "../testdata/plugins/model/trivial2.so"
weight: 2
threshold: 0.1
params:
Expand All @@ -33,7 +33,7 @@ modelplugins:
plugintype: "RequestHeaders"
decisionplugins:
- id: "test"
path: "../_plugins/decision/test.so"
path: "../testdata/plugins/decision/test.so"
wafweight: 0.5
decisionbalance: 0.5
params:
Expand Down Expand Up @@ -108,7 +108,7 @@ loglevel: ERROR
logpath: /dev/null
modelplugins:
- id: "testplugin"
path: "../_plugins/model/trivial.so"
path: "../testdata/plugins/model/trivial.so"
plugintype: InvalidPluginType
`))
if err == nil {
Expand All @@ -120,7 +120,7 @@ loglevel: ERROR
logpath: /dev/null
modelplugins:
- id: "testplugin"
path: "../_plugins/model/trivial.so"
path: "../testdata/plugins/model/trivial.so"
plugintype: ""
`))
if err == nil {
Expand All @@ -132,7 +132,7 @@ loglevel: ERROR
logpath: /dev/null
modelplugins:
- id: "testplugin"
path: "../_plugins/model/nonexistent.so"
path: "../testdata/plugins/model/nonexistent.so"
plugintype: "RequestHeaders"
`))
if err == nil {
Expand Down Expand Up @@ -167,7 +167,7 @@ loglevel: ERROR
logpath: /dev/null
decisionplugins:
- id: "testplugin"
path: "../_plugins/decision/nonexistent.so"
path: "../testdata/plugins/decision/nonexistent.so"
`))
if err == nil {
t.Errorf("nonexistent decision plugin path does not return error")
Expand All @@ -189,7 +189,7 @@ loglevel: ERROR
logpath: /dev/null
modelplugins:
- id: "testplugin"
path: "../_plugins/model/trivial.so"
path: "../testdata/plugins/model/trivial.so"
plugintype: "` + v + `"
`
err = initialize([]byte(config))
Expand Down
26 changes: 13 additions & 13 deletions pluginmanager/pluginmanager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ loglevel: "WARN"
`

var trivialPlugin = ` - id: "trivial"
path: "../_plugins/model/trivial.so"
path: "../testdata/plugins/model/trivial.so"
weight: 1
params:
param1: "first value"
Expand All @@ -28,7 +28,7 @@ var trivialPlugin = ` - id: "trivial"
`

var testPlugin = ` - id: "test"
path: "../_plugins/decision/test.so"
path: "../testdata/plugins/decision/test.so"
wafweight: 0.5
decisionbalance: 0.5
params:
Expand Down Expand Up @@ -84,19 +84,19 @@ func init() {
// func TestPluginInit(t *testing.T) {
// cases := []struct{ id, conf string }{
// // {"invalid_path", ` - id: "invalid_path"
// // path: "../_plugins/model/nonexistent.so"
// // path: "../testdata/plugins/model/nonexistent.so"
// // plugintype: "AllRequest"
// // `},
// {"no_init", ` - id: "no_init"
// path: "../_plugins/model/no_init.so"
// path: "../testdata/plugins/model/no_init.so"
// plugintype: "AllRequest"
// `},
// {"wrong_init", ` - id: "wrong_init"
// path: "../_plugins/model/wrong_init.so"
// path: "../testdata/plugins/model/wrong_init.so"
// plugintype: "AllRequest"
// `},
// {"error_init", ` - id: "error_init"
// path: "../_plugins/model/error_init.so"
// path: "../testdata/plugins/model/error_init.so"
// plugintype: "AllRequest"
// `},
// }
Expand Down Expand Up @@ -223,7 +223,7 @@ func init() {
// for _, c := range cases {
// config := baseConfig + "modelplugins:\n" +
// " - id: \"" + c.id + "\"\n" +
// " path: \"../_plugins/model/trivial.so\"\n" +
// " path: \"../testdata/plugins/model/trivial.so\"\n" +
// " plugintype: \"" + c.pluginType.String() + "\"\n"

// err := initilize([]byte(config))
Expand Down Expand Up @@ -267,15 +267,15 @@ func init() {
// func TestProcessRequestInvalid(t *testing.T) {
// cases := []struct{ id, conf string }{
// {"no_req", ` - id: "no_req"
// path: "../_plugins/model/no_req.so"
// path: "../testdata/plugins/model/no_req.so"
// plugintype: "Everything"
// `},
// {"wrong_req", ` - id: "wrong_req"
// path: "../_plugins/model/wrong_req.so"
// path: "../testdata/plugins/model/wrong_req.so"
// plugintype: "Everything"
// `},
// {"error_req", ` - id: "error_req"
// path: "../_plugins/model/error_req.so"
// path: "../testdata/plugins/model/error_req.so"
// plugintype: "Everything"
// `},
// }
Expand Down Expand Up @@ -326,13 +326,13 @@ func init() {
// func TestCheckResultInvalid(t *testing.T) {
// cases := []struct{ id, conf string }{
// {"no_check", ` - id: "no_check"
// path: "../_plugins/decision/no_check.so"
// path: "../testdata/plugins/decision/no_check.so"
// `},
// {"wrong_check", ` - id: "wrong_check"
// path: "../_plugins/decision/wrong_check.so"
// path: "../testdata/plugins/decision/wrong_check.so"
// `},
// {"error_check", ` - id: "error_check"
// path: "../_plugins/decision/error_check.so"
// path: "../testdata/plugins/decision/error_check.so"
// `},
// }

Expand Down
12 changes: 12 additions & 0 deletions testdata/plugins/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
all: model/trivial.so model/trivial2.so \
model/no_init.so model/wrong_init.so model/error_init.so \
model/no_req.so model/wrong_req.so model/error_req.so \
decision/test.so \
decision/no_check.so decision/wrong_check.so decision/error_check.so \
decision/simple.so

%.so: %.go
go build $(FLAGS) -buildmode=plugin -o $@ $<

clean:
rm -f model/*.so decision/*.so
23 changes: 23 additions & 0 deletions testdata/plugins/decision/error_check.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/* Trivial Decision Plugin that always returns no attack
*/

package main

import (
"errors"

lg "github.com/tilsor/ModSecIntl_logging/logging"
)

// InitPlugin intitalizes the plugins (does nothing in this case)
func InitPlugin(params map[string]string) error {
logger := lg.Get()
logger.Printf(lg.WARN, "[simple:InitPlugin] %v\n", params)
return nil
}

// CheckResults returns true (block traffic) if WAF says so, and false
// in other case.
func CheckResults(transactionID string, modelRes map[string]float64, modelWeight map[string]float64, modelThres map[string]float64, wafData map[string]string) (bool, error) {
return false, errors.New("Some error")
}
15 changes: 15 additions & 0 deletions testdata/plugins/decision/no_check.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/* Trivial Decision Plugin that always returns no attack
*/

package main

import (
lg "github.com/tilsor/ModSecIntl_logging/logging"
)

// InitPlugin intitalizes the plugins (does nothing in this case)
func InitPlugin(params map[string]string) error {
logger := lg.Get()
logger.Printf(lg.WARN, "[simple:InitPlugin] %v\n", params)
return nil
}
92 changes: 92 additions & 0 deletions testdata/plugins/decision/simple.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/* Trivial Decision Plugin that always returns no attack
*/

package main

import (
"context"
"strconv"

lg "github.com/tilsor/ModSecIntl_logging/logging"
pm "github.com/tilsor/ModSecIntl_wace_lib/pluginmanager"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/metric"
)

func InitPlugin(params map[string]string, meter metric.Meter) error {
// Create counter for plugin register
ctx := context.Background()
pluginCounter, err := meter.Int64Counter("plugin_register")
if err != nil {
return err
}
pluginCounter.Add(ctx, 1, metric.WithAttributes(attribute.String("plugin_name", "simple"), attribute.String("plugin_type", "decision")))
return nil
}

func CheckResults(decisionInput pm.DecisionInput) (bool, error) {
logger := lg.Get()
var totalModelW float64 = 0
var modelDetectionCount int = 0
var totalModelProb float64 = 0
for key, value := range decisionInput.Results {
logger.TPrintf(lg.DEBUG, decisionInput.TransactionId, "simple | model_id: %v result: %v", key, value)
if value.ProbAttack >= 0.5 {
modelDetectionCount++
totalModelW += decisionInput.ModelWeight[key]
}
}

for key, value := range decisionInput.WAFdata {
logger.TPrintf(lg.DEBUG, decisionInput.TransactionId, "simple | WAF data: %v: %v", key, value)
}

// if we have some model results
if modelDetectionCount > 0 {
totalModelProb = totalModelW / float64(modelDetectionCount)
}
if len(decisionInput.WAFdata) != 0 {
as, _ := strconv.Atoi(decisionInput.WAFdata["inbound_blocking"])
it, _ := strconv.Atoi(decisionInput.WAFdata["inbound_threshold"])
logger.TPrintf(lg.DEBUG, decisionInput.TransactionId, "Coraza | Anomaly score: %v Anomaly score threshold: %v ", as, it)

if as >= it && totalModelProb > 0.5 { // coraza wants to block and models agree
return true, nil
}
}
return false, nil
}

// func CheckResults(transactionID string, modelRes map[string]float64, modelWeight map[string]float64, modelThres map[string]float64, WAFdata map[string]string) (bool, error) {
// logger := lg.Get()
// var totalModelW float64 = 0
// var modelDetectionCount int = 0
// var totalModelProb float64 = 0
// for key, value := range modelRes {
// logger.TPrintf(lg.DEBUG, transactionID, "simple | model_id: %v result: %v threshold: %v", key, value, modelThres[key])
// if value >= modelThres[key] {
// modelDetectionCount++
// totalModelW += modelWeight[key]
// }
// }

// // DEBUG: print WAF data
// for key, value := range WAFdata {
// logger.TPrintf(lg.DEBUG, transactionID, "simple | WAF data: %v: %v", key, value)
// }

// // if we have some model results
// if modelDetectionCount > 0 {
// totalModelProb = totalModelW / float64(modelDetectionCount)
// }
// if len(WAFdata) != 0 {
// as, _ := strconv.Atoi(WAFdata["inbound_blocking"])
// it, _ := strconv.Atoi(WAFdata["inbound_threshold"])
// logger.TPrintf(lg.DEBUG, transactionID, "Coraza | Anomaly score: %v Anomaly score threshold: %v ", as, it)

// if as >= it && totalModelProb > 0.5 { // modsec wants to block
// return true, nil
// }
// }
// return false, nil
// }
49 changes: 49 additions & 0 deletions testdata/plugins/decision/test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/* Trivial Test Decision Plugin that always returns no attack
*/

package main

import (
"strconv"

lg "github.com/tilsor/ModSecIntl_logging/logging"
pm "github.com/tilsor/ModSecIntl_wace_lib/pluginmanager"
"go.opentelemetry.io/otel/metric"
)

// InitPlugin intitalizes the plugins (does nothing in this case)
func InitPlugin(params map[string]string, meter metric.Meter) error {
logger := lg.Get()
logger.Printf(lg.WARN, "[test:InitPlugin] %v\n", params)

return nil
}

// CheckResults returns true (block traffic) if WAF says so, and false
// in other case.
// func CheckResults(transactionID string, modelRes map[string]float64, modelWeight map[string]float64, modelThres map[string]float64, wafData map[string]string) (bool, error) {
func CheckResults(decisionInput pm.DecisionInput) (bool, error) {
logger := lg.Get()

modelRes := decisionInput.Results
modelWeight := decisionInput.ModelWeight
wafData := decisionInput.WAFdata
transactionID := decisionInput.TransactionId

logger.TPrintf(lg.WARN, transactionID, "[test:CheckResults]\n modelRes: %v\n modelWeight: %v\n modelThres: %v\n wafData: %v\n", modelRes, modelWeight, wafData)

if len(wafData) != 0 {
as, err := strconv.Atoi(wafData["anomalyscore"])
if err != nil {
return false, err
}
it, err := strconv.Atoi(wafData["inboundthreshold"])
if err != nil {
return false, err
}
if as >= it { // modsec wants to block
return true, nil
}
}
return false, nil
}
Loading