diff --git a/go.mod b/go.mod index 8cd4e84d..3d107586 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( github.com/pocketbase/pocketbase v0.22.14 github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.9.0 + github.com/tidwall/sjson v1.2.5 ) require ( @@ -63,6 +64,9 @@ require ( github.com/rogpeppe/go-internal v1.10.0 // indirect github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect + github.com/tidwall/gjson v1.14.2 // indirect + github.com/tidwall/match v1.1.1 // indirect + github.com/tidwall/pretty v1.2.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect go.opencensus.io v0.24.0 // indirect diff --git a/go.sum b/go.sum index 21a63f7d..75b8b548 100644 --- a/go.sum +++ b/go.sum @@ -204,6 +204,14 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tidwall/gjson v1.14.2 h1:6BBkirS0rAHjumnjHF6qgy5d2YAJ1TLIaFE2lzfOLqo= +github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= +github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= diff --git a/reaction/action/python/python_test.go b/reaction/action/python/python_test.go new file mode 100644 index 00000000..7615f96a --- /dev/null +++ b/reaction/action/python/python_test.go @@ -0,0 +1,86 @@ +package python + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestPython_Run(t *testing.T) { + type fields struct { + Bootstrap string + Script string + } + + type args struct { + payload string + } + + tests := []struct { + name string + fields fields + args args + want []byte + wantErr assert.ErrorAssertionFunc + }{ + { + name: "empty", + fields: fields{ + Script: "pass", + }, + args: args{ + payload: "test", + }, + want: []byte(""), + wantErr: assert.NoError, + }, + { + name: "hello world", + fields: fields{ + Script: "print('hello world')", + }, + args: args{ + payload: "test", + }, + want: []byte("hello world\n"), + wantErr: assert.NoError, + }, + { + name: "echo", + fields: fields{ + Script: "import sys; print(sys.argv[1])", + }, + args: args{ + payload: "test", + }, + want: []byte("test\n"), + wantErr: assert.NoError, + }, + { + name: "error", + fields: fields{ + Script: "import sys; sys.exit(1)", + }, + args: args{ + payload: "test", + }, + want: nil, + wantErr: assert.Error, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ctx := context.Background() + + a := &Python{ + Bootstrap: tt.fields.Bootstrap, + Script: tt.fields.Script, + } + got, err := a.Run(ctx, tt.args.payload) + tt.wantErr(t, err) + + assert.Equal(t, tt.want, got) + }) + } +} diff --git a/reaction/action/webhook/webhook_test.go b/reaction/action/webhook/webhook_test.go new file mode 100644 index 00000000..e831f3fd --- /dev/null +++ b/reaction/action/webhook/webhook_test.go @@ -0,0 +1,79 @@ +package webhook_test + +import ( + "context" + "encoding/json" + "net/http" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/tidwall/sjson" + + "github.com/SecurityBrewery/catalyst/reaction/action/webhook" + catalystTesting "github.com/SecurityBrewery/catalyst/testing" +) + +func TestWebhook_Run(t *testing.T) { + server := catalystTesting.NewRecordingServer() + + go http.ListenAndServe("127.0.0.1:12347", server) //nolint:gosec,errcheck + + type fields struct { + Headers map[string]string + URL string + } + + type args struct { + payload string + } + + tests := []struct { + name string + fields fields + args args + want map[string]any + wantErr assert.ErrorAssertionFunc + }{ + { + name: "", + fields: fields{ + Headers: map[string]string{}, + URL: "http://127.0.0.1:12347/foo", + }, + args: args{ + payload: "test", + }, + want: map[string]any{ + "statusCode": 200, + "headers": map[string]any{ + "Content-Length": []any{"13"}, + "Content-Type": []any{"text/plain; charset=utf-8"}, + }, + "body": `{"test":true}`, + "isBase64Encoded": false, + }, + wantErr: assert.NoError, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ctx := context.Background() + + a := &webhook.Webhook{ + Headers: tt.fields.Headers, + URL: tt.fields.URL, + } + got, err := a.Run(ctx, tt.args.payload) + tt.wantErr(t, err) + + want, err := json.Marshal(tt.want) + require.NoError(t, err) + + got, err = sjson.DeleteBytes(got, "headers.Date") + require.NoError(t, err) + + assert.JSONEq(t, string(want), string(got)) + }) + } +} diff --git a/testing/reaction_test.go b/testing/reaction_test.go index 5eb65a38..a1f0b85f 100644 --- a/testing/reaction_test.go +++ b/testing/reaction_test.go @@ -3,7 +3,6 @@ package testing import ( "net/http" "testing" - "time" "github.com/stretchr/testify/require" ) @@ -12,10 +11,9 @@ func TestWebhookReactions(t *testing.T) { baseApp, adminToken, analystToken, baseAppCleanup := BaseApp(t) defer baseAppCleanup() - server := testWebhookServer() - defer server.Close() + server := NewRecordingServer() - go server.ListenAndServe() //nolint:errcheck + go http.ListenAndServe("127.0.0.1:12345", server) //nolint:gosec,errcheck testSets := []authMatrixText{ { @@ -83,37 +81,6 @@ func TestWebhookReactions(t *testing.T) { } } -func testWebhookServer() *http.Server { - mux := http.NewServeMux() - mux.HandleFunc("/webhook", func(w http.ResponseWriter, _ *http.Request) { - w.WriteHeader(http.StatusOK) - w.Header().Set("Content-Type", "application/json") - w.Write([]byte(`{"test":true}`)) //nolint:errcheck - }) - - return &http.Server{ - Addr: "127.0.0.1:12345", - Handler: mux, - ReadHeaderTimeout: 3 * time.Second, - } -} - -type RecordingServer struct { - Entries []string -} - -func NewRecordingServer() *RecordingServer { - return &RecordingServer{} -} - -func (s *RecordingServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { - s.Entries = append(s.Entries, r.URL.Path) - - w.WriteHeader(http.StatusOK) - w.Header().Set("Content-Type", "application/json") - w.Write([]byte(`{"test":true}`)) //nolint:errcheck -} - func TestHookReactions(t *testing.T) { baseApp, _, analystToken, baseAppCleanup := BaseApp(t) defer baseAppCleanup() diff --git a/testing/recordingserver.go b/testing/recordingserver.go new file mode 100644 index 00000000..b388a01f --- /dev/null +++ b/testing/recordingserver.go @@ -0,0 +1,19 @@ +package testing + +import "net/http" + +type RecordingServer struct { + Entries []string +} + +func NewRecordingServer() *RecordingServer { + return &RecordingServer{} +} + +func (s *RecordingServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { + s.Entries = append(s.Entries, r.URL.Path) + + w.WriteHeader(http.StatusOK) + w.Header().Set("Content-Type", "application/json") + w.Write([]byte(`{"test":true}`)) //nolint:errcheck +}