Skip to content

Commit

Permalink
Merge pull request #357 from Security-Onion-Solutions/jertel/detdisable
Browse files Browse the repository at this point in the history
disable community rule auto updates by default
  • Loading branch information
jertel authored Feb 23, 2024
2 parents b5f0e4a + fc8ed6d commit e664b0b
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 48 deletions.
21 changes: 17 additions & 4 deletions server/modules/elastalert/elastalert.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ type ElastAlertEngine struct {
thread *sync.WaitGroup
allowRegex *regexp.Regexp
denyRegex *regexp.Regexp
autoUpdateEnabled bool
IOManager
}

Expand All @@ -82,6 +83,7 @@ func (e *ElastAlertEngine) Init(config module.ModuleConfig) error {
e.sigmaPackageDownloadTemplate = module.GetStringDefault(config, "sigmaPackageDownloadTemplate", "https://github.com/SigmaHQ/sigma/releases/latest/download/sigma_%s.zip")
e.elastAlertRulesFolder = module.GetStringDefault(config, "elastAlertRulesFolder", "/opt/so/rules/elastalert")
e.rulesFingerprintFile = module.GetStringDefault(config, "rulesFingerprintFile", "/opt/so/conf/soc/sigma.fingerprint")
e.autoUpdateEnabled = module.GetBoolDefault(config, "autoUpdateEnabled", false)

pkgs := module.GetStringArrayDefault(config, "sigmaRulePackages", []string{"core"})
e.parseSigmaPackages(pkgs)
Expand Down Expand Up @@ -302,10 +304,21 @@ func (e *ElastAlertEngine) startCommunityRuleImport() {
templateFound = true
}

zips, errMap := e.downloadSigmaPackages(ctx)
if len(errMap) != 0 {
log.WithField("errorMap", errMap).Error("something went wrong downloading sigma packages")
continue
var zips map[string][]byte
var errMap map[string]error
if e.autoUpdateEnabled {
zips, errMap = e.downloadSigmaPackages(ctx)
if len(errMap) != 0 {
log.WithField("errorMap", errMap).Error("something went wrong downloading sigma packages")
continue
}
} else {
// Possible airgap installation, or admin has disabled auto-updates.

// TODO: Perform a one-time check for a pre-downloaded ruleset on disk and if exists,
// let the rest of the loop continue but then exit the loop. For now we're just hardcoding
// to always exit the loop.
return
}

zipHashes := map[string]string{}
Expand Down
1 change: 1 addition & 0 deletions server/modules/elastalert/elastalert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ func TestElastAlertModule(t *testing.T) {

err := mod.Init(nil)
assert.NoError(t, err)
assert.False(t, mod.autoUpdateEnabled)

err = mod.Start()
assert.NoError(t, err)
Expand Down
99 changes: 55 additions & 44 deletions server/modules/strelka/strelka.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ type StrelkaEngine struct {
allowRegex *regexp.Regexp
denyRegex *regexp.Regexp
compileRules bool
autoUpdateEnabled bool
IOManager
}

Expand All @@ -76,6 +77,7 @@ func (e *StrelkaEngine) Init(config module.ModuleConfig) error {
e.rulesRepos = module.GetStringArrayDefault(config, "rulesRepos", []string{"github.com/Security-Onion-Solutions/securityonion-yara"})
e.compileYaraPythonScriptPath = module.GetStringDefault(config, "compileYaraPythonScriptPath", "/opt/so/conf/strelka/compile_yara.py")
e.compileRules = module.GetBoolDefault(config, "compileRules", true)
e.autoUpdateEnabled = module.GetBoolDefault(config, "autoUpdateEnabled", false)

allow := module.GetStringDefault(config, "allowRegex", "")
deny := module.GetStringDefault(config, "denyRegex", "")
Expand Down Expand Up @@ -200,61 +202,70 @@ func (e *StrelkaEngine) startCommunityRuleImport() {

upToDate := map[string]struct{}{}

// pull or clone repos
for _, repo := range e.rulesRepos {
parser, err := url.Parse(repo)
if err != nil {
log.WithError(err).WithField("repo", repo).Error("Failed to parse repo URL, doing nothing with it")
continue
}

_, lastFolder := path.Split(parser.Path)
repoPath := filepath.Join(e.reposFolder, lastFolder)

if _, ok := existingRepos[lastFolder]; ok {
// repo already exists, pull
repo, err := git.PlainOpen(repoPath)
if e.autoUpdateEnabled {
// pull or clone repos
for _, repo := range e.rulesRepos {
parser, err := url.Parse(repo)
if err != nil {
log.WithError(err).WithField("repo", repo).Error("Failed to open repo, doing nothing with it")
log.WithError(err).WithField("repo", repo).Error("Failed to parse repo URL, doing nothing with it")
continue
}

work, err := repo.Worktree()
if err != nil {
log.WithError(err).WithField("repo", repo).Error("Failed to get worktree, doing nothing with it")
continue
}
_, lastFolder := path.Split(parser.Path)
repoPath := filepath.Join(e.reposFolder, lastFolder)

if _, ok := existingRepos[lastFolder]; ok {
// repo already exists, pull
repo, err := git.PlainOpen(repoPath)
if err != nil {
log.WithError(err).WithField("repo", repo).Error("Failed to open repo, doing nothing with it")
continue
}

ctx, cancel := context.WithTimeout(e.srv.Context, time.Minute*5)
work, err := repo.Worktree()
if err != nil {
log.WithError(err).WithField("repo", repo).Error("Failed to get worktree, doing nothing with it")
continue
}

ctx, cancel := context.WithTimeout(e.srv.Context, time.Minute*5)

err = work.PullContext(ctx, &git.PullOptions{
Depth: 1,
SingleBranch: true,
})
if err != nil && err != git.NoErrAlreadyUpToDate {
err = work.PullContext(ctx, &git.PullOptions{
Depth: 1,
SingleBranch: true,
})
if err != nil && err != git.NoErrAlreadyUpToDate {
cancel()
log.WithError(err).WithField("repo", repo).Error("Failed to pull repo, doing nothing with it")
continue
}
cancel()
log.WithError(err).WithField("repo", repo).Error("Failed to pull repo, doing nothing with it")
continue
}
cancel()

if err == nil {
if err == nil {
upToDate[repoPath] = struct{}{}
}
} else {
// repo does not exist, clone
_, err = git.PlainClone(repoPath, false, &git.CloneOptions{
Depth: 1,
SingleBranch: true,
URL: repo,
})
if err != nil {
log.WithError(err).WithField("repo", repo).Error("Failed to clone repo, doing nothing with it")
continue
}

upToDate[repoPath] = struct{}{}
}
} else {
// repo does not exist, clone
_, err = git.PlainClone(repoPath, false, &git.CloneOptions{
Depth: 1,
SingleBranch: true,
URL: repo,
})
if err != nil {
log.WithError(err).WithField("repo", repo).Error("Failed to clone repo, doing nothing with it")
continue
}

upToDate[repoPath] = struct{}{}
}
} else {
// Possible airgap installation, or admin has disabled auto-updates.

// TODO: Perform a one-time check for a pre-downloaded ruleset on disk and if exists,
// let the rest of the loop continue but then exit the loop. For now we're just hardcoding
// to always exit the loop.
return
}

if len(upToDate) == 0 {
Expand Down
1 change: 1 addition & 0 deletions server/modules/strelka/strelka_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ func TestStrelkaModule(t *testing.T) {

err := mod.Init(nil)
assert.NoError(t, err)
assert.False(t, mod.autoUpdateEnabled)

err = mod.Start()
assert.NoError(t, err)
Expand Down

0 comments on commit e664b0b

Please sign in to comment.