зеркало из https://github.com/mozilla/mig.git
Agent: Filechecker module: use flexible JSON syntax in module commands
This commit reworks the arguments passed to agent's modules as an undefined interface{} in JSON format. It will allow complex commands to be passed to the modules.
This commit is contained in:
Родитель
0b2bab7e7e
Коммит
2817bca128
|
@ -2,7 +2,13 @@
|
|||
"Name": "MOZSYSCOMP_LOWENCCRED",
|
||||
"Target": "linux",
|
||||
"Check": "filechecker",
|
||||
"Arguments":["/etc/shadow:contains=root:$1$"],
|
||||
"Arguments": {
|
||||
"MOZSYSCOMPLOWENCCRED1" : {
|
||||
"Path": "/etc/shadow",
|
||||
"Type": "contains",
|
||||
"Value": "root:\\$6"
|
||||
}
|
||||
},
|
||||
"RunDate": "immediate",
|
||||
"Expiration": "30m"
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// TODO
|
||||
// * syntax check mig.Action.Arguments before exec()
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
|
@ -114,8 +117,7 @@ func main() {
|
|||
go getCommands(msgChan, actionsChan, termChan)
|
||||
}
|
||||
go parseCommands(actionsChan, fCommandChan, termChan)
|
||||
go runFilechecker(fCommandChan, alertChan, resultChan, termChan)
|
||||
go raiseAlerts(alertChan, termChan)
|
||||
go runFilechecker(fCommandChan, resultChan, termChan)
|
||||
go sendResults(c, regMsg.QueueLoc, resultChan, termChan)
|
||||
|
||||
// All set, ready to keepAlive
|
||||
|
@ -162,72 +164,36 @@ func parseCommands(commands <-chan []byte, fCommandChan chan mig.Command, termin
|
|||
return nil
|
||||
}
|
||||
|
||||
func runFilechecker(fCommandChan <-chan mig.Command, alertChan chan mig.Alert, resultChan chan mig.Command, terminate chan bool) error {
|
||||
func runFilechecker(fCommandChan <-chan mig.Command, resultChan chan mig.Command, terminate chan bool) error {
|
||||
for migCmd := range fCommandChan {
|
||||
log.Printf("RunFilechecker: running with args '%s'", migCmd.Action.Arguments)
|
||||
var cmdArg string
|
||||
for _, arg := range migCmd.Action.Arguments {
|
||||
cmdArg += arg
|
||||
}
|
||||
runCmd := exec.Command("./filechecker", cmdArg)
|
||||
cmdout, err := runCmd.StdoutPipe()
|
||||
// Arguments can contain anything. Syntax Check before feeding
|
||||
// them to exec()
|
||||
args, err := json.Marshal(migCmd.Action.Arguments)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
log.Fatal("runFilechecker json.Marshal(migCmd.Action.Arguments): ", err)
|
||||
}
|
||||
st := time.Now()
|
||||
err = runCmd.Start()
|
||||
s_args := fmt.Sprintf("%s", args)
|
||||
log.Printf("runFilechecker: arguments %s", s_args)
|
||||
runCmd := exec.Command("/opt/agent","-m","filechecker",s_args)
|
||||
output, err := runCmd.CombinedOutput()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
log.Fatal("runFilechecker cmd.CombinedOutput(): ",
|
||||
fmt.Sprint(err), " - ", string(output))
|
||||
} else {
|
||||
log.Println("runFilechecker cmd.CombinedOutput(): ",
|
||||
string(output))
|
||||
}
|
||||
results := make(map[string]mig.FileCheckerResult)
|
||||
err = json.NewDecoder(cmdout).Decode(&results)
|
||||
err = json.Unmarshal([]byte(output), &migCmd.Results)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
cmdDone := make(chan error)
|
||||
go func() {
|
||||
cmdDone <- runCmd.Wait()
|
||||
}()
|
||||
select {
|
||||
// kill the process when timeout expires
|
||||
case <-time.After(30 * time.Second):
|
||||
if err := runCmd.Process.Kill(); err != nil {
|
||||
log.Fatal("failed to kill:", err)
|
||||
}
|
||||
log.Fatal("runFileChecker: command '%s' timed out", migCmd)
|
||||
// exit normally
|
||||
case err := <-cmdDone:
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
for _, r := range results {
|
||||
log.Println("runFileChecker: command", migCmd, "tested",
|
||||
r.TestedFiles, "files in", time.Now().Sub(st))
|
||||
if r.ResultCount > 0 {
|
||||
for _, f := range r.Files {
|
||||
alertChan <- mig.Alert{
|
||||
Arguments: migCmd.Action.Arguments,
|
||||
Item: f,
|
||||
}
|
||||
}
|
||||
}
|
||||
migCmd.FCResults = append(migCmd.FCResults, r)
|
||||
log.Fatal("runFilechecker json.Unmarshal(): ", err)
|
||||
}
|
||||
// send the results back to the scheduler
|
||||
resultChan <- migCmd
|
||||
}
|
||||
terminate <- true
|
||||
return nil
|
||||
}
|
||||
|
||||
func raiseAlerts(alertChan chan mig.Alert, terminate chan bool) error {
|
||||
for a := range alertChan {
|
||||
log.Printf("raiseAlerts: IOC '%s' positive match on '%s'",
|
||||
a.Arguments, a.Item)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func sendResults(c *amqp.Channel, agtQueueLoc string, resultChan <-chan mig.Command, terminate chan bool) error {
|
||||
rKey := fmt.Sprintf("mig.sched.%s", agtQueueLoc)
|
||||
for r := range resultChan {
|
||||
|
|
|
@ -41,10 +41,10 @@ import (
|
|||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"hash"
|
||||
"io"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"regexp"
|
||||
)
|
||||
|
@ -69,16 +69,20 @@ const (
|
|||
CheckSHA3_512
|
||||
)
|
||||
|
||||
/* Representation of a File Check.
|
||||
- Path is the file system path to inspect
|
||||
- Type is the name of the type of check
|
||||
- Value is the value of the check, such as a md5 hash
|
||||
- CodeType is the type of check in integer form
|
||||
- FilesCount is the total number of files inspected for each Check
|
||||
- MatchCount is a counter of positive results for this Check
|
||||
- Result is a boolean set to True when the Check has matched once or more
|
||||
- Files is an slice of string that contains paths of matching files
|
||||
*/
|
||||
type Arguments struct {
|
||||
Arg map[string]FileCheck
|
||||
}
|
||||
|
||||
// Representation of a File Check.
|
||||
// Path is the file system path to inspect
|
||||
// Type is the name of the type of check
|
||||
// Value is the value of the check, such as a md5 hash
|
||||
// CodeType is the type of check in integer form
|
||||
// FilesCount is the total number of files inspected for each Check
|
||||
// MatchCount is a counter of positive results for this Check
|
||||
// Result is a boolean set to True when the Check has matched once or more
|
||||
// Files is an slice of string that contains paths of matching files
|
||||
// Re is a regular expression
|
||||
type FileCheck struct {
|
||||
ID, Path, Type, Value string
|
||||
CodeType, FilesCount, MatchCount int
|
||||
|
@ -87,9 +91,9 @@ type FileCheck struct {
|
|||
Re *regexp.Regexp
|
||||
}
|
||||
|
||||
type CheckResult struct {
|
||||
type Results struct {
|
||||
TestedFiles, MatchCount int
|
||||
Files []string
|
||||
Files []string
|
||||
}
|
||||
|
||||
/* Statistic counters:
|
||||
|
@ -529,7 +533,7 @@ func GetDownThatPath(path string, ActiveCheckIDs []string, CheckBitMask int,
|
|||
- nil on success, error on failure
|
||||
*/
|
||||
func BuildResults(Checks map[string]FileCheck, Statistics *Stats) (string) {
|
||||
Results := make(map[string]CheckResult)
|
||||
res := make(map[string]Results)
|
||||
FileHistory := make(map[string]int)
|
||||
for _, check := range Checks {
|
||||
if VERBOSE {
|
||||
|
@ -553,7 +557,7 @@ func BuildResults(Checks map[string]FileCheck, Statistics *Stats) (string) {
|
|||
for f, _ := range check.Files {
|
||||
listPosFiles = append(listPosFiles, f)
|
||||
}
|
||||
Results[check.ID] = CheckResult{
|
||||
res[check.ID] = Results{
|
||||
TestedFiles: check.FilesCount,
|
||||
MatchCount: check.MatchCount,
|
||||
Files: listPosFiles,
|
||||
|
@ -569,7 +573,7 @@ func BuildResults(Checks map[string]FileCheck, Statistics *Stats) (string) {
|
|||
Statistics.ChecksMatch, Statistics.UniqueFiles,
|
||||
Statistics.TotalHits)
|
||||
}
|
||||
JsonResults, err := json.Marshal(Results)
|
||||
JsonResults, err := json.Marshal(res)
|
||||
if err != nil { panic(err) }
|
||||
return string(JsonResults[:])
|
||||
}
|
||||
|
|
|
@ -6,24 +6,19 @@ import(
|
|||
|
||||
type Action struct {
|
||||
Name, Target, Check, RunDate, Expiration string
|
||||
Arguments []string
|
||||
Arguments interface{}
|
||||
UniqID uint32
|
||||
}
|
||||
|
||||
type Command struct {
|
||||
AgentName, AgentQueueLoc string
|
||||
Action Action
|
||||
FCResults []FileCheckerResult
|
||||
Results interface{}
|
||||
UniqID uint32
|
||||
}
|
||||
|
||||
type FileCheckerResult struct {
|
||||
TestedFiles, ResultCount int
|
||||
Files []string
|
||||
}
|
||||
|
||||
type Alert struct {
|
||||
Arguments []string
|
||||
Arguments interface{}
|
||||
Item string
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче