Skip to content

Commit

Permalink
Merge pull request #618 from Security-Onion-Solutions/jertel/an2
Browse files Browse the repository at this point in the history
update gofast images; tiered notifications
  • Loading branch information
jertel authored Aug 21, 2024
2 parents 3c4c5aa + e36a9eb commit 4a0b527
Show file tree
Hide file tree
Showing 4 changed files with 184 additions and 33 deletions.
Binary file added html/images/appliances/GOFASTv2_back_thumb.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
152 changes: 123 additions & 29 deletions server/modules/elastalert/elastalert.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,30 +83,41 @@ var acceptedExtensions = map[string]bool{
}

type ElastAlertEngine struct {
srv *server.Server
airgapBasePath string
failAfterConsecutiveErrorCount int
sigmaPackageDownloadTemplate string
elastAlertRulesFolder string
rulesFingerprintFile string
sigmaPipelineFinal string
sigmaPipelineSO string
sigmaPipelinesFingerprintFile string
sigmaRulePackages []string
autoEnabledSigmaRules []string
additionalAlerters []string
rulesRepos []*model.RuleRepo
reposFolder string
isRunning bool
interm sync.Mutex
airgapEnabled bool
notify bool
writeNoRead *string
aiSummaries *sync.Map // map[string]*detections.AiSummary{}
showAiSummaries bool
aiRepoUrl string
aiRepoBranch string
aiRepoPath string
srv *server.Server
airgapBasePath string
failAfterConsecutiveErrorCount int
sigmaPackageDownloadTemplate string
elastAlertRulesFolder string
rulesFingerprintFile string
sigmaPipelineFinal string
sigmaPipelineSO string
sigmaPipelinesFingerprintFile string
sigmaRulePackages []string
autoEnabledSigmaRules []string
additionalAlerters []string
additionalAlerterParams string
informationalSeverityAlerters []string
informationalSeverityAlerterParams string
lowSeverityAlerters []string
lowSeverityAlerterParams string
mediumSeverityAlerters []string
mediumSeverityAlerterParams string
highSeverityAlerters []string
highSeverityAlerterParams string
criticalSeverityAlerters []string
criticalSeverityAlerterParams string
rulesRepos []*model.RuleRepo
reposFolder string
isRunning bool
interm sync.Mutex
airgapEnabled bool
notify bool
writeNoRead *string
aiSummaries *sync.Map // map[string]*detections.AiSummary{}
showAiSummaries bool
aiRepoUrl string
aiRepoBranch string
aiRepoPath string
detections.SyncSchedulerParams
detections.IntegrityCheckerData
detections.IOManager
Expand Down Expand Up @@ -167,6 +178,17 @@ func (e *ElastAlertEngine) Init(config module.ModuleConfig) (err error) {
e.CommunityRulesImportErrorSeconds = module.GetIntDefault(config, "communityRulesImportErrorSeconds", DEFAULT_COMMUNITY_RULES_IMPORT_ERROR_SECS)
e.failAfterConsecutiveErrorCount = module.GetIntDefault(config, "failAfterConsecutiveErrorCount", DEFAULT_FAIL_AFTER_CONSECUTIVE_ERROR_COUNT)
e.additionalAlerters = module.GetStringArrayDefault(config, "additionalAlerters", []string{})
e.additionalAlerterParams = module.GetStringDefault(config, "additionalSev0AlertersParams", "")
e.informationalSeverityAlerters = module.GetStringArrayDefault(config, "additionalSev1Alerters", []string{})
e.informationalSeverityAlerterParams = module.GetStringDefault(config, "additionalSev1AlertersParams", "")
e.lowSeverityAlerters = module.GetStringArrayDefault(config, "additionalSev2Alerters", []string{})
e.lowSeverityAlerterParams = module.GetStringDefault(config, "additionalSev2AlertersParams", "")
e.mediumSeverityAlerters = module.GetStringArrayDefault(config, "additionalSev3Alerters", []string{})
e.mediumSeverityAlerterParams = module.GetStringDefault(config, "additionalSev3AlertersParams", "")
e.highSeverityAlerters = module.GetStringArrayDefault(config, "additionalSev4Alerters", []string{})
e.highSeverityAlerterParams = module.GetStringDefault(config, "additionalSev4AlertersParams", "")
e.criticalSeverityAlerters = module.GetStringArrayDefault(config, "additionalSev5Alerters", []string{})
e.criticalSeverityAlerterParams = module.GetStringDefault(config, "additionalSev5AlertersParams", "")
e.IntegrityCheckerData.FrequencySeconds = module.GetIntDefault(config, "integrityCheckFrequencySeconds", DEFAULT_INTEGRITY_CHECK_FREQUENCY_SECONDS)

pkgs := module.GetStringArrayDefault(config, "sigmaRulePackages", []string{"core", "emerging_threats_addon"})
Expand Down Expand Up @@ -427,7 +449,7 @@ func (e *ElastAlertEngine) SyncLocalDetections(ctx context.Context, detections [
continue
}

wrapped, err := wrapRule(det, eaRule, e.additionalAlerters)
wrapped, err := e.wrapRule(det, eaRule)
if err != nil {
continue
}
Expand Down Expand Up @@ -1075,7 +1097,7 @@ func (e *ElastAlertEngine) syncCommunityDetections(ctx context.Context, logger *
continue
}

rule, err = wrapRule(detect, rule, e.additionalAlerters)
rule, err = e.wrapRule(detect, rule)
if err != nil {
continue
}
Expand Down Expand Up @@ -1508,6 +1530,64 @@ func (e *ElastAlertEngine) MergeAuxiliaryData(detect *model.Detection) error {
return nil
}

func (e *ElastAlertEngine) getAdditionalAlerters(severity int) ([]string, string) {
// Start with default alerters
alerters := e.additionalAlerters
params := e.additionalAlerterParams

// Override if info or above severity
if severity > 0 {
if len(e.informationalSeverityAlerters) > 0 {
alerters = e.informationalSeverityAlerters
}
if len(e.informationalSeverityAlerterParams) > 0 {
params = e.informationalSeverityAlerterParams
}
}

// Override if low or above severity
if severity > 1 {
if len(e.lowSeverityAlerters) > 0 {
alerters = e.lowSeverityAlerters
}
if len(e.lowSeverityAlerterParams) > 0 {
params = e.lowSeverityAlerterParams
}
}

// Override if med or above severity
if severity > 2 {
if len(e.mediumSeverityAlerters) > 0 {
alerters = e.mediumSeverityAlerters
}
if len(e.mediumSeverityAlerterParams) > 0 {
params = e.mediumSeverityAlerterParams
}
}

// Override if high or crit severity
if severity > 3 {
if len(e.highSeverityAlerters) > 0 {
alerters = e.highSeverityAlerters
}
if len(e.highSeverityAlerterParams) > 0 {
params = e.highSeverityAlerterParams
}
}

// Override if crit severity
if severity > 4 {
if len(e.criticalSeverityAlerters) > 0 {
alerters = e.criticalSeverityAlerters
}
if len(e.criticalSeverityAlerterParams) > 0 {
params = e.criticalSeverityAlerterParams
}
}

return alerters, params
}

type CustomWrapper struct {
DetectionTitle string `yaml:"detection_title"`
DetectionPublicId string `yaml:"detection_public_id"`
Expand Down Expand Up @@ -1644,7 +1724,7 @@ func (dur *TimeFrame) UnmarshalYAML(unmarshal func(interface{}) error) error {
return err
}

func wrapRule(det *model.Detection, rule string, additionalAlerters []string) (string, error) {
func (e *ElastAlertEngine) wrapRule(det *model.Detection, rule string) (string, error) {
severities := map[model.Severity]int{
model.SeverityUnknown: 0,
model.SeverityInformational: 1,
Expand All @@ -1654,6 +1734,13 @@ func wrapRule(det *model.Detection, rule string, additionalAlerters []string) (s
model.SeverityCritical: 5,
}

alerters, params := e.getAdditionalAlerters(severities[det.Severity])
log.WithFields(log.Fields{
"sevNum": severities[det.Severity],
"sev": det.Severity,
"params": params,
}).Error("********** Got params")

sevNum := severities[det.Severity]
realert := TimeFrame{}
realert.SetSeconds(0)
Expand All @@ -1678,7 +1765,7 @@ func wrapRule(det *model.Detection, rule string, additionalAlerters []string) (s

if licensing.IsEnabled(licensing.FEAT_NTF) {
// Add any custom alerters to the rule.
for _, alerter := range additionalAlerters {
for _, alerter := range alerters {
alerter = strings.TrimSpace(alerter)
if len(alerter) > 0 {
wrapper.Alert = append(wrapper.Alert, alerter)
Expand All @@ -1690,8 +1777,15 @@ func wrapRule(det *model.Detection, rule string, additionalAlerters []string) (s
if err != nil {
return "", err
}
strYaml := string(rawYaml)

if licensing.IsEnabled(licensing.FEAT_NTF) {
if len(params) > 0 {
strYaml += "\n" + params + "\n"
}
}

return string(rawYaml), nil
return strYaml, nil
}

func (e *ElastAlertEngine) IntegrityCheck(canInterrupt bool, logger *log.Entry) (deployedButNotEnabled []string, enabledButNotDeployed []string, err error) {
Expand Down
65 changes: 61 additions & 4 deletions server/modules/elastalert/elastalert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,8 @@ func TestSigmaToElastAlertSunnyDay(t *testing.T) {
})).Return([]byte("<eql>"), 0, time.Duration(0), nil)

engine := ElastAlertEngine{
IOManager: iom,
IOManager: iom,
additionalAlerters: []string{"email", "slack"},
}

det := &model.Detection{
Expand All @@ -362,7 +363,7 @@ func TestSigmaToElastAlertSunnyDay(t *testing.T) {
assert.NoError(t, err)

// No license
wrappedRule, err := wrapRule(det, query, []string{"email", "slack"})
wrappedRule, err := engine.wrapRule(det, query)
assert.NoError(t, err)

expected := `detection_title: Test Detection
Expand Down Expand Up @@ -409,7 +410,9 @@ func TestSigmaToElastAlertSunnyDayLicensed(t *testing.T) {
})).Return([]byte("<eql>"), 0, time.Duration(0), nil)

engine := ElastAlertEngine{
IOManager: iom,
IOManager: iom,
additionalAlerters: []string{"email", "slack"},
additionalAlerterParams: "foo: bar",
}

det := &model.Detection{
Expand All @@ -424,7 +427,7 @@ func TestSigmaToElastAlertSunnyDayLicensed(t *testing.T) {

// License
licensing.Test(licensing.FEAT_NTF, 0, 0, "", "")
wrappedRule, err := wrapRule(det, query, []string{"email", "slack"})
wrappedRule, err := engine.wrapRule(det, query)
assert.NoError(t, err)

expected := `detection_title: Test Detection
Expand All @@ -444,10 +447,64 @@ realert:
seconds: 0
filter:
- eql: <eql>
foo: bar
`
assert.YAMLEq(t, expected, wrappedRule)
}

func TestAdditionalAlertersSev0(t *testing.T) {
engine := ElastAlertEngine{
additionalAlerters: []string{"email", "slack"},
additionalAlerterParams: "foo: bar",
}

for sev := range 6 {
alerters, params := engine.getAdditionalAlerters(sev)
assert.Equal(t, []string{"email", "slack"}, alerters)
assert.Equal(t, "foo: bar", params)
}
}

func TestAdditionalAlertersSev0Sev3(t *testing.T) {
engine := ElastAlertEngine{
additionalAlerters: []string{"email", "slack"},
additionalAlerterParams: "foo: bar",
mediumSeverityAlerters: []string{"teams"},
mediumSeverityAlerterParams: "foo: boo",
}

for sev := range 6 {
alerters, params := engine.getAdditionalAlerters(sev)
if sev < 3 {
assert.Equal(t, []string{"email", "slack"}, alerters)
assert.Equal(t, "foo: bar", params)
} else {
assert.Equal(t, []string{"teams"}, alerters)
assert.Equal(t, "foo: boo", params)
}
}
}

func TestAdditionalAlertersSev0Sev5(t *testing.T) {
engine := ElastAlertEngine{
additionalAlerters: []string{"email", "slack"},
additionalAlerterParams: "foo: bar",
criticalSeverityAlerters: []string{"teams"},
criticalSeverityAlerterParams: "foo: boo",
}

for sev := range 6 {
alerters, params := engine.getAdditionalAlerters(sev)
if sev < 5 {
assert.Equal(t, []string{"email", "slack"}, alerters)
assert.Equal(t, "foo: bar", params)
} else {
assert.Equal(t, []string{"teams"}, alerters)
assert.Equal(t, "foo: boo", params)
}
}
}

func TestSigmaToElastAlertError(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
Expand Down

0 comments on commit 4a0b527

Please sign in to comment.