From 3b5c9510d99192f478bbfc2d15b4ae048359054e Mon Sep 17 00:00:00 2001 From: Corey Ogburn Date: Thu, 30 May 2024 16:25:02 -0600 Subject: [PATCH 01/57] Detection Templates When you select a language from the dropdown on the New Detection page, a request is made to get an unused public Id for that engine (except YARA/Strelka). The source field is then filled with the template for that language/engine with publicId inserted in the right place. --- config/clientparameters.go | 54 +++++++++++++--------- html/index.html | 2 +- html/js/routes/detection.js | 28 +++++++++++ html/js/routes/detection.test.js | 38 +++++++++++++-- server/detectionengine.go | 1 + server/detectionhandler.go | 28 +++++++++++ server/modules/elastalert/elastalert.go | 4 +- server/modules/elastalert/validate_test.go | 2 +- server/modules/strelka/strelka.go | 6 +++ server/modules/suricata/suricata.go | 4 +- server/modules/suricata/validate_test.go | 2 +- 11 files changed, 134 insertions(+), 35 deletions(-) diff --git a/config/clientparameters.go b/config/clientparameters.go index 7856e3ea..df6b7248 100644 --- a/config/clientparameters.go +++ b/config/clientparameters.go @@ -16,27 +16,27 @@ const DEFAULT_CHART_LABEL_OTHER_LIMIT = 10 const DEFAULT_CHART_LABEL_FIELD_SEPARATOR = ", " type ClientParameters struct { - HuntingParams HuntingParameters `json:"hunt"` - AlertingParams HuntingParameters `json:"alerts"` - CasesParams HuntingParameters `json:"cases"` - CaseParams CaseParameters `json:"case"` - DashboardsParams HuntingParameters `json:"dashboards"` - JobParams HuntingParameters `json:"job"` - DetectionsParams DetectionParameters `json:"detections"` - DetectionParams DetectionParameters `json:"detection"` - DocsUrl string `json:"docsUrl"` - CheatsheetUrl string `json:"cheatsheetUrl"` - ReleaseNotesUrl string `json:"releaseNotesUrl"` - GridParams GridParameters `json:"grid"` - WebSocketTimeoutMs int `json:"webSocketTimeoutMs"` - TipTimeoutMs int `json:"tipTimeoutMs"` - ApiTimeoutMs int `json:"apiTimeoutMs"` - CacheExpirationMs int `json:"cacheExpirationMs"` - InactiveTools []string `json:"inactiveTools"` - Tools []ClientTool `json:"tools"` - CasesEnabled bool `json:"casesEnabled"` - EnableReverseLookup bool `json:"enableReverseLookup"` - DetectionsEnabled bool `json:"detectionsEnabled"` + HuntingParams HuntingParameters `json:"hunt"` + AlertingParams HuntingParameters `json:"alerts"` + CasesParams HuntingParameters `json:"cases"` + CaseParams CaseParameters `json:"case"` + DashboardsParams HuntingParameters `json:"dashboards"` + JobParams HuntingParameters `json:"job"` + DetectionsParams DetectionsParameters `json:"detections"` + DetectionParams DetectionParameters `json:"detection"` + DocsUrl string `json:"docsUrl"` + CheatsheetUrl string `json:"cheatsheetUrl"` + ReleaseNotesUrl string `json:"releaseNotesUrl"` + GridParams GridParameters `json:"grid"` + WebSocketTimeoutMs int `json:"webSocketTimeoutMs"` + TipTimeoutMs int `json:"tipTimeoutMs"` + ApiTimeoutMs int `json:"apiTimeoutMs"` + CacheExpirationMs int `json:"cacheExpirationMs"` + InactiveTools []string `json:"inactiveTools"` + Tools []ClientTool `json:"tools"` + CasesEnabled bool `json:"casesEnabled"` + EnableReverseLookup bool `json:"enableReverseLookup"` + DetectionsEnabled bool `json:"detectionsEnabled"` } func (config *ClientParameters) Verify() error { @@ -190,15 +190,23 @@ type GridParameters struct { StaleMetricsMs uint64 `json:"staleMetricsMs,omitempty"` } -type DetectionParameters struct { +type DetectionsParameters struct { HuntingParameters + DetectionParameters +} + +type DetectionParameters struct { Presets map[string]PresetParameters `json:"presets"` SeverityTranslations map[string]string `json:"severityTranslations"` + TemplateDetections map[string]string `json:"templateDetections"` } -func (params *DetectionParameters) Verify() error { +func (params *DetectionsParameters) Verify() error { err := params.HuntingParameters.Verify() return err +} +func (params *DetectionParameters) Verify() error { + return nil } diff --git a/html/index.html b/html/index.html index a79737b4..7c19c14c 100644 --- a/html/index.html +++ b/html/index.html @@ -1064,7 +1064,7 @@

{{ detect.title }}

{{ i18n.add }} {{ i18n.detection }}
- + diff --git a/html/js/routes/detection.js b/html/js/routes/detection.js index 1088f9cc..d5b6cd9f 100644 --- a/html/js/routes/detection.js +++ b/html/js/routes/detection.js @@ -121,6 +121,12 @@ routes.push({ path: '/detection/:id', name: 'detection', component: { convertedRule: '', confirmDeleteDialog: false, showDirtySourceDialog: false, + ruleTemplates: {}, + languageToEngine: { + 'suricata': 'suricata', + 'sigma': 'elastalert', + 'yara': 'strelka', + }, }}, created() { this.onDetectionChange = debounce(this.onDetectionChange, 300); @@ -141,6 +147,7 @@ routes.push({ path: '/detection/:id', name: 'detection', component: { this.presets = params['presets']; this.renderAbbreviatedCount = params["renderAbbreviatedCount"]; this.severityTranslations = params['severityTranslations']; + this.ruleTemplates = params['templateDetections']; if (this.$route.params.id === 'create') { this.detect = this.newDetection(); @@ -813,6 +820,27 @@ routes.push({ path: '/detection/:id', name: 'detection', component: { } } }, + async onNewDetectionLanguageChange() { + const lang = (this.detect.language || '').toLowerCase(); + const engine = this.languageToEngine[lang]; + + if (engine) { + let publicId = ''; + + if (engine !== 'strelka') { + try { + const response = await this.$root.papi.get(`detection/${engine}/genpublicid`); + publicId = response.data.publicId; + } catch (error) { + this.$root.showError(error); + } + } + + this.detect.content = this.ruleTemplates[engine].replaceAll('[publicId]', publicId); + } + + this.onDetectionChange(); + }, onDetectionChange() { if (this.detect.engine) { this.extractPublicID(); diff --git a/html/js/routes/detection.test.js b/html/js/routes/detection.test.js index 8e55af28..36a7e687 100644 --- a/html/js/routes/detection.test.js +++ b/html/js/routes/detection.test.js @@ -327,7 +327,7 @@ test('deleteDetectionCancel', () => { comp.cancelDeleteDetection(); expect(comp.confirmDeleteDialog).toBe(false); comp.deleteDetection(); -}) +}); test('deleteDetectionFailure', async () => { resetPapi().mockPapi("delete", null, new Error("something bad")); @@ -389,17 +389,45 @@ test('revertEnabled', () => { comp.revertEnabled(); expect(comp.detect.isEnabled).toBe(false); expect(comp.origDetect.isEnabled).toBe(false); -}) +}); test('isFieldValid', () => { comp.$refs = {} expect(comp.isFieldValid('foo')).toBe(true) - comp.$refs = {bar: { valid: false}} + comp.$refs = { bar: { valid: false } } expect(comp.isFieldValid('foo')).toBe(true) expect(comp.isFieldValid('bar')).toBe(false) - comp.$refs = {bar: { valid: true}} + comp.$refs = { bar: { valid: true } } expect(comp.isFieldValid('bar')).toBe(true) +}); -}) \ No newline at end of file +test('onNewDetectionLanguageChange', async () => { + comp.ruleTemplates = { + "suricata": 'a [publicId]', + "strelka": 'b [publicId]', + "elastalert": 'c [publicId]', + } + // no language means no engine means no request means no change + comp.detect = { language: '', content: 'x' }; + await comp.onNewDetectionLanguageChange(); + expect(comp.detect.content).toBe('x'); + + // yara, no publicId, results in template without publicId + comp.detect = { language:'yara', content: 'x' }; + await comp.onNewDetectionLanguageChange(); + expect(comp.detect.content).toBe('b '); + + // suricata, sid, results in template with publicId + resetPapi().mockPapi("get", { data: { publicId: 'X' } }, null); + comp.detect = { language:'suricata', content: 'x' }; + await comp.onNewDetectionLanguageChange(); + expect(comp.detect.content).toBe('a X'); + + // sigma, uuid, results in template with publicId + resetPapi().mockPapi("get", { data: { publicId: 'X' } }, null); + comp.detect = { language:'sigma', content: 'x' }; + await comp.onNewDetectionLanguageChange(); + expect(comp.detect.content).toBe('c X'); +}); diff --git a/server/detectionengine.go b/server/detectionengine.go index a4b88f8f..465a95e4 100644 --- a/server/detectionengine.go +++ b/server/detectionengine.go @@ -19,6 +19,7 @@ type DetectionEngine interface { InterruptSync(forceFull bool, notify bool) DuplicateDetection(ctx context.Context, detection *model.Detection) (*model.Detection, error) GetState() *model.EngineState + GenerateUnusedPublicId(ctx context.Context) (string, error) } type SyncStatus struct { diff --git a/server/detectionhandler.go b/server/detectionhandler.go index be09c8e4..5acd79c2 100644 --- a/server/detectionhandler.go +++ b/server/detectionhandler.go @@ -65,6 +65,8 @@ func RegisterDetectionRoutes(srv *Server, r chi.Router, prefix string) { r.Post("/bulk/{newStatus}", h.bulkUpdateDetection) r.Post("/sync/{engine}/{type}", h.syncEngineDetections) + + r.Get("/{engine}/genpublicid", h.genPublicId) }) } @@ -683,6 +685,32 @@ func (h *DetectionHandler) syncEngineDetections(w http.ResponseWriter, r *http.R web.Respond(w, r, http.StatusOK, nil) } +func (h *DetectionHandler) genPublicId(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + + engine := chi.URLParam(r, "engine") + + eng, ok := h.server.DetectionEngines[model.EngineName(engine)] + if !ok { + web.Respond(w, r, http.StatusBadRequest, errors.New("unsupported engine")) + return + } + + id, err := eng.GenerateUnusedPublicId(ctx) + if err != nil { + if err.Error() == "not implemented" { + web.Respond(w, r, http.StatusNotImplemented, nil) + } else { + web.Respond(w, r, http.StatusInternalServerError, err) + } + return + } + + web.Respond(w, r, http.StatusOK, map[string]string{ + "publicId": id, + }) +} + func (h *DetectionHandler) PrepareForSave(ctx context.Context, detect *model.Detection, e DetectionEngine) error { err := e.ExtractDetails(detect) if err != nil { diff --git a/server/modules/elastalert/elastalert.go b/server/modules/elastalert/elastalert.go index f8e49850..1fdc51db 100644 --- a/server/modules/elastalert/elastalert.go +++ b/server/modules/elastalert/elastalert.go @@ -1333,7 +1333,7 @@ func (e *ElastAlertEngine) sigmaToElastAlert(ctx context.Context, det *model.Det return query, nil } -func (e *ElastAlertEngine) generateUnusedPublicId(ctx context.Context) (string, error) { +func (e *ElastAlertEngine) GenerateUnusedPublicId(ctx context.Context) (string, error) { id := uuid.New().String() i := 0 @@ -1359,7 +1359,7 @@ func (e *ElastAlertEngine) generateUnusedPublicId(ctx context.Context) (string, } func (e *ElastAlertEngine) DuplicateDetection(ctx context.Context, detection *model.Detection) (*model.Detection, error) { - id, err := e.generateUnusedPublicId(ctx) + id, err := e.GenerateUnusedPublicId(ctx) if err != nil { return nil, err } diff --git a/server/modules/elastalert/validate_test.go b/server/modules/elastalert/validate_test.go index 89637d2a..5ab12ca9 100644 --- a/server/modules/elastalert/validate_test.go +++ b/server/modules/elastalert/validate_test.go @@ -189,7 +189,7 @@ func TestGenerateUnusedPublicId(t *testing.T) { isRunning: true, } - id, err := eng.generateUnusedPublicId(ctx) + id, err := eng.GenerateUnusedPublicId(ctx) assert.Empty(t, id) assert.Error(t, err) diff --git a/server/modules/strelka/strelka.go b/server/modules/strelka/strelka.go index f8ac6e94..b8aaff11 100644 --- a/server/modules/strelka/strelka.go +++ b/server/modules/strelka/strelka.go @@ -1003,6 +1003,12 @@ func (e *StrelkaEngine) DuplicateDetection(ctx context.Context, detection *model return det, nil } +func (e *StrelkaEngine) GenerateUnusedPublicId(ctx context.Context) (string, error) { + // PublicIDs for Strelka are the rule name which should correlate with what the rule does. + // Cannot generate arbitrary but still useful public IDs + return "", fmt.Errorf("not implemented") +} + func (e *StrelkaEngine) IntegrityCheck(canInterrupt bool) error { // escape if canInterrupt && !e.IntegrityCheckerData.IsRunning { diff --git a/server/modules/suricata/suricata.go b/server/modules/suricata/suricata.go index 60508f38..fec933b3 100644 --- a/server/modules/suricata/suricata.go +++ b/server/modules/suricata/suricata.go @@ -1506,7 +1506,7 @@ func lookupLicense(ruleset string) string { return license } -func (e *SuricataEngine) generateUnusedPublicId(ctx context.Context) (string, error) { +func (e *SuricataEngine) GenerateUnusedPublicId(ctx context.Context) (string, error) { id := strconv.Itoa(rand.IntN(1000000) + 1000000) // [1000000, 2000000) i := 0 @@ -1532,7 +1532,7 @@ func (e *SuricataEngine) generateUnusedPublicId(ctx context.Context) (string, er } func (e *SuricataEngine) DuplicateDetection(ctx context.Context, detection *model.Detection) (*model.Detection, error) { - id, err := e.generateUnusedPublicId(ctx) + id, err := e.GenerateUnusedPublicId(ctx) if err != nil { return nil, err } diff --git a/server/modules/suricata/validate_test.go b/server/modules/suricata/validate_test.go index 74341d65..ae8ee19a 100644 --- a/server/modules/suricata/validate_test.go +++ b/server/modules/suricata/validate_test.go @@ -215,7 +215,7 @@ func TestGenerateUnusedPublicId(t *testing.T) { isRunning: true, } - id, err := eng.generateUnusedPublicId(ctx) + id, err := eng.GenerateUnusedPublicId(ctx) assert.Empty(t, id) assert.Error(t, err) From e41f8e51a4ce8f046ef927e4c524388004762b4a Mon Sep 17 00:00:00 2001 From: Corey Ogburn Date: Tue, 28 May 2024 16:02:39 -0600 Subject: [PATCH 02/57] GetAll now uses Options for it's Options Instead of always accepting engine, isEnabled, and isCommunity, GetAllDetections now accepts a variable number of options. Previous call sites have been updated to do the same thing with the new approach. Updated tests. --- model/detection_options.go | 23 +++++++++++++++++++ server/detectionstore.go | 2 +- server/mock/mock_detectionstore.go | 13 +++++++---- server/modules/elastalert/elastalert.go | 4 ++-- .../modules/elastic/elasticdetectionstore.go | 14 +++-------- .../elastic/elasticdetectionstore_test.go | 5 ++-- server/modules/strelka/strelka.go | 6 ++--- server/modules/strelka/strelka_test.go | 7 +++--- server/modules/suricata/migration-2.4.70.go | 6 ++--- server/modules/suricata/suricata.go | 4 ++-- server/modules/suricata/suricata_test.go | 5 ++-- 11 files changed, 56 insertions(+), 33 deletions(-) create mode 100644 model/detection_options.go diff --git a/model/detection_options.go b/model/detection_options.go new file mode 100644 index 00000000..7be55f81 --- /dev/null +++ b/model/detection_options.go @@ -0,0 +1,23 @@ +package model + +import "fmt" + +type GetAllOption func(query string, schemaPrefix string) string + +func WithEngine(engine EngineName) GetAllOption { + return func(query string, schemaPrefix string) string { + return fmt.Sprintf(`%s AND %sdetection.engine:"%s"`, query, schemaPrefix, engine) + } +} + +func WithEnabled(isEnabled bool) GetAllOption { + return func(query string, schemaPrefix string) string { + return fmt.Sprintf(`%s AND %sdetection.isEnabled:"%t"`, query, schemaPrefix, isEnabled) + } +} + +func WithCommunity(isCommunity bool) GetAllOption { + return func(query string, schemaPrefix string) string { + return fmt.Sprintf(`%s AND %sdetection.isCommunity:"%t"`, query, schemaPrefix, isCommunity) + } +} diff --git a/server/detectionstore.go b/server/detectionstore.go index 05dd8150..e8ac11ee 100644 --- a/server/detectionstore.go +++ b/server/detectionstore.go @@ -19,7 +19,7 @@ type Detectionstore interface { UpdateDetection(ctx context.Context, detect *model.Detection) (*model.Detection, error) UpdateDetectionField(ctx context.Context, id string, fields map[string]interface{}) (*model.Detection, error) DeleteDetection(ctx context.Context, detectID string) (*model.Detection, error) - GetAllDetections(ctx context.Context, engine *model.EngineName, isEnabled *bool, isCommunity *bool) (map[string]*model.Detection, error) // map[detection.PublicId]detection + GetAllDetections(ctx context.Context, opts ...model.GetAllOption) (map[string]*model.Detection, error) // map[detection.PublicId]detection Query(ctx context.Context, query string, max int) ([]interface{}, error) GetDetectionHistory(ctx context.Context, detectID string) ([]interface{}, error) diff --git a/server/mock/mock_detectionstore.go b/server/mock/mock_detectionstore.go index 6aa627b6..614d4c9c 100644 --- a/server/mock/mock_detectionstore.go +++ b/server/mock/mock_detectionstore.go @@ -114,18 +114,23 @@ func (mr *MockDetectionstoreMockRecorder) DoesTemplateExist(arg0, arg1 any) *gom } // GetAllDetections mocks base method. -func (m *MockDetectionstore) GetAllDetections(arg0 context.Context, arg1 *model.EngineName, arg2, arg3 *bool) (map[string]*model.Detection, error) { +func (m *MockDetectionstore) GetAllDetections(arg0 context.Context, arg1 ...model.GetAllOption) (map[string]*model.Detection, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetAllDetections", arg0, arg1, arg2, arg3) + varargs := []any{arg0} + for _, a := range arg1 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "GetAllDetections", varargs...) ret0, _ := ret[0].(map[string]*model.Detection) ret1, _ := ret[1].(error) return ret0, ret1 } // GetAllDetections indicates an expected call of GetAllDetections. -func (mr *MockDetectionstoreMockRecorder) GetAllDetections(arg0, arg1, arg2, arg3 any) *gomock.Call { +func (mr *MockDetectionstoreMockRecorder) GetAllDetections(arg0 any, arg1 ...any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllDetections", reflect.TypeOf((*MockDetectionstore)(nil).GetAllDetections), arg0, arg1, arg2, arg3) + varargs := append([]any{arg0}, arg1...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllDetections", reflect.TypeOf((*MockDetectionstore)(nil).GetAllDetections), varargs...) } // GetComment mocks base method. diff --git a/server/modules/elastalert/elastalert.go b/server/modules/elastalert/elastalert.go index 1fdc51db..31ac2ad6 100644 --- a/server/modules/elastalert/elastalert.go +++ b/server/modules/elastalert/elastalert.go @@ -990,7 +990,7 @@ func (e *ElastAlertEngine) syncCommunityDetections(ctx context.Context, detects return nil, err } - community, err := e.srv.Detectionstore.GetAllDetections(ctx, util.Ptr(model.EngineNameElastAlert), nil, util.Ptr(true)) + community, err := e.srv.Detectionstore.GetAllDetections(ctx, model.WithEngine(model.EngineNameElastAlert), model.WithCommunity(true)) if err != nil { return nil, err } @@ -1601,7 +1601,7 @@ func (e *ElastAlertEngine) IntegrityCheck(canInterrupt bool) error { return detections.ErrIntCheckerStopped } - ret, err := e.srv.Detectionstore.GetAllDetections(e.srv.Context, util.Ptr(model.EngineNameElastAlert), util.Ptr(true), nil) + ret, err := e.srv.Detectionstore.GetAllDetections(e.srv.Context, model.WithEngine(model.EngineNameElastAlert), model.WithEnabled(true)) if err != nil { logger.WithError(err).Error("unable to query for enabled detections") return detections.ErrIntCheckFailed diff --git a/server/modules/elastic/elasticdetectionstore.go b/server/modules/elastic/elasticdetectionstore.go index 42ec7f18..67e88252 100644 --- a/server/modules/elastic/elasticdetectionstore.go +++ b/server/modules/elastic/elasticdetectionstore.go @@ -619,19 +619,11 @@ func (store *ElasticDetectionstore) DeleteDetection(ctx context.Context, id stri return detect, err } -func (store *ElasticDetectionstore) GetAllDetections(ctx context.Context, engine *model.EngineName, isEnabled *bool, isCommunity *bool) (map[string]*model.Detection, error) { +func (store *ElasticDetectionstore) GetAllDetections(ctx context.Context, opts ...model.GetAllOption) (map[string]*model.Detection, error) { query := fmt.Sprintf(`_index:"%s" AND %skind:"%s"`, store.index, store.schemaPrefix, "detection") - if engine != nil { - query += fmt.Sprintf(` AND %sdetection.engine:"%s"`, store.schemaPrefix, *engine) - } - - if isEnabled != nil { - query += fmt.Sprintf(` AND %sdetection.isEnabled:%t`, store.schemaPrefix, *isEnabled) - } - - if isCommunity != nil { - query += fmt.Sprintf(` AND %sdetection.isCommunity:%t`, store.schemaPrefix, *isCommunity) + for _, opt := range opts { + query = opt(query, store.schemaPrefix) } all, err := store.Query(ctx, query, -1) diff --git a/server/modules/elastic/elasticdetectionstore_test.go b/server/modules/elastic/elasticdetectionstore_test.go index 6f51b0dd..59f19bcf 100644 --- a/server/modules/elastic/elasticdetectionstore_test.go +++ b/server/modules/elastic/elasticdetectionstore_test.go @@ -15,6 +15,7 @@ import ( modmock "github.com/security-onion-solutions/securityonion-soc/server/modules/mock" "github.com/security-onion-solutions/securityonion-soc/util" "github.com/security-onion-solutions/securityonion-soc/web" + "github.com/stretchr/testify/assert" "github.com/tidwall/gjson" ) @@ -1091,12 +1092,12 @@ func TestGetAllCommunitySIDs(t *testing.T) { ctx := context.WithValue(context.Background(), web.ContextKeyRequestorId, "myRequestorId") - sids, err := store.GetAllDetections(ctx, nil, nil, nil) + sids, err := store.GetAllDetections(ctx) assert.NoError(t, err) assert.Equal(t, 1, len(sids)) assert.NotNil(t, sids["ABC123"]) - sids, err = store.GetAllDetections(ctx, util.Ptr(model.EngineName("suricata")), nil, nil) + sids, err = store.GetAllDetections(ctx, model.WithEngine(model.EngineNameSuricata)) assert.NoError(t, err) assert.Equal(t, 1, len(sids)) assert.NotNil(t, sids["ABC123"]) diff --git a/server/modules/strelka/strelka.go b/server/modules/strelka/strelka.go index b8aaff11..064c4f40 100644 --- a/server/modules/strelka/strelka.go +++ b/server/modules/strelka/strelka.go @@ -445,7 +445,7 @@ func (e *StrelkaEngine) startCommunityRuleImport() { } } - communityDetections, err := e.srv.Detectionstore.GetAllDetections(e.srv.Context, util.Ptr(model.EngineNameStrelka), nil, util.Ptr(true)) + communityDetections, err := e.srv.Detectionstore.GetAllDetections(e.srv.Context, model.WithEngine(model.EngineNameStrelka), model.WithCommunity(true)) if err != nil { log.WithError(err).Error("Failed to get all community SIDs") @@ -902,7 +902,7 @@ func buildImportChecker(pkg string) *regexp.Regexp { } func (e *StrelkaEngine) syncDetections(ctx context.Context) (errMap map[string]string, err error) { - results, err := e.srv.Detectionstore.GetAllDetections(ctx, util.Ptr(model.EngineNameStrelka), util.Ptr(true), nil) + results, err := e.srv.Detectionstore.GetAllDetections(ctx, model.WithEngine(model.EngineNameStrelka), model.WithEnabled(true)) if err != nil { return nil, err } @@ -1064,7 +1064,7 @@ func (e *StrelkaEngine) IntegrityCheck(canInterrupt bool) error { return detections.ErrIntCheckerStopped } - ret, err := e.srv.Detectionstore.GetAllDetections(e.srv.Context, util.Ptr(model.EngineNameStrelka), util.Ptr(true), nil) + ret, err := e.srv.Detectionstore.GetAllDetections(e.srv.Context, model.WithEngine(model.EngineNameStrelka), model.WithEnabled(true)) if err != nil { logger.WithError(err).Error("unable to query for enabled detections") return detections.ErrIntCheckFailed diff --git a/server/modules/strelka/strelka_test.go b/server/modules/strelka/strelka_test.go index 162d5166..5630145f 100644 --- a/server/modules/strelka/strelka_test.go +++ b/server/modules/strelka/strelka_test.go @@ -17,6 +17,7 @@ import ( servermock "github.com/security-onion-solutions/securityonion-soc/server/mock" "github.com/security-onion-solutions/securityonion-soc/server/modules/strelka/mock" "github.com/security-onion-solutions/securityonion-soc/util" + "github.com/tj/assert" "go.uber.org/mock/gomock" ) @@ -272,14 +273,14 @@ func TestSyncStrelka(t *testing.T) { { Name: "Enable Simple Rules", InitMock: func(mockDetStore *servermock.MockDetectionstore, mio *mock.MockIOManager) { - mockDetStore.EXPECT().GetAllDetections(gomock.Any(), util.Ptr(model.EngineNameStrelka), util.Ptr(true), nil).Return(map[string]*model.Detection{ - "1": &model.Detection{ + mockDetStore.EXPECT().GetAllDetections(gomock.Any(), gomock.Any(), gomock.Any()).Return(map[string]*model.Detection{ + "1": { PublicID: "1", Engine: model.EngineNameStrelka, Content: simpleRule, IsEnabled: true, }, - "2": &model.Detection{ + "2": { PublicID: "2", Engine: model.EngineNameStrelka, Content: simpleRule, diff --git a/server/modules/suricata/migration-2.4.70.go b/server/modules/suricata/migration-2.4.70.go index 001f5ecd..297c28b7 100644 --- a/server/modules/suricata/migration-2.4.70.go +++ b/server/modules/suricata/migration-2.4.70.go @@ -7,9 +7,9 @@ import ( "strings" "time" - "github.com/apex/log" "github.com/security-onion-solutions/securityonion-soc/model" - "github.com/security-onion-solutions/securityonion-soc/util" + + "github.com/apex/log" "gopkg.in/yaml.v3" ) @@ -45,7 +45,7 @@ func (e *SuricataEngine) Migration2470(statePath string) error { dirty := map[string]struct{}{} // map[sid]X // retrieve all suricata rules - detects, err := e.srv.Detectionstore.GetAllDetections(e.srv.Context, util.Ptr(model.EngineNameSuricata), nil, nil) + detects, err := e.srv.Detectionstore.GetAllDetections(e.srv.Context, model.WithEngine(model.EngineNameSuricata)) if err != nil { return err } diff --git a/server/modules/suricata/suricata.go b/server/modules/suricata/suricata.go index fec933b3..56aa6125 100644 --- a/server/modules/suricata/suricata.go +++ b/server/modules/suricata/suricata.go @@ -1208,7 +1208,7 @@ func (e *SuricataEngine) syncCommunityDetections(ctx context.Context, detects [] return nil, err } - commSIDs, err := e.srv.Detectionstore.GetAllDetections(ctx, util.Ptr(model.EngineNameSuricata), nil, util.Ptr(true)) + commSIDs, err := e.srv.Detectionstore.GetAllDetections(ctx, model.WithEngine(model.EngineNameSuricata), model.WithCommunity(true)) if err != nil { return nil, err } @@ -1654,7 +1654,7 @@ func (e *SuricataEngine) IntegrityCheck(canInterrupt bool) error { return detections.ErrIntCheckerStopped } - ret, err := e.srv.Detectionstore.GetAllDetections(e.srv.Context, util.Ptr(model.EngineNameSuricata), util.Ptr(true), util.Ptr(true)) + ret, err := e.srv.Detectionstore.GetAllDetections(e.srv.Context, model.WithEngine(model.EngineNameSuricata), model.WithEnabled(true), model.WithCommunity(true)) if err != nil { logger.WithError(err).Error("unable to query for enabled detections") return detections.ErrIntCheckFailed diff --git a/server/modules/suricata/suricata_test.go b/server/modules/suricata/suricata_test.go index 0cd182b2..36fedc99 100644 --- a/server/modules/suricata/suricata_test.go +++ b/server/modules/suricata/suricata_test.go @@ -18,6 +18,7 @@ import ( servermock "github.com/security-onion-solutions/securityonion-soc/server/mock" "github.com/security-onion-solutions/securityonion-soc/util" "github.com/security-onion-solutions/securityonion-soc/web" + "github.com/stretchr/testify/assert" "go.uber.org/mock/gomock" ) @@ -777,7 +778,7 @@ func TestSyncCommunitySuricata(t *testing.T) { }, }, InitMock: func(detStore *servermock.MockDetectionstore) { - detStore.EXPECT().GetAllDetections(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(map[string]*model.Detection{}, nil) + detStore.EXPECT().GetAllDetections(gomock.Any(), gomock.Any(), gomock.Any()).Return(map[string]*model.Detection{}, nil) detStore.EXPECT().CreateDetection(gomock.Any(), gomock.Any()).Return(nil, nil) }, ExpectedSettings: map[string]string{ @@ -800,7 +801,7 @@ func TestSyncCommunitySuricata(t *testing.T) { }, ChangedByUser: true, InitMock: func(detStore *servermock.MockDetectionstore) { - detStore.EXPECT().GetAllDetections(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(map[string]*model.Detection{}, nil) + detStore.EXPECT().GetAllDetections(gomock.Any(), gomock.Any(), gomock.Any()).Return(map[string]*model.Detection{}, nil) detStore.EXPECT().CreateDetection(gomock.Any(), gomock.Any()).Return(nil, nil) }, ExpectedSettings: map[string]string{ From ab1fa7d7d5e302bee2d238604d27f71e853a0b2d Mon Sep 17 00:00:00 2001 From: Corey Ogburn Date: Fri, 31 May 2024 10:10:36 -0600 Subject: [PATCH 03/57] Tests for the options --- model/detection_options_test.go | 45 +++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 model/detection_options_test.go diff --git a/model/detection_options_test.go b/model/detection_options_test.go new file mode 100644 index 00000000..90284981 --- /dev/null +++ b/model/detection_options_test.go @@ -0,0 +1,45 @@ +package model + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestWithEngine(t *testing.T) { + queryModder := WithEngine(EngineNameElastAlert) + query := queryModder("query", "schemaPrefix") + assert.Equal(t, query, `query AND schemaPrefixdetection.engine:"elastalert"`) + + queryModder = WithEngine(EngineNameStrelka) + query = queryModder("query", "schemaPrefix") + assert.Equal(t, query, `query AND schemaPrefixdetection.engine:"strelka"`) + + queryModder = WithEngine(EngineNameSuricata) + query = queryModder("query", "schemaPrefix") + assert.Equal(t, query, `query AND schemaPrefixdetection.engine:"suricata"`) + + queryModder = WithEngine(EngineName("unknown")) + query = queryModder("query", "schemaPrefix") + assert.Equal(t, query, `query AND schemaPrefixdetection.engine:"unknown"`) +} + +func TestWithEnabled(t *testing.T) { + queryModder := WithEnabled(true) + query := queryModder("query", "schemaPrefix") + assert.Equal(t, query, `query AND schemaPrefixdetection.isEnabled:"true"`) + + queryModder = WithEnabled(false) + query = queryModder("query", "schemaPrefix") + assert.Equal(t, query, `query AND schemaPrefixdetection.isEnabled:"false"`) +} + +func TestWithCommunity(t *testing.T) { + queryModder := WithCommunity(true) + query := queryModder("query", "schemaPrefix") + assert.Equal(t, query, `query AND schemaPrefixdetection.isCommunity:"true"`) + + queryModder = WithCommunity(false) + query = queryModder("query", "schemaPrefix") + assert.Equal(t, query, `query AND schemaPrefixdetection.isCommunity:"false"`) +} From 0151c9e728f58b0a0011f08d1902e55db1ab561b Mon Sep 17 00:00:00 2001 From: Corey Ogburn Date: Fri, 31 May 2024 11:17:11 -0600 Subject: [PATCH 04/57] Updated go-git go-git at version v5.11.0 was using a vulnerable version of github.com/cloudflare/circl (v1.3.3). Updating go-git to v5.12.0 updates the dependency to v1.3.8 which is not currently known to have any issues. Also ran go mod tidy. --- go.mod | 25 +++++++++++----------- go.sum | 65 ++++++++++++++++++++++++++++------------------------------ 2 files changed, 43 insertions(+), 47 deletions(-) diff --git a/go.mod b/go.mod index 9406e4c6..d65134af 100644 --- a/go.mod +++ b/go.mod @@ -11,31 +11,32 @@ require ( github.com/gorilla/websocket v1.5.1 github.com/influxdata/influxdb-client-go/v2 v2.13.0 github.com/kennygrant/sanitize v1.2.4 - github.com/stretchr/testify v1.8.4 + github.com/stretchr/testify v1.9.0 github.com/tidwall/gjson v1.17.0 - golang.org/x/crypto v0.21.0 - golang.org/x/net v0.23.0 // indirect - golang.org/x/sys v0.18.0 // indirect + golang.org/x/crypto v0.23.0 + golang.org/x/net v0.25.0 // indirect + golang.org/x/sys v0.20.0 // indirect gopkg.in/yaml.v3 v3.0.1 ) require ( - github.com/go-git/go-git/v5 v5.11.0 + github.com/go-git/go-git/v5 v5.12.0 github.com/hashicorp/go-multierror v1.1.1 github.com/pierrec/lz4/v4 v4.1.21 github.com/pkg/errors v0.9.1 github.com/samber/lo v1.39.0 github.com/tj/assert v0.0.3 go.uber.org/mock v0.3.0 + golang.org/x/mod v0.17.0 ) require ( dario.cat/mergo v1.0.0 // indirect - github.com/Microsoft/go-winio v0.6.1 // indirect - github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/ProtonMail/go-crypto v1.0.0 // indirect github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect - github.com/cloudflare/circl v1.3.3 // indirect - github.com/cyphar/filepath-securejoin v0.2.4 // indirect + github.com/cloudflare/circl v1.3.8 // indirect + github.com/cyphar/filepath-securejoin v0.2.5 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/elastic/elastic-transport-go/v8 v8.3.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect @@ -49,13 +50,11 @@ require ( github.com/oapi-codegen/runtime v1.0.0 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/sergi/go-diff v1.1.0 // indirect - github.com/skeema/knownhosts v1.2.1 // indirect + github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect + github.com/skeema/knownhosts v1.2.2 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 // indirect - golang.org/x/mod v0.14.0 // indirect - golang.org/x/tools v0.16.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect ) diff --git a/go.sum b/go.sum index bb7cb388..9f7f307d 100644 --- a/go.sum +++ b/go.sum @@ -1,10 +1,10 @@ dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= -github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg= -github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78= +github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= @@ -21,10 +21,11 @@ github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w= github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= -github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= -github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= -github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +github.com/cloudflare/circl v1.3.8 h1:j+V8jJt09PoeMFIu2uh5JUyEaIHTXVOHslFoLNAKqwI= +github.com/cloudflare/circl v1.3.8/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU= +github.com/cyphar/filepath-securejoin v0.2.5 h1:6iR5tXJ/e6tJZzzdMc1km3Sa7RRIVBKAK32O2s7AYfo= +github.com/cyphar/filepath-securejoin v0.2.5/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -38,8 +39,8 @@ github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= -github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4= +github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE= +github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8= github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk= github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= @@ -48,8 +49,8 @@ github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+ github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4= -github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY= +github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys= +github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -117,11 +118,11 @@ github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUz github.com/samber/lo v1.39.0 h1:4gTz1wUhNYLhFSKl6O+8peW0v2F4BCY034GRpU9WnuA= github.com/samber/lo v1.39.0/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= -github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= +github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ= -github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= +github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A= +github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM= github.com/smartystreets/gunit v1.0.0/go.mod h1:qwPWnhz6pn0NnRBP++URONOVyNkPyr4SauJk4cUOwJs= @@ -131,8 +132,8 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +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.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM= github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= @@ -159,16 +160,16 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 h1:qCEDpW1G+vcj3Y7Fy52pEM1AWm3abj8WimGYejI3SC4= golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -178,14 +179,12 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= -golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -202,15 +201,15 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= -golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -219,15 +218,13 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM= -golang.org/x/tools v0.16.0/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -240,7 +237,7 @@ gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= From 35552b7e7d37e64f0bffa05b818974c7d0e842cf Mon Sep 17 00:00:00 2001 From: Corey Ogburn Date: Wed, 29 May 2024 11:49:30 -0600 Subject: [PATCH 05/57] dateAwareSort for v-data-tables Some cypress tests fail because the newly added item wasn't added to the top or bottom of a table as expected. This is because those tables aren't sorting their dates as dates, but as strings. This new date aware sort fixes that. It's not actually aware that the data contains a date, it flags off the field being sorted to determine if it should be converted to date before sorting. Currently sorting by "createTime" and "updateTime" will treat their values as dates, everything else is converted to strings. The new sort has been applied to Case Observables, Case History, and Detection History. Hunt seems to use a different format for it's timestamps such that when sorted as a string it will sort it chronologically. Leaving that table untouched for now. Added test. Cypress tests already assume sorts work so they don't need updating. --- html/index.html | 8 ++++---- html/js/app.js | 23 ++++++++++++++++++++- html/js/app.test.js | 50 +++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 74 insertions(+), 7 deletions(-) diff --git a/html/index.html b/html/index.html index 7c19c14c..770ce1bb 100644 --- a/html/index.html +++ b/html/index.html @@ -1426,7 +1426,7 @@

{{ i18n.commentAddDetection }}

{{ i18n.save }} - +
@@ -1584,7 +1584,7 @@

{{ i18n.commentAddDetection }}

+ :items="history" item-key="id" :loading="historyTableOpts.loading" :expanded="historyTableOpts.expanded" class="history-table" :custom-sort="$root.dateAwareSort">