<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Contributor: <NAME> <EMAIL> [:alm]
package main

// This is a plugin for use with mig-runner that processes incoming compliance
// results from MIG and sends them to MozDef
//
// It replaces the historical compliance item worker process. This program
// generally is not run directly, but instead should be called by mig-runner
// as a plugin.

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"time"

	"github.com/jvehent/gozdef"
	"gopkg.in/gcfg.v1"
	"mig.ninja/mig"
	"mig.ninja/mig/modules"
	"mig.ninja/mig/modules/file"
)

type Config struct {
	MIG struct {
		// The MIG API URL
		API string
	}
	MozDef struct {
		// URL to post events to MozDef
		URL string
	}
	Vmintgr struct {
		// Location of vmintgr wrapper executable
		Bin string
	}
}

const configPath string = "/etc/mig/runner-compliance.conf"

var conf Config

func main() {
	defer func() {
		if e := recover(); e != nil {
			fmt.Fprintf(os.Stderr, "error: %v\n", e)
			os.Exit(1)
		}
	}()

	var (
		err     error
		results mig.RunnerResult
	)

	err = gcfg.ReadFileInto(&conf, configPath)
	if err != nil {
		panic(err)
	}

	buf, err := ioutil.ReadAll(os.Stdin)
	if err != nil {
		panic(err)
	}
	err = json.Unmarshal(buf, &results)
	if err != nil {
		panic(err)
	}
	for _, x := range results.Commands {
		items, err := makeComplianceItem(x)
		if err != nil {
			panic(err)
		}
		for _, y := range items {
			err = sendItem(y)
			if err != nil {
				panic(err)
			}
		}
	}
}

// Send a compliance item to MozDef
func sendItem(item gozdef.ComplianceItem) (err error) {
	ev, err := gozdef.NewEvent()
	if err != nil {
		return
	}
	ev.Category = "complianceitems"
	ev.Source = "mig"
	cverb := "fails"
	if item.Compliance {
		cverb = "passes"
	}
	ev.Summary = fmt.Sprintf("%s %s compliance with %s", item.Target, cverb, item.Check.Ref)
	ev.Tags = append(ev.Tags, "mig")
	ev.Tags = append(ev.Tags, "compliance")
	ev.Info()
	ev.Details = item
	ac := gozdef.ApiConf{Url: conf.MozDef.URL}
	pub, err := gozdef.InitApi(ac)
	if err != nil {
		return
	}
	err = pub.Send(ev)
	return
}

// Convert a MIG command result into a MozDef compliance event
func makeComplianceItem(cmd mig.Command) (items []gozdef.ComplianceItem, err error) {
	var ci gozdef.ComplianceItem
	ci.Utctimestamp = time.Now().UTC().Format(time.RFC3339Nano)
	ci.Target = cmd.Agent.Name
	ci.Policy.Name = cmd.Action.Threat.Type
	ci.Policy.URL = cmd.Action.Description.URL
	ci.Policy.Level = cmd.Action.Threat.Level
	ci.Check.Ref = cmd.Action.Threat.Ref
	ci.Check.Description = cmd.Action.Name
	ci.Link = fmt.Sprintf("%s/command?commandid=%.0f", conf.MIG.API, cmd.ID)
	if cmd.Agent.Tags != nil {
		operator := ""
		if _, ok := cmd.Agent.Tags.(map[string]interface{})["operator"]; ok {
			operator = cmd.Agent.Tags.(map[string]interface{})["operator"].(string)
		}
		team := getTeam(cmd.Agent, conf)
		ci.Tags = struct {
			Operator string `json:"operator"`
			Team     string `json:"team"`
		}{
			Operator: operator,
			Team:     team,
		}
	}
	for i, result := range cmd.Results {
		buf, err := json.Marshal(result)
		if err != nil {
			return items, err
		}
		if i > (len(cmd.Action.Operations) - 1) {
			// skip this entry if the lookup fails
			continue
		}
		switch cmd.Action.Operations[i].Module {
		case "file":
			var r modules.Result
			var el file.SearchResults
			err = json.Unmarshal(buf, &r)
			if err != nil {
				return items, err
			}
			err = r.GetElements(&el)
			if err != nil {
				return items, err
			}
			for label, sr := range el {
				for _, mf := range sr {
					ci.Check.Location = mf.File
					ci.Check.Name = label
					ci.Check.Test.Type = "file"<commit_msg>runner-compliance: update for new gozdef, treat tags as a map<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Contributor: <NAME> <EMAIL> [:alm]
package main

// This is a plugin for use with mig-runner that processes incoming compliance
// results from MIG and sends them to MozDef
//
// It replaces the historical compliance item worker process. This program
// generally is not run directly, but instead should be called by mig-runner
// as a plugin.

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"time"

	"github.com/jvehent/gozdef"
	"gopkg.in/gcfg.v1"
	"mig.ninja/mig"
	"mig.ninja/mig/modules"
	"mig.ninja/mig/modules/file"
)

type Config struct {
	MIG struct {
		// The MIG API URL
		API string
	}
	MozDef struct {
		// URL to post events to MozDef
		URL string
	}
	Vmintgr struct {
		// Location of vmintgr wrapper executable
		Bin string
	}
}

const configPath string = "/etc/mig/runner-compliance.conf"

var conf Config

func main() {
	defer func() {
		if e := recover(); e != nil {
			fmt.Fprintf(os.Stderr, "error: %v\n", e)
			os.Exit(1)
		}
	}()

	var (
		err     error
		results mig.RunnerResult
	)

	err = gcfg.ReadFileInto(&conf, configPath)
	if err != nil {
		panic(err)
	}

	buf, err := ioutil.ReadAll(os.Stdin)
	if err != nil {
		panic(err)
	}
	err = json.Unmarshal(buf, &results)
	if err != nil {
		panic(err)
	}
	for _, x := range results.Commands {
		items, err := makeComplianceItem(x)
		if err != nil {
			panic(err)
		}
		for _, y := range items {
			err = sendItem(y)
			if err != nil {
				panic(err)
			}
		}
	}
}

// Send a compliance item to MozDef
func sendItem(item gozdef.ComplianceItem) (err error) {
	ev, err := gozdef.NewEvent()
	if err != nil {
		return
	}
	ev.Category = "complianceitems"
	ev.Source = "mig"
	cverb := "fails"
	if item.Compliance {
		cverb = "passes"
	}
	ev.Summary = fmt.Sprintf("%s %s compliance with %s", item.Target, cverb, item.Check.Ref)
	ev.Tags = append(ev.Tags, "mig")
	ev.Tags = append(ev.Tags, "compliance")
	ev.Info()
	ev.Details = item
	ac := gozdef.APIConf{URL: conf.MozDef.URL}
	pub, err := gozdef.InitAPI(ac)
	if err != nil {
		return
	}
	err = pub.Send(ev)
	return
}

// Convert a MIG command result into a MozDef compliance event
func makeComplianceItem(cmd mig.Command) (items []gozdef.ComplianceItem, err error) {
	var ci gozdef.ComplianceItem
	ci.Utctimestamp = time.Now().UTC().Format(time.RFC3339Nano)
	ci.Target = cmd.Agent.Name
	ci.Policy.Name = cmd.Action.Threat.Type
	ci.Policy.URL = cmd.Action.Description.URL
	ci.Policy.Level = cmd.Action.Threat.Level
	ci.Check.Ref = cmd.Action.Threat.Ref
	ci.Check.Description = cmd.Action.Name
	ci.Link = fmt.Sprintf("%s/command?commandid=%.0f", conf.MIG.API, cmd.ID)
	if len(cmd.Agent.Tags) != 0 {
		if _, ok := cmd.Agent.Tags["operator"]; ok {
			ci.Tags["operator"] = cmd.Agent.Tags["operator"]
		}
	}
	for i, result := range cmd.Results {
		buf, err := json.Marshal(result)
		if err != nil {
			return items, err
		}
		if i > (len(cmd.Action.Operations) - 1) {
			// skip this entry if the lookup fails
			continue
		}
		switch cmd.Action.Operations[i].Module {
		case "file":
			var r modules.Result
			var el file.SearchResults
			err = json.Unmarshal(buf, &r)
			if err != nil {
				return items, err
			}
			err = r.GetElements(&el)
			if err != nil {
				return items, err
			}
			for label, sr := range el {
				for _, mf := range sr {
					ci.Check.Location = mf.File
					ci.Check.Name = label
					ci.Check.Test.Type = "file"
{'fraction_non_alphanumeric': 0.1406062224596074, 'fraction_numerical': 0.0033382294031245826, 'mean_word_length': 3.0139335476956055, 'pattern_counts': {'":': 2, '<': 7, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4216014', 'n_tokens_mistral': 3033, 'n_tokens_neox': 2774, 'n_words': 764}