Change code generator (#4)

* Change code generator
* Remove gin
This commit is contained in:
Jonas Plum
2022-01-08 00:48:44 +01:00
committed by GitHub
parent b5dd0cfacd
commit 8333ea88a8
148 changed files with 3077 additions and 23976 deletions

View File

@@ -6,13 +6,13 @@ import (
"github.com/SecurityBrewery/catalyst/database"
"github.com/SecurityBrewery/catalyst/database/migrations"
"github.com/SecurityBrewery/catalyst/generated/models"
"github.com/SecurityBrewery/catalyst/generated/model"
"github.com/SecurityBrewery/catalyst/pointer"
)
var bobSetting = &models.UserData{Email: pointer.String("bob@example.org"), Name: pointer.String("Bob Bad")}
var bobForm = &models.UserForm{ID: "bob", Blocked: false, Roles: []string{"admin"}}
var Bob = &models.UserResponse{ID: "bob", Blocked: false, Roles: []string{"admin"}}
var bobSetting = &model.UserData{Email: pointer.String("bob@example.org"), Name: pointer.String("Bob Bad")}
var bobForm = &model.UserForm{ID: "bob", Blocked: false, Roles: []string{"admin"}}
var Bob = &model.UserResponse{ID: "bob", Blocked: false, Roles: []string{"admin"}}
func SetupTestData(ctx context.Context, db *database.Database) error {
if err := db.UserDataCreate(ctx, "bob", bobSetting); err != nil {
@@ -22,18 +22,18 @@ func SetupTestData(ctx context.Context, db *database.Database) error {
if _, err := db.UserCreate(ctx, bobForm); err != nil {
return err
}
if _, err := db.UserCreate(ctx, &models.UserForm{ID: "script", Roles: []string{"engineer"}, Apikey: true}); err != nil {
if _, err := db.UserCreate(ctx, &model.UserForm{ID: "script", Roles: []string{"engineer"}, Apikey: true}); err != nil {
return err
}
if _, err := db.TicketBatchCreate(ctx, []*models.TicketForm{
if _, err := db.TicketBatchCreate(ctx, []*model.TicketForm{
{
ID: pointer.Int64(8125),
Created: parse("2021-10-02T18:04:59.078186+02:00"),
Modified: parse("2021-10-02T18:04:59.078186+02:00"),
Name: "phishing from selenafadel@von.com detected",
Owner: pointer.String("demo"),
References: []*models.Reference{{Href: "https://www.seniorleading-edge.name/users/efficient", Name: "recovery"}, {Href: "http://www.dynamicseamless.com/clicks-and-mortar", Name: "force"}, {Href: "http://www.leadscalable.biz/envisioneer", Name: "fund"}},
References: []*model.Reference{{Href: "https://www.seniorleading-edge.name/users/efficient", Name: "recovery"}, {Href: "http://www.dynamicseamless.com/clicks-and-mortar", Name: "force"}, {Href: "http://www.leadscalable.biz/envisioneer", Name: "fund"}},
Schema: pointer.String("{}"),
Status: "closed",
Type: "alert",
@@ -43,7 +43,7 @@ func SetupTestData(ctx context.Context, db *database.Database) error {
Modified: parse("2021-10-02T18:04:59.078186+02:00"),
Name: "Surfaceintroduce virus detected",
Owner: pointer.String("demo"),
References: []*models.Reference{{Href: "http://www.centralworld-class.io/synthesize", Name: "university"}, {Href: "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", Name: "goal"}, {Href: "http://www.chiefsyndicate.io/action-items", Name: "unemployment"}},
References: []*model.Reference{{Href: "http://www.centralworld-class.io/synthesize", Name: "university"}, {Href: "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", Name: "goal"}, {Href: "http://www.chiefsyndicate.io/action-items", Name: "unemployment"}},
Schema: pointer.String("{}"),
Status: "closed",
Type: "alert",
@@ -51,18 +51,18 @@ func SetupTestData(ctx context.Context, db *database.Database) error {
ID: pointer.Int64(8123),
Created: parse("2021-10-02T18:04:59.078206+02:00"),
Modified: parse("2021-10-02T18:04:59.078206+02:00"),
Artifacts: []*models.Artifact{
Artifacts: []*model.Artifact{
{Name: "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", Status: pointer.String("unknown")},
{Name: "http://www.customerviral.io/scalable/vertical/killer", Status: pointer.String("clean")},
{Name: "leadreintermediate.io", Status: pointer.String("malicious")},
},
Name: "live zebra",
Owner: pointer.String("demo"),
References: []*models.Reference{{Href: "https://www.leadmaximize.net/e-services/back-end", Name: "performance"}, {Href: "http://www.corporateinteractive.name/rich", Name: "autumn"}, {Href: "https://www.corporateintuitive.org/intuitive/platforms/integrate", Name: "suggest"}},
References: []*model.Reference{{Href: "https://www.leadmaximize.net/e-services/back-end", Name: "performance"}, {Href: "http://www.corporateinteractive.name/rich", Name: "autumn"}, {Href: "https://www.corporateintuitive.org/intuitive/platforms/integrate", Name: "suggest"}},
Schema: pointer.String("{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n"),
Status: "closed",
Type: "incident",
Playbooks: []*models.PlaybookTemplateForm{
Playbooks: []*model.PlaybookTemplateForm{
{Yaml: migrations.PhishingPlaybook},
},
},
@@ -73,7 +73,7 @@ func SetupTestData(ctx context.Context, db *database.Database) error {
if err := db.RelatedCreate(ctx, 8125, 8126); err != nil {
return err
}
if _, err := db.PlaybookCreate(ctx, &models.PlaybookTemplateForm{Yaml: "name: Simple\ntasks:\n input:\n name: Enter something to hash\n type: input\n schema:\n title: Something\n type: object\n properties:\n something:\n type: string\n title: Something\n default: \"\"\n next:\n hash: \"something != ''\"\n\n hash:\n name: Hash the something\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['input'].data['something']\"\n next:\n comment: \"hash != ''\"\n\n comment:\n name: Comment the hash\n type: automation\n automation: comment\n payload:\n default: \"playbook.tasks['hash'].data['hash']\"\n next:\n done: \"done\"\n\n done:\n name: You can close this case now\n type: task\n"}); err != nil {
if _, err := db.PlaybookCreate(ctx, &model.PlaybookTemplateForm{Yaml: "name: Simple\ntasks:\n input:\n name: Enter something to hash\n type: input\n schema:\n title: Something\n type: object\n properties:\n something:\n type: string\n title: Something\n default: \"\"\n next:\n hash: \"something != ''\"\n\n hash:\n name: Hash the something\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['input'].data['something']\"\n next:\n comment: \"hash != ''\"\n\n comment:\n name: Comment the hash\n type: automation\n automation: comment\n payload:\n default: \"playbook.tasks['hash'].data['hash']\"\n next:\n done: \"done\"\n\n done:\n name: You can close this case now\n type: task\n"}); err != nil {
return err
}

View File

@@ -10,25 +10,81 @@ import (
"mime/multipart"
"net/http"
"net/http/httptest"
"reflect"
"regexp"
"strings"
"testing"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/aws/aws-sdk-go/service/s3/s3manager"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"github.com/tidwall/gjson"
"github.com/tidwall/sjson"
"github.com/SecurityBrewery/catalyst"
"github.com/SecurityBrewery/catalyst/database/busdb"
"github.com/SecurityBrewery/catalyst/generated/models"
"github.com/SecurityBrewery/catalyst/generated/api"
"github.com/SecurityBrewery/catalyst/generated/model"
"github.com/SecurityBrewery/catalyst/pointer"
ctime "github.com/SecurityBrewery/catalyst/time"
)
func TestService(t *testing.T) {
gin.SetMode(gin.TestMode)
type testClock struct{}
func (testClock) Now() time.Time {
return time.Date(2021, 12, 12, 12, 12, 12, 12, time.UTC)
}
func TestServer(t *testing.T) {
ctime.DefaultClock = testClock{}
for _, tt := range api.Tests {
t.Run(tt.Name, func(t *testing.T) {
ctx, _, _, _, _, db, _, server, cleanup, err := Server(t)
if err != nil {
t.Fatal(err)
}
defer cleanup()
if err := SetupTestData(ctx, db); err != nil {
t.Fatal(err)
}
w := httptest.NewRecorder()
// setup request
var req *http.Request
if tt.Args.Data != nil {
b, err := json.Marshal(tt.Args.Data)
if err != nil {
t.Fatal(err)
}
req = httptest.NewRequest(strings.ToUpper(tt.Args.Method), tt.Args.URL, bytes.NewBuffer(b))
req.Header.Set("Content-Type", "application/json")
} else {
req = httptest.NewRequest(strings.ToUpper(tt.Args.Method), tt.Args.URL, nil)
}
// run request
server.ServeHTTP(w, req)
result := w.Result()
// assert results
if result.StatusCode != tt.Want.Status {
msg, _ := io.ReadAll(result.Body)
t.Fatalf("Status got = %v, want %v: %s", result.Status, tt.Want.Status, msg)
}
if tt.Want.Status != http.StatusNoContent {
jsonEqual(t, result.Body, tt.Want.Body)
}
})
}
}
func TestService(t *testing.T) {
type args struct {
method string
url string
@@ -43,8 +99,8 @@ func TestService(t *testing.T) {
args args
want want
}{
{name: "GetUser not existing", args: args{method: http.MethodGet, url: "/api/users/123"}, want: want{status: http.StatusNotFound, body: gin.H{"error": "document not found"}}},
{name: "ListUsers", args: args{method: http.MethodGet, url: "/api/users"}, want: want{status: http.StatusOK}},
{name: "GetUser not existing", args: args{method: http.MethodGet, url: "/users/123"}, want: want{status: http.StatusNotFound, body: map[string]string{"error": "document not found"}}},
{name: "ListUsers", args: args{method: http.MethodGet, url: "/users"}, want: want{status: http.StatusOK}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -54,12 +110,7 @@ func TestService(t *testing.T) {
}
defer cleanup()
setUser := func(context *gin.Context) {
busdb.SetContext(context, Bob)
}
server.Use(setUser)
server.ConfigureRoutes()
// server.ConfigureRoutes()
w := httptest.NewRecorder()
// setup request
@@ -93,21 +144,13 @@ func TestService(t *testing.T) {
}
func TestBackupAndRestore(t *testing.T) {
gin.SetMode(gin.TestMode)
log.SetFlags(log.LstdFlags | log.Lshortfile)
type args struct {
method string
url string
data interface{}
}
type want struct {
status int
// body interface{}
}
tests := []struct {
name string
// args args
want want
}{
{name: "Backup", want: want{status: http.StatusOK}},
@@ -125,10 +168,6 @@ func TestBackupAndRestore(t *testing.T) {
createFile(ctx, server)
server.Server.Use(func(context *gin.Context) {
busdb.SetContext(context, Bob)
})
zipB := assertBackup(t, server)
assertZipFile(t, readZipFile(t, zipB))
@@ -233,6 +272,8 @@ func assertRestore(t *testing.T, zipB []byte, server *catalyst.Server) {
restoreResult := restoreRequestRecorder.Result()
if !assert.Equal(t, http.StatusOK, restoreResult.StatusCode) {
b, _ := io.ReadAll(restoreResult.Body)
log.Println(string(b))
t.FailNow()
}
}
@@ -246,7 +287,7 @@ func createFile(ctx context.Context, server *catalyst.Server) {
log.Fatal(err)
}
if _, err := server.DB.LinkFiles(ctx, 8125, []*models.File{{Key: "test.txt", Name: "test.txt"}}); err != nil {
if _, err := server.DB.LinkFiles(ctx, 8125, []*model.File{{Key: "test.txt", Name: "test.txt"}}); err != nil {
log.Fatal(err)
}
}
@@ -269,7 +310,7 @@ func assertTicketExists(t *testing.T, server *catalyst.Server) {
}
assert.NoError(t, backupResult.Body.Close())
var ticket models.Ticket
var ticket model.Ticket
assert.NoError(t, json.Unmarshal(zipBuf.Bytes(), &ticket))
assert.Equal(t, "phishing from selenafadel@von.com detected", ticket.Name)
@@ -314,24 +355,37 @@ func readZipFile(t *testing.T, b []byte) *zip.Reader {
}
func jsonEqual(t *testing.T, got io.Reader, want interface{}) {
var j, j2 interface{}
c, err := io.ReadAll(got)
var gotObject, wantObject interface{}
// load bytes
wantBytes, err := json.Marshal(want)
if err != nil {
t.Fatal(err)
}
if err := json.Unmarshal(c, &j); err != nil {
t.Fatal(string(c), err)
}
b, err := json.Marshal(want)
gotBytes, err := io.ReadAll(got)
if err != nil {
t.Fatal(err)
}
if err = json.Unmarshal(b, &j2); err != nil {
t.Fatal(err)
fields := []string{"secret"}
for _, field := range fields {
gField := gjson.GetBytes(wantBytes, field)
if gField.Exists() && gjson.GetBytes(gotBytes, field).Exists() {
gotBytes, err = sjson.SetBytes(gotBytes, field, gField.Value())
if err != nil {
t.Fatal(err)
}
}
}
if !reflect.DeepEqual(j2, j) {
t.Errorf("Body got = %T:%v, want %T:%v", j, j, j2, j2)
// normalize bytes
if err = json.Unmarshal(wantBytes, &wantObject); err != nil {
t.Fatal(err)
}
if err := json.Unmarshal(gotBytes, &gotObject); err != nil {
t.Fatal(string(gotBytes), err)
}
// compare
assert.Equal(t, wantObject, gotObject)
}

View File

@@ -3,7 +3,7 @@ package test
import (
"context"
"log"
"net/http/httptest"
"net/http"
"os"
"path"
"strings"
@@ -11,15 +11,15 @@ import (
"github.com/arangodb/go-driver"
"github.com/coreos/go-oidc/v3/oidc"
"github.com/gin-gonic/gin"
"github.com/go-chi/chi"
"golang.org/x/oauth2"
"github.com/SecurityBrewery/catalyst"
"github.com/SecurityBrewery/catalyst/bus"
"github.com/SecurityBrewery/catalyst/database"
"github.com/SecurityBrewery/catalyst/database/busdb"
"github.com/SecurityBrewery/catalyst/generated/models"
"github.com/SecurityBrewery/catalyst/generated/restapi"
"github.com/SecurityBrewery/catalyst/generated/api"
"github.com/SecurityBrewery/catalyst/generated/model"
"github.com/SecurityBrewery/catalyst/hooks"
"github.com/SecurityBrewery/catalyst/index"
"github.com/SecurityBrewery/catalyst/pointer"
@@ -28,10 +28,7 @@ import (
)
func Context() context.Context {
w := httptest.NewRecorder()
gctx, _ := gin.CreateTestContext(w)
busdb.SetContext(gctx, Bob)
return gctx
return busdb.UserContext(context.Background(), Bob)
}
func Config(ctx context.Context) (*catalyst.Config, error) {
@@ -53,20 +50,20 @@ func Config(ctx context.Context) (*catalyst.Config, error) {
Key: "A9RysEsPJni8RaHeg_K0FKXQNfBrUyw-",
APIUrl: "http://localhost:8002/api",
},
UISettings: &models.Settings{
ArtifactStates: []*models.Type{
{Icon: "mdi-help-circle-outline", ID: "unknown", Name: "Unknown", Color: pointer.String(models.TypeColorInfo)},
{Icon: "mdi-skull", ID: "malicious", Name: "Malicious", Color: pointer.String(models.TypeColorError)},
{Icon: "mdi-check", ID: "clean", Name: "Clean", Color: pointer.String(models.TypeColorSuccess)},
UISettings: &model.Settings{
ArtifactStates: []*model.Type{
{Icon: "mdi-help-circle-outline", ID: "unknown", Name: "Unknown", Color: pointer.String(model.TypeColorInfo)},
{Icon: "mdi-skull", ID: "malicious", Name: "Malicious", Color: pointer.String(model.TypeColorError)},
{Icon: "mdi-check", ID: "clean", Name: "Clean", Color: pointer.String(model.TypeColorSuccess)},
},
TicketTypes: []*models.TicketTypeResponse{
TicketTypes: []*model.TicketTypeResponse{
{ID: "alert", Icon: "mdi-alert", Name: "Alerts"},
{ID: "incident", Icon: "mdi-radioactive", Name: "Incidents"},
{ID: "investigation", Icon: "mdi-fingerprint", Name: "Forensic Investigations"},
{ID: "hunt", Icon: "mdi-target", Name: "Threat Hunting"},
},
Version: "0.0.0-test",
Tier: models.SettingsTierCommunity,
Tier: model.SettingsTierCommunity,
Timeformat: "YYYY-MM-DDThh:mm:ss",
},
Secret: []byte("4ef5b29539b70233dd40c02a1799d25079595565e05a193b09da2c3e60ada1cd"),
@@ -146,7 +143,7 @@ func DB(t *testing.T) (context.Context, *catalyst.Config, *bus.Bus, *index.Index
return nil, nil, nil, nil, nil, nil, nil, err
}
_, err = db.JobCreate(ctx, "99cd67131b48", &models.JobForm{
_, err = db.JobCreate(ctx, "99cd67131b48", &model.JobForm{
Automation: "hash.sha1",
Payload: "test",
Origin: nil,
@@ -178,13 +175,19 @@ func Service(t *testing.T) (context.Context, *catalyst.Config, *bus.Bus, *index.
return ctx, config, rbus, catalystIndex, catalystStorage, db, catalystService, cleanup, err
}
func Server(t *testing.T) (context.Context, *catalyst.Config, *bus.Bus, *index.Index, *storage.Storage, *database.Database, *service.Service, *restapi.Server, func(), error) {
func Server(t *testing.T) (context.Context, *catalyst.Config, *bus.Bus, *index.Index, *storage.Storage, *database.Database, *service.Service, chi.Router, func(), error) {
ctx, config, rbus, catalystIndex, catalystStorage, db, catalystService, cleanup, err := Service(t)
if err != nil {
t.Fatal(err)
}
catalystServer := restapi.New(catalystService, &restapi.Config{Address: "0.0.0.0:8000", InsecureHTTP: true})
catalystServer := api.NewServer(catalystService, func(s []string) func(http.Handler) http.Handler {
return func(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
handler.ServeHTTP(w, busdb.SetContext(r, Bob))
})
}
})
return ctx, config, rbus, catalystIndex, catalystStorage, db, catalystService, catalystServer, cleanup, err
}